1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020-2022 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 Basic cmdTraceRays* tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingTraceRaysTests.hpp"
25 
26 #include "vkDefs.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 
38 #include "vkRayTracingUtil.hpp"
39 
40 #include <limits>
41 #include <tuple>
42 
43 namespace vkt
44 {
45 namespace RayTracing
46 {
47 namespace
48 {
49 using namespace vk;
50 using namespace vkt;
51 
52 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
53                                               VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
54                                               VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
55 
56 constexpr uint32_t kClearColorValue = 0xFFu;
57 constexpr uint32_t kHitColorValue   = 2u;
58 constexpr uint32_t kMissColorValue  = 1u;
59 
60 enum class TraceType
61 {
62     DIRECT        = 0,
63     INDIRECT_CPU  = 1,
64     INDIRECT_GPU  = 2,
65     INDIRECT2_GPU = 3,
66     INDIRECT2_CPU = 4,
67 };
68 
69 struct TestParams
70 {
71     TraceType traceType;
72     VkTraceRaysIndirectCommandKHR traceDimensions; // Note: to be used for both direct and indirect variants.
73     bool useKhrMaintenance1Semantics;
74     VkTraceRaysIndirectCommand2KHR extendedTraceDimensions;
75 };
76 struct TestParams2
77 {
78     TraceType traceType;
79     VkExtent3D traceDimensions;
80     bool partialCopy;
81     VkQueueFlagBits submitQueue;
82 };
83 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)84 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
85 {
86     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
87 
88     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
89     return rayTracingPropertiesKHR->getShaderGroupHandleSize();
90 }
91 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)92 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
93 {
94     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
95 
96     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
97     return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
98 }
99 
100 template <typename T>
isNullTrace(const T cmd)101 bool isNullTrace(const T cmd)
102 {
103     return (cmd.width == 0u || cmd.height == 0u || cmd.depth == 0u);
104 }
105 
106 template <typename T>
getImageExtent(const T cmd)107 VkExtent3D getImageExtent(const T cmd)
108 {
109     return (isNullTrace(cmd) ? makeExtent3D(8u, 8u, 1u) : makeExtent3D(cmd.width, cmd.height, cmd.depth));
110 }
111 
isNullExtent(const VkExtent3D & extent)112 bool isNullExtent(const VkExtent3D &extent)
113 {
114     return (extent.width == 0u || extent.height == 0u || extent.depth == 0u);
115 }
116 
getNonNullImageExtent(const VkExtent3D & extent)117 VkExtent3D getNonNullImageExtent(const VkExtent3D &extent)
118 {
119     return (isNullExtent(extent) ? makeExtent3D(8u, 8u, 1u) : makeExtent3D(extent.width, extent.height, extent.depth));
120 }
121 
makeImageCreateInfo(uint32_t width,uint32_t height,uint32_t depth,VkFormat format)122 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format)
123 {
124     const VkImageCreateInfo imageCreateInfo = {
125         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
126         DE_NULL,                             // const void* pNext;
127         (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
128         VK_IMAGE_TYPE_3D,                    // VkImageType imageType;
129         format,                              // VkFormat format;
130         makeExtent3D(width, height, depth),  // VkExtent3D extent;
131         1u,                                  // uint32_t mipLevels;
132         1u,                                  // uint32_t arrayLayers;
133         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
134         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
135         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
136             VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
137         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
138         0u,                                  // uint32_t queueFamilyIndexCount;
139         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
140         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
141     };
142 
143     return imageCreateInfo;
144 }
145 
getQueueFamilyIndexAtExact(const DeviceInterface & vkd,const InstanceInterface & vki,VkPhysicalDevice physDevice,VkDevice device,VkQueueFlagBits bits,uint32_t queueIndex=0)146 std::tuple<bool, VkQueue, uint32_t> getQueueFamilyIndexAtExact(const DeviceInterface &vkd, const InstanceInterface &vki,
147                                                                VkPhysicalDevice physDevice, VkDevice device,
148                                                                VkQueueFlagBits bits, uint32_t queueIndex = 0)
149 {
150     bool found                = false;
151     VkQueue queue             = 0;
152     uint32_t queueFamilyCount = 0;
153     uint32_t queueFamilyIndex = std::numeric_limits<uint32_t>::max();
154 
155     vki.getPhysicalDeviceQueueFamilyProperties(physDevice, &queueFamilyCount, nullptr);
156 
157     std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
158     vki.getPhysicalDeviceQueueFamilyProperties(physDevice, &queueFamilyCount, queueFamilies.data());
159 
160     for (uint32_t index = 0; index < queueFamilyCount; ++index)
161     {
162         if ((queueFamilies[index].queueFlags & bits) == bits)
163         {
164             queueFamilyIndex = index;
165             break;
166         }
167     }
168 
169     if (std::numeric_limits<uint32_t>::max() != queueFamilyIndex)
170     {
171         found = true;
172         vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
173     }
174 #ifdef __cpp_lib_constexpr_tuple
175     return {found, queue, queueFamilyIndex};
176 #else
177     return std::tuple<bool, VkQueue, uint32_t>(found, queue, queueFamilyIndex);
178 #endif
179 }
180 
181 typedef std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> BlasVec;
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,const BlasVec & bottomLevelAccelerationStructures,Context & context,const VkExtent3D & imageExtent)182 auto initTopAccelerationStructure(VkCommandBuffer cmdBuffer, const BlasVec &bottomLevelAccelerationStructures,
183                                   Context &context, const VkExtent3D &imageExtent)
184     -> de::MovePtr<TopLevelAccelerationStructure>
185 {
186     const DeviceInterface &vkd   = context.getDeviceInterface();
187     const VkDevice device        = context.getDevice();
188     Allocator &allocator         = context.getDefaultAllocator();
189     const uint32_t instanceCount = imageExtent.depth * imageExtent.height * imageExtent.width / 2;
190 
191     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
192     result->setInstanceCount(instanceCount);
193 
194     uint32_t currentInstanceIndex = 0;
195 
196     for (uint32_t z = 0; z < imageExtent.depth; ++z)
197         for (uint32_t y = 0; y < imageExtent.height; ++y)
198             for (uint32_t x = 0; x < imageExtent.width; ++x)
199             {
200                 if (((x + y + z) % 2) == 0)
201                     continue;
202                 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]);
203             }
204     result->createAndBuild(vkd, device, cmdBuffer, allocator);
205 
206     return result;
207 }
208 
209 class RayTracingTraceRaysIndirectTestCase : public TestCase
210 {
211 public:
212     RayTracingTraceRaysIndirectTestCase(tcu::TestContext &context, const char *name, const TestParams data);
213     ~RayTracingTraceRaysIndirectTestCase(void);
214 
215     virtual void checkSupport(Context &context) const;
216     virtual void initPrograms(SourceCollections &programCollection) const;
217     virtual TestInstance *createInstance(Context &context) const;
218 
219 private:
220     TestParams m_data;
221 };
222 
223 class RayTracingTraceRaysIndirectTestInstance : public TestInstance
224 {
225 public:
226     RayTracingTraceRaysIndirectTestInstance(Context &context, const TestParams &data);
227     ~RayTracingTraceRaysIndirectTestInstance(void);
228     tcu::TestStatus iterate(void);
229 
230 protected:
231     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
232         VkCommandBuffer cmdBuffer);
233     de::MovePtr<BufferWithMemory> runTest();
234 
235 private:
236     TestParams m_data;
237     VkExtent3D m_imageExtent;
238 };
239 
RayTracingTraceRaysIndirectTestCase(tcu::TestContext & context,const char * name,const TestParams data)240 RayTracingTraceRaysIndirectTestCase::RayTracingTraceRaysIndirectTestCase(tcu::TestContext &context, const char *name,
241                                                                          const TestParams data)
242     : vkt::TestCase(context, name)
243     , m_data(data)
244 {
245 }
246 
~RayTracingTraceRaysIndirectTestCase(void)247 RayTracingTraceRaysIndirectTestCase::~RayTracingTraceRaysIndirectTestCase(void)
248 {
249 }
250 
checkSupport(Context & context) const251 void RayTracingTraceRaysIndirectTestCase::checkSupport(Context &context) const
252 {
253     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
254     context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
255 
256     const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
257         context.getRayTracingPipelineFeatures();
258     if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
259         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
260 
261     if (rayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect == false)
262         TCU_THROW(NotSupportedError,
263                   "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect");
264 
265     if (m_data.useKhrMaintenance1Semantics)
266     {
267         context.requireDeviceFunctionality("VK_KHR_ray_tracing_maintenance1");
268 
269         const VkPhysicalDeviceFeatures deviceFeatures =
270             getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
271         if (!deviceFeatures.shaderInt64)
272         {
273             TCU_THROW(NotSupportedError, "Device feature shaderInt64 is not supported");
274         }
275     }
276 
277     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
278         context.getAccelerationStructureFeatures();
279     if (accelerationStructureFeaturesKHR.accelerationStructure == false)
280         TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
281                              "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
282 }
283 
initPrograms(SourceCollections & programCollection) const284 void RayTracingTraceRaysIndirectTestCase::initPrograms(SourceCollections &programCollection) const
285 {
286     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
287     {
288         std::stringstream css;
289         css << "#version 460 core\n"
290             << (m_data.useKhrMaintenance1Semantics ? "#extension GL_ARB_gpu_shader_int64: enable\n" : "\n")
291             << "struct TraceRaysIndirectCommand\n"
292                "{\n";
293         if (m_data.useKhrMaintenance1Semantics)
294         {
295             css << "    uint64_t raygenShaderRecordAddress;\n"
296                    "    uint64_t raygenShaderRecordSize;\n"
297                    "    uint64_t missShaderBindingTableAddress;\n"
298                    "    uint64_t missShaderBindingTableSize;\n"
299                    "    uint64_t missShaderBindingTableStride;\n"
300                    "    uint64_t hitShaderBindingTableAddress;\n"
301                    "    uint64_t hitShaderBindingTableSize;\n"
302                    "    uint64_t hitShaderBindingTableStride;\n"
303                    "    uint64_t callableShaderBindingTableAddress;\n"
304                    "    uint64_t callableShaderBindingTableSize;\n"
305                    "    uint64_t callableShaderBindingTableStride;\n";
306         }
307         css << "    uint width;\n"
308                "    uint height;\n"
309                "    uint depth;\n"
310                "};\n"
311                "layout(binding = 0) uniform IndirectCommandsUBO\n"
312                "{\n"
313                "    TraceRaysIndirectCommand indirectCommands;\n"
314                "} ubo;\n"
315                "layout(binding = 1) buffer IndirectCommandsSBO\n"
316                "{\n"
317                "    TraceRaysIndirectCommand indirectCommands;\n"
318                "};\n"
319                "void main()\n"
320                "{\n";
321         if (m_data.useKhrMaintenance1Semantics)
322         {
323             css << "  indirectCommands.raygenShaderRecordAddress         = "
324                    "ubo.indirectCommands.raygenShaderRecordAddress;\n"
325                    "  indirectCommands.raygenShaderRecordSize            = "
326                    "ubo.indirectCommands.raygenShaderRecordSize;\n"
327                    "  indirectCommands.missShaderBindingTableAddress     = "
328                    "ubo.indirectCommands.missShaderBindingTableAddress;\n"
329                    "  indirectCommands.missShaderBindingTableSize        = "
330                    "ubo.indirectCommands.missShaderBindingTableSize;\n"
331                    "  indirectCommands.missShaderBindingTableStride      = "
332                    "ubo.indirectCommands.missShaderBindingTableStride;\n"
333                    "  indirectCommands.hitShaderBindingTableAddress      = "
334                    "ubo.indirectCommands.hitShaderBindingTableAddress;\n"
335                    "  indirectCommands.hitShaderBindingTableSize         = "
336                    "ubo.indirectCommands.hitShaderBindingTableSize;\n"
337                    "  indirectCommands.hitShaderBindingTableStride       = "
338                    "ubo.indirectCommands.hitShaderBindingTableStride;\n"
339                    "  indirectCommands.callableShaderBindingTableAddress = "
340                    "ubo.indirectCommands.callableShaderBindingTableAddress;\n"
341                    "  indirectCommands.callableShaderBindingTableSize    = "
342                    "ubo.indirectCommands.callableShaderBindingTableSize;\n"
343                    "  indirectCommands.callableShaderBindingTableStride  = "
344                    "ubo.indirectCommands.callableShaderBindingTableStride;\n";
345         }
346         css << "  indirectCommands.width  = ubo.indirectCommands.width;\n"
347                "  indirectCommands.height = ubo.indirectCommands.height;\n"
348                "  indirectCommands.depth  = ubo.indirectCommands.depth;\n"
349                "}\n";
350 
351         programCollection.glslSources.add("compute_indirect_command") << glu::ComputeSource(css.str()) << buildOptions;
352     }
353 
354     {
355         std::stringstream css;
356         css << "#version 460 core\n"
357                "#extension GL_EXT_ray_tracing : require\n"
358                "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
359                "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
360                "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
361                "\n"
362                "void main()\n"
363                "{\n"
364                "  float tmin     = 0.0;\n"
365                "  float tmax     = 1.0;\n"
366                "  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, "
367                "float(gl_LaunchIDEXT.z + 0.5f));\n"
368                "  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
369                "  hitValue       = uvec4(0,0,0,0);\n"
370                "  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
371                "  imageStore(result, ivec3(gl_LaunchIDEXT), hitValue);\n"
372                "}\n";
373         programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
374     }
375 
376     {
377         std::stringstream css;
378         css << "#version 460 core\n"
379                "#extension GL_EXT_ray_tracing : require\n"
380                "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
381                "void main()\n"
382                "{\n"
383                "  hitValue = uvec4("
384             << kHitColorValue
385             << ",0,0,1);\n"
386                "}\n";
387         programCollection.glslSources.add("chit")
388             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
389     }
390 
391     {
392         std::stringstream css;
393         css << "#version 460 core\n"
394                "#extension GL_EXT_ray_tracing : require\n"
395                "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
396                "void main()\n"
397                "{\n"
398                "  hitValue = uvec4("
399             << kMissColorValue
400             << ",0,0,1);\n"
401                "}\n";
402 
403         programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
404     }
405 }
406 
createInstance(Context & context) const407 TestInstance *RayTracingTraceRaysIndirectTestCase::createInstance(Context &context) const
408 {
409     return new RayTracingTraceRaysIndirectTestInstance(context, m_data);
410 }
411 
RayTracingTraceRaysIndirectTestInstance(Context & context,const TestParams & data)412 RayTracingTraceRaysIndirectTestInstance::RayTracingTraceRaysIndirectTestInstance(Context &context,
413                                                                                  const TestParams &data)
414     : vkt::TestInstance(context)
415     , m_data(data)
416 {
417     m_imageExtent = data.useKhrMaintenance1Semantics ? getImageExtent(data.extendedTraceDimensions) :
418                                                        getImageExtent(data.traceDimensions);
419 }
420 
~RayTracingTraceRaysIndirectTestInstance(void)421 RayTracingTraceRaysIndirectTestInstance::~RayTracingTraceRaysIndirectTestInstance(void)
422 {
423 }
424 
425 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> RayTracingTraceRaysIndirectTestInstance::
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)426     initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)
427 {
428     const DeviceInterface &vkd = m_context.getDeviceInterface();
429     const VkDevice device      = m_context.getDevice();
430     Allocator &allocator       = m_context.getDefaultAllocator();
431     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
432 
433     tcu::Vec3 v0(0.0, 1.0, 0.0);
434     tcu::Vec3 v1(0.0, 0.0, 0.0);
435     tcu::Vec3 v2(1.0, 1.0, 0.0);
436     tcu::Vec3 v3(1.0, 0.0, 0.0);
437 
438     for (uint32_t z = 0; z < m_imageExtent.depth; ++z)
439         for (uint32_t y = 0; y < m_imageExtent.height; ++y)
440             for (uint32_t x = 0; x < m_imageExtent.width; ++x)
441             {
442                 // let's build a 3D chessboard of geometries
443                 if (((x + y + z) % 2) == 0)
444                     continue;
445                 tcu::Vec3 xyz((float)x, (float)y, (float)z);
446                 std::vector<tcu::Vec3> geometryData;
447 
448                 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
449                     makeBottomLevelAccelerationStructure();
450                 bottomLevelAccelerationStructure->setGeometryCount(1u);
451 
452                 geometryData.push_back(xyz + v0);
453                 geometryData.push_back(xyz + v1);
454                 geometryData.push_back(xyz + v2);
455                 geometryData.push_back(xyz + v2);
456                 geometryData.push_back(xyz + v1);
457                 geometryData.push_back(xyz + v3);
458 
459                 bottomLevelAccelerationStructure->addGeometry(geometryData, true);
460                 bottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
461                 result.push_back(
462                     de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
463             }
464 
465     return result;
466 }
467 
runTest()468 de::MovePtr<BufferWithMemory> RayTracingTraceRaysIndirectTestInstance::runTest()
469 {
470     const InstanceInterface &vki            = m_context.getInstanceInterface();
471     const DeviceInterface &vkd              = m_context.getDeviceInterface();
472     const VkDevice device                   = m_context.getDevice();
473     const VkPhysicalDevice physicalDevice   = m_context.getPhysicalDevice();
474     const uint32_t queueFamilyIndex         = m_context.getUniversalQueueFamilyIndex();
475     const VkQueue queue                     = m_context.getUniversalQueue();
476     Allocator &allocator                    = m_context.getDefaultAllocator();
477     const uint32_t pixelCount               = m_imageExtent.depth * m_imageExtent.height * m_imageExtent.width;
478     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
479     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
480 
481     Move<VkDescriptorSetLayout> computeDescriptorSetLayout;
482     Move<VkDescriptorPool> computeDescriptorPool;
483     Move<VkDescriptorSet> computeDescriptorSet;
484     Move<VkPipelineLayout> computePipelineLayout;
485     Move<VkShaderModule> computeShader;
486     Move<VkPipeline> computePipeline;
487 
488     if (m_data.traceType == TraceType::INDIRECT_GPU || m_data.traceType == TraceType::INDIRECT2_GPU)
489     {
490         computeDescriptorSetLayout =
491             DescriptorSetLayoutBuilder()
492                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
493                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
494                 .build(vkd, device);
495         computeDescriptorPool = DescriptorPoolBuilder()
496                                     .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
497                                     .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
498                                     .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
499         computeDescriptorSet  = makeDescriptorSet(vkd, device, *computeDescriptorPool, *computeDescriptorSetLayout);
500         computePipelineLayout = makePipelineLayout(vkd, device, computeDescriptorSetLayout.get());
501 
502         computeShader =
503             createShaderModule(vkd, device, m_context.getBinaryCollection().get("compute_indirect_command"), 0);
504         const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = {
505             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
506             DE_NULL,                                             // const void* pNext;
507             VkPipelineShaderStageCreateFlags(0u),                // VkPipelineShaderStageCreateFlags flags;
508             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
509             *computeShader,                                      // VkShaderModule module;
510             "main",                                              // const char* pName;
511             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
512         };
513         const VkComputePipelineCreateInfo pipelineCreateInfo = {
514             VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
515             DE_NULL,                                        // const void* pNext;
516             VkPipelineCreateFlags(0u),                      // VkPipelineCreateFlags flags;
517             pipelineShaderStageParams,                      // VkPipelineShaderStageCreateInfo stage;
518             *computePipelineLayout,                         // VkPipelineLayout layout;
519             DE_NULL,                                        // VkPipeline basePipelineHandle;
520             0,                                              // int32_t basePipelineIndex;
521         };
522 
523         computePipeline = vk::createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo);
524     }
525 
526     const Move<VkDescriptorSetLayout> descriptorSetLayout =
527         DescriptorSetLayoutBuilder()
528             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
529             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
530             .build(vkd, device);
531     const Move<VkDescriptorPool> descriptorPool =
532         DescriptorPoolBuilder()
533             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
534             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
535             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
536     const Move<VkDescriptorSet> descriptorSet   = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
537     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
538 
539     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
540     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
541                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
542     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
543                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
544     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
545                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0), 2);
546     Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
547 
548     const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
549         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
550     const de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
551         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
552     const de::MovePtr<BufferWithMemory> missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
553         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
554 
555     const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
556         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
557                                           shaderGroupHandleSize, shaderGroupHandleSize);
558     const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
559         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
560                                           shaderGroupHandleSize, shaderGroupHandleSize);
561     const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
562         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
563                                           shaderGroupHandleSize, shaderGroupHandleSize);
564     const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
565         makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
566 
567     const VkFormat imageFormat = VK_FORMAT_R32_UINT;
568     const VkImageCreateInfo imageCreateInfo =
569         makeImageCreateInfo(m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, imageFormat);
570     const VkImageSubresourceRange imageSubresourceRange =
571         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
572     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
573         new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
574     const Move<VkImageView> imageView =
575         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
576 
577     const VkBufferCreateInfo resultBufferCreateInfo =
578         makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
579     const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
580         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
581     const VkBufferImageCopy resultBufferImageRegion =
582         makeBufferImageCopy(m_imageExtent, resultBufferImageSubresourceLayers);
583     de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
584         new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
585 
586     const VkDescriptorImageInfo descriptorImageInfo =
587         makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
588 
589     // create indirect command buffer and fill it with parameter values
590     de::MovePtr<BufferWithMemory> indirectBuffer;
591     de::MovePtr<BufferWithMemory> uniformBuffer;
592 
593     // Update trace details according to VK_KHR_ray_tracing_maintenance1 semantics
594     m_data.extendedTraceDimensions.raygenShaderRecordAddress         = raygenShaderBindingTableRegion.deviceAddress;
595     m_data.extendedTraceDimensions.raygenShaderRecordSize            = raygenShaderBindingTableRegion.size;
596     m_data.extendedTraceDimensions.missShaderBindingTableAddress     = missShaderBindingTableRegion.deviceAddress;
597     m_data.extendedTraceDimensions.missShaderBindingTableSize        = missShaderBindingTableRegion.size;
598     m_data.extendedTraceDimensions.missShaderBindingTableStride      = missShaderBindingTableRegion.stride;
599     m_data.extendedTraceDimensions.hitShaderBindingTableAddress      = hitShaderBindingTableRegion.deviceAddress;
600     m_data.extendedTraceDimensions.hitShaderBindingTableSize         = hitShaderBindingTableRegion.size;
601     m_data.extendedTraceDimensions.hitShaderBindingTableStride       = hitShaderBindingTableRegion.stride;
602     m_data.extendedTraceDimensions.callableShaderBindingTableAddress = callableShaderBindingTableRegion.deviceAddress;
603     m_data.extendedTraceDimensions.callableShaderBindingTableSize    = callableShaderBindingTableRegion.size;
604     m_data.extendedTraceDimensions.callableShaderBindingTableStride  = callableShaderBindingTableRegion.stride;
605 
606     if (m_data.traceType != TraceType::DIRECT)
607     {
608         const bool indirectGpu =
609             (m_data.traceType == TraceType::INDIRECT_GPU || m_data.traceType == TraceType::INDIRECT2_GPU);
610         VkDeviceSize bufferSize = m_data.useKhrMaintenance1Semantics ? sizeof(VkTraceRaysIndirectCommand2KHR) :
611                                                                        sizeof(VkTraceRaysIndirectCommandKHR);
612         VkBufferUsageFlags indirectBufferUsageFlags =
613             VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
614             (indirectGpu ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT);
615         const VkBufferCreateInfo indirectBufferCreateInfo = makeBufferCreateInfo(bufferSize, indirectBufferUsageFlags);
616         vk::MemoryRequirement indirectBufferMemoryRequirement =
617             MemoryRequirement::DeviceAddress | (indirectGpu ? MemoryRequirement::Any : MemoryRequirement::HostVisible);
618         indirectBuffer = de::MovePtr<BufferWithMemory>(
619             new BufferWithMemory(vkd, device, allocator, indirectBufferCreateInfo, indirectBufferMemoryRequirement));
620     }
621 
622     if (m_data.traceType == TraceType::INDIRECT_GPU)
623     {
624         const VkBufferCreateInfo uniformBufferCreateInfo =
625             makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommandKHR),
626                                  VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
627         uniformBuffer = de::MovePtr<BufferWithMemory>(
628             new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
629         deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions,
630                  sizeof(VkTraceRaysIndirectCommandKHR));
631         flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(),
632                                uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
633     }
634     else if (m_data.traceType == TraceType::INDIRECT_CPU)
635     {
636         deMemcpy(indirectBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions,
637                  sizeof(VkTraceRaysIndirectCommandKHR));
638         flushMappedMemoryRange(vkd, device, indirectBuffer->getAllocation().getMemory(),
639                                indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
640     }
641     else if (m_data.traceType == TraceType::INDIRECT2_GPU)
642     {
643         const VkBufferCreateInfo uniformBufferCreateInfo =
644             makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommand2KHR),
645                                  VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
646         uniformBuffer = de::MovePtr<BufferWithMemory>(
647             new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
648         deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &m_data.extendedTraceDimensions,
649                  sizeof(VkTraceRaysIndirectCommand2KHR));
650         flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(),
651                                uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
652     }
653     else if (m_data.traceType == TraceType::INDIRECT2_CPU)
654     {
655         deMemcpy(indirectBuffer->getAllocation().getHostPtr(), &m_data.extendedTraceDimensions,
656                  sizeof(VkTraceRaysIndirectCommand2KHR));
657         flushMappedMemoryRange(vkd, device, indirectBuffer->getAllocation().getMemory(),
658                                indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
659     }
660 
661     const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
662     const Move<VkCommandBuffer> cmdBuffer =
663         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
664 
665     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
666     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
667 
668     beginCommandBuffer(vkd, *cmdBuffer, 0u);
669     {
670         const VkImageMemoryBarrier preImageBarrier =
671             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
672                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
673         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
674                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
675 
676         const VkClearValue clearValue = makeClearValueColorU32(kClearColorValue, 0u, 0u, 0u);
677         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
678                                &imageSubresourceRange);
679 
680         const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
681             VK_ACCESS_TRANSFER_WRITE_BIT,
682             VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
683             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
684         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
685                                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
686 
687         bottomLevelAccelerationStructures = initBottomAccelerationStructures(*cmdBuffer);
688         topLevelAccelerationStructure =
689             initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures, m_context, m_imageExtent);
690 
691         if (m_data.traceType == TraceType::INDIRECT_GPU)
692         {
693             const VkDescriptorBufferInfo uniformBufferDescriptorInfo =
694                 makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
695             const VkDescriptorBufferInfo indirectBufferDescriptorInfo =
696                 makeDescriptorBufferInfo(indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
697 
698             DescriptorSetUpdateBuilder()
699                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
700                              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
701                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
702                              VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
703                 .update(vkd, device);
704 
705             vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
706             vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u,
707                                       &computeDescriptorSet.get(), 0u, DE_NULL);
708             vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
709 
710             const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier =
711                 makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
712                                         indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
713             cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
714                                            VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
715         }
716         else if (m_data.traceType == TraceType::INDIRECT2_GPU)
717         {
718             const VkDescriptorBufferInfo uniformBufferDescriptorInfo =
719                 makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommand2KHR));
720             const VkDescriptorBufferInfo indirectBufferDescriptorInfo =
721                 makeDescriptorBufferInfo(indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommand2KHR));
722 
723             DescriptorSetUpdateBuilder()
724                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
725                              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
726                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
727                              VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
728                 .update(vkd, device);
729 
730             vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
731             vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u,
732                                       &computeDescriptorSet.get(), 0u, DE_NULL);
733             vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
734 
735             const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier =
736                 makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
737                                         indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommand2KHR));
738             cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
739                                            VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
740         }
741 
742         const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
743         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
744             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
745             DE_NULL,                                                           //  const void* pNext;
746             1u,                                                                //  uint32_t accelerationStructureCount;
747             topLevelAccelerationStructurePtr->getPtr(), //  const VkAccelerationStructureKHR* pAccelerationStructures;
748         };
749 
750         DescriptorSetUpdateBuilder()
751             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
752                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
753             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
754                          VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
755             .update(vkd, device);
756 
757         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
758                                   &descriptorSet.get(), 0, DE_NULL);
759 
760         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
761 
762         // Both calls should give the same results.
763         if (m_data.traceType == TraceType::DIRECT)
764         {
765             cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
766                          &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.traceDimensions.width,
767                          m_data.traceDimensions.height, m_data.traceDimensions.depth);
768         }
769         else if (m_data.traceType == TraceType::INDIRECT_CPU || m_data.traceType == TraceType::INDIRECT_GPU)
770         {
771             cmdTraceRaysIndirect(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
772                                  &hitShaderBindingTableRegion, &callableShaderBindingTableRegion,
773                                  getBufferDeviceAddress(vkd, device, indirectBuffer->get(), 0));
774         }
775         else if (m_data.traceType == TraceType::INDIRECT2_CPU || m_data.traceType == TraceType::INDIRECT2_GPU)
776         {
777             vkd.cmdTraceRaysIndirect2KHR(*cmdBuffer, getBufferDeviceAddress(vkd, device, indirectBuffer->get(), 0));
778         }
779 
780         const VkMemoryBarrier postTraceMemoryBarrier =
781             makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
782         const VkMemoryBarrier postCopyMemoryBarrier =
783             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
784         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
785                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
786 
787         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
788                                  &resultBufferImageRegion);
789 
790         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
791                                  &postCopyMemoryBarrier);
792     }
793     endCommandBuffer(vkd, *cmdBuffer);
794 
795     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
796 
797     invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
798                                 resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
799 
800     return resultBuffer;
801 }
802 
iterate(void)803 tcu::TestStatus RayTracingTraceRaysIndirectTestInstance::iterate(void)
804 {
805     // run test using arrays of pointers
806     const de::MovePtr<BufferWithMemory> buffer = runTest();
807     const uint32_t *bufferPtr                  = (uint32_t *)buffer->getAllocation().getHostPtr();
808     const bool noWrites = m_data.useKhrMaintenance1Semantics ? isNullTrace(m_data.extendedTraceDimensions) :
809                                                                isNullTrace(m_data.traceDimensions);
810 
811     uint32_t failures = 0;
812     uint32_t pos      = 0;
813 
814     // verify results
815     for (uint32_t z = 0; z < m_imageExtent.depth; ++z)
816         for (uint32_t y = 0; y < m_imageExtent.height; ++y)
817             for (uint32_t x = 0; x < m_imageExtent.width; ++x)
818             {
819                 const uint32_t expectedResult =
820                     (noWrites ? kClearColorValue : (((x + y + z) % 2) ? kHitColorValue : kMissColorValue));
821                 if (bufferPtr[pos] != expectedResult)
822                     failures++;
823                 ++pos;
824             }
825 
826     if (failures == 0)
827         return tcu::TestStatus::pass("Pass");
828     else
829         return tcu::TestStatus::fail("Fail (failures=" + de::toString(failures) + ")");
830 }
831 
832 template <typename T>
makeDimensionsName(const T cmd)833 std::string makeDimensionsName(const T cmd)
834 {
835     std::ostringstream name;
836     name << cmd.width << "_" << cmd.height << "_" << cmd.depth;
837     return name.str();
838 }
839 
840 using namespace tcu;
841 
842 class TraceRaysIndirect2Instance : public TestInstance
843 {
844 public:
845     TraceRaysIndirect2Instance(Context &context, const TestParams2 &params);
846     virtual ~TraceRaysIndirect2Instance(void) override = default;
847     virtual TestStatus iterate(void) override;
848 
849 protected:
850     void makeIndirectStructAndFlush(BufferWithMemory &buffer, const bool source, const BufferWithMemory &rgenSbt,
851                                     const BufferWithMemory &hitSbt, const BufferWithMemory &missSbt,
852                                     const BufferWithMemory &callSbt) const;
853     void initBottomAccellStructures(VkCommandBuffer cmdBuffer, BottomLevelAccelerationStructurePool &pool,
854                                     const uint32_t &batchStructCount) const;
855 
856 private:
857     TestParams2 m_params;
858     const VkExtent3D m_imageExtent;
859 };
860 
861 class TraceRaysIndirect2Case : public TestCase
862 {
863 public:
864     TraceRaysIndirect2Case(TestContext &testCtx, const std::string &name, const TestParams2 &params);
865     virtual ~TraceRaysIndirect2Case(void) override = default;
866     virtual void initPrograms(SourceCollections &programCollection) const override;
867     virtual TestInstance *createInstance(Context &context) const override;
868     virtual void checkSupport(Context &context) const override;
869 
870 private:
871     TestParams2 m_params;
872 };
873 
TraceRaysIndirect2Case(TestContext & testCtx,const std::string & name,const TestParams2 & params)874 TraceRaysIndirect2Case::TraceRaysIndirect2Case(TestContext &testCtx, const std::string &name, const TestParams2 &params)
875     : TestCase(testCtx, name)
876     , m_params(params)
877 {
878 }
879 
createInstance(Context & context) const880 TestInstance *TraceRaysIndirect2Case::createInstance(Context &context) const
881 {
882     return new TraceRaysIndirect2Instance(context, m_params);
883 }
884 
checkSupport(Context & context) const885 void TraceRaysIndirect2Case::checkSupport(Context &context) const
886 {
887     context.requireInstanceFunctionality(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
888     context.requireDeviceFunctionality(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
889     context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
890 
891     const VkPhysicalDeviceFeatures &features = context.getDeviceFeatures();
892     if (features.shaderInt64 == VK_FALSE)
893         TCU_THROW(NotSupportedError, "64-bit integers not supported by device");
894 
895     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
896         context.getAccelerationStructureFeatures();
897     if (accelerationStructureFeaturesKHR.accelerationStructure == VK_FALSE)
898         TCU_THROW(NotSupportedError,
899                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure");
900 
901     const VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR &maintenance1FeaturesKHR =
902         context.getRayTracingMaintenance1Features();
903     if (maintenance1FeaturesKHR.rayTracingMaintenance1 == VK_FALSE)
904         TCU_THROW(NotSupportedError,
905                   "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingMaintenance1");
906     if (maintenance1FeaturesKHR.rayTracingPipelineTraceRaysIndirect2 == VK_FALSE)
907         TCU_THROW(NotSupportedError,
908                   "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingPipelineTraceRaysIndirect2");
909 
910     auto desiredQueue =
911         getQueueFamilyIndexAtExact(context.getDeviceInterface(), context.getInstanceInterface(),
912                                    context.getPhysicalDevice(), context.getDevice(), m_params.submitQueue);
913     if (!std::get<0>(desiredQueue))
914     {
915         std::stringstream errorMsg;
916         errorMsg << "Desired queue " << m_params.submitQueue << " is not supported by device";
917         errorMsg.flush();
918         TCU_THROW(NotSupportedError, errorMsg.str());
919     }
920 }
921 
initPrograms(SourceCollections & programCollection) const922 void TraceRaysIndirect2Case::initPrograms(SourceCollections &programCollection) const
923 {
924     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
925     {
926         std::stringstream css;
927         std::string comp(R"(
928         #version 460 core
929         #extension GL_ARB_gpu_shader_int64: enable
930         struct TraceRaysIndirectCommand
931         {
932             uint64_t raygenShaderRecordAddress;
933             uint64_t raygenShaderRecordSize;
934             uint64_t missShaderBindingTableAddress;
935             uint64_t missShaderBindingTableSize;
936             uint64_t missShaderBindingTableStride;
937             uint64_t hitShaderBindingTableAddress;
938             uint64_t hitShaderBindingTableSize;
939             uint64_t hitShaderBindingTableStride;
940             uint64_t callableShaderBindingTableAddress;
941             uint64_t callableShaderBindingTableSize;
942             uint64_t callableShaderBindingTableStride;
943             uint     width;
944             uint     height;
945             uint     depth;
946         };
947         layout(push_constant) uniform CopyStyle {
948             uint full;
949         } cs;
950         layout(binding = 0) uniform IndirectCommandsUBO {
951             TraceRaysIndirectCommand indirectCommands;
952         } ubo;
953         layout(binding = 1) buffer IndirectCommandsSBO {
954             TraceRaysIndirectCommand indirectCommands;
955         };
956         void main()
957         {
958             if (cs.full != 0) {
959                 indirectCommands.raygenShaderRecordAddress         = ubo.indirectCommands.raygenShaderRecordAddress;
960                 indirectCommands.raygenShaderRecordSize            = ubo.indirectCommands.raygenShaderRecordSize;
961                 indirectCommands.missShaderBindingTableAddress     = ubo.indirectCommands.missShaderBindingTableAddress;
962                 indirectCommands.missShaderBindingTableSize        = ubo.indirectCommands.missShaderBindingTableSize;
963                 indirectCommands.missShaderBindingTableStride      = ubo.indirectCommands.missShaderBindingTableStride;
964                 indirectCommands.hitShaderBindingTableAddress      = ubo.indirectCommands.hitShaderBindingTableAddress;
965                 indirectCommands.hitShaderBindingTableSize         = ubo.indirectCommands.hitShaderBindingTableSize;
966                 indirectCommands.hitShaderBindingTableStride       = ubo.indirectCommands.hitShaderBindingTableStride;
967                 indirectCommands.callableShaderBindingTableAddress = ubo.indirectCommands.callableShaderBindingTableAddress;
968                 indirectCommands.callableShaderBindingTableSize    = ubo.indirectCommands.callableShaderBindingTableSize;
969                 indirectCommands.callableShaderBindingTableStride  = ubo.indirectCommands.callableShaderBindingTableStride;
970             }
971             else {
972                 indirectCommands.raygenShaderRecordAddress         = ubo.indirectCommands.raygenShaderRecordAddress;
973 
974                 indirectCommands.missShaderBindingTableStride      = ubo.indirectCommands.missShaderBindingTableStride;
975 
976                 indirectCommands.hitShaderBindingTableSize         = ubo.indirectCommands.hitShaderBindingTableSize;
977 
978                 indirectCommands.callableShaderBindingTableAddress = ubo.indirectCommands.callableShaderBindingTableAddress;
979                 indirectCommands.callableShaderBindingTableStride  = ubo.indirectCommands.callableShaderBindingTableStride;
980             }
981 
982             indirectCommands.width                                 = ubo.indirectCommands.width;
983             indirectCommands.height                                = ubo.indirectCommands.height;
984             indirectCommands.depth                                 = ubo.indirectCommands.depth;
985 
986         })");
987 
988         programCollection.glslSources.add("compute_indirect_command") << glu::ComputeSource(comp) << buildOptions;
989     }
990 
991     {
992         std::stringstream css;
993         css << "#version 460 core\n"
994                "#extension GL_EXT_ray_tracing : require\n"
995                "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
996                "layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
997                "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
998                "\n"
999                "void main()\n"
1000                "{\n"
1001                "  float tmin     = 0.0;\n"
1002                "  float tmax     = 1.0;\n"
1003                "  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, "
1004                "float(gl_LaunchIDEXT.z + 0.5f));\n"
1005                "  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
1006                "  hitValue       = uvec4(0,0,0,0);\n"
1007                "  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
1008                "  imageStore(result, ivec3(gl_LaunchIDEXT), hitValue);\n"
1009                "}\n";
1010         programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1011     }
1012 
1013     {
1014         std::stringstream css;
1015         css << "#version 460 core\n"
1016                "#extension GL_EXT_ray_tracing : require\n"
1017                "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
1018                "void main()\n"
1019                "{\n"
1020                "  hitValue = uvec4("
1021             << kHitColorValue
1022             << ",0,0,1);\n"
1023                "}\n";
1024         programCollection.glslSources.add("chit")
1025             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1026     }
1027 
1028     {
1029         std::stringstream css;
1030         css << "#version 460 core\n"
1031                "#extension GL_EXT_ray_tracing : require\n"
1032                "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
1033                "void main()\n"
1034                "{\n"
1035                "  hitValue = uvec4("
1036             << kMissColorValue
1037             << ",0,0,1);\n"
1038                "}\n";
1039 
1040         programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1041     }
1042 }
1043 
TraceRaysIndirect2Instance(Context & context,const TestParams2 & params)1044 TraceRaysIndirect2Instance::TraceRaysIndirect2Instance(Context &context, const TestParams2 &params)
1045     : TestInstance(context)
1046     , m_params(params)
1047     , m_imageExtent(getNonNullImageExtent(params.traceDimensions))
1048 {
1049 }
1050 
makeIndirectStructAndFlush(BufferWithMemory & buffer,const bool source,const BufferWithMemory & rgenSbt,const BufferWithMemory & hitSbt,const BufferWithMemory & missSbt,const BufferWithMemory & callSbt) const1051 void TraceRaysIndirect2Instance::makeIndirectStructAndFlush(BufferWithMemory &buffer, const bool source,
1052                                                             const BufferWithMemory &rgenSbt,
1053                                                             const BufferWithMemory &hitSbt,
1054                                                             const BufferWithMemory &missSbt,
1055                                                             const BufferWithMemory &callSbt) const
1056 {
1057     DE_UNREF(callSbt);
1058 
1059     const DeviceInterface &vkd            = m_context.getDeviceInterface();
1060     const InstanceInterface &vki          = m_context.getInstanceInterface();
1061     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1062     const VkDevice device                 = m_context.getDevice();
1063     const uint32_t shaderGroupHandleSize  = getShaderGroupSize(vki, physicalDevice);
1064     Allocation &alloc                     = buffer.getAllocation();
1065 
1066     VkTraceRaysIndirectCommand2KHR data{};
1067 
1068     if (m_params.traceType == TraceType::INDIRECT_GPU && m_params.partialCopy)
1069     {
1070         if (source)
1071         {
1072             data.raygenShaderRecordAddress         = getBufferDeviceAddress(vkd, device, *rgenSbt, 0);
1073             data.missShaderBindingTableStride      = shaderGroupHandleSize;
1074             data.hitShaderBindingTableSize         = shaderGroupHandleSize;
1075             data.callableShaderBindingTableAddress = 0;
1076             data.callableShaderBindingTableStride  = 0;
1077         }
1078         else
1079         {
1080             data.raygenShaderRecordSize         = shaderGroupHandleSize;
1081             data.missShaderBindingTableAddress  = getBufferDeviceAddress(vkd, device, *missSbt, 0);
1082             data.missShaderBindingTableSize     = shaderGroupHandleSize;
1083             data.hitShaderBindingTableAddress   = getBufferDeviceAddress(vkd, device, *hitSbt, 0);
1084             data.hitShaderBindingTableStride    = shaderGroupHandleSize;
1085             data.callableShaderBindingTableSize = 0;
1086         }
1087     }
1088     else
1089     {
1090         data.raygenShaderRecordAddress = getBufferDeviceAddress(vkd, device, *rgenSbt, 0);
1091         data.raygenShaderRecordSize    = shaderGroupHandleSize;
1092 
1093         data.missShaderBindingTableAddress = getBufferDeviceAddress(vkd, device, *missSbt, 0);
1094         data.missShaderBindingTableSize    = shaderGroupHandleSize;
1095         data.missShaderBindingTableStride  = shaderGroupHandleSize;
1096 
1097         data.hitShaderBindingTableAddress = getBufferDeviceAddress(vkd, device, *hitSbt, 0);
1098         data.hitShaderBindingTableSize    = shaderGroupHandleSize;
1099         data.hitShaderBindingTableStride  = shaderGroupHandleSize;
1100 
1101         data.callableShaderBindingTableAddress = 0;
1102         data.callableShaderBindingTableSize    = 0;
1103         data.callableShaderBindingTableStride  = 0;
1104     }
1105 
1106     data.width  = m_params.traceDimensions.width;
1107     data.height = m_params.traceDimensions.height;
1108     data.depth  = m_params.traceDimensions.depth;
1109 
1110     deMemcpy(alloc.getHostPtr(), &data, sizeof(data));
1111     flushMappedMemoryRange(vkd, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
1112 }
1113 
initBottomAccellStructures(VkCommandBuffer cmdBuffer,BottomLevelAccelerationStructurePool & pool,const uint32_t & batchStructCount) const1114 void TraceRaysIndirect2Instance::initBottomAccellStructures(VkCommandBuffer cmdBuffer,
1115                                                             BottomLevelAccelerationStructurePool &pool,
1116                                                             const uint32_t &batchStructCount) const
1117 {
1118     const DeviceInterface &vkd = m_context.getDeviceInterface();
1119     const VkDevice device      = m_context.getDevice();
1120     Allocator &allocator       = m_context.getDefaultAllocator();
1121 
1122     pool.batchStructCount(batchStructCount);
1123     pool.batchGeomCount(batchStructCount * 8);
1124 
1125     tcu::Vec3 v0(0.0, 1.0, 0.0);
1126     tcu::Vec3 v1(0.0, 0.0, 0.0);
1127     tcu::Vec3 v2(1.0, 1.0, 0.0);
1128     tcu::Vec3 v3(1.0, 0.0, 0.0);
1129 
1130     for (uint32_t z = 0; z < m_imageExtent.depth; ++z)
1131         for (uint32_t y = 0; y < m_imageExtent.height; ++y)
1132             for (uint32_t x = 0; x < m_imageExtent.width; ++x)
1133             {
1134                 // let's build a 3D chessboard of geometries
1135                 if (((x + y + z) % 2) == 0)
1136                     continue;
1137                 tcu::Vec3 xyz((float)x, (float)y, (float)z);
1138                 std::vector<tcu::Vec3> geometryData;
1139 
1140                 auto bottomLevelAccelerationStructure = pool.add();
1141                 bottomLevelAccelerationStructure->setGeometryCount(1u);
1142 
1143                 geometryData.push_back(xyz + v0);
1144                 geometryData.push_back(xyz + v1);
1145                 geometryData.push_back(xyz + v2);
1146                 geometryData.push_back(xyz + v2);
1147                 geometryData.push_back(xyz + v1);
1148                 geometryData.push_back(xyz + v3);
1149 
1150                 bottomLevelAccelerationStructure->addGeometry(geometryData, true);
1151             }
1152 
1153     pool.batchCreate(vkd, device, allocator);
1154     pool.batchBuild(vkd, device, cmdBuffer);
1155 }
1156 
iterate(void)1157 TestStatus TraceRaysIndirect2Instance::iterate(void)
1158 {
1159     const InstanceInterface &vki          = m_context.getInstanceInterface();
1160     const DeviceInterface &vkd            = m_context.getDeviceInterface();
1161     const VkDevice device                 = m_context.getDevice();
1162     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1163     const auto queueAndFamilyIndex = getQueueFamilyIndexAtExact(vkd, vki, physicalDevice, device, m_params.submitQueue);
1164     const VkQueue queue            = std::get<1>(queueAndFamilyIndex);
1165     const uint32_t queueFamilyIndex         = std::get<2>(queueAndFamilyIndex);
1166     Allocator &allocator                    = m_context.getDefaultAllocator();
1167     const uint32_t width                    = m_imageExtent.width;
1168     const uint32_t height                   = m_imageExtent.height;
1169     const uint32_t depth                    = m_imageExtent.depth;
1170     const uint32_t pixelCount               = width * height * depth;
1171     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
1172     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1173 
1174     Move<VkDescriptorSetLayout> computeDescriptorSetLayout;
1175     Move<VkDescriptorPool> computeDescriptorPool;
1176     Move<VkDescriptorSet> computeDescriptorSet;
1177     Move<VkPipelineLayout> computePipelineLayout;
1178     Move<VkShaderModule> computeShader;
1179     Move<VkPipeline> computePipeline;
1180 
1181     if (m_params.traceType == TraceType::INDIRECT_GPU)
1182     {
1183         computeDescriptorSetLayout =
1184             DescriptorSetLayoutBuilder()
1185                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1186                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1187                 .build(vkd, device);
1188         computeDescriptorPool = DescriptorPoolBuilder()
1189                                     .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1190                                     .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1191                                     .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1192         const VkPushConstantRange full{VK_SHADER_STAGE_COMPUTE_BIT, 0, uint32_t(sizeof(uint32_t))};
1193         computeDescriptorSet  = makeDescriptorSet(vkd, device, *computeDescriptorPool, *computeDescriptorSetLayout);
1194         computePipelineLayout = makePipelineLayout(vkd, device, 1, &computeDescriptorSetLayout.get(), 1, &full);
1195 
1196         computeShader =
1197             createShaderModule(vkd, device, m_context.getBinaryCollection().get("compute_indirect_command"), 0);
1198         const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = {
1199             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1200             DE_NULL,                                             // const void* pNext;
1201             VkPipelineShaderStageCreateFlags(0u),                // VkPipelineShaderStageCreateFlags flags;
1202             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
1203             *computeShader,                                      // VkShaderModule module;
1204             "main",                                              // const char* pName;
1205             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
1206         };
1207         const VkComputePipelineCreateInfo pipelineCreateInfo = {
1208             VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1209             DE_NULL,                                        // const void* pNext;
1210             VkPipelineCreateFlags(0u),                      // VkPipelineCreateFlags flags;
1211             pipelineShaderStageParams,                      // VkPipelineShaderStageCreateInfo stage;
1212             *computePipelineLayout,                         // VkPipelineLayout layout;
1213             DE_NULL,                                        // VkPipeline basePipelineHandle;
1214             0,                                              // int32_t basePipelineIndex;
1215         };
1216 
1217         computePipeline = vk::createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo);
1218     }
1219 
1220     const Move<VkDescriptorSetLayout> descriptorSetLayout =
1221         DescriptorSetLayoutBuilder()
1222             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1223             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1224             .build(vkd, device);
1225     const Move<VkDescriptorPool> descriptorPool =
1226         DescriptorPoolBuilder()
1227             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1228             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1229             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1230     const Move<VkDescriptorSet> descriptorSet   = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1231     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1232 
1233     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1234     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
1235                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
1236     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
1237                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
1238     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
1239                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0), 2);
1240     Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1241 
1242     const de::MovePtr<BufferWithMemory> rgenSbt = rayTracingPipeline->createShaderBindingTable(
1243         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1244     const de::MovePtr<BufferWithMemory> hitSbt = rayTracingPipeline->createShaderBindingTable(
1245         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1246     const de::MovePtr<BufferWithMemory> missSbt = rayTracingPipeline->createShaderBindingTable(
1247         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
1248 
1249     const VkFormat imageFormat              = VK_FORMAT_R32_UINT;
1250     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(width, height, depth, imageFormat);
1251     const VkImageSubresourceRange imageSubresourceRange =
1252         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1253     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1254         new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1255     const Move<VkImageView> imageView =
1256         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
1257 
1258     const VkBufferCreateInfo resultBufferCreateInfo =
1259         makeBufferCreateInfo(pixelCount * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1260     const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
1261         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1262     const VkBufferImageCopy resultBufferImageRegion =
1263         makeBufferImageCopy(m_params.traceDimensions, resultBufferImageSubresourceLayers);
1264     de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
1265         new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1266     Allocation &resultBufferAllocation = resultBuffer->getAllocation();
1267 
1268     const VkDescriptorImageInfo descriptorImageInfo =
1269         makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1270 
1271     // create indirect command buffer and fill it with parameter values
1272     const VkDeviceSize bufferSize = sizeof(VkTraceRaysIndirectCommand2KHR);
1273     de::MovePtr<BufferWithMemory> indirectBuffer;
1274     de::MovePtr<BufferWithMemory> uniformBuffer;
1275 
1276     const bool indirectGpu = (m_params.traceType == TraceType::INDIRECT_GPU);
1277     VkBufferUsageFlags indirectBufferUsageFlags =
1278         VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
1279         (indirectGpu ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1280     const VkBufferCreateInfo indirectBufferCreateInfo = makeBufferCreateInfo(bufferSize, indirectBufferUsageFlags);
1281     vk::MemoryRequirement indirectBufferMemoryRequirement =
1282         MemoryRequirement::DeviceAddress | MemoryRequirement::HostVisible;
1283     indirectBuffer = de::MovePtr<BufferWithMemory>(
1284         new BufferWithMemory(vkd, device, allocator, indirectBufferCreateInfo, indirectBufferMemoryRequirement));
1285 
1286     if (m_params.traceType == TraceType::INDIRECT_GPU)
1287     {
1288         const VkBufferCreateInfo uniformBufferCreateInfo =
1289             makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1290         uniformBuffer = de::MovePtr<BufferWithMemory>(
1291             new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1292         makeIndirectStructAndFlush(*uniformBuffer, true, *rgenSbt, *hitSbt, *missSbt, *missSbt);
1293         makeIndirectStructAndFlush(*indirectBuffer, false, *rgenSbt, *hitSbt, *missSbt, *missSbt);
1294     }
1295     else if (m_params.traceType == TraceType::INDIRECT_CPU)
1296     {
1297         makeIndirectStructAndFlush(*indirectBuffer, true, *rgenSbt, *hitSbt, *missSbt, *missSbt);
1298     }
1299     else
1300     {
1301         TCU_THROW(NotSupportedError, "Invalid test parameters");
1302     }
1303 
1304     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1305     BottomLevelAccelerationStructurePool blasPool;
1306     const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1307     const Move<VkCommandBuffer> cmdBuffer =
1308         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1309 
1310     beginCommandBuffer(vkd, *cmdBuffer, 0u);
1311     {
1312         const VkImageMemoryBarrier preImageBarrier =
1313             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1314                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
1315         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1316                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1317 
1318         const VkClearValue clearValue = makeClearValueColorU32(kClearColorValue, 0u, 0u, 0u);
1319         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
1320                                &imageSubresourceRange);
1321 
1322         const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
1323             VK_ACCESS_TRANSFER_WRITE_BIT,
1324             VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1325             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
1326         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1327                                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1328 
1329         initBottomAccellStructures(*cmdBuffer, blasPool, 4);
1330         topLevelAccelerationStructure =
1331             initTopAccelerationStructure(*cmdBuffer, blasPool.structures(), m_context, m_imageExtent);
1332 
1333         if (m_params.traceType == TraceType::INDIRECT_GPU)
1334         {
1335             const uint32_t fullCopyStyle = m_params.partialCopy ? 0 : 1;
1336             const VkDescriptorBufferInfo uniformBufferDescriptorInfo =
1337                 makeDescriptorBufferInfo(**uniformBuffer, 0ull, bufferSize);
1338             const VkDescriptorBufferInfo indirectBufferDescriptorInfo =
1339                 makeDescriptorBufferInfo(**indirectBuffer, 0ull, bufferSize);
1340             DescriptorSetUpdateBuilder()
1341                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1342                              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
1343                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1344                              VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
1345                 .update(vkd, device);
1346 
1347             vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1348             vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u,
1349                                       &computeDescriptorSet.get(), 0u, DE_NULL);
1350             vkd.cmdPushConstants(*cmdBuffer, *computePipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
1351                                  uint32_t(sizeof(uint32_t)), &fullCopyStyle);
1352             vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
1353 
1354             const VkBufferMemoryBarrier fillIndirectBufferMemoryBarrier = makeBufferMemoryBarrier(
1355                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, **indirectBuffer, 0ull, bufferSize);
1356             cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1357                                            VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
1358         }
1359 
1360         const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
1361         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
1362             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
1363             DE_NULL,                                                           //  const void* pNext;
1364             1u,                                                                //  uint32_t accelerationStructureCount;
1365             topLevelAccelerationStructurePtr->getPtr(), //  const VkAccelerationStructureKHR* pAccelerationStructures;
1366         };
1367 
1368         DescriptorSetUpdateBuilder()
1369             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1370                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1371             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1372                          VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1373             .update(vkd, device);
1374 
1375         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
1376                                   &descriptorSet.get(), 0, DE_NULL);
1377 
1378         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1379 
1380         cmdTraceRaysIndirect2(vkd, *cmdBuffer, getBufferDeviceAddress(vkd, device, **indirectBuffer, 0));
1381 
1382         const VkMemoryBarrier postTraceMemoryBarrier =
1383             makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1384         const VkMemoryBarrier postCopyMemoryBarrier =
1385             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1386         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
1387                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1388 
1389         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
1390                                  &resultBufferImageRegion);
1391 
1392         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1393                                  &postCopyMemoryBarrier);
1394     }
1395     endCommandBuffer(vkd, *cmdBuffer);
1396 
1397     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1398 
1399     invalidateMappedMemoryRange(vkd, device, resultBufferAllocation.getMemory(), resultBufferAllocation.getOffset(),
1400                                 VK_WHOLE_SIZE);
1401 
1402     // run test using arrays of pointers
1403     const uint32_t *bufferPtr = (uint32_t *)resultBufferAllocation.getHostPtr();
1404     const bool noWrites       = isNullExtent(m_params.traceDimensions);
1405 
1406     const auto allocationCount = blasPool.getAllocationCount();
1407     uint32_t failures          = 0;
1408     uint32_t pos               = 0;
1409     uint32_t all               = 0;
1410 
1411     // verify results
1412     for (uint32_t z = 0; z < depth; ++z)
1413         for (uint32_t y = 0; y < height; ++y)
1414             for (uint32_t x = 0; x < width; ++x)
1415             {
1416                 const uint32_t expectedResult =
1417                     (noWrites ? kClearColorValue : (((x + y + z) % 2) ? kHitColorValue : kMissColorValue));
1418                 if (bufferPtr[pos] != expectedResult)
1419                     failures++;
1420                 ++pos;
1421                 ++all;
1422             }
1423 
1424     if (failures == 0)
1425         return tcu::TestStatus::pass(std::to_string(allocationCount) + " allocations");
1426     else
1427     {
1428         const auto msg = std::to_string(allocationCount) + " allocations, " + std::to_string(failures) +
1429                          " failures from " + std::to_string(all);
1430         return tcu::TestStatus::fail(msg);
1431     }
1432 }
1433 
makeDimensionsName(const VkTraceRaysIndirectCommandKHR & cmd)1434 std::string makeDimensionsName(const VkTraceRaysIndirectCommandKHR &cmd)
1435 {
1436     std::ostringstream name;
1437     name << cmd.width << "_" << cmd.height << "_" << cmd.depth;
1438     return name.str();
1439 }
1440 
makeDimensionsName(const VkExtent3D & extent)1441 std::string makeDimensionsName(const VkExtent3D &extent)
1442 {
1443     std::ostringstream name;
1444     name << extent.width << "x" << extent.height << "x" << extent.depth;
1445     return name.str();
1446 }
1447 
1448 } // namespace
1449 
createTraceRaysTests(tcu::TestContext & testCtx)1450 tcu::TestCaseGroup *createTraceRaysTests(tcu::TestContext &testCtx)
1451 {
1452     // Tests veryfying vkCmdTraceRays* commands
1453     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "trace_rays_cmds"));
1454 
1455     struct BufferSourceTypeData
1456     {
1457         TraceType traceType;
1458         const char *name;
1459     } bufferSourceTypes[] = {
1460         {TraceType::DIRECT, "direct"},
1461         {TraceType::INDIRECT_CPU, "indirect_cpu"},
1462         {TraceType::INDIRECT_GPU, "indirect_gpu"},
1463     };
1464 
1465     const VkTraceRaysIndirectCommandKHR traceDimensions[] = {
1466         {0, 0, 0}, {0, 1, 1}, {1, 0, 1},  {1, 1, 0},   {8, 1, 1},
1467         {8, 8, 1}, {8, 8, 8}, {11, 1, 1}, {11, 13, 1}, {11, 13, 5},
1468     };
1469 
1470     for (size_t bufferSourceNdx = 0; bufferSourceNdx < DE_LENGTH_OF_ARRAY(bufferSourceTypes); ++bufferSourceNdx)
1471     {
1472         de::MovePtr<tcu::TestCaseGroup> bufferSourceGroup(
1473             new tcu::TestCaseGroup(group->getTestContext(), bufferSourceTypes[bufferSourceNdx].name));
1474 
1475         for (size_t traceDimensionsIdx = 0; traceDimensionsIdx < DE_LENGTH_OF_ARRAY(traceDimensions);
1476              ++traceDimensionsIdx)
1477         {
1478             TestParams testParams{
1479                 bufferSourceTypes[bufferSourceNdx].traceType,
1480                 traceDimensions[traceDimensionsIdx],
1481                 false,
1482                 {/* Intentionally empty */},
1483             };
1484             const auto testName = makeDimensionsName(traceDimensions[traceDimensionsIdx]);
1485             bufferSourceGroup->addChild(
1486                 new RayTracingTraceRaysIndirectTestCase(group->getTestContext(), testName.c_str(), testParams));
1487         }
1488 
1489         group->addChild(bufferSourceGroup.release());
1490     }
1491 
1492     return group.release();
1493 }
1494 
createTraceRaysMaintenance1Tests(tcu::TestContext & testCtx)1495 tcu::TestCaseGroup *createTraceRaysMaintenance1Tests(tcu::TestContext &testCtx)
1496 {
1497     // Tests veryfying vkCmdTraceRays* commands
1498     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "trace_rays_cmds_maintenance_1"));
1499 
1500     struct BufferSourceTypeData
1501     {
1502         TraceType traceType;
1503         const char *name;
1504     } bufferSourceTypes[] = {
1505         {TraceType::INDIRECT2_CPU, "indirect2_cpu"},
1506         {TraceType::INDIRECT2_GPU, "indirect2_gpu"},
1507     };
1508 
1509     const VkTraceRaysIndirectCommand2KHR extendedTraceDimensions[] = {
1510         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
1511         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
1512         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 1},   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 1},
1513         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8},   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 1, 1},
1514         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 13, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 13, 5},
1515     };
1516 
1517     for (size_t bufferSourceNdx = 0; bufferSourceNdx < DE_LENGTH_OF_ARRAY(bufferSourceTypes); ++bufferSourceNdx)
1518     {
1519         de::MovePtr<tcu::TestCaseGroup> bufferSourceGroup(
1520             new tcu::TestCaseGroup(group->getTestContext(), bufferSourceTypes[bufferSourceNdx].name));
1521 
1522         for (size_t extendedTraceDimensionsIdx = 0;
1523              extendedTraceDimensionsIdx < DE_LENGTH_OF_ARRAY(extendedTraceDimensions); ++extendedTraceDimensionsIdx)
1524         {
1525             TestParams testParams{
1526                 bufferSourceTypes[bufferSourceNdx].traceType,
1527                 {/* Intentionally empty */},
1528                 true,
1529                 extendedTraceDimensions[extendedTraceDimensionsIdx],
1530             };
1531             const auto testName = makeDimensionsName(extendedTraceDimensions[extendedTraceDimensionsIdx]);
1532             bufferSourceGroup->addChild(
1533                 new RayTracingTraceRaysIndirectTestCase(group->getTestContext(), testName.c_str(), testParams));
1534         }
1535 
1536         group->addChild(bufferSourceGroup.release());
1537     }
1538 
1539     return group.release();
1540 }
1541 
createTraceRays2Tests(tcu::TestContext & testCtx)1542 tcu::TestCaseGroup *createTraceRays2Tests(tcu::TestContext &testCtx)
1543 {
1544     auto group = new tcu::TestCaseGroup(testCtx, "trace_rays_indirect2");
1545 
1546     std::pair<TraceType, const char *> const bufferSources[]{
1547         {TraceType::INDIRECT_CPU, "indirect_cpu"},
1548         {TraceType::INDIRECT_GPU, "indirect_gpu"},
1549     };
1550 
1551     std::pair<bool, const char *> const copyStyles[]{{true, "full_copy"}, {false, "partial_copy"}};
1552 
1553     std::pair<VkQueueFlagBits, const char *> submitQueues[]{{VK_QUEUE_GRAPHICS_BIT, "submit_graphics"},
1554                                                             {VK_QUEUE_COMPUTE_BIT, "submit_compute"}};
1555 
1556     const VkExtent3D traceDimensions[] = {{11, 17, 1}, {19, 11, 2}, {23, 47, 3}, {47, 19, 4}};
1557 
1558     for (const auto &bufferSource : bufferSources)
1559     {
1560         auto bufferSourceGroup = new TestCaseGroup(testCtx, bufferSource.second);
1561 
1562         for (const auto &copyStyle : copyStyles)
1563         {
1564             auto copyStyleGroup = new TestCaseGroup(testCtx, copyStyle.second);
1565 
1566             for (const auto &submitQueue : submitQueues)
1567             {
1568                 auto submitQueueGroup = new TestCaseGroup(testCtx, submitQueue.second);
1569 
1570                 for (const auto &traceDimension : traceDimensions)
1571                 {
1572                     TestParams2 testParams{bufferSource.first, traceDimension, copyStyle.first, submitQueue.first};
1573                     const auto testName = makeDimensionsName(traceDimension);
1574                     submitQueueGroup->addChild(new TraceRaysIndirect2Case(testCtx, testName.c_str(), testParams));
1575                 }
1576                 copyStyleGroup->addChild(submitQueueGroup);
1577             }
1578             bufferSourceGroup->addChild(copyStyleGroup);
1579         }
1580         group->addChild(bufferSourceGroup);
1581     }
1582 
1583     return group;
1584 }
1585 
1586 } // namespace RayTracing
1587 
1588 } // namespace vkt
1589