1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Ray Tracing Watertightness tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingWatertightnessTests.hpp"
25 
26 #include "vkDefs.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkTypeUtil.hpp"
36 
37 #include "vkRayTracingUtil.hpp"
38 
39 #include "deRandom.hpp"
40 
41 namespace vkt
42 {
43 namespace RayTracing
44 {
45 namespace
46 {
47 using namespace vk;
48 using namespace std;
49 
50 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
51                                               VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
52                                               VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
53 
54 enum TestType
55 {
56     TEST_TYPE_INSIDE_STAGE,
57     TEST_TYPE_BETWEEN_STAGES,
58 };
59 
60 struct CaseDef
61 {
62     TestType testType;
63     VkShaderStageFlagBits stage;
64     uint32_t width;
65     uint32_t height;
66     uint32_t squaresGroupCount;
67     uint32_t geometriesGroupCount;
68     uint32_t instancesGroupCount;
69 };
70 
71 enum ShaderGroups
72 {
73     FIRST_GROUP  = 0,
74     RAYGEN_GROUP = FIRST_GROUP,
75     MISS_GROUP,
76     HIT_GROUP,
77     GROUP_COUNT
78 };
79 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)80 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
81 {
82     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
83 
84     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
85     return rayTracingPropertiesKHR->getShaderGroupHandleSize();
86 }
87 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)88 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
89 {
90     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
91 
92     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
93     return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
94 }
95 
makeImageCreateInfo(uint32_t width,uint32_t height,VkFormat format)96 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, VkFormat format)
97 {
98     const VkImageUsageFlags usage =
99         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
100     const VkImageCreateInfo imageCreateInfo = {
101         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
102         DE_NULL,                             // const void* pNext;
103         (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
104         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
105         format,                              // VkFormat format;
106         makeExtent3D(width, height, 1u),     // VkExtent3D extent;
107         1u,                                  // uint32_t mipLevels;
108         1u,                                  // uint32_t arrayLayers;
109         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
110         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
111         usage,                               // VkImageUsageFlags usage;
112         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
113         0u,                                  // uint32_t queueFamilyIndexCount;
114         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
115         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
116     };
117 
118     return imageCreateInfo;
119 }
120 
121 class RayTracingBuildTestInstance : public TestInstance
122 {
123 public:
124     RayTracingBuildTestInstance(Context &context, const CaseDef &data);
125     ~RayTracingBuildTestInstance(void);
126     tcu::TestStatus iterate(void);
127 
128 protected:
129     void checkSupportInInstance(void) const;
130     de::MovePtr<BufferWithMemory> runTest(void);
131     Move<VkPipeline> makePipeline(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, VkPipelineLayout pipelineLayout);
132     de::MovePtr<BufferWithMemory> createShaderBindingTable(const InstanceInterface &vki, const DeviceInterface &vkd,
133                                                            const VkDevice device, const VkPhysicalDevice physicalDevice,
134                                                            const VkPipeline pipeline, Allocator &allocator,
135                                                            de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
136                                                            const uint32_t group, const uint32_t groupCount = 1u);
137     de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
138         VkCommandBuffer cmdBuffer,
139         vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures);
140     vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(VkCommandBuffer cmdBuffer);
141     de::MovePtr<BottomLevelAccelerationStructure> initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,
142                                                                                   tcu::UVec2 &startPos);
143 
144 private:
145     CaseDef m_data;
146     VkShaderStageFlags m_shaders;
147     VkShaderStageFlags m_extraCallShaders;
148     uint32_t m_raygenShaderGroup;
149     uint32_t m_missShaderGroup;
150     uint32_t m_hitShaderGroup;
151     uint32_t m_callableShaderGroup;
152     uint32_t m_shaderGroupCount;
153 };
154 
RayTracingBuildTestInstance(Context & context,const CaseDef & data)155 RayTracingBuildTestInstance::RayTracingBuildTestInstance(Context &context, const CaseDef &data)
156     : vkt::TestInstance(context)
157     , m_data(data)
158     , m_shaders(0)
159     , m_extraCallShaders(0)
160     , m_raygenShaderGroup(~0u)
161     , m_missShaderGroup(~0u)
162     , m_hitShaderGroup(~0u)
163     , m_callableShaderGroup(~0u)
164     , m_shaderGroupCount(0)
165 {
166     const VkShaderStageFlags hitStages =
167         VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
168     BinaryCollection &collection = m_context.getBinaryCollection();
169     uint32_t group               = 0;
170     uint32_t shaderCount         = 0;
171 
172     if (collection.contains("rgen"))
173         m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
174     if (collection.contains("ahit"))
175         m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
176     if (collection.contains("chit"))
177         m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
178     if (collection.contains("miss"))
179         m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
180     if (collection.contains("sect"))
181         m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
182     if (collection.contains("call"))
183         m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
184 
185     if (collection.contains("cal0"))
186         m_extraCallShaders++;
187 
188     for (BinaryCollection::Iterator it = collection.begin(); it != collection.end(); ++it)
189         shaderCount++;
190 
191     if (shaderCount != m_extraCallShaders + (uint32_t)dePop32(m_shaders))
192         TCU_THROW(InternalError, "Unused shaders detected in the collection");
193 
194     if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
195         m_raygenShaderGroup = group++;
196 
197     if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
198         m_missShaderGroup = group++;
199 
200     if (0 != (m_shaders & hitStages))
201         m_hitShaderGroup = group++;
202 
203     if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR) || m_extraCallShaders > 0)
204         m_callableShaderGroup = group++;
205 
206     m_shaderGroupCount = group;
207 }
208 
~RayTracingBuildTestInstance(void)209 RayTracingBuildTestInstance::~RayTracingBuildTestInstance(void)
210 {
211 }
212 
213 class RayTracingTestCase : public TestCase
214 {
215 public:
216     RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
217     ~RayTracingTestCase(void);
218 
219     virtual void initPrograms(SourceCollections &programCollection) const;
220     virtual TestInstance *createInstance(Context &context) const;
221     virtual void checkSupport(Context &context) const;
222 
223 private:
224     static inline const std::string getIntersectionPassthrough(void);
225     static inline const std::string getMissPassthrough(void);
226     static inline const std::string getHitPassthrough(void);
227 
228     CaseDef m_data;
229 };
230 
RayTracingTestCase(tcu::TestContext & context,const char * name,const CaseDef data)231 RayTracingTestCase::RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
232     : vkt::TestCase(context, name)
233     , m_data(data)
234 {
235     DE_ASSERT((m_data.width * m_data.height) ==
236               (m_data.squaresGroupCount * m_data.geometriesGroupCount * m_data.instancesGroupCount));
237 }
238 
~RayTracingTestCase(void)239 RayTracingTestCase::~RayTracingTestCase(void)
240 {
241 }
242 
checkSupport(Context & context) const243 void RayTracingTestCase::checkSupport(Context &context) const
244 {
245     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
246     context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
247 
248     const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
249         context.getRayTracingPipelineFeatures();
250     if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
251         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
252 
253     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
254         context.getAccelerationStructureFeatures();
255     if (accelerationStructureFeaturesKHR.accelerationStructure == false)
256         TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
257                              "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
258 }
259 
getIntersectionPassthrough(void)260 const std::string RayTracingTestCase::getIntersectionPassthrough(void)
261 {
262     const std::string intersectionPassthrough = "#version 460 core\n"
263                                                 "#extension GL_EXT_ray_tracing : require\n"
264                                                 "hitAttributeEXT vec3 hitAttribute;\n"
265                                                 "\n"
266                                                 "void main()\n"
267                                                 "{\n"
268                                                 "  reportIntersectionEXT(0.95f, 0x7Eu);\n"
269                                                 "}\n";
270 
271     return intersectionPassthrough;
272 }
273 
getMissPassthrough(void)274 const std::string RayTracingTestCase::getMissPassthrough(void)
275 {
276     const std::string missPassthrough = "#version 460 core\n"
277                                         "#extension GL_EXT_ray_tracing : require\n"
278                                         "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
279                                         "\n"
280                                         "void main()\n"
281                                         "{\n"
282                                         "}\n";
283 
284     return missPassthrough;
285 }
286 
getHitPassthrough(void)287 const std::string RayTracingTestCase::getHitPassthrough(void)
288 {
289     const std::string hitPassthrough = "#version 460 core\n"
290                                        "#extension GL_EXT_ray_tracing : require\n"
291                                        "hitAttributeEXT vec3 attribs;\n"
292                                        "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
293                                        "\n"
294                                        "void main()\n"
295                                        "{\n"
296                                        "}\n";
297 
298     return hitPassthrough;
299 }
300 
initPrograms(SourceCollections & programCollection) const301 void RayTracingTestCase::initPrograms(SourceCollections &programCollection) const
302 {
303     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
304 
305     const std::string imageQualifiers = (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? " shadercallcoherent " : "");
306     const std::string glslExtensions =
307         (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? "#extension GL_KHR_memory_scope_semantics : require\n" : "");
308     const bool calleeIsAnyHit = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
309     const std::string repackInstruction =
310         calleeIsAnyHit ? "reportIntersectionEXT(0.95f, 0u)" : "executeCallableEXT(0, 0)";
311     const std::string updateBarrierCaller =
312         (m_data.testType == TEST_TYPE_BETWEEN_STAGES ?
313              "  memoryBarrier(gl_ScopeShaderCallEXT, gl_StorageSemanticsImage, gl_SemanticsRelease);\n" :
314              "");
315     const std::string updateBarrierCallee =
316         (m_data.testType == TEST_TYPE_BETWEEN_STAGES ?
317              "  memoryBarrier(gl_ScopeShaderCallEXT, gl_StorageSemanticsImage, gl_SemanticsAcquire);\n" :
318              "");
319     const std::string updateImage0 = "  uint  r = uint(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * gl_LaunchIDEXT.y);\n"
320                                      "  uvec4 c = uvec4(r, 0, 0, 1);\n"
321                                      "  imageStore(result, ivec2(gl_LaunchIDEXT), c);\n"
322                                      "\n" +
323                                      updateBarrierCaller +
324                                      "\n"
325                                      "  " +
326                                      repackInstruction + ";\n";
327     const std::string updateImage1 = "  uint  d = imageLoad(result, ivec2(gl_LaunchIDEXT)).x;\n"
328                                      "  imageStore(result, ivec2(gl_LaunchIDEXT), uvec4(d + 1, 0, 0, 1));\n";
329     const std::string updateImageCaller =
330         updateImage0 + (m_data.testType == TEST_TYPE_INSIDE_STAGE ? updateImage1 : "");
331     const std::string updateImageCallee = (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? updateImage1 : "");
332     const std::string calleeShaderParam = calleeIsAnyHit ? "" : "layout(location = 0) callableDataInEXT float dummy;\n";
333     const std::string calleeShader      = "#version 460 core\n"
334                                           "#extension GL_EXT_ray_tracing : require\n" +
335                                      glslExtensions + calleeShaderParam +
336                                      "layout(set = 0, binding = 0, r32ui) uniform uimage2D result;\n"
337                                      "\n"
338                                      "void main()\n"
339                                      "{\n" +
340                                      updateBarrierCallee + updateImageCallee + "}\n";
341 
342     switch (m_data.stage)
343     {
344     case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
345     {
346         std::stringstream css;
347         css << "#version 460 core\n"
348                "#extension GL_EXT_ray_tracing : require\n" +
349                    glslExtensions + "layout(set = 0, binding = 0, r32ui)" + imageQualifiers +
350                    "uniform uimage2D result;\n"
351                    "layout(location = 0) callableDataEXT float dummy;\n"
352                    "\n"
353                    "void main()\n"
354                    "{\n"
355             << updateImageCaller << "}\n";
356 
357         programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
358         programCollection.glslSources.add("cal0")
359             << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
360 
361         break;
362     }
363 
364     case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
365     {
366         programCollection.glslSources.add("rgen")
367             << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
368 
369         std::stringstream css;
370         css << "#version 460 core\n"
371                "#extension GL_EXT_ray_tracing : require\n" +
372                    glslExtensions +
373                    "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
374                    "hitAttributeEXT vec3 attribs;\n"
375                    "layout(r32ui, set = 0, binding = 0)" +
376                    imageQualifiers +
377                    "uniform uimage2D result;\n"
378                    "layout(location = 0) callableDataEXT float dummy;\n"
379                    "\n"
380                    "void main()\n"
381                    "{\n"
382             << updateImageCaller << "}\n";
383 
384         programCollection.glslSources.add("chit")
385             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
386         programCollection.glslSources.add("cal0")
387             << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
388 
389         programCollection.glslSources.add("ahit")
390             << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
391         programCollection.glslSources.add("miss")
392             << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
393         programCollection.glslSources.add("sect")
394             << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
395 
396         break;
397     }
398 
399     case VK_SHADER_STAGE_MISS_BIT_KHR:
400     {
401         programCollection.glslSources.add("rgen")
402             << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
403 
404         std::stringstream css;
405         css << "#version 460 core\n"
406                "#extension GL_EXT_ray_tracing : require\n" +
407                    glslExtensions + "layout(r32ui, set = 0, binding = 0)" + imageQualifiers +
408                    "uniform uimage2D result;\n"
409                    "layout(location = 0) callableDataEXT float dummy;\n"
410                    "\n"
411                    "void main()\n"
412                    "{\n"
413             << updateImageCaller << "}\n";
414 
415         programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
416         programCollection.glslSources.add("cal0")
417             << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
418 
419         programCollection.glslSources.add("ahit")
420             << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
421         programCollection.glslSources.add("chit")
422             << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
423         programCollection.glslSources.add("sect")
424             << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
425 
426         break;
427     }
428 
429     case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
430     {
431         programCollection.glslSources.add("rgen")
432             << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
433 
434         std::stringstream css;
435         css << "#version 460 core\n"
436                "#extension GL_EXT_ray_tracing : require\n" +
437                    glslExtensions + "layout(r32ui, set = 0, binding = 0)" + imageQualifiers +
438                    "uniform uimage2D result;\n"
439                    "\n"
440                    "void main()\n"
441                    "{\n"
442             << updateImageCaller << "}\n";
443 
444         programCollection.glslSources.add("sect")
445             << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
446         programCollection.glslSources.add("ahit")
447             << glu::AnyHitSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
448 
449         programCollection.glslSources.add("chit")
450             << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
451         programCollection.glslSources.add("miss")
452             << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
453 
454         break;
455     }
456 
457     case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
458     {
459         {
460             std::stringstream css;
461             css << "#version 460 core\n"
462                    "#extension GL_EXT_ray_tracing : require\n" +
463                        glslExtensions +
464                        "layout(location = 0) callableDataEXT float dummy;\n"
465                        "layout(set = 0, binding = 0, r32ui)" +
466                        imageQualifiers +
467                        "uniform uimage2D result;\n"
468                        "\n"
469                        "void main()\n"
470                        "{\n"
471                        "  executeCallableEXT(1, 0);\n"
472                        "}\n";
473 
474             programCollection.glslSources.add("rgen")
475                 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
476         }
477 
478         {
479             std::stringstream css;
480             css << "#version 460 core\n"
481                    "#extension GL_EXT_ray_tracing : require\n" +
482                        glslExtensions +
483                        "layout(location = 1) callableDataInEXT float dummyIn;\n"
484                        "layout(location = 0) callableDataEXT float dummyOut;\n"
485                        "layout(set = 0, binding = 0, r32ui)" +
486                        imageQualifiers +
487                        "uniform uimage2D result;\n"
488                        "\n"
489                        "void main()\n"
490                        "{\n"
491                 << updateImageCaller << "}\n";
492 
493             programCollection.glslSources.add("call")
494                 << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
495         }
496 
497         programCollection.glslSources.add("cal0")
498             << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
499 
500         break;
501     }
502 
503     default:
504         TCU_THROW(InternalError, "Unknown stage");
505     }
506 }
507 
createInstance(Context & context) const508 TestInstance *RayTracingTestCase::createInstance(Context &context) const
509 {
510     return new RayTracingBuildTestInstance(context, m_data);
511 }
512 
makePipeline(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,VkPipelineLayout pipelineLayout)513 Move<VkPipeline> RayTracingBuildTestInstance::makePipeline(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
514                                                            VkPipelineLayout pipelineLayout)
515 {
516     const DeviceInterface &vkd       = m_context.getDeviceInterface();
517     const VkDevice device            = m_context.getDevice();
518     vk::BinaryCollection &collection = m_context.getBinaryCollection();
519 
520     if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
521         rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
522                                       createShaderModule(vkd, device, collection.get("rgen"), 0), m_raygenShaderGroup);
523     if (0 != (m_shaders & VK_SHADER_STAGE_ANY_HIT_BIT_KHR))
524         rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
525                                       createShaderModule(vkd, device, collection.get("ahit"), 0), m_hitShaderGroup);
526     if (0 != (m_shaders & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))
527         rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
528                                       createShaderModule(vkd, device, collection.get("chit"), 0), m_hitShaderGroup);
529     if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
530         rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
531                                       createShaderModule(vkd, device, collection.get("miss"), 0), m_missShaderGroup);
532     if (0 != (m_shaders & VK_SHADER_STAGE_INTERSECTION_BIT_KHR))
533         rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
534                                       createShaderModule(vkd, device, collection.get("sect"), 0), m_hitShaderGroup);
535     if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
536         rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR,
537                                       createShaderModule(vkd, device, collection.get("call"), 0),
538                                       m_callableShaderGroup + 1);
539     if (m_extraCallShaders)
540         rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR,
541                                       createShaderModule(vkd, device, collection.get("cal0"), 0),
542                                       m_callableShaderGroup);
543 
544     Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
545 
546     return pipeline;
547 }
548 
createShaderBindingTable(const InstanceInterface & vki,const DeviceInterface & vkd,const VkDevice device,const VkPhysicalDevice physicalDevice,const VkPipeline pipeline,Allocator & allocator,de::MovePtr<RayTracingPipeline> & rayTracingPipeline,const uint32_t group,const uint32_t groupCount)549 de::MovePtr<BufferWithMemory> RayTracingBuildTestInstance::createShaderBindingTable(
550     const InstanceInterface &vki, const DeviceInterface &vkd, const VkDevice device,
551     const VkPhysicalDevice physicalDevice, const VkPipeline pipeline, Allocator &allocator,
552     de::MovePtr<RayTracingPipeline> &rayTracingPipeline, const uint32_t group, const uint32_t groupCount)
553 {
554     de::MovePtr<BufferWithMemory> shaderBindingTable;
555 
556     if (group < m_shaderGroupCount)
557     {
558         const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
559         const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
560 
561         shaderBindingTable = rayTracingPipeline->createShaderBindingTable(
562             vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, groupCount);
563     }
564 
565     return shaderBindingTable;
566 }
567 
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)568 de::MovePtr<TopLevelAccelerationStructure> RayTracingBuildTestInstance::initTopAccelerationStructure(
569     VkCommandBuffer cmdBuffer,
570     vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
571 {
572     const DeviceInterface &vkd                        = m_context.getDeviceInterface();
573     const VkDevice device                             = m_context.getDevice();
574     Allocator &allocator                              = m_context.getDefaultAllocator();
575     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
576 
577     result->setInstanceCount(bottomLevelAccelerationStructures.size());
578 
579     for (size_t structNdx = 0; structNdx < bottomLevelAccelerationStructures.size(); ++structNdx)
580         result->addInstance(bottomLevelAccelerationStructures[structNdx]);
581 
582     result->createAndBuild(vkd, device, cmdBuffer, allocator);
583 
584     return result;
585 }
586 
initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,tcu::UVec2 & startPos)587 de::MovePtr<BottomLevelAccelerationStructure> RayTracingBuildTestInstance::initBottomAccelerationStructure(
588     VkCommandBuffer cmdBuffer, tcu::UVec2 &startPos)
589 {
590     const DeviceInterface &vkd                           = m_context.getDeviceInterface();
591     const VkDevice device                                = m_context.getDevice();
592     Allocator &allocator                                 = m_context.getDefaultAllocator();
593     de::MovePtr<BottomLevelAccelerationStructure> result = makeBottomLevelAccelerationStructure();
594 
595     result->setGeometryCount(m_data.geometriesGroupCount);
596 
597     for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
598     {
599         const float z = (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR) ? +1.0f : -1.0f;
600         std::vector<tcu::Vec3> geometryData;
601 
602         geometryData.reserve(2u * m_data.squaresGroupCount);
603 
604         for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
605         {
606             const uint32_t n = m_data.width * startPos.y() + startPos.x();
607             const float x0   = float(startPos.x() + 0) / float(m_data.width);
608             const float y0   = float(startPos.y() + 0) / float(m_data.height);
609             const float x1   = float(startPos.x() + 1) / float(m_data.width);
610             const float y1   = float(startPos.y() + 1) / float(m_data.height);
611             const uint32_t m = (73 * (n + 1)) % (m_data.width * m_data.height);
612 
613             geometryData.push_back(tcu::Vec3(x0, y0, z));
614             geometryData.push_back(tcu::Vec3(x1, y1, z));
615 
616             startPos.y() = m / m_data.width;
617             startPos.x() = m % m_data.width;
618         }
619 
620         result->addGeometry(geometryData, false);
621     }
622 
623     result->createAndBuild(vkd, device, cmdBuffer, allocator);
624 
625     return result;
626 }
627 
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)628 vector<de::SharedPtr<BottomLevelAccelerationStructure>> RayTracingBuildTestInstance::initBottomAccelerationStructures(
629     VkCommandBuffer cmdBuffer)
630 {
631     tcu::UVec2 startPos;
632     vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
633 
634     for (size_t instanceNdx = 0; instanceNdx < m_data.instancesGroupCount; ++instanceNdx)
635     {
636         de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
637             initBottomAccelerationStructure(cmdBuffer, startPos);
638 
639         result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
640     }
641 
642     return result;
643 }
644 
runTest(void)645 de::MovePtr<BufferWithMemory> RayTracingBuildTestInstance::runTest(void)
646 {
647     const InstanceInterface &vki          = m_context.getInstanceInterface();
648     const DeviceInterface &vkd            = m_context.getDeviceInterface();
649     const VkDevice device                 = m_context.getDevice();
650     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
651     const uint32_t queueFamilyIndex       = m_context.getUniversalQueueFamilyIndex();
652     const VkQueue queue                   = m_context.getUniversalQueue();
653     Allocator &allocator                  = m_context.getDefaultAllocator();
654     const VkFormat format                 = VK_FORMAT_R32_UINT;
655     const uint32_t pixelCount             = m_data.width * m_data.height;
656     const uint32_t shaderGroupHandleSize  = getShaderGroupSize(vki, physicalDevice);
657 
658     const Move<VkDescriptorSetLayout> descriptorSetLayout =
659         DescriptorSetLayoutBuilder()
660             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
661             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
662             .build(vkd, device);
663     const Move<VkDescriptorPool> descriptorPool =
664         DescriptorPoolBuilder()
665             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
666             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
667             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
668     const Move<VkDescriptorSet> descriptorSet   = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
669     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
670     const Move<VkCommandPool> cmdPool           = createCommandPool(vkd, device, 0, queueFamilyIndex);
671     const Move<VkCommandBuffer> cmdBuffer =
672         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
673 
674     const uint32_t callableGroups = m_extraCallShaders + ((m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR) != 0 ? 1 : 0);
675     de::MovePtr<RayTracingPipeline> rayTracingPipeline           = de::newMovePtr<RayTracingPipeline>();
676     const Move<VkPipeline> pipeline                              = makePipeline(rayTracingPipeline, *pipelineLayout);
677     const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = createShaderBindingTable(
678         vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_raygenShaderGroup);
679     const de::MovePtr<BufferWithMemory> missShaderBindingTable = createShaderBindingTable(
680         vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_missShaderGroup);
681     const de::MovePtr<BufferWithMemory> hitShaderBindingTable = createShaderBindingTable(
682         vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_hitShaderGroup);
683     const de::MovePtr<BufferWithMemory> callableShaderBindingTable =
684         createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline,
685                                  m_callableShaderGroup, callableGroups);
686 
687     const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
688         raygenShaderBindingTable.get() != NULL ?
689             makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
690                                               shaderGroupHandleSize, shaderGroupHandleSize) :
691             makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
692     const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
693         missShaderBindingTable.get() != NULL ?
694             makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
695                                               shaderGroupHandleSize, shaderGroupHandleSize) :
696             makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
697     const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
698         hitShaderBindingTable.get() != NULL ?
699             makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
700                                               shaderGroupHandleSize, shaderGroupHandleSize) :
701             makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
702     const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
703         callableShaderBindingTable.get() != NULL ?
704             makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0),
705                                               shaderGroupHandleSize, shaderGroupHandleSize * callableGroups) :
706             makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
707 
708     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, format);
709     const VkImageSubresourceRange imageSubresourceRange =
710         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
711     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
712         new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
713     const Move<VkImageView> imageView =
714         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
715 
716     const VkBufferCreateInfo bufferCreateInfo =
717         makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
718     const VkImageSubresourceLayers bufferImageSubresourceLayers =
719         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
720     const VkBufferImageCopy bufferImageRegion =
721         makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), bufferImageSubresourceLayers);
722     de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
723         new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
724 
725     const VkDescriptorImageInfo descriptorImageInfo =
726         makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
727 
728     const VkImageMemoryBarrier preImageBarrier =
729         makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
730                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
731     const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
732         VK_ACCESS_TRANSFER_WRITE_BIT,
733         VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
734         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
735     const VkMemoryBarrier postTraceMemoryBarrier =
736         makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
737     const VkMemoryBarrier postCopyMemoryBarrier =
738         makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
739     const VkClearValue clearValue = makeClearValueColorU32(1000000u, 0u, 0u, 255u);
740 
741     vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
742     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
743 
744     beginCommandBuffer(vkd, *cmdBuffer, 0u);
745     {
746         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
747                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
748         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
749                                &imageSubresourceRange);
750         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
751                                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
752 
753         bottomLevelAccelerationStructures = initBottomAccelerationStructures(*cmdBuffer);
754         topLevelAccelerationStructure     = initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
755 
756         const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
757         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
758             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
759             DE_NULL,                                                           //  const void* pNext;
760             1u,                                                                //  uint32_t accelerationStructureCount;
761             topLevelAccelerationStructurePtr->getPtr(), //  const VkAccelerationStructureKHR* pAccelerationStructures;
762         };
763 
764         DescriptorSetUpdateBuilder()
765             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
766                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
767             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
768                          VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
769             .update(vkd, device);
770 
771         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
772                                   &descriptorSet.get(), 0, DE_NULL);
773 
774         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
775 
776         cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
777                      &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height, 1);
778 
779         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
780                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
781 
782         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
783 
784         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
785                                  &postCopyMemoryBarrier);
786     }
787     endCommandBuffer(vkd, *cmdBuffer);
788 
789     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
790 
791     invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(),
792                                 pixelCount * sizeof(uint32_t));
793 
794     return buffer;
795 }
796 
checkSupportInInstance(void) const797 void RayTracingBuildTestInstance::checkSupportInInstance(void) const
798 {
799     const InstanceInterface &vki                     = m_context.getInstanceInterface();
800     const VkPhysicalDevice physicalDevice            = m_context.getPhysicalDevice();
801     const vk::VkPhysicalDeviceProperties &properties = m_context.getDeviceProperties();
802     const uint32_t requiredAllocations =
803         8u + TopLevelAccelerationStructure::getRequiredAllocationCount() +
804         m_data.instancesGroupCount * BottomLevelAccelerationStructure::getRequiredAllocationCount();
805     de::MovePtr<RayTracingProperties> rayTracingProperties = makeRayTracingProperties(vki, physicalDevice);
806 
807     if (rayTracingProperties->getMaxPrimitiveCount() < m_data.squaresGroupCount)
808         TCU_THROW(NotSupportedError, "Triangles required more than supported");
809 
810     if (rayTracingProperties->getMaxGeometryCount() < m_data.geometriesGroupCount)
811         TCU_THROW(NotSupportedError, "Geometries required more than supported");
812 
813     if (rayTracingProperties->getMaxInstanceCount() < m_data.instancesGroupCount)
814         TCU_THROW(NotSupportedError, "Instances required more than supported");
815 
816     if (properties.limits.maxMemoryAllocationCount < requiredAllocations)
817         TCU_THROW(NotSupportedError, "Test requires more allocations allowed");
818 }
819 
iterate(void)820 tcu::TestStatus RayTracingBuildTestInstance::iterate(void)
821 {
822     checkSupportInInstance();
823 
824     const de::MovePtr<BufferWithMemory> buffer = runTest();
825     const uint32_t *bufferPtr                  = (uint32_t *)buffer->getAllocation().getHostPtr();
826     uint32_t failures                          = 0;
827     uint32_t pos                               = 0;
828 
829     for (uint32_t y = 0; y < m_data.height; ++y)
830     {
831         for (uint32_t x = 0; x < m_data.width; ++x)
832         {
833             const uint32_t expectedValue = pos + 1;
834 
835             if (bufferPtr[pos] != expectedValue)
836                 failures++;
837 
838             ++pos;
839         }
840     }
841 
842     if (failures == 0)
843         return tcu::TestStatus::pass("Pass");
844     else
845         return tcu::TestStatus::fail("failures=" + de::toString(failures));
846 }
847 
848 } // namespace
createMemGuaranteeTests(tcu::TestContext & testCtx)849 tcu::TestCaseGroup *createMemGuaranteeTests(tcu::TestContext &testCtx)
850 {
851     static const struct
852     {
853         const char *name;
854         VkShaderStageFlagBits stage;
855     } stages[]{
856         {"rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR},       {"chit", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR},
857         {"sect", VK_SHADER_STAGE_INTERSECTION_BIT_KHR}, {"miss", VK_SHADER_STAGE_MISS_BIT_KHR},
858         {"call", VK_SHADER_STAGE_CALLABLE_BIT_KHR},
859     };
860 
861     static const struct
862     {
863         const char *name;
864         TestType testType;
865     } testTypes[]{
866         {"inside", TEST_TYPE_INSIDE_STAGE},
867         {"between", TEST_TYPE_BETWEEN_STAGES},
868     };
869 
870     // Ray tracing memory guarantee tests
871     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "memguarantee"));
872 
873     for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
874     {
875         de::MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(testCtx, testTypes[testTypeNdx].name));
876 
877         for (size_t stagesNdx = 0; stagesNdx < DE_LENGTH_OF_ARRAY(stages); ++stagesNdx)
878         {
879             const uint32_t width                = 16u;
880             const uint32_t height               = 16u;
881             const uint32_t geometriesGroupCount = 4;
882             const uint32_t instancesGroupCount  = 8;
883             const uint32_t squaresGroupCount    = width * height / geometriesGroupCount / instancesGroupCount;
884             const CaseDef caseDef               = {
885                 testTypes[testTypeNdx].testType, //  TestType testType;
886                 stages[stagesNdx].stage,         //  VkShaderStageFlagBits stage;
887                 width,                           //  uint32_t width;
888                 height,                          //  uint32_t height;
889                 squaresGroupCount,               //  uint32_t squaresGroupCount;
890                 geometriesGroupCount,            //  uint32_t geometriesGroupCount;
891                 instancesGroupCount,             //  uint32_t instancesGroupCount;
892             };
893             const std::string testName = de::toString(stages[stagesNdx].name);
894 
895             testTypeGroup->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
896         }
897 
898         group->addChild(testTypeGroup.release());
899     }
900 
901     return group.release();
902 }
903 
904 } // namespace RayTracing
905 } // namespace vkt
906