1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 LunarG, Inc.
6 * Copyright (c) 2023 Nintendo
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Shader Object Performance Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktShaderObjectPerformanceTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkShaderObjectUtil.hpp"
30 #include "vktShaderObjectCreateUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include <chrono>
37
38 namespace vkt
39 {
40 namespace ShaderObject
41 {
42
43 namespace
44 {
45
46 enum TestType
47 {
48 DRAW_STATIC_PIPELINE,
49 DRAW_DYNAMIC_PIPELINE,
50 DRAW_LINKED_SHADERS,
51 DRAW_BINARY,
52 DRAW_BINARY_BIND,
53 };
54
55 enum BinaryType
56 {
57 BINARY_SHADER_CREATE,
58 BINARY_MEMCPY,
59 };
60
61 enum DrawType
62 {
63 DRAW,
64 DRAW_INDEXED,
65 DRAW_INDEXED_INDIRECT,
66 DRAW_INDEXED_INDIRECT_COUNT,
67 DRAW_INDIRECT,
68 DRAW_INDIRECT_COUNT,
69 };
70
71 enum DispatchType
72 {
73 DISPATCH,
74 DISPATCH_BASE,
75 DISPATCH_INDIRECT,
76 };
77
78 class ShaderObjectPerformanceInstance : public vkt::TestInstance
79 {
80 public:
ShaderObjectPerformanceInstance(Context & context,const DrawType drawType,const TestType & type)81 ShaderObjectPerformanceInstance(Context &context, const DrawType drawType, const TestType &type)
82 : vkt::TestInstance(context)
83 , m_drawType(drawType)
84 , m_type(type)
85 {
86 }
~ShaderObjectPerformanceInstance(void)87 virtual ~ShaderObjectPerformanceInstance(void)
88 {
89 }
90
91 tcu::TestStatus iterate(void) override;
92
93 private:
94 std::chrono::nanoseconds draw(const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer,
95 vk::VkBuffer indexBuffer, vk::VkBuffer indirectBuffer,
96 vk::VkBuffer countBuffer) const;
97
98 const DrawType m_drawType;
99 const TestType m_type;
100 };
101
extensionEnabled(const std::vector<std::string> & deviceExtensions,const std::string & ext)102 bool extensionEnabled(const std::vector<std::string> &deviceExtensions, const std::string &ext)
103 {
104 return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
105 }
106
getDynamicStates(Context & context)107 std::vector<vk::VkDynamicState> getDynamicStates(Context &context)
108 {
109 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(
110 context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceExtensions());
111 const auto &edsFeatures = context.getExtendedDynamicStateFeaturesEXT();
112 const auto &eds2Features = context.getExtendedDynamicState2FeaturesEXT();
113 const auto &eds3Features = context.getExtendedDynamicState3FeaturesEXT();
114 const auto &viFeatures = context.getVertexInputDynamicStateFeaturesEXT();
115
116 std::vector<vk::VkDynamicState> dynamicStates = {
117 vk::VK_DYNAMIC_STATE_LINE_WIDTH, vk::VK_DYNAMIC_STATE_DEPTH_BIAS,
118 vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS, vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS,
119 vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
120 vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE,
121 };
122
123 if (edsFeatures.extendedDynamicState)
124 {
125 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
126 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
127 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
128 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
129 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
130 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
131 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
132 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
133 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
134 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
135 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
136 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
137 }
138 else
139 {
140 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT);
141 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR);
142 }
143 if (eds2Features.extendedDynamicState2)
144 {
145 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
146 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
147 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
148 }
149 if (eds2Features.extendedDynamicState2LogicOp)
150 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
151 if (eds2Features.extendedDynamicState2PatchControlPoints)
152 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
153
154 if (eds3Features.extendedDynamicState3TessellationDomainOrigin)
155 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
156 if (eds3Features.extendedDynamicState3DepthClampEnable)
157 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
158 if (eds3Features.extendedDynamicState3PolygonMode)
159 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
160 if (eds3Features.extendedDynamicState3RasterizationSamples)
161 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
162 if (eds3Features.extendedDynamicState3SampleMask)
163 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
164 if (eds3Features.extendedDynamicState3AlphaToCoverageEnable)
165 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
166 if (eds3Features.extendedDynamicState3AlphaToOneEnable)
167 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
168 if (eds3Features.extendedDynamicState3LogicOpEnable)
169 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
170 if (eds3Features.extendedDynamicState3ColorBlendEnable)
171 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
172 if (eds3Features.extendedDynamicState3ColorBlendEquation)
173 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
174 if (eds3Features.extendedDynamicState3ColorWriteMask)
175 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
176 if (viFeatures.vertexInputDynamicState)
177 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
178
179 if (extensionEnabled(deviceExtensions, "VK_EXT_transform_feedback") &&
180 eds3Features.extendedDynamicState3RasterizationStream)
181 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
182 if (extensionEnabled(deviceExtensions, "VK_EXT_blend_operation_advanced") &&
183 eds3Features.extendedDynamicState3ColorBlendAdvanced)
184 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
185 if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") &&
186 eds3Features.extendedDynamicState3ConservativeRasterizationMode)
187 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
188 if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") &&
189 eds3Features.extendedDynamicState3CoverageModulationMode)
190 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
191 if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") &&
192 eds3Features.extendedDynamicState3CoverageModulationTableEnable)
193 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
194 if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") &&
195 eds3Features.extendedDynamicState3CoverageModulationTable)
196 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
197 if (extensionEnabled(deviceExtensions, "VK_NV_coverage_reduction_mode") &&
198 eds3Features.extendedDynamicState3CoverageReductionMode)
199 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
200 if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") &&
201 eds3Features.extendedDynamicState3CoverageToColorEnable)
202 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
203 if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") &&
204 eds3Features.extendedDynamicState3CoverageToColorLocation)
205 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
206 if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_enable") &&
207 eds3Features.extendedDynamicState3DepthClipEnable)
208 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
209 if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_control") &&
210 eds3Features.extendedDynamicState3DepthClipNegativeOneToOne)
211 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
212 if (extensionEnabled(deviceExtensions, "VK_EXT_color_write_enable"))
213 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
214 if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") &&
215 eds3Features.extendedDynamicState3ExtraPrimitiveOverestimationSize)
216 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
217 if ((extensionEnabled(deviceExtensions, "VK_KHR_line_rasterization") ||
218 extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization")) &&
219 eds3Features.extendedDynamicState3LineRasterizationMode)
220 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
221 if ((extensionEnabled(deviceExtensions, "VK_KHR_line_rasterization") ||
222 extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization")) &&
223 eds3Features.extendedDynamicState3LineStippleEnable)
224 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
225 if ((extensionEnabled(deviceExtensions, "VK_KHR_line_rasterization") ||
226 extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization")))
227 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
228 if (extensionEnabled(deviceExtensions, "VK_EXT_provoking_vertex") &&
229 eds3Features.extendedDynamicState3ProvokingVertexMode)
230 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
231 if (extensionEnabled(deviceExtensions, "VK_KHR_fragment_shading_rate"))
232 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
233 if (extensionEnabled(deviceExtensions, "VK_NV_representative_fragment_test") &&
234 eds3Features.extendedDynamicState3RepresentativeFragmentTestEnable)
235 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
236 if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations") &&
237 eds3Features.extendedDynamicState3SampleLocationsEnable)
238 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
239 if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations"))
240 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
241 if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image") &&
242 eds3Features.extendedDynamicState3ShadingRateImageEnable)
243 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
244 if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
245 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
246 if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
247 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);
248 if (extensionEnabled(deviceExtensions, "VK_NV_viewport_swizzle") &&
249 eds3Features.extendedDynamicState3ViewportSwizzle)
250 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
251 if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling") &&
252 eds3Features.extendedDynamicState3ViewportWScalingEnable)
253 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
254 if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling"))
255 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
256 if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
257 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
258 if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
259 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
260 if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
261 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
262 if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
263 dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
264
265 return dynamicStates;
266 }
267
createShaderFromBinary(const vk::DeviceInterface & vk,const vk::VkDevice device,const vk::Move<vk::VkShaderEXT> & shader,vk::VkShaderStageFlagBits stage)268 vk::VkShaderEXT createShaderFromBinary(const vk::DeviceInterface &vk, const vk::VkDevice device,
269 const vk::Move<vk::VkShaderEXT> &shader, vk::VkShaderStageFlagBits stage)
270 {
271 size_t dataSize = 0;
272 vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
273 std::vector<uint8_t> data(dataSize);
274 vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
275
276 const vk::VkShaderCreateInfoEXT binaryShaderCreateInfo = {
277 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 0u, // VkShaderCreateFlagsEXT flags;
280 stage, // VkShaderStageFlagBits stage;
281 0u, // VkShaderStageFlags nextStage;
282 vk::VK_SHADER_CODE_TYPE_BINARY_EXT, // VkShaderCodeTypeEXT codeType;
283 dataSize, // size_t codeSize;
284 data.data(), // const void* pCode;
285 "main", // const char* pName;
286 0u, // uint32_t setLayoutCount;
287 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
288 0u, // uint32_t pushConstantRangeCount;
289 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
290 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
291 };
292
293 vk::VkShaderEXT binaryShader;
294 vk.createShadersEXT(device, 1, &binaryShaderCreateInfo, DE_NULL, &binaryShader);
295 return binaryShader;
296 }
297
draw(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkBuffer indexBuffer,vk::VkBuffer indirectBuffer,vk::VkBuffer countBuffer) const298 std::chrono::nanoseconds ShaderObjectPerformanceInstance::draw(const vk::DeviceInterface &vk,
299 vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indexBuffer,
300 vk::VkBuffer indirectBuffer,
301 vk::VkBuffer countBuffer) const
302 {
303 if (m_drawType == DRAW)
304 {
305 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
306 vk.cmdDraw(cmdBuffer, 4, 1, 0, 0);
307 return std::chrono::high_resolution_clock::now() - shaderObjectStart;
308 }
309 else if (m_drawType == DRAW_INDEXED)
310 {
311 vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0u, vk::VK_INDEX_TYPE_UINT16);
312 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
313 vk.cmdDrawIndexed(cmdBuffer, 4, 1, 0, 0, 0);
314 return std::chrono::high_resolution_clock::now() - shaderObjectStart;
315 }
316 else if (m_drawType == DRAW_INDEXED_INDIRECT)
317 {
318 vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0u, vk::VK_INDEX_TYPE_UINT16);
319 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
320 vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndexedIndirectCommand));
321 return std::chrono::high_resolution_clock::now() - shaderObjectStart;
322 }
323 else if (m_drawType == DRAW_INDEXED_INDIRECT_COUNT)
324 {
325 vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0u, vk::VK_INDEX_TYPE_UINT16);
326 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
327 vk.cmdDrawIndexedIndirectCount(cmdBuffer, indirectBuffer, 0u, countBuffer, 0u, 1u,
328 sizeof(vk::VkDrawIndexedIndirectCommand));
329 return std::chrono::high_resolution_clock::now() - shaderObjectStart;
330 }
331 else if (m_drawType == DRAW_INDIRECT)
332 {
333 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
334 vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
335 return std::chrono::high_resolution_clock::now() - shaderObjectStart;
336 }
337 else if (m_drawType == DRAW_INDIRECT_COUNT)
338 {
339 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
340 vk.cmdDrawIndirectCount(cmdBuffer, indirectBuffer, 0u, countBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
341 return std::chrono::high_resolution_clock::now() - shaderObjectStart;
342 }
343 return std::chrono::nanoseconds(0);
344 }
345
iterate(void)346 tcu::TestStatus ShaderObjectPerformanceInstance::iterate(void)
347 {
348 const vk::VkInstance instance = m_context.getInstance();
349 const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
350 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
351 const vk::VkDevice device = m_context.getDevice();
352 const vk::VkQueue queue = m_context.getUniversalQueue();
353 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
354 auto &alloc = m_context.getDefaultAllocator();
355 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(
356 m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
357 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
358 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
359 const bool taskSupported = m_context.getMeshShaderFeaturesEXT().taskShader;
360 const bool meshSupported = m_context.getMeshShaderFeaturesEXT().meshShader;
361
362 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
363 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
364
365 const vk::Move<vk::VkCommandPool> cmdPool(
366 createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
367 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
368 allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
369
370 const vk::VkPrimitiveTopology topology =
371 tessellationSupported ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
372
373 const uint32_t geomIndex = tessellationSupported ? 4u : 2u;
374
375 const vk::VkImageCreateInfo createInfo = {
376 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
377 DE_NULL, // const void* pNext
378 0u, // VkImageCreateFlags flags
379 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
380 colorAttachmentFormat, // VkFormat format
381 {32, 32, 1}, // VkExtent3D extent
382 1u, // uint32_t mipLevels
383 1u, // uint32_t arrayLayers
384 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
385 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
386 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
387 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
388 0, // uint32_t queueFamilyIndexCount
389 DE_NULL, // const uint32_t* pQueueFamilyIndices
390 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
391 };
392
393 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
394 new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
395 const auto imageView =
396 vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
397 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
398
399 const vk::VkDeviceSize colorOutputBufferSize =
400 renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
401 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
402 vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
403 vk::MemoryRequirement::HostVisible));
404
405 const auto &binaries = m_context.getBinaryCollection();
406
407 std::vector<vk::VkShaderCreateInfoEXT> createInfos = {
408 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"), tessellationSupported,
409 geometrySupported),
410 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"), tessellationSupported,
411 geometrySupported),
412 };
413
414 if (tessellationSupported)
415 {
416 createInfos.push_back(vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
417 binaries.get("tesc"), tessellationSupported, geometrySupported));
418 createInfos.push_back(vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
419 binaries.get("tese"), tessellationSupported, geometrySupported));
420 }
421 if (geometrySupported)
422 {
423 createInfos.push_back(vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, binaries.get("geom"),
424 tessellationSupported, geometrySupported));
425 }
426
427 if (tessellationSupported)
428 {
429 createInfos[0].nextStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
430 createInfos[2].nextStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
431 if (geometrySupported)
432 createInfos[3].nextStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
433 else
434 createInfos[3].nextStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
435 }
436 else if (geometrySupported)
437 {
438 createInfos[0].nextStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
439 createInfos[geomIndex].nextStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
440 }
441 else
442 {
443 createInfos[0].nextStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
444 }
445
446 vk::Move<vk::VkShaderEXT> vertShader = vk::createShader(vk, device, createInfos[0]);
447 vk::Move<vk::VkShaderEXT> fragShader = vk::createShader(vk, device, createInfos[1]);
448 vk::Move<vk::VkShaderEXT> tescShader;
449 vk::Move<vk::VkShaderEXT> teseShader;
450 vk::Move<vk::VkShaderEXT> geomShader;
451
452 if (tessellationSupported)
453 {
454 tescShader = vk::createShader(vk, device, createInfos[2]);
455 teseShader = vk::createShader(vk, device, createInfos[3]);
456 }
457 if (geometrySupported)
458 {
459 geomShader = vk::createShader(vk, device, createInfos[geomIndex]);
460 }
461
462 std::vector<vk::VkShaderEXT> refShaders;
463
464 if (m_type == DRAW_LINKED_SHADERS)
465 {
466 refShaders.resize(5, VK_NULL_HANDLE);
467 for (auto &info : createInfos)
468 info.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
469
470 vk.createShadersEXT(device, (uint32_t)createInfos.size(), createInfos.data(), DE_NULL, refShaders.data());
471 }
472 else if (m_type == DRAW_BINARY || m_type == DRAW_BINARY_BIND)
473 {
474 refShaders.resize(5, VK_NULL_HANDLE);
475 refShaders[0] = createShaderFromBinary(vk, device, vertShader, vk::VK_SHADER_STAGE_VERTEX_BIT);
476 refShaders[1] = createShaderFromBinary(vk, device, fragShader, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
477 if (tessellationSupported)
478 {
479 refShaders[2] =
480 createShaderFromBinary(vk, device, tescShader, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
481 refShaders[3] =
482 createShaderFromBinary(vk, device, teseShader, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
483 }
484 if (geometrySupported)
485 {
486 refShaders[geomIndex] = createShaderFromBinary(vk, device, geomShader, vk::VK_SHADER_STAGE_GEOMETRY_BIT);
487 }
488 }
489
490 vk::VkShaderEXT linkedShaders[5];
491 vk.createShadersEXT(device, static_cast<uint32_t>(createInfos.size()), createInfos.data(), nullptr, linkedShaders);
492
493 vk::Move<vk::VkShaderEXT> linkedVertShader = vk::Move<vk::VkShaderEXT>(
494 vk::check<vk::VkShaderEXT>(linkedShaders[0]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
495 vk::Move<vk::VkShaderEXT> linkedFragShader = vk::Move<vk::VkShaderEXT>(
496 vk::check<vk::VkShaderEXT>(linkedShaders[1]), vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
497 vk::Move<vk::VkShaderEXT> linkedTescShader;
498 vk::Move<vk::VkShaderEXT> linkedTeseShader;
499 vk::Move<vk::VkShaderEXT> linkedGeomShader;
500 if (tessellationSupported)
501 {
502 linkedTescShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[2]),
503 vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
504 linkedTeseShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[3]),
505 vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
506 }
507 if (geometrySupported)
508 {
509 linkedGeomShader = vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(linkedShaders[geomIndex]),
510 vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
511 }
512
513 vk::Move<vk::VkShaderModule> vertShaderModule = createShaderModule(vk, device, binaries.get("vert"));
514 vk::Move<vk::VkShaderModule> fragShaderModule = createShaderModule(vk, device, binaries.get("frag"));
515 vk::Move<vk::VkShaderModule> dummyVertShaderModule = createShaderModule(vk, device, binaries.get("dummyVert"));
516 vk::Move<vk::VkShaderModule> dummyFragShaderModule = createShaderModule(vk, device, binaries.get("dummyFrag"));
517 vk::Move<vk::VkShaderModule> tescShaderModule;
518 vk::Move<vk::VkShaderModule> teseShaderModule;
519 vk::Move<vk::VkShaderModule> geomShaderModule;
520 if (tessellationSupported)
521 {
522 tescShaderModule = createShaderModule(vk, device, binaries.get("tesc"));
523 teseShaderModule = createShaderModule(vk, device, binaries.get("tese"));
524 }
525 if (geometrySupported)
526 {
527 geomShaderModule = createShaderModule(vk, device, binaries.get("geom"));
528 }
529
530 const auto emptyPipelineLayout = makePipelineLayout(vk, device);
531
532 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
533 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
534 DE_NULL, // const void* pNext;
535 0u, // VkPipelineVertexInputStateCreateFlags flags;
536 0u, // uint32_t vertexBindingDescriptionCount;
537 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
538 0u, // uint32_t vertexAttributeDescriptionCount;
539 DE_NULL // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
540 };
541
542 const vk::VkPipelineTessellationStateCreateInfo tessStateCreateInfo = {
543 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
544 DE_NULL, // const void* pNext;
545 0u, // VkPipelineTessellationStateCreateFlags flags;
546 4u, // uint32_t patchControlPoints;
547 };
548
549 vk::VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
550 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
551 DE_NULL, // const void* pNext;
552 (vk::VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags;
553 topology, // VkPrimitiveTopology topology;
554 VK_FALSE, // VkBool32 primitiveRestartEnable;
555 };
556
557 vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {
558 vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType sType
559 DE_NULL, // const void* pNext
560 0u, // uint32_t viewMask
561 1u, // uint32_t colorAttachmentCount
562 &colorAttachmentFormat, // const VkFormat* pColorAttachmentFormats
563 vk::VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat
564 vk::VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat
565 };
566
567 const vk::VkViewport viewport =
568 vk::makeViewport((float)renderArea.extent.width, 0.0f, (float)renderArea.extent.width,
569 (float)renderArea.extent.height, 0.0f, 1.0f);
570 const vk::VkRect2D scissor = vk::makeRect2D(renderArea.extent);
571
572 vk::VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
573 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
574 DE_NULL, // const void* pNext
575 (vk::VkPipelineViewportStateCreateFlags)0u, // VkPipelineViewportStateCreateFlags flags
576 (m_type == DRAW_DYNAMIC_PIPELINE) ? 0u : 1u, // uint32_t viewportCount
577 &viewport, // const VkViewport* pViewports
578 (m_type == DRAW_DYNAMIC_PIPELINE) ? 0u : 1u, // uint32_t scissorCount
579 &scissor // const VkRect2D* pScissors
580 };
581
582 const auto dynamicStates = getDynamicStates(m_context);
583
584 const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
585 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
586 DE_NULL, // const void* pNext;
587 (vk::VkPipelineDynamicStateCreateFlags)0u, // VkPipelineDynamicStateCreateFlags flags;
588 static_cast<uint32_t>(dynamicStates.size()), // uint32_t dynamicStateCount;
589 dynamicStates.data(), // const VkDynamicState* pDynamicStates;
590 };
591
592 const vk::VkPipelineDynamicStateCreateInfo *pDynamicStateCreateInfo =
593 (m_type == DRAW_DYNAMIC_PIPELINE) ? &dynamicStateCreateInfo : DE_NULL;
594
595 const auto pipeline = makeGraphicsPipeline(
596 vk, device, emptyPipelineLayout.get(), vertShaderModule.get(), tescShaderModule.get(), teseShaderModule.get(),
597 geomShaderModule.get(), fragShaderModule.get(), VK_NULL_HANDLE, 0u, &vertexInputStateParams,
598 &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL,
599 DE_NULL, pDynamicStateCreateInfo, &pipelineRenderingCreateInfo);
600 pipelineInputAssemblyStateInfo.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
601 viewportStateCreateInfo.viewportCount = 1u;
602 viewportStateCreateInfo.scissorCount = 1u;
603 const auto dummyPipeline = makeGraphicsPipeline(
604 vk, device, emptyPipelineLayout.get(), dummyVertShaderModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE,
605 VK_NULL_HANDLE, dummyFragShaderModule.get(), VK_NULL_HANDLE, 0u, &vertexInputStateParams,
606 &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL,
607 DE_NULL, DE_NULL, &pipelineRenderingCreateInfo);
608
609 const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
610
611 vk::BufferWithMemory indirectBuffer(
612 vk, device, alloc,
613 vk::makeBufferCreateInfo(sizeof(vk::VkDrawIndirectCommand) + sizeof(vk::VkDrawIndexedIndirectCommand),
614 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
615 vk::MemoryRequirement::HostVisible);
616
617 if (m_drawType == DRAW_INDEXED_INDIRECT || m_drawType == DRAW_INDEXED_INDIRECT_COUNT)
618 {
619 vk::VkDrawIndexedIndirectCommand *indirectDataPtr =
620 reinterpret_cast<vk::VkDrawIndexedIndirectCommand *>(indirectBuffer.getAllocation().getHostPtr());
621 indirectDataPtr->indexCount = 4;
622 indirectDataPtr->instanceCount = 1;
623 indirectDataPtr->firstIndex = 0;
624 indirectDataPtr->vertexOffset = 0;
625 indirectDataPtr->firstInstance = 0;
626 }
627 else
628 {
629 vk::VkDrawIndirectCommand *indirectDataPtr =
630 reinterpret_cast<vk::VkDrawIndirectCommand *>(indirectBuffer.getAllocation().getHostPtr());
631 indirectDataPtr->vertexCount = 4;
632 indirectDataPtr->instanceCount = 1;
633 indirectDataPtr->firstVertex = 0;
634 indirectDataPtr->firstInstance = 0;
635 }
636
637 vk::BufferWithMemory countBuffer(
638 vk, device, alloc, vk::makeBufferCreateInfo(sizeof(uint32_t), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
639 vk::MemoryRequirement::HostVisible);
640 uint32_t *countDataPtr = reinterpret_cast<uint32_t *>(countBuffer.getAllocation().getHostPtr());
641 countDataPtr[0] = 1u;
642
643 vk::BufferWithMemory indexBuffer(
644 vk, device, alloc, vk::makeBufferCreateInfo(sizeof(uint32_t) * 4, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
645 vk::MemoryRequirement::HostVisible);
646 uint32_t *indexDataPtr = reinterpret_cast<uint32_t *>(indexBuffer.getAllocation().getHostPtr());
647 indexDataPtr[0] = 0u;
648 indexDataPtr[1] = 1u;
649 indexDataPtr[2] = 2u;
650 indexDataPtr[3] = 3u;
651
652 const vk::VkDeviceSize bufferSize = 64;
653 de::MovePtr<vk::BufferWithMemory> buffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
654 vk, device, alloc, vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
655 vk::MemoryRequirement::HostVisible));
656
657 // Do a dummy run, to ensure memory allocations are done with before performance testing
658 {
659 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
660 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *dummyPipeline);
661 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
662 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
663 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
664 vk::endRendering(vk, *cmdBuffer);
665 vk::endCommandBuffer(vk, *cmdBuffer);
666 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
667 }
668
669 std::chrono::nanoseconds time = std::chrono::nanoseconds(0);
670 std::chrono::nanoseconds refTime = std::chrono::nanoseconds(0);
671 std::chrono::nanoseconds maxTime = std::chrono::nanoseconds(0);
672 std::chrono::nanoseconds maxRefTime = std::chrono::nanoseconds(0);
673
674 for (uint32_t i = 0; i < 100; ++i)
675 {
676 std::chrono::nanoseconds currentTime;
677 std::chrono::nanoseconds currentRefTime;
678
679 if (m_type == DRAW_BINARY_BIND)
680 {
681 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
682 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
683 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
684 taskSupported, meshSupported);
685 currentTime = std::chrono::high_resolution_clock::now() - shaderObjectStart;
686 vk::endCommandBuffer(vk, *cmdBuffer);
687
688 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
689 const auto refShaderObjectStart = std::chrono::high_resolution_clock::now();
690 vk::bindGraphicsShaders(vk, *cmdBuffer, refShaders[0], refShaders[2], refShaders[3], refShaders[4],
691 refShaders[1], taskSupported, meshSupported);
692 currentRefTime = std::chrono::high_resolution_clock::now() - refShaderObjectStart;
693 vk::endCommandBuffer(vk, *cmdBuffer);
694 }
695 else
696 {
697 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
698 vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
699 taskSupported, meshSupported);
700 vk::setDefaultShaderObjectDynamicStates(
701 vk, *cmdBuffer, deviceExtensions, topology, false,
702 !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
703 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
704 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
705 currentTime = draw(vk, *cmdBuffer, *indexBuffer, *indirectBuffer, *countBuffer);
706 vk::endRendering(vk, *cmdBuffer);
707 vk::endCommandBuffer(vk, *cmdBuffer);
708 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
709
710 if (m_type == DRAW_LINKED_SHADERS || m_type == DRAW_BINARY)
711 {
712 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
713 vk::bindGraphicsShaders(vk, *cmdBuffer, refShaders[0], refShaders[2], refShaders[3], refShaders[4],
714 refShaders[1], taskSupported, meshSupported);
715 vk::setDefaultShaderObjectDynamicStates(
716 vk, *cmdBuffer, deviceExtensions, topology, false,
717 !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
718 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
719 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
720 currentRefTime = draw(vk, *cmdBuffer, *indexBuffer, *indirectBuffer, *countBuffer);
721 vk::endRendering(vk, *cmdBuffer);
722 vk::endCommandBuffer(vk, *cmdBuffer);
723 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
724 }
725 else
726 {
727 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
728 vk::VkDeviceSize offset = 0u;
729 vk::VkDeviceSize stride = 16u;
730 vk.cmdBindVertexBuffers2(*cmdBuffer, 0u, 1u, &**buffer, &offset, &bufferSize, &stride);
731 vk::setDefaultShaderObjectDynamicStates(
732 vk, *cmdBuffer, deviceExtensions, topology, false,
733 !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
734 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
735 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
736 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
737 currentRefTime = draw(vk, *cmdBuffer, *indexBuffer, *indirectBuffer, *countBuffer);
738 vk::endRendering(vk, *cmdBuffer);
739 vk::endCommandBuffer(vk, *cmdBuffer);
740 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
741 }
742 }
743
744 time += currentTime;
745 if (currentTime > maxTime)
746 maxTime = currentTime;
747
748 refTime += currentRefTime;
749 if (currentRefTime > maxRefTime)
750 maxRefTime = currentRefTime;
751 }
752
753 for (const auto &shader : refShaders)
754 vk.destroyShaderEXT(device, shader, DE_NULL);
755
756 if (m_type == DRAW_STATIC_PIPELINE)
757 {
758 if (maxTime > maxRefTime * 1.5f)
759 return tcu::TestStatus::fail("Maximum shader object rendering iteration was more than 50% slower than "
760 "maximum static pipeline iteration rendering");
761 if (time > refTime * 1.25f)
762 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING,
763 "Shader object rendering was more than 25% slower than static pipeline rendering");
764 if (maxTime > maxRefTime * 1.25f)
765 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING,
766 "Maximum shader object iteration rendering was more than 25% slower than maximum "
767 "static pipeline iteration rendering");
768 }
769 else if (m_type == DRAW_DYNAMIC_PIPELINE)
770 {
771 if (maxTime > maxRefTime * 1.2f)
772 return tcu::TestStatus::fail("Maximum shader object iteration rendering was more than 20% slower than "
773 "maximum dynamic pipeline iteration rendering");
774 if (time > refTime * 1.1f)
775 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING,
776 "Shader object rendering was more than 10% slower than dynamic pipeline rendering");
777 if (maxTime > maxRefTime * 1.1f)
778 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING,
779 "Maximum shader object iteration rendering was more than 10% slower than maximum "
780 "dynamic pipeline iteration rendering");
781 }
782 else if (m_type == DRAW_LINKED_SHADERS)
783 {
784 if (maxTime > maxRefTime * 1.05f)
785 return tcu::TestStatus::fail("Maximum unlinked shader object iteration rendering was more than 5% slower "
786 "than maximum linked shader object iteration rendering");
787 if (time * 1.05f < refTime)
788 return tcu::TestStatus::fail(
789 "Linked shader object rendering was more than 5% slower than unlinked shader object rendering");
790 if (maxTime * 1.05f < maxRefTime)
791 return tcu::TestStatus::fail("Maximum linked shader object iteration rendering was more than 5% slower "
792 "than maximum unlinked shader object iteratino rendering");
793 }
794 else if (m_type == DRAW_BINARY)
795 {
796 if (maxTime > maxRefTime * 1.05f)
797 return tcu::TestStatus::fail("Maximum shader object iteration rendering was more than 5% slower than "
798 "maximum binary shader object iteration rendering");
799 if (time * 1.05f < refTime)
800 return tcu::TestStatus::fail(
801 "Binary shader object rendering was more than 5% slower than shader object rendering");
802 if (maxTime * 1.05f < maxRefTime)
803 return tcu::TestStatus::fail("Maximum binary shader object iteration rendering was more than 5% slower "
804 "than maximum shader object iteration rendering");
805 }
806 else if (m_type == DRAW_BINARY_BIND)
807 {
808 if (maxTime > maxRefTime * 1.05f)
809 return tcu::TestStatus::fail("Maximum shader object iteration binding was more than 5% slower than maximum "
810 "binary shader object iteration binding");
811 if (time * 1.05f < refTime)
812 return tcu::TestStatus::fail(
813 "Binary shader object binding was more than 5% slower than shader object binding");
814 if (maxTime * 1.05f < maxRefTime)
815 return tcu::TestStatus::fail("Maximum binary shader object iteration binding was more than 5% slower than "
816 "maximum shader object iteration binding");
817 }
818
819 return tcu::TestStatus::pass("Pass");
820 }
821
822 class ShaderObjectPerformanceCase : public vkt::TestCase
823 {
824 public:
ShaderObjectPerformanceCase(tcu::TestContext & testCtx,const std::string & name,const DrawType drawType,const TestType & type)825 ShaderObjectPerformanceCase(tcu::TestContext &testCtx, const std::string &name, const DrawType drawType,
826 const TestType &type)
827 : vkt::TestCase(testCtx, name)
828 , m_drawType(drawType)
829 , m_type(type)
830 {
831 }
~ShaderObjectPerformanceCase(void)832 virtual ~ShaderObjectPerformanceCase(void)
833 {
834 }
835
836 void checkSupport(vkt::Context &context) const override;
837 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const838 TestInstance *createInstance(Context &context) const override
839 {
840 return new ShaderObjectPerformanceInstance(context, m_drawType, m_type);
841 }
842
843 private:
844 DrawType m_drawType;
845 TestType m_type;
846 };
847
checkSupport(Context & context) const848 void ShaderObjectPerformanceCase::checkSupport(Context &context) const
849 {
850 context.requireDeviceFunctionality("VK_EXT_shader_object");
851 }
852
initPrograms(vk::SourceCollections & programCollection) const853 void ShaderObjectPerformanceCase::initPrograms(vk::SourceCollections &programCollection) const
854 {
855 vk::addBasicShaderObjectShaders(programCollection);
856
857 std::stringstream dummyVert;
858 std::stringstream dummyFrag;
859
860 dummyVert << "#version 450\n"
861 << "layout(location = 0) out vec4 rgba;\n"
862 << "void main() {\n"
863 << " vec2 pos2 = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
864 << " vec3 pos3 = vec3(pos2, 0.0f) * gl_InstanceIndex;\n"
865 << " gl_Position = vec4(pos3, 1.0f);\n"
866 << " rgba = vec4(0.0f, pos3.zyx);\n"
867 << "}\n";
868
869 dummyFrag << "#version 450\n"
870 << "layout(location = 0) in vec4 rgba;\n"
871 << "layout(location = 0) out vec4 color;\n"
872 << "void main() {\n"
873 << " color = rgba * rgba;\n"
874 << "}\n";
875
876 programCollection.glslSources.add("dummyVert") << glu::VertexSource(dummyVert.str());
877 programCollection.glslSources.add("dummyFrag") << glu::FragmentSource(dummyFrag.str());
878 }
879
880 class ShaderObjectDispatchPerformanceInstance : public vkt::TestInstance
881 {
882 public:
ShaderObjectDispatchPerformanceInstance(Context & context,const DispatchType dispatchType)883 ShaderObjectDispatchPerformanceInstance(Context &context, const DispatchType dispatchType)
884 : vkt::TestInstance(context)
885 , m_dispatchType(dispatchType)
886 {
887 }
~ShaderObjectDispatchPerformanceInstance(void)888 virtual ~ShaderObjectDispatchPerformanceInstance(void)
889 {
890 }
891
892 tcu::TestStatus iterate(void) override;
893
894 private:
895 const DispatchType m_dispatchType;
896 };
897
iterate(void)898 tcu::TestStatus ShaderObjectDispatchPerformanceInstance::iterate(void)
899 {
900 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
901 const vk::VkDevice device = m_context.getDevice();
902 const vk::VkQueue queue = m_context.getUniversalQueue();
903 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
904 auto &alloc = m_context.getDefaultAllocator();
905
906 const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 16;
907 const vk::BufferWithMemory outputBuffer(
908 vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
909 vk::MemoryRequirement::HostVisible);
910 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
911 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
912
913 const auto &binaries = m_context.getBinaryCollection();
914
915 const auto &comp = binaries.get("comp");
916 const auto compShaderModule = createShaderModule(vk, device, comp);
917
918 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
919 vk::DescriptorSetLayoutBuilder()
920 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
921 .build(vk, device));
922
923 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
924 vk::DescriptorPoolBuilder()
925 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
926 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
927 const auto pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout.get());
928
929 const vk::Unique<vk::VkDescriptorSet> descriptorSet(
930 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
931 const vk::VkDescriptorBufferInfo descriptorInfo =
932 vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
933 vk::DescriptorSetUpdateBuilder()
934 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
935 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
936 .update(vk, device);
937
938 vk::VkShaderCreateInfoEXT shaderCreateInfo =
939 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_COMPUTE_BIT, binaries.get("comp"), tessellationSupported,
940 geometrySupported, &*descriptorSetLayout);
941 if (m_dispatchType == DISPATCH_BASE)
942 shaderCreateInfo.flags |= vk::VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT;
943
944 const auto compShader = vk::createShader(vk, device, shaderCreateInfo);
945 const vk::VkPipelineCreateFlags pipelineFlags =
946 (m_dispatchType == DISPATCH) ? (vk::VkPipelineCreateFlags)0u :
947 (vk::VkPipelineCreateFlags)vk::VK_PIPELINE_CREATE_DISPATCH_BASE_BIT;
948 const auto computePipeline =
949 vk::makeComputePipeline(vk, device, pipelineLayout.get(), pipelineFlags, nullptr, compShaderModule.get(),
950 (vk::VkPipelineShaderStageCreateFlags)0u);
951
952 const vk::Move<vk::VkCommandPool> cmdPool(
953 createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
954 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
955 allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
956
957 vk::BufferWithMemory indirectBuffer(
958 vk, device, alloc,
959 vk::makeBufferCreateInfo(sizeof(vk::VkDispatchIndirectCommand), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
960 vk::MemoryRequirement::HostVisible);
961
962 vk::VkDispatchIndirectCommand *indirectDataPtr =
963 reinterpret_cast<vk::VkDispatchIndirectCommand *>(indirectBuffer.getAllocation().getHostPtr());
964 indirectDataPtr->x = 1;
965 indirectDataPtr->y = 1;
966 indirectDataPtr->z = 1;
967
968 std::chrono::nanoseconds time = std::chrono::nanoseconds(0);
969 std::chrono::nanoseconds refTime = std::chrono::nanoseconds(0);
970
971 for (uint32_t i = 0; i < 100; ++i)
972 {
973 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
974 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1,
975 &descriptorSet.get(), 0, DE_NULL);
976 vk::bindComputeShader(vk, *cmdBuffer, *compShader);
977 if (m_dispatchType == DISPATCH)
978 {
979 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
980 vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
981 time += std::chrono::high_resolution_clock::now() - shaderObjectStart;
982 }
983 else if (m_dispatchType == DISPATCH_BASE)
984 {
985 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
986 vk.cmdDispatchBase(*cmdBuffer, 1, 1, 1, 0, 0, 0);
987 time += std::chrono::high_resolution_clock::now() - shaderObjectStart;
988 }
989 else if (m_dispatchType == DISPATCH_INDIRECT)
990 {
991 const auto shaderObjectStart = std::chrono::high_resolution_clock::now();
992 vk.cmdDispatchIndirect(*cmdBuffer, *indirectBuffer, 0u);
993 time += std::chrono::high_resolution_clock::now() - shaderObjectStart;
994 }
995 vk::endCommandBuffer(vk, *cmdBuffer);
996 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
997
998 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
999 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1,
1000 &descriptorSet.get(), 0, DE_NULL);
1001 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1002 if (m_dispatchType == DISPATCH)
1003 {
1004 const auto pipelineStart = std::chrono::high_resolution_clock::now();
1005 vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
1006 refTime += std::chrono::high_resolution_clock::now() - pipelineStart;
1007 }
1008 else if (m_dispatchType == DISPATCH_BASE)
1009 {
1010 const auto pipelineStart = std::chrono::high_resolution_clock::now();
1011 vk.cmdDispatchBase(*cmdBuffer, 1, 1, 1, 0, 0, 0);
1012 refTime += std::chrono::high_resolution_clock::now() - pipelineStart;
1013 }
1014 else if (m_dispatchType == DISPATCH_INDIRECT)
1015 {
1016 const auto pipelineStart = std::chrono::high_resolution_clock::now();
1017 vk.cmdDispatchIndirect(*cmdBuffer, *indirectBuffer, 0u);
1018 refTime += std::chrono::high_resolution_clock::now() - pipelineStart;
1019 }
1020 vk::endCommandBuffer(vk, *cmdBuffer);
1021 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1022
1023 // Ignore first iteration, there is a penalty on the first call
1024 if (i == 0)
1025 {
1026 time = std::chrono::nanoseconds(0);
1027 refTime = std::chrono::nanoseconds(0);
1028 }
1029 }
1030
1031 if (time > refTime * 1.05f)
1032 return tcu::TestStatus::fail("Shader object dispatch was more than 5% slower than compute pipeline dispatch");
1033 return tcu::TestStatus::pass("Pass");
1034 }
1035
1036 class ShaderObjectDispatchPerformanceCase : public vkt::TestCase
1037 {
1038 public:
ShaderObjectDispatchPerformanceCase(tcu::TestContext & testCtx,const std::string & name,const DispatchType dispatchType)1039 ShaderObjectDispatchPerformanceCase(tcu::TestContext &testCtx, const std::string &name,
1040 const DispatchType dispatchType)
1041 : vkt::TestCase(testCtx, name)
1042 , m_dispatchType(dispatchType)
1043 {
1044 }
~ShaderObjectDispatchPerformanceCase(void)1045 virtual ~ShaderObjectDispatchPerformanceCase(void)
1046 {
1047 }
1048
1049 void checkSupport(vkt::Context &context) const override;
1050 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1051 TestInstance *createInstance(Context &context) const override
1052 {
1053 return new ShaderObjectDispatchPerformanceInstance(context, m_dispatchType);
1054 }
1055
1056 private:
1057 const DispatchType m_dispatchType;
1058 };
1059
checkSupport(Context & context) const1060 void ShaderObjectDispatchPerformanceCase::checkSupport(Context &context) const
1061 {
1062 context.requireDeviceFunctionality("VK_EXT_shader_object");
1063 }
1064
initPrograms(vk::SourceCollections & programCollection) const1065 void ShaderObjectDispatchPerformanceCase::initPrograms(vk::SourceCollections &programCollection) const
1066 {
1067 vk::addBasicShaderObjectShaders(programCollection);
1068 }
1069
1070 class ShaderObjectBinaryPerformanceInstance : public vkt::TestInstance
1071 {
1072 public:
ShaderObjectBinaryPerformanceInstance(Context & context,BinaryType type)1073 ShaderObjectBinaryPerformanceInstance(Context &context, BinaryType type) : vkt::TestInstance(context), m_type(type)
1074 {
1075 }
~ShaderObjectBinaryPerformanceInstance(void)1076 virtual ~ShaderObjectBinaryPerformanceInstance(void)
1077 {
1078 }
1079
1080 tcu::TestStatus iterate(void) override;
1081
1082 private:
1083 const BinaryType m_type;
1084 };
1085
iterate(void)1086 tcu::TestStatus ShaderObjectBinaryPerformanceInstance::iterate(void)
1087 {
1088 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1089 const vk::VkDevice device = m_context.getDevice();
1090 auto &alloc = m_context.getDefaultAllocator();
1091 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
1092 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
1093
1094 const auto &binaries = m_context.getBinaryCollection();
1095
1096 std::chrono::nanoseconds time = std::chrono::nanoseconds(0);
1097 std::chrono::nanoseconds refTime = std::chrono::nanoseconds(0);
1098
1099 for (uint32_t i = 0; i < 100; ++i)
1100 {
1101 const auto spirvCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"),
1102 tessellationSupported, geometrySupported);
1103 vk::VkShaderEXT spirvShader;
1104 const auto spirvStart = std::chrono::high_resolution_clock::now();
1105 vk.createShadersEXT(device, 1u, &spirvCreateInfo, DE_NULL, &spirvShader);
1106 const auto spirvEnd = std::chrono::high_resolution_clock::now();
1107 if (m_type == BINARY_SHADER_CREATE)
1108 refTime += spirvEnd - spirvStart;
1109
1110 size_t dataSize = 0;
1111 vk.getShaderBinaryDataEXT(device, spirvShader, &dataSize, DE_NULL);
1112 std::vector<uint8_t> data(dataSize);
1113 vk.getShaderBinaryDataEXT(device, spirvShader, &dataSize, data.data());
1114
1115 const vk::VkShaderCreateInfoEXT binaryShaderCreateInfo = {
1116 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
1117 DE_NULL, // const void* pNext;
1118 0u, // VkShaderCreateFlagsEXT flags;
1119 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
1120 0u, // VkShaderStageFlags nextStage;
1121 vk::VK_SHADER_CODE_TYPE_BINARY_EXT, // VkShaderCodeTypeEXT codeType;
1122 dataSize, // size_t codeSize;
1123 data.data(), // const void* pCode;
1124 "main", // const char* pName;
1125 0u, // uint32_t setLayoutCount;
1126 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
1127 0u, // uint32_t pushConstantRangeCount;
1128 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
1129 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
1130 };
1131
1132 vk::VkShaderEXT binaryShader;
1133 const auto binaryStart = std::chrono::high_resolution_clock::now();
1134 vk.createShadersEXT(device, 1, &binaryShaderCreateInfo, DE_NULL, &binaryShader);
1135 time += std::chrono::high_resolution_clock::now() - binaryStart;
1136
1137 const auto bufferCreateInfo = vk::makeBufferCreateInfo(dataSize, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1138 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vk, device, &bufferCreateInfo);
1139 const auto bufferMemReqs = vk::getBufferMemoryRequirements(vk, device, *buffer);
1140 const auto memoryProperties =
1141 vk::getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
1142 const auto hostCachedDeviceLocal =
1143 bufferMemReqs.memoryTypeBits &
1144 vk::getCompatibleMemoryTypes(memoryProperties, vk::MemoryRequirement::Cached |
1145 vk::MemoryRequirement::Local |
1146 vk::MemoryRequirement::HostVisible);
1147
1148 vk::MemoryRequirement memoryRequirements =
1149 (hostCachedDeviceLocal != 0) ?
1150 vk::MemoryRequirement::Cached | vk::MemoryRequirement::Local | vk::MemoryRequirement::HostVisible :
1151 vk::MemoryRequirement::Coherent | vk::MemoryRequirement::Local | vk::MemoryRequirement::HostVisible;
1152 vk::BufferWithMemory bufferWithMemory(vk, device, alloc, bufferCreateInfo, memoryRequirements);
1153 const vk::Allocation &bufferAlloc = bufferWithMemory.getAllocation();
1154 const auto memcpyStart = std::chrono::high_resolution_clock::now();
1155 memcpy(bufferAlloc.getHostPtr(), data.data(), dataSize);
1156 flushAlloc(vk, device, bufferAlloc);
1157 const auto memcpyEnd = std::chrono::high_resolution_clock::now();
1158 if (m_type == BINARY_MEMCPY)
1159 refTime += memcpyEnd - memcpyStart;
1160
1161 vk.destroyShaderEXT(device, spirvShader, DE_NULL);
1162 vk.destroyShaderEXT(device, binaryShader, DE_NULL);
1163 }
1164
1165 if (m_type == BINARY_SHADER_CREATE)
1166 {
1167 if (time > refTime * 1.05f)
1168 return tcu::TestStatus::fail(
1169 "Binary shader object create time is more than 5% slower than spirv shader object create time");
1170 }
1171 else if (m_type == BINARY_MEMCPY)
1172 {
1173 if (time > refTime * 1.5f)
1174 return tcu::TestStatus::fail(
1175 "Binary shader object create time is more than 50% slower than memcpy of an equal amount of data");
1176 }
1177
1178 return tcu::TestStatus::pass("Pass");
1179 }
1180
1181 class ShaderObjectBinaryPerformanceCase : public vkt::TestCase
1182 {
1183 public:
ShaderObjectBinaryPerformanceCase(tcu::TestContext & testCtx,const std::string & name,BinaryType type)1184 ShaderObjectBinaryPerformanceCase(tcu::TestContext &testCtx, const std::string &name, BinaryType type)
1185 : vkt::TestCase(testCtx, name)
1186 , m_type(type)
1187 {
1188 }
~ShaderObjectBinaryPerformanceCase(void)1189 virtual ~ShaderObjectBinaryPerformanceCase(void)
1190 {
1191 }
1192
1193 void checkSupport(vkt::Context &context) const override;
1194 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1195 TestInstance *createInstance(Context &context) const override
1196 {
1197 return new ShaderObjectBinaryPerformanceInstance(context, m_type);
1198 }
1199
1200 private:
1201 const BinaryType m_type;
1202 };
1203
checkSupport(Context & context) const1204 void ShaderObjectBinaryPerformanceCase::checkSupport(Context &context) const
1205 {
1206 context.requireDeviceFunctionality("VK_EXT_shader_object");
1207 }
1208
initPrograms(vk::SourceCollections & programCollection) const1209 void ShaderObjectBinaryPerformanceCase::initPrograms(vk::SourceCollections &programCollection) const
1210 {
1211 vk::addBasicShaderObjectShaders(programCollection);
1212 }
1213
1214 } // namespace
1215
createShaderObjectPerformanceTests(tcu::TestContext & testCtx)1216 tcu::TestCaseGroup *createShaderObjectPerformanceTests(tcu::TestContext &testCtx)
1217 {
1218 de::MovePtr<tcu::TestCaseGroup> performanceGroup(new tcu::TestCaseGroup(testCtx, "performance"));
1219
1220 const struct
1221 {
1222 DrawType drawType;
1223 const char *name;
1224 } drawTypeTests[] = {
1225 {DRAW, "draw"},
1226 {DRAW_INDEXED, "draw_indexed"},
1227 {DRAW_INDEXED_INDIRECT, "draw_indexed_indirect"},
1228 {DRAW_INDEXED_INDIRECT_COUNT, "draw_indexed_indirect_count"},
1229 {DRAW_INDIRECT, "draw_indirect"},
1230 {DRAW_INDIRECT_COUNT, "draw_indirect_count"},
1231 };
1232
1233 const struct
1234 {
1235 TestType testTpye;
1236 const char *name;
1237 } typeTests[] = {
1238 {DRAW_STATIC_PIPELINE, "static_pipeline"},
1239 {DRAW_DYNAMIC_PIPELINE, "dynamic_pipeline"},
1240 {DRAW_LINKED_SHADERS, "linked_shaders"},
1241 {DRAW_BINARY, "binary_shaders"},
1242 };
1243
1244 for (const auto &drawType : drawTypeTests)
1245 {
1246 for (const auto &typeTest : typeTests)
1247 {
1248 performanceGroup->addChild(
1249 new ShaderObjectPerformanceCase(testCtx, std::string(drawType.name) + "_" + std::string(typeTest.name),
1250 drawType.drawType, typeTest.testTpye));
1251 }
1252 }
1253 performanceGroup->addChild(new ShaderObjectPerformanceCase(testCtx, "binary_bind_shaders", DRAW, DRAW_BINARY_BIND));
1254
1255 performanceGroup->addChild(new ShaderObjectDispatchPerformanceCase(testCtx, "dispatch", DISPATCH));
1256 performanceGroup->addChild(new ShaderObjectDispatchPerformanceCase(testCtx, "dispatch_base", DISPATCH_BASE));
1257 performanceGroup->addChild(
1258 new ShaderObjectDispatchPerformanceCase(testCtx, "dispatch_indirect", DISPATCH_INDIRECT));
1259
1260 performanceGroup->addChild(
1261 new ShaderObjectBinaryPerformanceCase(testCtx, "binary_shader_create", BINARY_SHADER_CREATE));
1262 performanceGroup->addChild(new ShaderObjectBinaryPerformanceCase(testCtx, "binary_memcpy", BINARY_MEMCPY));
1263
1264 return performanceGroup.release();
1265 }
1266
1267 } // namespace ShaderObject
1268 } // namespace vkt
1269