1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 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 Capture/Replay tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingCaptureReplayTests.hpp"
25 
26 #include <set>
27 #include "vkDefs.hpp"
28 
29 #include "vktTestCase.hpp"
30 #include "vktTestGroupUtil.hpp"
31 #include "vktCustomInstancesDevices.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBufferWithMemory.hpp"
37 #include "vkImageWithMemory.hpp"
38 #include "vkTypeUtil.hpp"
39 
40 #include "vkRayTracingUtil.hpp"
41 
42 #include "tcuCommandLine.hpp"
43 
44 namespace vkt
45 {
46 namespace RayTracing
47 {
48 namespace
49 {
50 using namespace vk;
51 using namespace vkt;
52 
53 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
54                                               VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
55                                               VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
56 
57 static const uint32_t RTCR_DEFAULT_SIZE = 8u;
58 static const uint32_t RTCR_SHADER_COUNT = 4u;
59 
60 enum SBTReplayTestType
61 {
62     TEST_ACCELERATION_STRUCTURES,
63     TEST_PIPELINE_SINGLE,
64     TEST_PIPELINE_AFTER,
65     TEST_PIPELINE_BEFORE
66 };
67 
68 enum ASOperationTarget
69 {
70     OT_NONE,
71     OT_TOP_ACCELERATION,
72     OT_BOTTOM_ACCELERATION
73 };
74 
75 enum ASOperationType
76 {
77     OP_NONE,
78     OP_COPY,
79     OP_COMPACT,
80     OP_SERIALIZE
81 };
82 
83 enum ASBottomTestType
84 {
85     BTT_TRIANGLES,
86     BTT_AABBS
87 };
88 
89 enum ASTopTestType
90 {
91     TTT_IDENTICAL_INSTANCES,
92     TTT_DIFFERENT_INSTANCES
93 };
94 
95 struct TestParams;
96 
97 struct PipelineOutput
98 {
99     Move<VkPipeline> pipeline;
100     de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
101     de::MovePtr<BufferWithMemory> missShaderBindingTable;
102     de::MovePtr<BufferWithMemory> hitShaderBindingTable;
103     Move<VkDescriptorSet> descriptorSet;
104     de::MovePtr<BufferWithMemory> uniformBuffer;
105 
106     VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion;
107     VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion;
108     VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion;
109     VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion;
110 };
111 
112 struct PipelineData
113 {
PipelineDatavkt::RayTracing::__anon147f66540111::PipelineData114     PipelineData(Allocator &alloc) : allocator(alloc)
115     {
116     }
117     VkDescriptorSetLayout descriptorSetLayout;
118     VkDescriptorPool descriptorPool;
119     VkPipelineLayout pipelineLayout;
120     Allocator &allocator;
121     PipelineOutput pipelines[2];
122 };
123 
124 class TestConfiguration
125 {
126 public:
~TestConfiguration()127     virtual ~TestConfiguration()
128     {
129     }
130 
131     virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
132         Context &context, TestParams &testParams) = 0;
133     virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
134         Context &context, TestParams &testParams,
135         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) = 0;
136     virtual void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
137                                        const DeviceInterface &vkd, const VkDevice device, TestParams &testParams,
138                                        bool replay)                                                      = 0;
139     virtual void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
140                                          const DeviceInterface &vkd, const VkDevice device, TestParams &testParams,
141                                          uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment,
142                                          PipelineData &pipelineData, bool replay)                        = 0;
143     virtual bool verifyImage(const std::vector<uint32_t> &captureResults, const std::vector<uint32_t> &replayResults,
144                              Context &context, TestParams &testParams)                                   = 0;
145     virtual VkFormat getResultImageFormat()                                                              = 0;
146     virtual size_t getResultImageFormatSize()                                                            = 0;
147     virtual VkClearValue getClearValue()                                                                 = 0;
148 };
149 
150 struct TestParams
151 {
152     SBTReplayTestType testType;                        // SBT
153     ASOperationTarget operationTarget;                 // AS
154     ASOperationType operationType;                     // AS
155     vk::VkAccelerationStructureBuildTypeKHR buildType; // AS
156     ASBottomTestType bottomType;                       // AS
157     ASTopTestType topType;                             // AS
158     uint32_t width;
159     uint32_t height;
160     de::SharedPtr<TestConfiguration> testConfiguration;
161 };
162 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)163 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
164 {
165     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
166 
167     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
168     return rayTracingPropertiesKHR->getShaderGroupHandleSize();
169 }
170 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)171 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
172 {
173     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
174 
175     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
176     return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
177 }
178 
makeImageCreateInfo(uint32_t width,uint32_t height,uint32_t depth,VkFormat format)179 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format)
180 {
181     const VkImageCreateInfo imageCreateInfo = {
182         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
183         DE_NULL,                             // const void* pNext;
184         (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
185         VK_IMAGE_TYPE_3D,                    // VkImageType imageType;
186         format,                              // VkFormat format;
187         makeExtent3D(width, height, depth),  // VkExtent3D extent;
188         1u,                                  // uint32_t mipLevels;
189         1u,                                  // uint32_t arrayLayers;
190         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
191         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
192         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
193             VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
194         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
195         0u,                                  // uint32_t queueFamilyIndexCount;
196         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
197         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
198     };
199 
200     return imageCreateInfo;
201 }
202 
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,uint32_t queryCount)203 Move<VkQueryPool> makeQueryPool(const DeviceInterface &vk, const VkDevice device, const VkQueryType queryType,
204                                 uint32_t queryCount)
205 {
206     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
207         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
208         DE_NULL,                                  // pNext
209         (VkQueryPoolCreateFlags)0,                // flags
210         queryType,                                // queryType
211         queryCount,                               // queryCount
212         0u,                                       // pipelineStatistics
213     };
214     return createQueryPool(vk, device, &queryPoolCreateInfo);
215 }
216 
getAccelerationStructureDeviceAddress(const DeviceInterface & vk,const VkDevice device,VkAccelerationStructureKHR accelerationStructure)217 VkDeviceAddress getAccelerationStructureDeviceAddress(const DeviceInterface &vk, const VkDevice device,
218                                                       VkAccelerationStructureKHR accelerationStructure)
219 {
220     const VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {
221         VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType               sType;
222         DE_NULL,                                                          // const void*                   pNext;
223         accelerationStructure // VkAccelerationStructureKHR    accelerationStructure
224     };
225     return vk.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
226 }
227 
228 class TestShaderBindingTablesConfiguration : public TestConfiguration
229 {
230 public:
231     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
232         Context &context, TestParams &testParams) override;
233     de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
234         Context &context, TestParams &testParams,
235         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
236     void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
237                                const DeviceInterface &vkd, const VkDevice device, TestParams &testParams,
238                                bool replay) override;
239     void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
240                                  const DeviceInterface &vkd, const VkDevice device, TestParams &testParams,
241                                  uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment,
242                                  PipelineData &pipelineData, bool replay) override;
243     bool verifyImage(const std::vector<uint32_t> &captureResults, const std::vector<uint32_t> &replayResults,
244                      Context &context, TestParams &testParams) override;
245     VkFormat getResultImageFormat() override;
246     size_t getResultImageFormatSize() override;
247     VkClearValue getClearValue() override;
248 
249 protected:
250     VkDeviceAddress sbtSavedRaygenAddress = 0u;
251     VkDeviceAddress sbtSavedMissAddress   = 0u;
252     VkDeviceAddress sbtSavedHitAddress    = 0u;
253 };
254 
255 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> TestShaderBindingTablesConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)256     initBottomAccelerationStructures(Context &context, TestParams &testParams)
257 {
258     DE_UNREF(context);
259     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
260 
261     tcu::Vec3 v0(0.0, 1.0, 0.0);
262     tcu::Vec3 v1(0.0, 0.0, 0.0);
263     tcu::Vec3 v2(1.0, 1.0, 0.0);
264     tcu::Vec3 v3(1.0, 0.0, 0.0);
265 
266     for (uint32_t y = 0; y < testParams.height; ++y)
267         for (uint32_t x = 0; x < testParams.width; ++x)
268         {
269             // let's build a chessboard of geometries
270             if (((x + y) % 2) == 0)
271                 continue;
272             tcu::Vec3 xyz((float)x, (float)y, 0.0f);
273             std::vector<tcu::Vec3> geometryData;
274 
275             de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
276                 makeBottomLevelAccelerationStructure();
277             bottomLevelAccelerationStructure->setGeometryCount(1u);
278 
279             geometryData.push_back(xyz + v0);
280             geometryData.push_back(xyz + v1);
281             geometryData.push_back(xyz + v2);
282             geometryData.push_back(xyz + v2);
283             geometryData.push_back(xyz + v1);
284             geometryData.push_back(xyz + v3);
285 
286             bottomLevelAccelerationStructure->addGeometry(geometryData, true);
287             result.push_back(
288                 de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
289         }
290 
291     return result;
292 }
293 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)294 de::MovePtr<TopLevelAccelerationStructure> TestShaderBindingTablesConfiguration::initTopAccelerationStructure(
295     Context &context, TestParams &testParams,
296     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
297 {
298     DE_UNREF(context);
299     uint32_t instanceCount = testParams.width * testParams.height / 2;
300 
301     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
302     result->setInstanceCount(instanceCount);
303 
304     uint32_t currentInstanceIndex       = 0;
305     VkTransformMatrixKHR identityMatrix = {
306         {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}}};
307 
308     for (uint32_t y = 0; y < testParams.height; ++y)
309     {
310         uint32_t shaderOffset = y % RTCR_SHADER_COUNT;
311         for (uint32_t x = 0; x < testParams.width; ++x)
312         {
313             if (((x + y) % 2) == 0)
314                 continue;
315             result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix, 0, 0xFF,
316                                 shaderOffset);
317         }
318     }
319 
320     return result;
321 }
322 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,bool replay)323 void TestShaderBindingTablesConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
324                                                                  Context &context, const DeviceInterface &vkd,
325                                                                  const VkDevice device, TestParams &testParams,
326                                                                  bool replay)
327 {
328     DE_UNREF(testParams);
329     DE_UNREF(replay);
330     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
331                                   createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
332     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
333                                   createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 1);
334     for (uint32_t shaderNdx = 0; shaderNdx < RTCR_SHADER_COUNT; ++shaderNdx)
335     {
336         std::stringstream shaderName;
337         shaderName << "chit" << shaderNdx;
338         rayTracingPipeline->addShader(
339             VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
340             createShaderModule(vkd, device, context.getBinaryCollection().get(shaderName.str()), 0), 2 + shaderNdx);
341     }
342 }
343 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,PipelineData & pipelineData,bool replay)344 void TestShaderBindingTablesConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
345                                                                    Context &context, const DeviceInterface &vkd,
346                                                                    const VkDevice device, TestParams &testParams,
347                                                                    uint32_t shaderGroupHandleSize,
348                                                                    uint32_t shaderGroupBaseAlignment,
349                                                                    PipelineData &pipelineData, bool replay)
350 {
351     DE_UNREF(context);
352     const VkBufferCreateInfo uniformBufferCreateInfo =
353         makeBufferCreateInfo(sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
354 
355     if (!replay) // capture phase
356     {
357         pipelineData.pipelines[0].pipeline =
358             rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
359         pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
360             vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
361             shaderGroupBaseAlignment, 0, 1, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
362             VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u);
363         pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
364             vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
365             shaderGroupBaseAlignment, 1, 1, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
366             VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u);
367         pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
368             vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
369             shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
370             VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u);
371         pipelineData.pipelines[0].descriptorSet =
372             makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
373         pipelineData.pipelines[0].uniformBuffer                  = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
374             vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
375         pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
376             getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0),
377             shaderGroupHandleSize, shaderGroupHandleSize);
378         pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
379             getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0),
380             shaderGroupHandleSize, shaderGroupHandleSize);
381         pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
382             getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0),
383             shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
384         pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
385 
386         // capture SBT addresses
387         VkBufferDeviceAddressInfo deviceAddressInfo = {
388             VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, //VkStructureType    sType;
389             DE_NULL,                                      //const void*        pNext;
390             DE_NULL                                       //VkBuffer           buffer;
391         };
392         deviceAddressInfo.buffer = pipelineData.pipelines[0].raygenShaderBindingTable->get();
393         sbtSavedRaygenAddress    = vkd.getBufferOpaqueCaptureAddress(device, &deviceAddressInfo);
394         deviceAddressInfo.buffer = pipelineData.pipelines[0].missShaderBindingTable->get();
395         sbtSavedMissAddress      = vkd.getBufferOpaqueCaptureAddress(device, &deviceAddressInfo);
396         deviceAddressInfo.buffer = pipelineData.pipelines[0].hitShaderBindingTable->get();
397         sbtSavedHitAddress       = vkd.getBufferOpaqueCaptureAddress(device, &deviceAddressInfo);
398     }
399     else // replay phase
400     {
401         switch (testParams.testType)
402         {
403         case TEST_PIPELINE_SINGLE:
404             pipelineData.pipelines[0].pipeline =
405                 rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
406             pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
407                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
408                 shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress);
409             pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
410                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
411                 shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress);
412             pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
413                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
414                 shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress);
415             pipelineData.pipelines[0].descriptorSet =
416                 makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
417             pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
418                 vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
419             pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
420                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0),
421                 shaderGroupHandleSize, shaderGroupHandleSize);
422             pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
423                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0),
424                 shaderGroupHandleSize, shaderGroupHandleSize);
425             pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
426                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0),
427                 shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
428             pipelineData.pipelines[0].callableShaderBindingTableRegion =
429                 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
430 
431             break;
432         case TEST_PIPELINE_AFTER:
433             pipelineData.pipelines[0].pipeline =
434                 rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
435             pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
436                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
437                 shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress);
438             pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
439                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
440                 shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress);
441             pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
442                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
443                 shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress);
444             pipelineData.pipelines[0].descriptorSet =
445                 makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
446             pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
447                 vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
448             pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
449                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0),
450                 shaderGroupHandleSize, shaderGroupHandleSize);
451             pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
452                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0),
453                 shaderGroupHandleSize, shaderGroupHandleSize);
454             pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
455                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0),
456                 shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
457             pipelineData.pipelines[0].callableShaderBindingTableRegion =
458                 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
459 
460             pipelineData.pipelines[1].pipeline =
461                 rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
462             pipelineData.pipelines[1].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
463                 vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize,
464                 shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, 0u);
465             pipelineData.pipelines[1].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
466                 vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize,
467                 shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, 0u);
468             pipelineData.pipelines[1].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
469                 vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize,
470                 shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, 0u);
471             pipelineData.pipelines[1].descriptorSet =
472                 makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
473             pipelineData.pipelines[1].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
474                 vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
475             pipelineData.pipelines[1].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
476                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].raygenShaderBindingTable->get(), 0),
477                 shaderGroupHandleSize, shaderGroupHandleSize);
478             pipelineData.pipelines[1].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
479                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].missShaderBindingTable->get(), 0),
480                 shaderGroupHandleSize, shaderGroupHandleSize);
481             pipelineData.pipelines[1].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
482                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].hitShaderBindingTable->get(), 0),
483                 shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
484             pipelineData.pipelines[1].callableShaderBindingTableRegion =
485                 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
486 
487             break;
488         case TEST_PIPELINE_BEFORE:
489             pipelineData.pipelines[0].pipeline =
490                 rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
491             pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
492                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
493                 shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, 0u);
494             pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
495                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
496                 shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, 0u);
497             pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
498                 vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
499                 shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, 0u);
500             pipelineData.pipelines[0].descriptorSet =
501                 makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
502             pipelineData.pipelines[0].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
503                 vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
504             pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
505                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0),
506                 shaderGroupHandleSize, shaderGroupHandleSize);
507             pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
508                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0),
509                 shaderGroupHandleSize, shaderGroupHandleSize);
510             pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
511                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0),
512                 shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
513             pipelineData.pipelines[0].callableShaderBindingTableRegion =
514                 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
515 
516             pipelineData.pipelines[1].pipeline =
517                 rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
518             pipelineData.pipelines[1].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
519                 vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize,
520                 shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress);
521             pipelineData.pipelines[1].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
522                 vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize,
523                 shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress);
524             pipelineData.pipelines[1].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
525                 vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize,
526                 shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress);
527             pipelineData.pipelines[1].descriptorSet =
528                 makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
529             pipelineData.pipelines[1].uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
530                 vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
531             pipelineData.pipelines[1].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
532                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].raygenShaderBindingTable->get(), 0),
533                 shaderGroupHandleSize, shaderGroupHandleSize);
534             pipelineData.pipelines[1].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
535                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].missShaderBindingTable->get(), 0),
536                 shaderGroupHandleSize, shaderGroupHandleSize);
537             pipelineData.pipelines[1].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
538                 getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].hitShaderBindingTable->get(), 0),
539                 shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
540             pipelineData.pipelines[1].callableShaderBindingTableRegion =
541                 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
542             break;
543         default:
544             TCU_THROW(InternalError, "Wrong test type");
545         }
546     }
547 }
548 
verifyImage(const std::vector<uint32_t> & captureResults,const std::vector<uint32_t> & replayResults,Context & context,TestParams & testParams)549 bool TestShaderBindingTablesConfiguration::verifyImage(const std::vector<uint32_t> &captureResults,
550                                                        const std::vector<uint32_t> &replayResults, Context &context,
551                                                        TestParams &testParams)
552 {
553     DE_UNREF(context);
554 
555     uint32_t pipelineCount = (testParams.testType == TEST_PIPELINE_SINGLE) ? 1u : 2u;
556     uint32_t imageSize     = testParams.height * testParams.width;
557     uint32_t failures      = 0;
558 
559     // verify results - each test case should generate checkerboard pattern
560     for (uint32_t pipelineNdx = 0; pipelineNdx < pipelineCount; ++pipelineNdx)
561         for (uint32_t pos = 0; pos < imageSize; ++pos)
562         {
563             if (captureResults[pos] != replayResults[pipelineNdx * imageSize + pos])
564                 failures++;
565         }
566     return failures == 0;
567 }
568 
getResultImageFormat()569 VkFormat TestShaderBindingTablesConfiguration::getResultImageFormat()
570 {
571     return VK_FORMAT_R32_UINT;
572 }
573 
getResultImageFormatSize()574 size_t TestShaderBindingTablesConfiguration::getResultImageFormatSize()
575 {
576     return sizeof(uint32_t);
577 }
578 
getClearValue()579 VkClearValue TestShaderBindingTablesConfiguration::getClearValue()
580 {
581     return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
582 }
583 
584 class TestAccelerationStructuresConfiguration : public TestConfiguration
585 {
586 public:
587     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
588         Context &context, TestParams &testParams) override;
589     de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
590         Context &context, TestParams &testParams,
591         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
592     void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
593                                const DeviceInterface &vkd, const VkDevice device, TestParams &testParams,
594                                bool replay) override;
595     void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
596                                  const DeviceInterface &vkd, const VkDevice device, TestParams &testParams,
597                                  uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment,
598                                  PipelineData &pipelineData, bool replay) override;
599     bool verifyImage(const std::vector<uint32_t> &captureResults, const std::vector<uint32_t> &replayResults,
600                      Context &context, TestParams &testParams) override;
601     VkFormat getResultImageFormat() override;
602     size_t getResultImageFormatSize() override;
603     VkClearValue getClearValue() override;
604 
605 protected:
606     VkDeviceAddress sbtSavedRaygenAddress = 0u;
607     VkDeviceAddress sbtSavedMissAddress   = 0u;
608     VkDeviceAddress sbtSavedHitAddress    = 0u;
609 };
610 
611 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> TestAccelerationStructuresConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)612     initBottomAccelerationStructures(Context &context, TestParams &testParams)
613 {
614     DE_UNREF(context);
615     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
616 
617     tcu::Vec3 v0(0.0, 1.0, 0.0);
618     tcu::Vec3 v1(0.0, 0.0, 0.0);
619     tcu::Vec3 v2(1.0, 1.0, 0.0);
620     tcu::Vec3 v3(1.0, 0.0, 0.0);
621 
622     if (testParams.topType == TTT_DIFFERENT_INSTANCES)
623     {
624         de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
625             makeBottomLevelAccelerationStructure();
626         bottomLevelAccelerationStructure->setGeometryCount(1u);
627         de::SharedPtr<RaytracedGeometryBase> geometry;
628         if (testParams.bottomType == BTT_TRIANGLES)
629         {
630             geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT,
631                                              VK_INDEX_TYPE_NONE_KHR);
632             geometry->addVertex(v0);
633             geometry->addVertex(v1);
634             geometry->addVertex(v2);
635             geometry->addVertex(v2);
636             geometry->addVertex(v1);
637             geometry->addVertex(v3);
638         }
639         else // m_data.bottomType == BTT_AABBS
640         {
641             geometry =
642                 makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
643             geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
644             geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
645         }
646 
647         bottomLevelAccelerationStructure->addGeometry(geometry);
648         result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
649     }
650     else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
651     {
652         // triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
653         for (uint32_t y = 0; y < testParams.height; ++y)
654             for (uint32_t x = 0; x < testParams.width; ++x)
655             {
656                 // let's build a chessboard of geometries
657                 if (((x + y) % 2) == 0)
658                     continue;
659                 tcu::Vec3 xyz((float)x, (float)y, 0.0f);
660 
661                 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
662                     makeBottomLevelAccelerationStructure();
663                 bottomLevelAccelerationStructure->setGeometryCount(1u);
664 
665                 de::SharedPtr<RaytracedGeometryBase> geometry;
666                 if (testParams.bottomType == BTT_TRIANGLES)
667                 {
668                     geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT,
669                                                      VK_INDEX_TYPE_NONE_KHR);
670                     geometry->addVertex(xyz + v0);
671                     geometry->addVertex(xyz + v1);
672                     geometry->addVertex(xyz + v2);
673                     geometry->addVertex(xyz + v2);
674                     geometry->addVertex(xyz + v1);
675                     geometry->addVertex(xyz + v3);
676                 }
677                 else // testParams.bottomTestType == BTT_AABBS
678                 {
679                     geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT,
680                                                      VK_INDEX_TYPE_NONE_KHR);
681                     geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
682                     geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
683                 }
684 
685                 bottomLevelAccelerationStructure->addGeometry(geometry);
686                 result.push_back(
687                     de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
688             }
689     }
690 
691     return result;
692 }
693 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)694 de::MovePtr<TopLevelAccelerationStructure> TestAccelerationStructuresConfiguration::initTopAccelerationStructure(
695     Context &context, TestParams &testParams,
696     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
697 {
698     DE_UNREF(context);
699 
700     uint32_t instanceCount = testParams.width * testParams.height / 2;
701 
702     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
703     result->setInstanceCount(instanceCount);
704 
705     if (testParams.topType == TTT_DIFFERENT_INSTANCES)
706     {
707 
708         for (uint32_t y = 0; y < testParams.height; ++y)
709             for (uint32_t x = 0; x < testParams.width; ++x)
710             {
711                 if (((x + y) % 2) == 0)
712                     continue;
713                 const VkTransformMatrixKHR transformMatrixKHR = {{
714                     //  float matrix[3][4];
715                     {1.0f, 0.0f, 0.0f, (float)x},
716                     {0.0f, 1.0f, 0.0f, (float)y},
717                     {0.0f, 0.0f, 1.0f, 0.0f},
718                 }};
719                 result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR);
720             }
721     }
722     else // testParams.topType == TTT_IDENTICAL_INSTANCES
723     {
724         uint32_t currentInstanceIndex = 0;
725 
726         for (uint32_t y = 0; y < testParams.height; ++y)
727             for (uint32_t x = 0; x < testParams.width; ++x)
728             {
729                 if (((x + y) % 2) == 0)
730                     continue;
731                 result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]);
732             }
733     }
734 
735     return result;
736 }
737 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,bool replay)738 void TestAccelerationStructuresConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
739                                                                     Context &context, const DeviceInterface &vkd,
740                                                                     const VkDevice device, TestParams &testParams,
741                                                                     bool replay)
742 {
743     DE_UNREF(testParams);
744     DE_UNREF(replay);
745     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
746                                   createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
747     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
748                                   createShaderModule(vkd, device, context.getBinaryCollection().get("chit1"), 0), 1);
749     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
750                                   createShaderModule(vkd, device, context.getBinaryCollection().get("chit1"), 0), 2);
751     rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
752                                   createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0), 2);
753     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
754                                   createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 3);
755 }
756 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,PipelineData & pipelineData,bool replay)757 void TestAccelerationStructuresConfiguration::initShaderBindingTables(
758     de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context, const DeviceInterface &vkd,
759     const VkDevice device, TestParams &testParams, uint32_t shaderGroupHandleSize, uint32_t shaderGroupBaseAlignment,
760     PipelineData &pipelineData, bool replay)
761 {
762     DE_UNREF(context);
763     DE_UNREF(replay);
764     const VkBufferCreateInfo uniformBufferCreateInfo =
765         makeBufferCreateInfo(sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
766 
767     pipelineData.pipelines[0].pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
768     pipelineData.pipelines[0].raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
769         vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
770         shaderGroupBaseAlignment, 0, 1);
771     if (testParams.bottomType == BTT_AABBS)
772         pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
773             vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
774             shaderGroupBaseAlignment, 2, 1);
775     else // testParams.bottomType == BTT_TRIANGLES
776         pipelineData.pipelines[0].hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
777             vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
778             shaderGroupBaseAlignment, 1, 1);
779     pipelineData.pipelines[0].missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
780         vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize,
781         shaderGroupBaseAlignment, 3, 1);
782     pipelineData.pipelines[0].descriptorSet =
783         makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
784     pipelineData.pipelines[0].uniformBuffer                  = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
785         vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
786     pipelineData.pipelines[0].raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
787         getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0),
788         shaderGroupHandleSize, shaderGroupHandleSize);
789     pipelineData.pipelines[0].missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
790         getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0),
791         shaderGroupHandleSize, shaderGroupHandleSize);
792     pipelineData.pipelines[0].hitShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
793         getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0),
794         shaderGroupHandleSize, shaderGroupHandleSize);
795     pipelineData.pipelines[0].callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
796 }
797 
verifyImage(const std::vector<uint32_t> & captureResults,const std::vector<uint32_t> & replayResults,Context & context,TestParams & testParams)798 bool TestAccelerationStructuresConfiguration::verifyImage(const std::vector<uint32_t> &captureResults,
799                                                           const std::vector<uint32_t> &replayResults, Context &context,
800                                                           TestParams &testParams)
801 {
802     DE_UNREF(context);
803 
804     uint32_t imageSize = testParams.height * testParams.width;
805     uint32_t failures  = 0;
806 
807     // verify results - each test case should generate checkerboard pattern
808     for (uint32_t pos = 0; pos < imageSize; ++pos)
809     {
810         if (captureResults[pos] != replayResults[pos])
811             failures++;
812     }
813     return failures == 0;
814 }
815 
getResultImageFormat()816 VkFormat TestAccelerationStructuresConfiguration::getResultImageFormat()
817 {
818     return VK_FORMAT_R32_UINT;
819 }
820 
getResultImageFormatSize()821 size_t TestAccelerationStructuresConfiguration::getResultImageFormatSize()
822 {
823     return sizeof(uint32_t);
824 }
825 
getClearValue()826 VkClearValue TestAccelerationStructuresConfiguration::getClearValue()
827 {
828     return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
829 }
830 
831 class RayTracingCaptureReplayTestCase : public TestCase
832 {
833 public:
834     RayTracingCaptureReplayTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
835     ~RayTracingCaptureReplayTestCase(void);
836 
837     virtual void checkSupport(Context &context) const;
838     virtual void initPrograms(SourceCollections &programCollection) const;
839     virtual TestInstance *createInstance(Context &context) const;
840 
841 private:
842     TestParams m_data;
843 };
844 
845 class RayTracingCaptureReplayTestInstance : public TestInstance
846 {
847 public:
848     RayTracingCaptureReplayTestInstance(Context &context, const TestParams &data);
849     ~RayTracingCaptureReplayTestInstance(void);
850     tcu::TestStatus iterate(void);
851 
852 protected:
853     std::vector<uint32_t> runTest(bool replay);
854 
855 private:
856     TestParams m_data;
857     std::vector<VkDeviceAddress> buildBLASAddresses;
858     std::vector<VkDeviceAddress> copyBLASAddresses;
859     VkDeviceAddress buildTLASAddress;
860     VkDeviceAddress copyTLASAddress;
861 };
862 
RayTracingCaptureReplayTestCase(tcu::TestContext & context,const char * name,const TestParams & data)863 RayTracingCaptureReplayTestCase::RayTracingCaptureReplayTestCase(tcu::TestContext &context, const char *name,
864                                                                  const TestParams &data)
865     : vkt::TestCase(context, name)
866     , m_data(data)
867 {
868 }
869 
~RayTracingCaptureReplayTestCase(void)870 RayTracingCaptureReplayTestCase::~RayTracingCaptureReplayTestCase(void)
871 {
872 }
873 
checkSupport(Context & context) const874 void RayTracingCaptureReplayTestCase::checkSupport(Context &context) const
875 {
876     context.requireDeviceFunctionality("VK_KHR_buffer_device_address");
877     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
878     context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
879 
880     const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
881         context.getRayTracingPipelineFeatures();
882     if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
883         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
884 
885     if (m_data.testType == TEST_PIPELINE_BEFORE &&
886         rayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplayMixed == false)
887         TCU_THROW(
888             NotSupportedError,
889             "Requires "
890             "VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplayMixed");
891 
892     if (m_data.testType != TEST_ACCELERATION_STRUCTURES &&
893         rayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplay == false)
894         TCU_THROW(
895             NotSupportedError,
896             "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplay");
897 
898     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
899         context.getAccelerationStructureFeatures();
900     if (accelerationStructureFeaturesKHR.accelerationStructure == false)
901         TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
902                              "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
903 
904     if (m_data.testType == TEST_ACCELERATION_STRUCTURES &&
905         accelerationStructureFeaturesKHR.accelerationStructureCaptureReplay == false)
906         TCU_THROW(NotSupportedError,
907                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureCaptureReplay");
908 
909     if (m_data.testType == TEST_ACCELERATION_STRUCTURES &&
910         m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
911         accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
912         TCU_THROW(NotSupportedError,
913                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
914 
915     const VkPhysicalDeviceBufferDeviceAddressFeatures &bufferDeviceAddressFeatures =
916         context.getBufferDeviceAddressFeatures();
917 
918     if (bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay == false)
919         TCU_THROW(NotSupportedError, "Requires bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay");
920 }
921 
initPrograms(SourceCollections & programCollection) const922 void RayTracingCaptureReplayTestCase::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         css << "#version 460 core\n"
928                "#extension GL_EXT_ray_tracing : require\n"
929                "layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
930                "layout(set = 0, binding = 0) uniform UniformParams\n"
931                "{\n"
932                "  uint targetLayer;\n"
933                "} uniformParams;\n"
934                "layout(r32ui, set = 0, binding = 1) uniform uimage3D result;\n"
935                "layout(set = 0, binding = 2) uniform accelerationStructureEXT topLevelAS;\n"
936                "\n"
937                "void main()\n"
938                "{\n"
939                "  float tmin     = 0.0;\n"
940                "  float tmax     = 1.0;\n"
941                "  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n"
942                "  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
943                "  hitValue       = uvec4(0,0,0,0);\n"
944                "  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
945                "  imageStore(result, ivec3(gl_LaunchIDEXT.xy, uniformParams.targetLayer), hitValue);\n"
946                "}\n";
947         programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
948     }
949 
950     for (uint32_t shaderNdx = 0; shaderNdx < RTCR_SHADER_COUNT; ++shaderNdx)
951     {
952         uint32_t colorValue = 2 * (shaderNdx + 1);
953         std::stringstream css;
954         css << "#version 460 core\n"
955                "#extension GL_EXT_ray_tracing : require\n"
956                "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
957                "void main()\n"
958                "{\n"
959                "  hitValue = uvec4("
960             << colorValue
961             << ",0,0,1);\n"
962                "}\n";
963         std::stringstream shaderName;
964         shaderName << "chit" << shaderNdx;
965 
966         programCollection.glslSources.add(shaderName.str())
967             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
968     }
969 
970     {
971         std::stringstream css;
972         css << "#version 460 core\n"
973                "#extension GL_EXT_ray_tracing : require\n"
974                "hitAttributeEXT uvec4 hitAttribute;\n"
975                "void main()\n"
976                "{\n"
977                "  hitAttribute = uvec4(0,0,0,0);\n"
978                "  reportIntersectionEXT(0.5f, 0);\n"
979                "}\n";
980 
981         programCollection.glslSources.add("isect")
982             << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
983     }
984 
985     {
986         std::stringstream css;
987         css << "#version 460 core\n"
988                "#extension GL_EXT_ray_tracing : require\n"
989                "layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
990                "void main()\n"
991                "{\n"
992                "  hitValue = uvec4(1,0,0,1);\n"
993                "}\n";
994 
995         programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
996     }
997 }
998 
createInstance(Context & context) const999 TestInstance *RayTracingCaptureReplayTestCase::createInstance(Context &context) const
1000 {
1001     return new RayTracingCaptureReplayTestInstance(context, m_data);
1002 }
1003 
RayTracingCaptureReplayTestInstance(Context & context,const TestParams & data)1004 RayTracingCaptureReplayTestInstance::RayTracingCaptureReplayTestInstance(Context &context, const TestParams &data)
1005     : vkt::TestInstance(context)
1006     , m_data(data)
1007 {
1008 }
1009 
~RayTracingCaptureReplayTestInstance(void)1010 RayTracingCaptureReplayTestInstance::~RayTracingCaptureReplayTestInstance(void)
1011 {
1012 }
1013 
runTest(bool replay)1014 std::vector<uint32_t> RayTracingCaptureReplayTestInstance::runTest(bool replay)
1015 {
1016     const auto &vki             = m_context.getInstanceInterface();
1017     const auto physicalDevice   = m_context.getPhysicalDevice();
1018     const auto &vkd             = m_context.getDeviceInterface();
1019     const auto device           = m_context.getDevice();
1020     auto allocator              = &m_context.getDefaultAllocator();
1021     const auto queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1022     const auto queue            = m_context.getUniversalQueue();
1023 
1024     // Create common pipeline layout for all raytracing pipelines
1025     const Move<VkDescriptorSetLayout> descriptorSetLayout =
1026         DescriptorSetLayoutBuilder()
1027             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ALL_RAY_TRACING_STAGES)
1028             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1029             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1030             .build(vkd, device);
1031     uint32_t pipelineCount =
1032         (!replay || (m_data.testType == TEST_PIPELINE_SINGLE) || (m_data.testType == TEST_ACCELERATION_STRUCTURES)) ?
1033             1u :
1034             2u;
1035     const Move<VkDescriptorPool> descriptorPool =
1036         DescriptorPoolBuilder()
1037             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pipelineCount)
1038             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, pipelineCount)
1039             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, pipelineCount)
1040             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, pipelineCount);
1041     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1042 
1043     // All pipelines will be using the same set of shaders and shader groups.
1044     // Single RayTracingPipeline object will be enough to define it
1045     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1046     m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, vkd, device, m_data, replay);
1047 
1048     // Capture phase ( replay==false ):
1049     // - TEST_ACCELERATION_STRUCTURES:
1050     //   - build/copy/compact/serialize structure, record addresses
1051     // - TEST_PIPELINE_SINGLE:
1052     // - TEST_PIPELINE_AFTER:
1053     // - TEST_PIPELINE_BEFORE:
1054     //   - single pipeline records addresses and fills test data
1055     // Replay phase ( replay==true ):
1056     // - TEST_ACCELERATION_STRUCTURES:
1057     //   - build/copy/compact/serialize structure with addresses captured previously
1058     // - TEST_PIPELINE_SINGLE:
1059     //   - single pipeline with addresses captured previously - writes into first image layer
1060     // - TEST_PIPELINE_AFTER:
1061     //   - first pipeline with addresses captured previously - writes into first image layer
1062     //   - second pipeline created without captured addresses - writes into second image layer
1063     // - TEST_PIPELINE_BEFORE:
1064     //   - first pipeline created without captured addresses - writes into first image layer
1065     //   - second pipeline with addresses captured previously - writes into second image layer
1066     //
1067     // Comparing results in all tests: all layers must be identical to the layer from capture phase
1068 
1069     PipelineData pipelineData(*allocator);
1070     pipelineData.pipelineLayout             = *pipelineLayout;
1071     pipelineData.descriptorSetLayout        = *descriptorSetLayout;
1072     pipelineData.descriptorPool             = *descriptorPool;
1073     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
1074     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1075     m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, vkd, device, m_data,
1076                                                       shaderGroupHandleSize, shaderGroupBaseAlignment, pipelineData,
1077                                                       replay);
1078 
1079     const VkFormat imageFormat = m_data.testConfiguration->getResultImageFormat();
1080     const VkImageCreateInfo imageCreateInfo =
1081         makeImageCreateInfo(m_data.width, m_data.height, pipelineCount, imageFormat);
1082     const VkImageSubresourceRange imageSubresourceRange =
1083         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1084     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1085         new ImageWithMemory(vkd, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
1086     const Move<VkImageView> imageView =
1087         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
1088     const VkDescriptorImageInfo descriptorImageInfo =
1089         makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1090 
1091     const uint32_t pixelCount                       = m_data.width * m_data.height * pipelineCount;
1092     const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(
1093         pixelCount * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1094     const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
1095         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1096     const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy(
1097         makeExtent3D(m_data.width, m_data.height, pipelineCount), resultBufferImageSubresourceLayers);
1098     de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
1099         new BufferWithMemory(vkd, device, *allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1100 
1101     const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1102     const Move<VkCommandBuffer> cmdBuffer =
1103         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1104 
1105     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
1106     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1107     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
1108     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
1109     std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
1110     std::vector<de::SharedPtr<SerialStorage>> topSerialized;
1111     Move<VkQueryPool> m_queryPoolCompact;
1112     Move<VkQueryPool> m_queryPoolSerial;
1113 
1114     beginCommandBuffer(vkd, *cmdBuffer, 0u);
1115     {
1116         const VkImageMemoryBarrier preImageBarrier =
1117             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1118                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
1119         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1120                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1121         const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
1122         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
1123                                &imageSubresourceRange);
1124         const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
1125             VK_ACCESS_TRANSFER_WRITE_BIT,
1126             VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1127             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
1128         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1129                                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1130 
1131         // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
1132         bool bottomCompact = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_COMPACT &&
1133                              m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1134         bool bottomSerial = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_SERIALIZE &&
1135                             m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1136         bottomLevelAccelerationStructures =
1137             m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1138         VkBuildAccelerationStructureFlagsKHR allowCompactionFlag =
1139             VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
1140         VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
1141         VkBuildAccelerationStructureFlagsKHR bottomBuildFlags =
1142             (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
1143         std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
1144         std::vector<VkDeviceSize> bottomBlasCompactSize;
1145         std::vector<VkDeviceSize> bottomBlasSerialSize;
1146 
1147         for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1148         {
1149             bottomLevelAccelerationStructures[idx]->setBuildFlags(bottomBuildFlags);
1150             bottomLevelAccelerationStructures[idx]->setBuildType(m_data.buildType);
1151             VkDeviceAddress deviceAddress =
1152                 (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay) ? buildBLASAddresses[idx] : 0u;
1153             if (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay)
1154                 bottomLevelAccelerationStructures[idx]->setCreateFlags(
1155                     VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1156             bottomLevelAccelerationStructures[idx]->createAndBuild(vkd, device, *cmdBuffer, *allocator, deviceAddress);
1157             accelerationStructureHandles.push_back(*(bottomLevelAccelerationStructures[idx]->getPtr()));
1158             if (m_data.testType == TEST_ACCELERATION_STRUCTURES && !replay)
1159                 buildBLASAddresses.push_back(getAccelerationStructureDeviceAddress(
1160                     vkd, device, *(bottomLevelAccelerationStructures[idx]->getPtr())));
1161         }
1162 
1163         if (m_data.operationType == OP_COMPACT)
1164         {
1165             uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
1166                                       uint32_t(bottomLevelAccelerationStructures.size()) :
1167                                       1u;
1168             if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1169                 m_queryPoolCompact =
1170                     makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
1171             if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1172                 queryAccelerationStructureSize(
1173                     vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
1174                     VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
1175         }
1176         if (m_data.operationType == OP_SERIALIZE)
1177         {
1178             uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
1179                                       uint32_t(bottomLevelAccelerationStructures.size()) :
1180                                       1u;
1181             if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1182                 m_queryPoolSerial =
1183                     makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
1184             if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1185                 queryAccelerationStructureSize(
1186                     vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
1187                     VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
1188         }
1189 
1190         // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1191         if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
1192         {
1193             endCommandBuffer(vkd, *cmdBuffer);
1194 
1195             submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1196 
1197             if (bottomCompact)
1198                 VK_CHECK(vkd.getQueryPoolResults(
1199                     device, *m_queryPoolCompact, 0u, uint32_t(bottomBlasCompactSize.size()),
1200                     sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(),
1201                     sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1202             if (bottomSerial)
1203                 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(bottomBlasSerialSize.size()),
1204                                                  sizeof(VkDeviceSize) * bottomBlasSerialSize.size(),
1205                                                  bottomBlasSerialSize.data(), sizeof(VkDeviceSize),
1206                                                  VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1207 
1208             vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1209             beginCommandBuffer(vkd, *cmdBuffer, 0u);
1210         }
1211 
1212         auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
1213         if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1214         {
1215             switch (m_data.operationType)
1216             {
1217             case OP_COPY:
1218             {
1219                 for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1220                 {
1221                     de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1222                     asCopy->setBuildType(m_data.buildType);
1223                     VkDeviceAddress deviceAddress = replay ? copyBLASAddresses[idx] : 0u;
1224                     if (replay)
1225                         asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1226                     asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator,
1227                                               bottomLevelAccelerationStructures[idx].get(), 0u, deviceAddress);
1228                     bottomLevelAccelerationStructureCopies.push_back(
1229                         de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1230                     if (!replay)
1231                         copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress(
1232                             vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr())));
1233                 }
1234                 break;
1235             }
1236             case OP_COMPACT:
1237             {
1238                 for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1239                 {
1240                     de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1241                     asCopy->setBuildType(m_data.buildType);
1242                     VkDeviceAddress deviceAddress = replay ? copyBLASAddresses[idx] : 0u;
1243                     if (replay)
1244                         asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1245                     asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator,
1246                                               bottomLevelAccelerationStructures[idx].get(), bottomBlasCompactSize[idx],
1247                                               deviceAddress);
1248                     bottomLevelAccelerationStructureCopies.push_back(
1249                         de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1250                     if (!replay)
1251                         copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress(
1252                             vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr())));
1253                 }
1254                 break;
1255             }
1256             case OP_SERIALIZE:
1257             {
1258                 for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1259                 {
1260                     de::SharedPtr<SerialStorage> storage(
1261                         new SerialStorage(vkd, device, *allocator, m_data.buildType, bottomBlasSerialSize[idx]));
1262                     bottomLevelAccelerationStructures[idx]->serialize(vkd, device, *cmdBuffer, storage.get());
1263                     bottomSerialized.push_back(storage);
1264 
1265                     if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1266                     {
1267                         endCommandBuffer(vkd, *cmdBuffer);
1268 
1269                         submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1270 
1271                         vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1272                         beginCommandBuffer(vkd, *cmdBuffer, 0u);
1273                     }
1274 
1275                     de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1276                     asCopy->setBuildType(m_data.buildType);
1277                     VkDeviceAddress deviceAddress = replay ? copyBLASAddresses[idx] : 0u;
1278                     if (replay)
1279                         asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1280                     asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, *allocator, storage.get(), deviceAddress);
1281                     bottomLevelAccelerationStructureCopies.push_back(
1282                         de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1283                     if (!replay)
1284                         copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress(
1285                             vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr())));
1286                 }
1287                 break;
1288             }
1289             default:
1290                 DE_ASSERT(false);
1291             }
1292             bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
1293         }
1294 
1295         // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
1296         bool topCompact = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_COMPACT &&
1297                           m_data.operationTarget == OT_TOP_ACCELERATION;
1298         bool topSerial = m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_SERIALIZE &&
1299                          m_data.operationTarget == OT_TOP_ACCELERATION;
1300         VkBuildAccelerationStructureFlagsKHR topBuildFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
1301         std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
1302         std::vector<VkDeviceSize> topBlasCompactSize;
1303         std::vector<VkDeviceSize> topBlasSerialSize;
1304 
1305         topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(
1306             m_context, m_data, *bottomLevelAccelerationStructuresPtr);
1307         topLevelAccelerationStructure->setBuildFlags(topBuildFlags);
1308         topLevelAccelerationStructure->setBuildType(m_data.buildType);
1309         VkDeviceAddress deviceAddressBuild =
1310             (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay) ? buildTLASAddress : 0u;
1311         if (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay)
1312             topLevelAccelerationStructure->setCreateFlags(
1313                 VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1314         topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, *allocator, deviceAddressBuild);
1315         topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr()));
1316         if (m_data.testType == TEST_ACCELERATION_STRUCTURES && !replay)
1317             buildTLASAddress =
1318                 getAccelerationStructureDeviceAddress(vkd, device, *(topLevelAccelerationStructure->getPtr()));
1319 
1320         if (topCompact)
1321             queryAccelerationStructureSize(
1322                 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
1323                 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
1324         if (topSerial)
1325             queryAccelerationStructureSize(
1326                 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
1327                 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
1328 
1329         // if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1330         if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
1331         {
1332             endCommandBuffer(vkd, *cmdBuffer);
1333 
1334             submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1335 
1336             if (topCompact)
1337                 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, uint32_t(topBlasCompactSize.size()),
1338                                                  sizeof(VkDeviceSize) * topBlasCompactSize.size(),
1339                                                  topBlasCompactSize.data(), sizeof(VkDeviceSize),
1340                                                  VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1341             if (topSerial)
1342                 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(topBlasSerialSize.size()),
1343                                                  sizeof(VkDeviceSize) * topBlasSerialSize.size(),
1344                                                  topBlasSerialSize.data(), sizeof(VkDeviceSize),
1345                                                  VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1346 
1347             vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1348             beginCommandBuffer(vkd, *cmdBuffer, 0u);
1349         }
1350 
1351         const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get();
1352         if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
1353         {
1354             switch (m_data.operationType)
1355             {
1356             case OP_COPY:
1357             {
1358                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1359                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1360                 VkDeviceAddress deviceAddress = replay ? copyTLASAddress : 0u;
1361                 if (replay)
1362                     topLevelAccelerationStructureCopy->setCreateFlags(
1363                         VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1364                 topLevelAccelerationStructureCopy->createAndCopyFrom(
1365                     vkd, device, *cmdBuffer, *allocator, topLevelAccelerationStructure.get(), 0u, deviceAddress);
1366                 if (!replay)
1367                     copyTLASAddress = getAccelerationStructureDeviceAddress(
1368                         vkd, device, *(topLevelAccelerationStructureCopy->getPtr()));
1369                 break;
1370             }
1371             case OP_COMPACT:
1372             {
1373                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1374                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1375                 VkDeviceAddress deviceAddress = replay ? copyTLASAddress : 0u;
1376                 if (replay)
1377                     topLevelAccelerationStructureCopy->setCreateFlags(
1378                         VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1379                 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator,
1380                                                                      topLevelAccelerationStructure.get(),
1381                                                                      topBlasCompactSize[0], deviceAddress);
1382                 if (!replay)
1383                     copyTLASAddress = getAccelerationStructureDeviceAddress(
1384                         vkd, device, *(topLevelAccelerationStructureCopy->getPtr()));
1385                 break;
1386             }
1387             case OP_SERIALIZE:
1388             {
1389                 de::SharedPtr<SerialStorage> storage(
1390                     new SerialStorage(vkd, device, *allocator, m_data.buildType, topBlasSerialSize[0]));
1391                 topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
1392                 topSerialized.push_back(storage);
1393 
1394                 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1395                 {
1396                     endCommandBuffer(vkd, *cmdBuffer);
1397 
1398                     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1399 
1400                     vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1401                     beginCommandBuffer(vkd, *cmdBuffer, 0u);
1402                 }
1403 
1404                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1405                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1406                 VkDeviceAddress deviceAddress = replay ? copyTLASAddress : 0u;
1407                 if (replay)
1408                     topLevelAccelerationStructureCopy->setCreateFlags(
1409                         VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1410                 topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, *allocator,
1411                                                                             storage.get(), deviceAddress);
1412                 if (!replay)
1413                     copyTLASAddress = getAccelerationStructureDeviceAddress(
1414                         vkd, device, *(topLevelAccelerationStructureCopy->getPtr()));
1415                 break;
1416             }
1417             default:
1418                 DE_ASSERT(false);
1419             }
1420             topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
1421         }
1422 
1423         // copy layer index into uniform buffer
1424         for (uint32_t i = 0; i < pipelineCount; ++i)
1425         {
1426             deMemcpy(pipelineData.pipelines[i].uniformBuffer->getAllocation().getHostPtr(), &i, sizeof(uint32_t));
1427             flushMappedMemoryRange(vkd, device, pipelineData.pipelines[i].uniformBuffer->getAllocation().getMemory(),
1428                                    pipelineData.pipelines[i].uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1429         }
1430 
1431         const VkMemoryBarrier preTraceMemoryBarrier =
1432             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
1433         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1434                                  VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier);
1435 
1436         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
1437             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
1438             DE_NULL,                                                           //  const void* pNext;
1439             1u,                                                                //  uint32_t accelerationStructureCount;
1440             topLevelRayTracedPtr->getPtr() //  const VkAccelerationStructureKHR* pAccelerationStructures;
1441         };
1442 
1443         for (uint32_t i = 0; i < pipelineCount; ++i)
1444         {
1445             VkDescriptorBufferInfo uniformBufferInfo =
1446                 makeDescriptorBufferInfo(pipelineData.pipelines[i].uniformBuffer->get(), 0ull, sizeof(uint32_t));
1447 
1448             DescriptorSetUpdateBuilder()
1449                 .writeSingle(*(pipelineData.pipelines[i].descriptorSet),
1450                              DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1451                              &uniformBufferInfo)
1452                 .writeSingle(*(pipelineData.pipelines[i].descriptorSet),
1453                              DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1454                              &descriptorImageInfo)
1455                 .writeSingle(*(pipelineData.pipelines[i].descriptorSet),
1456                              DescriptorSetUpdateBuilder::Location::binding(2u),
1457                              VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1458                 .update(vkd, device);
1459 
1460             vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
1461                                       &(pipelineData.pipelines[i].descriptorSet.get()), 0, DE_NULL);
1462 
1463             vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
1464                                 *(pipelineData.pipelines[i].pipeline));
1465 
1466             cmdTraceRays(vkd, *cmdBuffer, &(pipelineData.pipelines[i].raygenShaderBindingTableRegion),
1467                          &(pipelineData.pipelines[i].missShaderBindingTableRegion),
1468                          &(pipelineData.pipelines[i].hitShaderBindingTableRegion),
1469                          &(pipelineData.pipelines[i].callableShaderBindingTableRegion), m_data.width, m_data.height, 1);
1470         }
1471 
1472         const VkMemoryBarrier postTraceMemoryBarrier =
1473             makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1474         const VkMemoryBarrier postCopyMemoryBarrier =
1475             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1476         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
1477                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1478 
1479         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
1480                                  &resultBufferImageRegion);
1481 
1482         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1483                                  &postCopyMemoryBarrier);
1484     }
1485     endCommandBuffer(vkd, *cmdBuffer);
1486 
1487     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1488 
1489     invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
1490                                 resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(uint32_t));
1491 
1492     std::vector<uint32_t> result(pixelCount);
1493     deMemcpy(result.data(), resultBuffer->getAllocation().getHostPtr(), pixelCount * sizeof(uint32_t));
1494     return result;
1495 }
1496 
iterate(void)1497 tcu::TestStatus RayTracingCaptureReplayTestInstance::iterate(void)
1498 {
1499     // run test capturing different elements
1500     const std::vector<uint32_t> captureResults = runTest(false);
1501 
1502     // run test that replays different elements
1503     const std::vector<uint32_t> replayResults = runTest(true);
1504 
1505     if (!m_data.testConfiguration->verifyImage(captureResults, replayResults, m_context, m_data))
1506         return tcu::TestStatus::fail("Fail");
1507     return tcu::TestStatus::pass("Pass");
1508 }
1509 
1510 } // namespace
1511 
addReplayShaderBindingTablesTests(tcu::TestCaseGroup * group)1512 void addReplayShaderBindingTablesTests(tcu::TestCaseGroup *group)
1513 {
1514     struct
1515     {
1516         SBTReplayTestType testType;
1517         const char *name;
1518     } testTypes[] = {
1519         // Capture-replay scenario with single captured pipeline
1520         {TEST_PIPELINE_SINGLE, "pipeline_single"},
1521         // Not captured pipeline created after captured one
1522         {TEST_PIPELINE_AFTER, "pipeline_after_captured"},
1523         // Not captured pipeline created before captured one
1524         {TEST_PIPELINE_BEFORE, "pipeline_before_captured"},
1525     };
1526 
1527     for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1528     {
1529         TestParams testParams{testTypes[testTypeNdx].testType,
1530                               OT_NONE,
1531                               OP_NONE,
1532                               VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
1533                               BTT_TRIANGLES,
1534                               TTT_IDENTICAL_INSTANCES,
1535                               RTCR_DEFAULT_SIZE,
1536                               RTCR_DEFAULT_SIZE,
1537                               de::SharedPtr<TestConfiguration>(new TestShaderBindingTablesConfiguration())};
1538         group->addChild(
1539             new RayTracingCaptureReplayTestCase(group->getTestContext(), testTypes[testTypeNdx].name, testParams));
1540     }
1541 }
1542 
addReplayAccelerationStruturesTests(tcu::TestCaseGroup * group)1543 void addReplayAccelerationStruturesTests(tcu::TestCaseGroup *group)
1544 {
1545     struct
1546     {
1547         ASOperationType operationType;
1548         const char *name;
1549     } operationTypes[] = {
1550         {OP_NONE, "building"},
1551         {OP_COPY, "copy"},
1552         {OP_COMPACT, "compaction"},
1553         {OP_SERIALIZE, "serialization"},
1554     };
1555 
1556     struct
1557     {
1558         vk::VkAccelerationStructureBuildTypeKHR buildType;
1559         const char *name;
1560     } buildTypes[] = {
1561         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
1562         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
1563     };
1564 
1565     struct
1566     {
1567         ASOperationTarget operationTarget;
1568         const char *name;
1569     } operationTargets[] = {
1570         {OT_TOP_ACCELERATION, "top_acceleration_structure"},
1571         {OT_BOTTOM_ACCELERATION, "bottom_acceleration_structure"},
1572     };
1573 
1574     struct
1575     {
1576         ASBottomTestType testType;
1577         const char *name;
1578     } bottomTestTypes[] = {
1579         {BTT_TRIANGLES, "triangles"},
1580         {BTT_AABBS, "aabbs"},
1581     };
1582 
1583     for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
1584     {
1585         de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(
1586             new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name));
1587 
1588         for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
1589         {
1590             de::MovePtr<tcu::TestCaseGroup> buildGroup(
1591                 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
1592 
1593             for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets);
1594                  ++operationTargetNdx)
1595             {
1596                 de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(
1597                     new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name));
1598 
1599                 for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
1600                 {
1601                     ASTopTestType topTest =
1602                         (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ?
1603                             TTT_DIFFERENT_INSTANCES :
1604                             TTT_IDENTICAL_INSTANCES;
1605 
1606                     TestParams testParams{
1607                         TEST_ACCELERATION_STRUCTURES,
1608                         operationTargets[operationTargetNdx].operationTarget,
1609                         operationTypes[operationTypeNdx].operationType,
1610                         buildTypes[buildTypeNdx].buildType,
1611                         bottomTestTypes[testTypeNdx].testType,
1612                         topTest,
1613                         RTCR_DEFAULT_SIZE,
1614                         RTCR_DEFAULT_SIZE,
1615                         de::SharedPtr<TestConfiguration>(new TestAccelerationStructuresConfiguration())};
1616                     operationTargetGroup->addChild(new RayTracingCaptureReplayTestCase(
1617                         group->getTestContext(), bottomTestTypes[testTypeNdx].name, testParams));
1618                 }
1619                 buildGroup->addChild(operationTargetGroup.release());
1620             }
1621             operationTypeGroup->addChild(buildGroup.release());
1622         }
1623         group->addChild(operationTypeGroup.release());
1624     }
1625 }
1626 
createCaptureReplayTests(tcu::TestContext & testCtx)1627 tcu::TestCaseGroup *createCaptureReplayTests(tcu::TestContext &testCtx)
1628 {
1629     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "capture_replay"));
1630 
1631     // Test replaying shader binding tables
1632     addTestGroup(group.get(), "shader_binding_tables", addReplayShaderBindingTablesTests);
1633     // Test replaying acceleration structure
1634     addTestGroup(group.get(), "acceleration_structures", addReplayAccelerationStruturesTests);
1635 
1636     return group.release();
1637 }
1638 
1639 } // namespace RayTracing
1640 
1641 } // namespace vkt
1642