• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Acceleration Structures tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingAccelerationStructuresTests.hpp"
25 
26 #include "vkDefs.hpp"
27 #include "deClock.h"
28 #include "deRandom.h"
29 
30 #include "vktTestCase.hpp"
31 #include "vktTestGroupUtil.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 #include "vkImageUtil.hpp"
40 #include "vkRayTracingUtil.hpp"
41 #include "tcuVectorUtil.hpp"
42 #include "tcuTexture.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuFloat.hpp"
46 #include "deModularCounter.hpp"
47 
48 #include <cmath>
49 #include <cstddef>
50 #include <set>
51 #include <limits>
52 #include <iostream>
53 
54 namespace vkt
55 {
56 namespace RayTracing
57 {
58 namespace
59 {
60 using namespace vk;
61 using namespace vkt;
62 using namespace tcu;
63 
64 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
65                                               VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
66                                               VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
67 
68 enum class BottomTestType
69 {
70     TRIANGLES = 0,
71     AABBS     = 1,
72 };
73 
74 enum class TopTestType
75 {
76     IDENTICAL_INSTANCES,
77     DIFFERENT_INSTANCES,
78     UPDATED_INSTANCES,
79     MIX_INSTANCES,
80 };
81 
82 enum OperationTarget
83 {
84     OT_NONE,
85     OT_TOP_ACCELERATION,
86     OT_BOTTOM_ACCELERATION
87 };
88 
89 enum OperationType
90 {
91     OP_NONE,
92     OP_COPY,
93     OP_COMPACT,
94     OP_SERIALIZE,
95     OP_UPDATE,
96     OP_UPDATE_IN_PLACE
97 };
98 
99 enum class InstanceCullFlags
100 {
101     NONE,
102     CULL_DISABLE,
103     COUNTERCLOCKWISE,
104     ALL,
105 };
106 
107 enum class EmptyAccelerationStructureCase
108 {
109     NOT_EMPTY            = 0,
110     INACTIVE_TRIANGLES   = 1,
111     INACTIVE_INSTANCES   = 2,
112     NO_GEOMETRIES_BOTTOM = 3, // geometryCount zero when building.
113     NO_PRIMITIVES_BOTTOM = 4, // primitiveCount zero when building.
114     NO_PRIMITIVES_TOP    = 5, // primitiveCount zero when building.
115 };
116 
117 enum class InstanceCustomIndexCase
118 {
119     NONE         = 0,
120     CLOSEST_HIT  = 1,
121     ANY_HIT      = 2,
122     INTERSECTION = 3,
123 };
124 
125 enum class UpdateCase
126 {
127     NONE,
128     VERTICES,
129     INDICES,
130     TRANSFORM
131 };
132 
133 static const uint32_t RTAS_DEFAULT_SIZE = 8u;
134 
135 // Chosen to have the most significant bit set to 1 when represented using 24 bits.
136 // This will make sure the instance custom index will not be sign-extended by mistake.
137 constexpr uint32_t INSTANCE_CUSTOM_INDEX_BASE = 0x807f00u;
138 
139 struct TestParams;
140 
141 class TestConfiguration
142 {
143 public:
~TestConfiguration()144     virtual ~TestConfiguration()
145     {
146     }
147 
148     virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
149         Context &context, TestParams &testParams) = 0;
150     virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
151         Context &context, TestParams &testParams,
152         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) = 0;
153     virtual void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
154                                        TestParams &testParams)                                           = 0;
155     virtual void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
156                                          TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
157                                          uint32_t shaderGroupBaseAlignment,
158                                          de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
159                                          de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
160                                          de::MovePtr<BufferWithMemory> &missShaderBindingTable)          = 0;
161     virtual bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)   = 0;
162     virtual VkFormat getResultImageFormat()                                                              = 0;
163     virtual size_t getResultImageFormatSize()                                                            = 0;
164     virtual VkClearValue getClearValue()                                                                 = 0;
165 };
166 
167 struct TestParams
168 {
169     vk::VkAccelerationStructureBuildTypeKHR buildType; // are we making AS on CPU or GPU
170     VkFormat vertexFormat;
171     bool padVertices;
172     VkIndexType indexType;
173     BottomTestType bottomTestType; // what kind of geometry is stored in bottom AS
174     InstanceCullFlags cullFlags;   // Flags for instances, if needed.
175     bool bottomUsesAOP;            // does bottom AS use arrays, or arrays of pointers
176     bool bottomGeneric;            // Bottom created as generic AS type.
177     bool bottomUnboundedCreation;  // Bottom created with unbounded buffer memory.
178     TopTestType topTestType;   // If instances are identical then bottom geometries must have different vertices/aabbs
179     bool topUsesAOP;           // does top AS use arrays, or arrays of pointers
180     bool topGeneric;           // Top created as generic AS type.
181     bool topUnboundedCreation; // Top created with unbounded buffer memory.
182     VkBuildAccelerationStructureFlagsKHR buildFlags;
183     OperationTarget operationTarget;
184     OperationType operationType;
185     uint32_t width;
186     uint32_t height;
187     de::SharedPtr<TestConfiguration> testConfiguration;
188     uint32_t workerThreadsCount;
189     EmptyAccelerationStructureCase emptyASCase;
190     InstanceCustomIndexCase instanceCustomIndexCase;
191     bool useCullMask;
192     uint32_t cullMask;
193     UpdateCase updateCase;
194 };
195 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)196 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
197 {
198     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
199 
200     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
201     return rayTracingPropertiesKHR->getShaderGroupHandleSize();
202 }
203 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)204 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
205 {
206     de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
207 
208     rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
209     return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
210 }
211 
makeImageCreateInfo(uint32_t width,uint32_t height,VkFormat format)212 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, VkFormat format)
213 {
214     const VkImageCreateInfo imageCreateInfo = {
215         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
216         nullptr,                             // const void* pNext;
217         (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
218         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
219         format,                              // VkFormat format;
220         makeExtent3D(width, height, 1u),     // VkExtent3D extent;
221         1u,                                  // uint32_t mipLevels;
222         1u,                                  // uint32_t arrayLayers;
223         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
224         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
225         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
226             VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
227         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
228         0u,                                  // uint32_t queueFamilyIndexCount;
229         nullptr,                             // const uint32_t* pQueueFamilyIndices;
230         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
231     };
232 
233     return imageCreateInfo;
234 }
235 
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,uint32_t queryCount)236 Move<VkQueryPool> makeQueryPool(const DeviceInterface &vk, const VkDevice device, const VkQueryType queryType,
237                                 uint32_t queryCount)
238 {
239     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
240         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
241         nullptr,                                  // pNext
242         (VkQueryPoolCreateFlags)0,                // flags
243         queryType,                                // queryType
244         queryCount,                               // queryCount
245         0u,                                       // pipelineStatistics
246     };
247     return createQueryPool(vk, device, &queryPoolCreateInfo);
248 }
249 
getCullFlags(InstanceCullFlags flags)250 VkGeometryInstanceFlagsKHR getCullFlags(InstanceCullFlags flags)
251 {
252     VkGeometryInstanceFlagsKHR cullFlags = 0u;
253 
254     if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
255         cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
256 
257     if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
258         cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
259 
260     return cullFlags;
261 }
262 
263 class CheckerboardConfiguration : public TestConfiguration
264 {
265 public:
266     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
267         Context &context, TestParams &testParams) override;
268     de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
269         Context &context, TestParams &testParams,
270         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
271     void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
272                                TestParams &testParams) override;
273     void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
274                                  TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
275                                  uint32_t shaderGroupBaseAlignment,
276                                  de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
277                                  de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
278                                  de::MovePtr<BufferWithMemory> &missShaderBindingTable) override;
279     bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
280     VkFormat getResultImageFormat() override;
281     size_t getResultImageFormatSize() override;
282     VkClearValue getClearValue() override;
283 };
284 
285 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> CheckerboardConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)286     initBottomAccelerationStructures(Context &context, TestParams &testParams)
287 {
288     DE_UNREF(context);
289 
290     // Cull flags can only be used with triangles.
291     DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE ||
292               testParams.bottomTestType == BottomTestType::TRIANGLES);
293 
294     // Checkerboard configuration does not support empty geometry tests.
295     DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
296 
297     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
298 
299     const auto instanceFlags = getCullFlags(testParams.cullFlags);
300 
301     tcu::Vec3 v0(0.0, 1.0, 0.0);
302     tcu::Vec3 v1(0.0, 0.0, 0.0);
303     tcu::Vec3 v2(1.0, 1.0, 0.0);
304     tcu::Vec3 v3(1.0, 0.0, 0.0);
305 
306     if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
307     {
308         de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
309             makeBottomLevelAccelerationStructure();
310         bottomLevelAccelerationStructure->setGeometryCount(1u);
311         de::SharedPtr<RaytracedGeometryBase> geometry;
312         if (testParams.bottomTestType == BottomTestType::TRIANGLES)
313         {
314             geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat,
315                                              testParams.indexType, testParams.padVertices);
316             if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
317             {
318                 if (instanceFlags == 0u)
319                 {
320                     geometry->addVertex(v0);
321                     geometry->addVertex(v1);
322                     geometry->addVertex(v2);
323                     geometry->addVertex(v2);
324                     geometry->addVertex(v1);
325                     geometry->addVertex(v3);
326                 }
327                 else // Counterclockwise so the flags will be needed for the geometry to be visible.
328                 {
329                     geometry->addVertex(v2);
330                     geometry->addVertex(v1);
331                     geometry->addVertex(v0);
332                     geometry->addVertex(v3);
333                     geometry->addVertex(v1);
334                     geometry->addVertex(v2);
335                 }
336             }
337             else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
338             {
339                 geometry->addVertex(v0);
340                 geometry->addVertex(v1);
341                 geometry->addVertex(v2);
342                 geometry->addVertex(v3);
343 
344                 if (instanceFlags == 0u)
345                 {
346                     geometry->addIndex(0);
347                     geometry->addIndex(1);
348                     geometry->addIndex(2);
349                     geometry->addIndex(2);
350                     geometry->addIndex(1);
351                     geometry->addIndex(3);
352                 }
353                 else // Counterclockwise so the flags will be needed for the geometry to be visible.
354                 {
355                     geometry->addIndex(2);
356                     geometry->addIndex(1);
357                     geometry->addIndex(0);
358                     geometry->addIndex(3);
359                     geometry->addIndex(1);
360                     geometry->addIndex(2);
361                 }
362             }
363         }
364         else // m_data.bottomTestType == BTT_AABBS
365         {
366             geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType,
367                                              testParams.padVertices);
368 
369             if (!testParams.padVertices)
370             {
371                 // Single AABB.
372                 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
373                 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
374             }
375             else
376             {
377                 // Multiple AABBs covering the same space.
378                 geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
379                 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, 0.1f));
380 
381                 geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
382                 geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
383 
384                 geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
385                 geometry->addVertex(tcu::Vec3(0.5f, 1.0f, 0.1f));
386 
387                 geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
388                 geometry->addVertex(tcu::Vec3(1.0f, 0.5f, 0.1f));
389             }
390         }
391 
392         bottomLevelAccelerationStructure->addGeometry(geometry);
393 
394         if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
395             geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
396 
397         result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
398     }
399     else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
400     {
401         // triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
402         for (uint32_t y = 0; y < testParams.height; ++y)
403             for (uint32_t x = 0; x < testParams.width; ++x)
404             {
405                 // let's build a chessboard of geometries
406                 if (((x + y) % 2) == 0)
407                     continue;
408                 tcu::Vec3 xyz((float)x, (float)y, 0.0f);
409 
410                 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
411                     makeBottomLevelAccelerationStructure();
412                 bottomLevelAccelerationStructure->setGeometryCount(1u);
413 
414                 de::SharedPtr<RaytracedGeometryBase> geometry;
415                 if (testParams.bottomTestType == BottomTestType::TRIANGLES)
416                 {
417                     geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat,
418                                                      testParams.indexType, testParams.padVertices);
419                     if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
420                     {
421                         if (instanceFlags == 0u)
422                         {
423                             geometry->addVertex(xyz + v0);
424                             geometry->addVertex(xyz + v1);
425                             geometry->addVertex(xyz + v2);
426                             geometry->addVertex(xyz + v2);
427                             geometry->addVertex(xyz + v1);
428                             geometry->addVertex(xyz + v3);
429                         }
430                         else // Counterclockwise so the flags will be needed for the geometry to be visible.
431                         {
432                             geometry->addVertex(xyz + v2);
433                             geometry->addVertex(xyz + v1);
434                             geometry->addVertex(xyz + v0);
435                             geometry->addVertex(xyz + v3);
436                             geometry->addVertex(xyz + v1);
437                             geometry->addVertex(xyz + v2);
438                         }
439                     }
440                     else
441                     {
442                         geometry->addVertex(xyz + v0);
443                         geometry->addVertex(xyz + v1);
444                         geometry->addVertex(xyz + v2);
445                         geometry->addVertex(xyz + v3);
446 
447                         if (instanceFlags == 0u)
448                         {
449                             geometry->addIndex(0);
450                             geometry->addIndex(1);
451                             geometry->addIndex(2);
452                             geometry->addIndex(2);
453                             geometry->addIndex(1);
454                             geometry->addIndex(3);
455                         }
456                         else // Counterclockwise so the flags will be needed for the geometry to be visible.
457                         {
458                             geometry->addIndex(2);
459                             geometry->addIndex(1);
460                             geometry->addIndex(0);
461                             geometry->addIndex(3);
462                             geometry->addIndex(1);
463                             geometry->addIndex(2);
464                         }
465                     }
466                 }
467                 else // testParams.bottomTestType == BTT_AABBS
468                 {
469                     geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat,
470                                                      testParams.indexType, testParams.padVertices);
471 
472                     if (!testParams.padVertices)
473                     {
474                         // Single AABB.
475                         geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
476                         geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
477                     }
478                     else
479                     {
480                         // Multiple AABBs covering the same space.
481                         geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
482                         geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, 0.1f));
483 
484                         geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, -0.1f));
485                         geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
486 
487                         geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.5f, -0.1f));
488                         geometry->addVertex(xyz + tcu::Vec3(0.5f, 1.0f, 0.1f));
489 
490                         geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.0f, -0.1f));
491                         geometry->addVertex(xyz + tcu::Vec3(1.0f, 0.5f, 0.1f));
492                     }
493                 }
494 
495                 bottomLevelAccelerationStructure->addGeometry(geometry);
496 
497                 if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
498                     geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
499 
500                 result.push_back(
501                     de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
502             }
503     }
504 
505     return result;
506 }
507 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)508 de::MovePtr<TopLevelAccelerationStructure> CheckerboardConfiguration::initTopAccelerationStructure(
509     Context &context, TestParams &testParams,
510     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
511 {
512     // Checkerboard configuration does not support empty geometry tests.
513     DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
514 
515     DE_UNREF(context);
516 
517     const auto instanceCount = testParams.width * testParams.height / 2u;
518     const auto instanceFlags = getCullFlags(testParams.cullFlags);
519 
520     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
521     result->setInstanceCount(instanceCount);
522 
523     if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
524     {
525 
526         for (uint32_t y = 0; y < testParams.height; ++y)
527             for (uint32_t x = 0; x < testParams.width; ++x)
528             {
529                 if (((x + y) % 2) == 0)
530                     continue;
531                 const VkTransformMatrixKHR transformMatrixKHR = {{
532                     //  float matrix[3][4];
533                     {1.0f, 0.0f, 0.0f, (float)x},
534                     {0.0f, 1.0f, 0.0f, (float)y},
535                     {0.0f, 0.0f, 1.0f, 0.0f},
536                 }};
537                 const uint32_t instanceCustomIndex =
538                     ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ?
539                          (INSTANCE_CUSTOM_INDEX_BASE + x + y) :
540                          0u);
541                 result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, instanceCustomIndex,
542                                     0xFFu, 0u, instanceFlags);
543             }
544     }
545     else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
546     {
547         uint32_t currentInstanceIndex = 0;
548 
549         for (uint32_t y = 0; y < testParams.height; ++y)
550             for (uint32_t x = 0; x < testParams.width; ++x)
551             {
552                 if (((x + y) % 2) == 0)
553                     continue;
554                 const uint32_t instanceCustomIndex =
555                     ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ?
556                          (INSTANCE_CUSTOM_INDEX_BASE + x + y) :
557                          0u);
558 
559                 if (testParams.useCullMask)
560                 {
561                     result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix3x4,
562                                         instanceCustomIndex, testParams.cullMask, 0u, instanceFlags);
563                 }
564                 else
565                 {
566                     result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix3x4,
567                                         instanceCustomIndex, 0xFFu, 0u, instanceFlags);
568                 }
569             }
570     }
571 
572     return result;
573 }
574 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)575 void CheckerboardConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
576                                                       Context &context, TestParams &testParams)
577 {
578     DE_UNREF(testParams);
579     const DeviceInterface &vkd = context.getDeviceInterface();
580     const VkDevice device      = context.getDevice();
581 
582     const bool useAnyHit      = (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT);
583     const auto hitShaderStage = (useAnyHit ? VK_SHADER_STAGE_ANY_HIT_BIT_KHR : VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
584     const auto hitShaderName  = (useAnyHit ? "ahit" : "chit");
585 
586     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
587                                   createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
588     rayTracingPipeline->addShader(
589         hitShaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName), 0), 1);
590     rayTracingPipeline->addShader(
591         hitShaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName), 0), 2);
592     if (testParams.bottomTestType == BottomTestType::AABBS)
593         rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
594                                       createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0),
595                                       2);
596     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
597                                   createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 3);
598 }
599 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)600 void CheckerboardConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
601                                                         Context &context, TestParams &testParams, VkPipeline pipeline,
602                                                         uint32_t shaderGroupHandleSize,
603                                                         uint32_t shaderGroupBaseAlignment,
604                                                         de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
605                                                         de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
606                                                         de::MovePtr<BufferWithMemory> &missShaderBindingTable)
607 {
608     const DeviceInterface &vkd = context.getDeviceInterface();
609     const VkDevice device      = context.getDevice();
610     Allocator &allocator       = context.getDefaultAllocator();
611 
612     raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
613         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
614     if (testParams.bottomTestType == BottomTestType::AABBS)
615         hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
616             vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
617     else // testParams.bottomTestType == BTT_TRIANGLES
618         hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
619             vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
620     missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
621         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1);
622 }
623 
bitfieldReverse(uint32_t num)624 uint32_t bitfieldReverse(uint32_t num)
625 {
626     uint32_t reverse_num = 0;
627     uint32_t i;
628     for (i = 0; i < 32; i++)
629     {
630         if ((num & (1 << i)))
631             reverse_num |= 1 << ((32 - 1) - i);
632     }
633     return reverse_num;
634 }
635 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)636 bool CheckerboardConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
637 {
638     // Checkerboard configuration does not support empty geometry tests.
639     DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
640 
641     DE_UNREF(context);
642     const auto *bufferPtr = (int32_t *)resultBuffer->getAllocation().getHostPtr();
643     uint32_t pos          = 0;
644     uint32_t failures     = 0;
645 
646     // verify results - each test case should generate checkerboard pattern
647     for (uint32_t y = 0; y < testParams.height; ++y)
648         for (uint32_t x = 0; x < testParams.width; ++x)
649         {
650             // The hit value should match the shader code.
651             if (testParams.useCullMask)
652             {
653                 const int32_t hitValue = testParams.cullMask & 0x000000FFu; // only 8 last bits are used by the cullMask
654                 const int32_t expectedResult =
655                     ((x + y) % 2) ? hitValue : bitfieldReverse(testParams.cullMask & 0x000000FFu);
656 
657                 if (bufferPtr[pos] != expectedResult)
658                     failures++;
659             }
660             else
661             {
662                 const int32_t hitValue       = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ?
663                                                     static_cast<int32_t>(INSTANCE_CUSTOM_INDEX_BASE + x + y) :
664                                                     2);
665                 const int32_t expectedResult = ((x + y) % 2) ? hitValue : 1;
666 
667                 if (bufferPtr[pos] != expectedResult)
668                     failures++;
669             }
670 
671             ++pos;
672         }
673     return failures == 0;
674 }
675 
getResultImageFormat()676 VkFormat CheckerboardConfiguration::getResultImageFormat()
677 {
678     return VK_FORMAT_R32_SINT;
679 }
680 
getResultImageFormatSize()681 size_t CheckerboardConfiguration::getResultImageFormatSize()
682 {
683     return sizeof(uint32_t);
684 }
685 
getClearValue()686 VkClearValue CheckerboardConfiguration::getClearValue()
687 {
688     return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
689 }
690 
691 class SingleTriangleConfiguration : public TestConfiguration
692 {
693 public:
694     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
695         Context &context, TestParams &testParams) override;
696     de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
697         Context &context, TestParams &testParams,
698         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
699     void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
700                                TestParams &testParams) override;
701     void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
702                                  TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
703                                  uint32_t shaderGroupBaseAlignment,
704                                  de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
705                                  de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
706                                  de::MovePtr<BufferWithMemory> &missShaderBindingTable) override;
707     bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
708     VkFormat getResultImageFormat() override;
709     size_t getResultImageFormatSize() override;
710     VkClearValue getClearValue() override;
711 
712     // well, actually we have 2 triangles, but we ignore the first one ( see raygen shader for this configuration )
713     const std::vector<tcu::Vec3> vertices = {
714         tcu::Vec3(0.0f, 0.0f, -0.1f), tcu::Vec3(-0.1f, 0.0f, 0.0f), tcu::Vec3(0.0f, -0.1f, 0.0f),
715         tcu::Vec3(0.0f, 0.0f, 0.0f),  tcu::Vec3(0.5f, 0.0f, -0.5f), tcu::Vec3(0.0f, 0.5f, -0.5f),
716     };
717 
718     const std::vector<uint32_t> indices = {3, 4, 5};
719     // Different vertex configurations of a triangle whose parameter x is set to NaN during inactive_triangles tests
720     const bool nanConfig[7][3] = {
721         {true, true, true},  {true, false, false}, {false, true, false}, {false, false, true},
722         {true, true, false}, {false, true, true},  {true, false, true},
723     };
724 };
725 
726 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> SingleTriangleConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)727     initBottomAccelerationStructures(Context &context, TestParams &testParams)
728 {
729     DE_UNREF(context);
730 
731     // No other cases supported for the single triangle configuration.
732     DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
733 
734     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
735 
736     de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
737         makeBottomLevelAccelerationStructure();
738 
739     unsigned int geometryCount = testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES ? 4U : 1U;
740 
741     if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
742     {
743         bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
744 
745         de::SharedPtr<RaytracedGeometryBase> geometry;
746         geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
747 
748         for (unsigned int i = 0; i < geometryCount; i++)
749         {
750             auto customVertices(vertices);
751 
752             const auto nanValue = tcu::Float32::nan().asFloat();
753 
754             if (nanConfig[i][0])
755                 customVertices[3].x() = nanValue;
756             if (nanConfig[i][1])
757                 customVertices[4].x() = nanValue;
758             if (nanConfig[i][2])
759                 customVertices[5].x() = nanValue;
760 
761             for (auto it = begin(customVertices), eit = end(customVertices); it != eit; ++it)
762                 geometry->addVertex(*it);
763 
764             if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
765             {
766                 for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
767                     geometry->addIndex(*it);
768             }
769             bottomLevelAccelerationStructure->addGeometry(geometry);
770         }
771     }
772     else
773     {
774         bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
775 
776         de::SharedPtr<RaytracedGeometryBase> geometry;
777         geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
778 
779         for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
780             geometry->addVertex(*it);
781 
782         if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
783         {
784             for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
785                 geometry->addIndex(*it);
786         }
787         bottomLevelAccelerationStructure->addGeometry(geometry);
788     }
789 
790     result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
791 
792     return result;
793 }
794 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)795 de::MovePtr<TopLevelAccelerationStructure> SingleTriangleConfiguration::initTopAccelerationStructure(
796     Context &context, TestParams &testParams,
797     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
798 {
799     DE_UNREF(context);
800     DE_UNREF(testParams);
801 
802     // Unsupported in this configuration.
803     DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
804 
805     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
806     result->setInstanceCount(1u);
807 
808     result->addInstance(bottomLevelAccelerationStructures[0]);
809 
810     return result;
811 }
812 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)813 void SingleTriangleConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
814                                                         Context &context, TestParams &testParams)
815 {
816     DE_UNREF(testParams);
817     const DeviceInterface &vkd = context.getDeviceInterface();
818     const VkDevice device      = context.getDevice();
819 
820     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
821                                   createShaderModule(vkd, device, context.getBinaryCollection().get("rgen_depth"), 0),
822                                   0);
823     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
824                                   createShaderModule(vkd, device, context.getBinaryCollection().get("chit_depth"), 0),
825                                   1);
826     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
827                                   createShaderModule(vkd, device, context.getBinaryCollection().get("miss_depth"), 0),
828                                   2);
829 }
830 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)831 void SingleTriangleConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
832                                                           Context &context, TestParams &testParams, VkPipeline pipeline,
833                                                           uint32_t shaderGroupHandleSize,
834                                                           uint32_t shaderGroupBaseAlignment,
835                                                           de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
836                                                           de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
837                                                           de::MovePtr<BufferWithMemory> &missShaderBindingTable)
838 {
839     DE_UNREF(testParams);
840     const DeviceInterface &vkd = context.getDeviceInterface();
841     const VkDevice device      = context.getDevice();
842     Allocator &allocator       = context.getDefaultAllocator();
843 
844     raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
845         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
846     hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
847         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
848     missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
849         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
850 }
851 
pointInTriangle2D(const tcu::Vec3 & p,const tcu::Vec3 & p0,const tcu::Vec3 & p1,const tcu::Vec3 & p2)852 bool pointInTriangle2D(const tcu::Vec3 &p, const tcu::Vec3 &p0, const tcu::Vec3 &p1, const tcu::Vec3 &p2)
853 {
854     float s = p0.y() * p2.x() - p0.x() * p2.y() + (p2.y() - p0.y()) * p.x() + (p0.x() - p2.x()) * p.y();
855     float t = p0.x() * p1.y() - p0.y() * p1.x() + (p0.y() - p1.y()) * p.x() + (p1.x() - p0.x()) * p.y();
856 
857     if ((s < 0) != (t < 0))
858         return false;
859 
860     float a = -p1.y() * p2.x() + p0.y() * (p2.x() - p1.x()) + p0.x() * (p1.y() - p2.y()) + p1.x() * p2.y();
861 
862     return a < 0 ? (s <= 0 && s + t >= a) : (s >= 0 && s + t <= a);
863 }
864 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)865 bool SingleTriangleConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
866 {
867     tcu::TextureFormat imageFormat  = vk::mapVkFormat(getResultImageFormat());
868     tcu::TextureFormat vertexFormat = vk::mapVkFormat(testParams.vertexFormat);
869     tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 1,
870                                              resultBuffer->getAllocation().getHostPtr());
871 
872     std::vector<float> reference(testParams.width * testParams.height);
873     tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 1, reference.data());
874 
875     // verify results
876     tcu::Vec3 v0          = vertices[3];
877     tcu::Vec3 v1          = vertices[4];
878     tcu::Vec3 v2          = vertices[5];
879     const int numChannels = tcu::getNumUsedChannels(vertexFormat.order);
880     if (numChannels < 3)
881     {
882         v0.z() = 0.0f;
883         v1.z() = 0.0f;
884         v2.z() = 0.0f;
885     }
886     tcu::Vec3 abc = tcu::cross((v2 - v0), (v1 - v0));
887 
888     for (uint32_t j = 0; j < testParams.height; ++j)
889     {
890         float y = 0.1f + 0.2f * float(j) / float(testParams.height - 1);
891         for (uint32_t i = 0; i < testParams.width; ++i)
892         {
893             float x         = 0.1f + 0.2f * float(i) / float(testParams.width - 1);
894             float z         = (abc.x() * x + abc.y() * y) / abc.z();
895             bool inTriangle = pointInTriangle2D(tcu::Vec3(x, y, z), v0, v1, v2);
896             float refValue =
897                 ((inTriangle && testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY) ? 1.0f + z : 0.0f);
898             referenceAccess.setPixel(tcu::Vec4(refValue, 0.0f, 0.0f, 1.0f), i, j);
899         }
900     }
901     return tcu::floatThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
902                                       resultAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
903 }
904 
getResultImageFormat()905 VkFormat SingleTriangleConfiguration::getResultImageFormat()
906 {
907     return VK_FORMAT_R32_SFLOAT;
908 }
909 
getResultImageFormatSize()910 size_t SingleTriangleConfiguration::getResultImageFormatSize()
911 {
912     return sizeof(float);
913 }
914 
getClearValue()915 VkClearValue SingleTriangleConfiguration::getClearValue()
916 {
917     return makeClearValueColorF32(32.0f, 0.0f, 0.0f, 0.0f);
918 }
919 
920 class UpdateableASConfiguration : public TestConfiguration
921 {
922 public:
923     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(
924         Context &context, TestParams &testParams) override;
925     de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
926         Context &context, TestParams &testParams,
927         std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures) override;
928     void initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
929                                TestParams &testParams) override;
930     void initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, Context &context,
931                                  TestParams &testParams, VkPipeline pipeline, uint32_t shaderGroupHandleSize,
932                                  uint32_t shaderGroupBaseAlignment,
933                                  de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
934                                  de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
935                                  de::MovePtr<BufferWithMemory> &missShaderBindingTable) override;
936     bool verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams) override;
937     VkFormat getResultImageFormat() override;
938     size_t getResultImageFormatSize() override;
939     VkClearValue getClearValue() override;
940 
941     // two triangles: one in the front we will replace with one in the back after updating
942     // update vertex: build with vertices[0], update vertices with vertices[1]
943     // update index: build with vertices[0], updade indices with indices[1]
944     const std::vector<tcu::Vec3> vertices = {
945         tcu::Vec3(0.0f, 0.0f, 0.0f),  tcu::Vec3(0.5f, 0.0f, 0.0f),  tcu::Vec3(0.0f, 0.5f, 0.0f),
946         tcu::Vec3(0.0f, 0.0f, -0.5f), tcu::Vec3(0.5f, 0.0f, -0.5f), tcu::Vec3(0.0f, 0.5f, -0.5f),
947     };
948 
949     const std::vector<uint32_t> indices = {0, 1, 2};
950 };
951 
952 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> UpdateableASConfiguration::
initBottomAccelerationStructures(Context & context,TestParams & testParams)953     initBottomAccelerationStructures(Context &context, TestParams &testParams)
954 {
955     DE_UNREF(context);
956 
957     // No other cases supported for the single triangle configuration.
958     DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
959 
960     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
961 
962     {
963         de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
964             makeBottomLevelAccelerationStructure();
965 
966         unsigned int geometryCount = 1U;
967 
968         bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
969 
970         de::SharedPtr<RaytracedGeometryBase> geometry;
971         geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
972 
973         for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
974             geometry->addVertex(*it);
975 
976         if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
977         {
978             for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
979                 geometry->addIndex(*it);
980         }
981         bottomLevelAccelerationStructure->addGeometry(geometry);
982 
983         result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
984     }
985     return result;
986 }
987 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)988 de::MovePtr<TopLevelAccelerationStructure> UpdateableASConfiguration::initTopAccelerationStructure(
989     Context &context, TestParams &testParams,
990     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
991 {
992     DE_UNREF(context);
993     DE_UNREF(testParams);
994 
995     // Unsupported in this configuration.
996     DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
997 
998     de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
999     result->setInstanceCount(1u);
1000 
1001     result->addInstance(bottomLevelAccelerationStructures[0]);
1002 
1003     return result;
1004 }
1005 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)1006 void UpdateableASConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
1007                                                       Context &context, TestParams &testParams)
1008 {
1009     DE_UNREF(testParams);
1010     const DeviceInterface &vkd = context.getDeviceInterface();
1011     const VkDevice device      = context.getDevice();
1012 
1013     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
1014                                   createShaderModule(vkd, device, context.getBinaryCollection().get("rgen_depth"), 0),
1015                                   0);
1016     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
1017                                   createShaderModule(vkd, device, context.getBinaryCollection().get("chit_depth"), 0),
1018                                   1);
1019     rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
1020                                   createShaderModule(vkd, device, context.getBinaryCollection().get("miss_depth"), 0),
1021                                   2);
1022 }
1023 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,uint32_t shaderGroupHandleSize,uint32_t shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)1024 void UpdateableASConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
1025                                                         Context &context, TestParams &testParams, VkPipeline pipeline,
1026                                                         uint32_t shaderGroupHandleSize,
1027                                                         uint32_t shaderGroupBaseAlignment,
1028                                                         de::MovePtr<BufferWithMemory> &raygenShaderBindingTable,
1029                                                         de::MovePtr<BufferWithMemory> &hitShaderBindingTable,
1030                                                         de::MovePtr<BufferWithMemory> &missShaderBindingTable)
1031 {
1032     DE_UNREF(testParams);
1033     const DeviceInterface &vkd = context.getDeviceInterface();
1034     const VkDevice device      = context.getDevice();
1035     Allocator &allocator       = context.getDefaultAllocator();
1036 
1037     raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1038         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1039     hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1040         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1041     missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1042         vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
1043 }
1044 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)1045 bool UpdateableASConfiguration::verifyImage(BufferWithMemory *resultBuffer, Context &context, TestParams &testParams)
1046 {
1047     tcu::TextureFormat imageFormat  = vk::mapVkFormat(getResultImageFormat());
1048     tcu::TextureFormat vertexFormat = vk::mapVkFormat(testParams.vertexFormat);
1049     tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 1,
1050                                              resultBuffer->getAllocation().getHostPtr());
1051 
1052     std::vector<float> reference(testParams.width * testParams.height);
1053     tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 1, reference.data());
1054 
1055     // verify results
1056     tcu::Vec3 v0          = vertices[3];
1057     tcu::Vec3 v1          = vertices[4];
1058     tcu::Vec3 v2          = vertices[5];
1059     const int numChannels = tcu::getNumUsedChannels(vertexFormat.order);
1060     if (numChannels < 3)
1061     {
1062         v0.z() = 0.0f;
1063         v1.z() = 0.0f;
1064         v2.z() = 0.0f;
1065     }
1066 
1067     for (uint32_t j = 0; j < testParams.height; ++j)
1068     {
1069         float y = 0.1f + 0.2f * float(j) / float(testParams.height - 1);
1070         for (uint32_t i = 0; i < testParams.width; ++i)
1071         {
1072             float x         = 0.1f + 0.2f * float(i) / float(testParams.width - 1);
1073             float z         = v0.z();
1074             bool inTriangle = pointInTriangle2D(tcu::Vec3(x, y, z), v0, v1, v2);
1075             float refValue =
1076                 ((inTriangle && testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY) ? 1.0f - z : 0.0f);
1077             referenceAccess.setPixel(tcu::Vec4(refValue, 0.0f, 0.0f, 1.0f), i, j);
1078         }
1079     }
1080     return tcu::floatThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess,
1081                                       resultAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
1082 }
1083 
getResultImageFormat()1084 VkFormat UpdateableASConfiguration::getResultImageFormat()
1085 {
1086     return VK_FORMAT_R32_SFLOAT;
1087 }
1088 
getResultImageFormatSize()1089 size_t UpdateableASConfiguration::getResultImageFormatSize()
1090 {
1091     return sizeof(float);
1092 }
1093 
getClearValue()1094 VkClearValue UpdateableASConfiguration::getClearValue()
1095 {
1096     return makeClearValueColorF32(32.0f, 0.0f, 0.0f, 0.0f);
1097 }
1098 
commonASTestsCheckSupport(Context & context)1099 void commonASTestsCheckSupport(Context &context)
1100 {
1101     context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
1102     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1103     context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1104 
1105     const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
1106         context.getRayTracingPipelineFeatures();
1107     if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
1108         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
1109 
1110     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
1111         context.getAccelerationStructureFeatures();
1112     if (accelerationStructureFeaturesKHR.accelerationStructure == false)
1113         TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
1114                              "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
1115 }
1116 
1117 class RayTracingASBasicTestCase : public TestCase
1118 {
1119 public:
1120     RayTracingASBasicTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
1121     ~RayTracingASBasicTestCase(void);
1122 
1123     void checkSupport(Context &context) const override;
1124     void initPrograms(SourceCollections &programCollection) const override;
1125     TestInstance *createInstance(Context &context) const override;
1126 
1127 protected:
1128     TestParams m_data;
1129 };
1130 
1131 // Same as RayTracingASBasicTestCase but it will only initialize programs for SingleTriangleConfiguration and use hand-tuned SPIR-V
1132 // assembly.
1133 class RayTracingASFuncArgTestCase : public RayTracingASBasicTestCase
1134 {
1135 public:
1136     RayTracingASFuncArgTestCase(tcu::TestContext &context, const char *name, const TestParams &data);
~RayTracingASFuncArgTestCase(void)1137     ~RayTracingASFuncArgTestCase(void)
1138     {
1139     }
1140 
1141     void initPrograms(SourceCollections &programCollection) const override;
1142 };
1143 
1144 class RayTracingASBasicTestInstance : public TestInstance
1145 {
1146 public:
1147     RayTracingASBasicTestInstance(Context &context, const TestParams &data);
1148     ~RayTracingASBasicTestInstance(void) = default;
1149     tcu::TestStatus iterate(void) override;
1150 
1151 protected:
1152     bool iterateNoWorkers(void);
1153     bool iterateWithWorkers(void);
1154     de::MovePtr<BufferWithMemory> runTest(const uint32_t workerThreadsCount);
1155 
1156 private:
1157     TestParams m_data;
1158 };
1159 
RayTracingASBasicTestCase(tcu::TestContext & context,const char * name,const TestParams & data)1160 RayTracingASBasicTestCase::RayTracingASBasicTestCase(tcu::TestContext &context, const char *name,
1161                                                      const TestParams &data)
1162     : vkt::TestCase(context, name)
1163     , m_data(data)
1164 {
1165 }
1166 
~RayTracingASBasicTestCase(void)1167 RayTracingASBasicTestCase::~RayTracingASBasicTestCase(void)
1168 {
1169 }
1170 
checkSupport(Context & context) const1171 void RayTracingASBasicTestCase::checkSupport(Context &context) const
1172 {
1173     commonASTestsCheckSupport(context);
1174 
1175     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
1176         context.getAccelerationStructureFeatures();
1177     if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
1178         accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
1179         TCU_THROW(NotSupportedError,
1180                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
1181 
1182     if (m_data.useCullMask)
1183         context.requireDeviceFunctionality("VK_KHR_ray_tracing_maintenance1");
1184 
1185     // Check supported vertex format.
1186     checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
1187                                                  m_data.vertexFormat);
1188 }
1189 
initPrograms(SourceCollections & programCollection) const1190 void RayTracingASBasicTestCase::initPrograms(SourceCollections &programCollection) const
1191 {
1192     bool storeInRGen = false;
1193     bool storeInAHit = false;
1194     bool storeInCHit = false;
1195     bool storeInISec = false;
1196 
1197     switch (m_data.instanceCustomIndexCase)
1198     {
1199     case InstanceCustomIndexCase::NONE:
1200         storeInRGen = true;
1201         break;
1202     case InstanceCustomIndexCase::CLOSEST_HIT:
1203         storeInCHit = true;
1204         break;
1205     case InstanceCustomIndexCase::ANY_HIT:
1206         storeInAHit = true;
1207         break;
1208     case InstanceCustomIndexCase::INTERSECTION:
1209         storeInISec = true;
1210         break;
1211     default:
1212         DE_ASSERT(false);
1213         break;
1214     }
1215 
1216     const std::string imageDeclaration = "layout(r32i, set = 0, binding = 0) uniform iimage2D result;\n";
1217     const std::string storeCustomIndex =
1218         "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(gl_InstanceCustomIndexEXT, 0, 0, 1));\n";
1219     const std::string storeCullMask =
1220         "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(gl_CullMaskEXT, 0, 0, 1));\n";
1221     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1222 
1223     {
1224         std::stringstream css;
1225         css << "#version 460 core\n"
1226             << "#extension GL_EXT_ray_tracing : require\n"
1227             << "layout(location = 0) rayPayloadEXT ivec4 hitValue;\n";
1228 
1229         if (storeInRGen)
1230             css << imageDeclaration;
1231 
1232         css << "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1233             << "\n"
1234             << "void main()\n"
1235             << "{\n"
1236             << "  float tmin      = 0.0;\n"
1237             << "  float tmax      = 1.0;\n"
1238             << "  vec3  origin    = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n"
1239             << "  vec3  direction = vec3(0.0,0.0,-1.0);\n"
1240             << "  hitValue        = ivec4(0,0,0,0);\n"
1241             << "  traceRayEXT(topLevelAS, "
1242             << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0, " : "gl_RayFlagsCullBackFacingTrianglesEXT, ")
1243             << m_data.cullMask << ", 0, 0, 0, origin, tmin, direction, tmax, 0);\n";
1244 
1245         if (storeInRGen)
1246             css << "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
1247 
1248         css << "}\n";
1249 
1250         programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1251     }
1252 
1253     {
1254         std::stringstream css;
1255         css << "#version 460 core\n"
1256             << "#extension GL_EXT_ray_tracing : require\n"
1257             << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n")
1258             << "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
1259 
1260         if (storeInCHit)
1261             css << imageDeclaration;
1262 
1263         css << "void main()\n"
1264             << "{\n"
1265             << "  hitValue = ivec4(2,0,0,1);\n";
1266 
1267         if (storeInCHit)
1268         {
1269             if (m_data.useCullMask)
1270             {
1271                 css << storeCullMask;
1272             }
1273             else
1274             {
1275                 css << storeCustomIndex;
1276             }
1277         }
1278 
1279         css << "}\n";
1280 
1281         programCollection.glslSources.add("chit")
1282             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1283     }
1284 
1285     if (storeInAHit)
1286     {
1287         std::stringstream css;
1288         css << "#version 460 core\n"
1289             << "#extension GL_EXT_ray_tracing : require\n"
1290             << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n") << imageDeclaration
1291             << "void main()\n"
1292             << "{\n"
1293             << ((m_data.useCullMask) ? storeCullMask : storeCustomIndex) << "}\n";
1294 
1295         programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1296     }
1297 
1298     {
1299         std::stringstream css;
1300         css << "#version 460 core\n"
1301             << "#extension GL_EXT_ray_tracing : require\n"
1302             << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n")
1303             << "hitAttributeEXT ivec4 hitAttribute;\n";
1304 
1305         if (storeInISec)
1306             css << imageDeclaration;
1307 
1308         css << "void main()\n"
1309             << "{\n"
1310             << "  hitAttribute = ivec4(0,0,0,0);\n"
1311             << "  reportIntersectionEXT(0.5f, 0);\n";
1312         if (storeInISec)
1313         {
1314             if (m_data.useCullMask)
1315             {
1316                 css << storeCullMask;
1317             }
1318             else
1319             {
1320                 css << storeCustomIndex;
1321             }
1322         }
1323 
1324         css << "}\n";
1325 
1326         programCollection.glslSources.add("isect")
1327             << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1328     }
1329 
1330     {
1331         std::stringstream css;
1332         css << "#version 460 core\n"
1333             << "#extension GL_EXT_ray_tracing : require\n"
1334             << ((m_data.useCullMask) ? "#extension GL_EXT_ray_cull_mask : require\n" : "\n")
1335             << "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
1336 
1337         if (!storeInRGen)
1338             css << imageDeclaration;
1339 
1340         css << "void main()\n"
1341             << "{\n"
1342             << "  hitValue = ivec4(1,0,0,1);\n";
1343         if (!storeInRGen)
1344         {
1345             if (m_data.useCullMask)
1346             {
1347                 css << "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(bitfieldReverse(uint(gl_CullMaskEXT)), 0, "
1348                        "0, 1)); \n";
1349             }
1350             else
1351             {
1352                 css << "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
1353             }
1354         }
1355 
1356         css << "}\n";
1357 
1358         programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1359     }
1360 
1361     {
1362         std::stringstream css;
1363         css << "#version 460 core\n"
1364                "#extension GL_EXT_ray_tracing : require\n"
1365                "layout(location = 0) rayPayloadEXT vec4 hitValue;\n"
1366                "layout(r32f, set = 0, binding = 0) uniform image2D result;\n"
1367                "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1368                "\n"
1369                "vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)\n"
1370                "{\n"
1371                "  return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + "
1372                "(float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;\n"
1373                "}\n"
1374                "\n"
1375                "void main()\n"
1376                "{\n"
1377                "  float tmin      = 0.0;\n"
1378                "  float tmax      = 2.0;\n"
1379                "  vec3  origin    = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );\n"
1380                "  vec3  direction = vec3(0.0,0.0,-1.0);\n"
1381                "  hitValue        = vec4(0.0,0.0,0.0,0.0);\n"
1382                "  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
1383                "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
1384                "}\n";
1385         programCollection.glslSources.add("rgen_depth")
1386             << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1387     }
1388 
1389     {
1390         std::stringstream css;
1391         css << "#version 460 core\n"
1392                "#extension GL_EXT_ray_tracing : require\n"
1393                "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1394                "void main()\n"
1395                "{\n"
1396                "  hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1397                "}\n";
1398 
1399         programCollection.glslSources.add("chit_depth")
1400             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1401     }
1402 
1403     {
1404         std::stringstream css;
1405         css << "#version 460 core\n"
1406                "#extension GL_EXT_ray_tracing : require\n"
1407                "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1408                "void main()\n"
1409                "{\n"
1410                "  hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1411                "}\n";
1412 
1413         programCollection.glslSources.add("miss_depth")
1414             << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1415     }
1416 }
1417 
createInstance(Context & context) const1418 TestInstance *RayTracingASBasicTestCase::createInstance(Context &context) const
1419 {
1420     return new RayTracingASBasicTestInstance(context, m_data);
1421 }
1422 
RayTracingASFuncArgTestCase(tcu::TestContext & context,const char * name,const TestParams & data)1423 RayTracingASFuncArgTestCase::RayTracingASFuncArgTestCase(tcu::TestContext &context, const char *name,
1424                                                          const TestParams &data)
1425     : RayTracingASBasicTestCase(context, name, data)
1426 {
1427 }
1428 
initPrograms(SourceCollections & programCollection) const1429 void RayTracingASFuncArgTestCase::initPrograms(SourceCollections &programCollection) const
1430 {
1431     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1432     const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1433 
1434     {
1435         // The SPIR-V assembly below is based on the following GLSL code. Some
1436         // modifications have been made to make traceRaysBottomWrapper take a bare
1437         // acceleration structure as its argument instead of a pointer to it, so we can
1438         // test passing a pointer and a bare value in the same test.
1439         //
1440         //    #version 460 core
1441         //    #extension GL_EXT_ray_tracing : require
1442         // layout(location = 0) rayPayloadEXT vec4 hitValue;
1443         // layout(r32f, set = 0, binding = 0) uniform image2D result;
1444         // layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;
1445         //
1446         //    void traceRaysBottomWrapper(
1447         //      accelerationStructureEXT topLevel,
1448         //      uint rayFlags,
1449         //      uint cullMask,
1450         //      uint sbtRecordOffset,
1451         //      uint sbtRecordStride,
1452         //      uint missIndex,
1453         //      vec3 origin,
1454         //      float Tmin,
1455         //      vec3 direction,
1456         //      float Tmax)
1457         //    {
1458         //   traceRayEXT(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax, 0);
1459         //    }
1460         //
1461         //    void traceRaysTopWrapper(
1462         //      accelerationStructureEXT topLevel,
1463         //      uint rayFlags,
1464         //      uint cullMask,
1465         //      uint sbtRecordOffset,
1466         //      uint sbtRecordStride,
1467         //      uint missIndex,
1468         //      vec3 origin,
1469         //      float Tmin,
1470         //      vec3 direction,
1471         //      float Tmax)
1472         //    {
1473         //   traceRaysBottomWrapper(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax);
1474         //    }
1475         //
1476         //    vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)
1477         //    {
1478         //   return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + (float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;
1479         //    }
1480         //
1481         //    void main()
1482         //    {
1483         //   float tmin      = 0.0;
1484         //   float tmax      = 2.0;
1485         //   vec3  origin    = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );
1486         //   vec3  direction = vec3(0.0,0.0,-1.0);
1487         //   hitValue        = vec4(0.0,0.0,0.0,0.0);
1488         //   traceRaysTopWrapper(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax);
1489         //   imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);
1490         //    }
1491 
1492         std::ostringstream rgen;
1493         rgen
1494             << "; SPIR-V\n"
1495             << "; Version: 1.4\n"
1496             << "; Generator: Khronos Glslang Reference Front End; 10\n"
1497             << "; Bound: 156\n"
1498             << "; Schema: 0\n"
1499             << "OpCapability RayTracingKHR\n"
1500             << "OpExtension \"SPV_KHR_ray_tracing\"\n"
1501             << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1502             << "OpMemoryModel Logical GLSL450\n"
1503             << "OpEntryPoint RayGenerationKHR %4 \"main\" %59 %82 %88 %130 %148\n"
1504             << "OpDecorate %59 Location 0\n"
1505             << "OpDecorate %82 BuiltIn LaunchIdKHR\n"
1506             << "OpDecorate %88 BuiltIn LaunchSizeKHR\n"
1507             << "OpDecorate %130 DescriptorSet 0\n"
1508             << "OpDecorate %130 Binding 1\n"
1509             << "OpDecorate %148 DescriptorSet 0\n"
1510             << "OpDecorate %148 Binding 0\n"
1511             << "%2 = OpTypeVoid\n"
1512             << "%3 = OpTypeFunction %2\n"
1513 
1514             // This is the bare type.
1515             << "%6 = OpTypeAccelerationStructureKHR\n"
1516 
1517             // This is the pointer type.
1518             << "%7 = OpTypePointer UniformConstant %6\n"
1519 
1520             << "%8 = OpTypeInt 32 0\n"
1521             << "%9 = OpTypePointer Function %8\n"
1522             << "%10 = OpTypeFloat 32\n"
1523             << "%11 = OpTypeVector %10 3\n"
1524             << "%12 = OpTypePointer Function %11\n"
1525             << "%13 = OpTypePointer Function %10\n"
1526 
1527             // This is the type for traceRaysTopWrapper and also the original traceRaysBottomWrapper.
1528             << "%14 = OpTypeFunction %2 %7 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1529 
1530             // This is the modified type to take a bare AS as the first argument, for the modified version of traceRaysBottomWrapper.
1531             << "%14b = OpTypeFunction %2 %6 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1532 
1533             << "%39 = OpTypeFunction %11 %12 %12 %12\n"
1534             << "%55 = OpTypeInt 32 1\n"
1535             << "%56 = OpConstant %55 0\n"
1536             << "%57 = OpTypeVector %10 4\n"
1537             << "%58 = OpTypePointer RayPayloadKHR %57\n"
1538             << "%59 = OpVariable %58 RayPayloadKHR\n"
1539             << "%80 = OpTypeVector %8 3\n"
1540             << "%81 = OpTypePointer Input %80\n"
1541             << "%82 = OpVariable %81 Input\n"
1542             << "%83 = OpConstant %8 0\n"
1543             << "%84 = OpTypePointer Input %8\n"
1544             << "%88 = OpVariable %81 Input\n"
1545             << "%91 = OpConstant %8 1\n"
1546             << "%112 = OpConstant %10 0\n"
1547             << "%114 = OpConstant %10 2\n"
1548             << "%116 = OpConstant %10 0.100000001\n"
1549             << "%117 = OpConstant %10 1\n"
1550             << "%118 = OpConstantComposite %11 %116 %116 %117\n"
1551             << "%119 = OpConstant %10 0.200000003\n"
1552             << "%120 = OpConstantComposite %11 %119 %112 %112\n"
1553             << "%121 = OpConstantComposite %11 %112 %119 %112\n"
1554             << "%127 = OpConstant %10 -1\n"
1555             << "%128 = OpConstantComposite %11 %112 %112 %127\n"
1556             << "%129 = OpConstantComposite %57 %112 %112 %112 %112\n"
1557             << "%130 = OpVariable %7 UniformConstant\n"
1558             << "%131 = OpConstant %8 255\n"
1559             << "%146 = OpTypeImage %10 2D 0 0 0 2 R32f\n"
1560             << "%147 = OpTypePointer UniformConstant %146\n"
1561             << "%148 = OpVariable %147 UniformConstant\n"
1562             << "%150 = OpTypeVector %8 2\n"
1563             << "%153 = OpTypeVector %55 2\n"
1564 
1565             // This is main().
1566             << "%4 = OpFunction %2 None %3\n"
1567             << "%5 = OpLabel\n"
1568             << "%111 = OpVariable %13 Function\n"
1569             << "%113 = OpVariable %13 Function\n"
1570             << "%115 = OpVariable %12 Function\n"
1571             << "%122 = OpVariable %12 Function\n"
1572             << "%123 = OpVariable %12 Function\n"
1573             << "%124 = OpVariable %12 Function\n"
1574             << "%126 = OpVariable %12 Function\n"
1575             << "%132 = OpVariable %9 Function\n"
1576             << "%133 = OpVariable %9 Function\n"
1577             << "%134 = OpVariable %9 Function\n"
1578             << "%135 = OpVariable %9 Function\n"
1579             << "%136 = OpVariable %9 Function\n"
1580             << "%137 = OpVariable %12 Function\n"
1581             << "%139 = OpVariable %13 Function\n"
1582             << "%141 = OpVariable %12 Function\n"
1583             << "%143 = OpVariable %13 Function\n"
1584             << "OpStore %111 %112\n"
1585             << "OpStore %113 %114\n"
1586             << "OpStore %122 %118\n"
1587             << "OpStore %123 %120\n"
1588             << "OpStore %124 %121\n"
1589             << "%125 = OpFunctionCall %11 %43 %122 %123 %124\n"
1590             << "OpStore %115 %125\n"
1591             << "OpStore %126 %128\n"
1592             << "OpStore %59 %129\n"
1593             << "OpStore %132 %83\n"
1594             << "OpStore %133 %131\n"
1595             << "OpStore %134 %83\n"
1596             << "OpStore %135 %83\n"
1597             << "OpStore %136 %83\n"
1598             << "%138 = OpLoad %11 %115\n"
1599             << "OpStore %137 %138\n"
1600             << "%140 = OpLoad %10 %111\n"
1601             << "OpStore %139 %140\n"
1602             << "%142 = OpLoad %11 %126\n"
1603             << "OpStore %141 %142\n"
1604             << "%144 = OpLoad %10 %113\n"
1605             << "OpStore %143 %144\n"
1606             << "%145 = OpFunctionCall %2 %37 %130 %132 %133 %134 %135 %136 %137 %139 %141 %143\n"
1607             << "%149 = OpLoad %146 %148\n"
1608             << "%151 = OpLoad %80 %82\n"
1609             << "%152 = OpVectorShuffle %150 %151 %151 0 1\n"
1610             << "%154 = OpBitcast %153 %152\n"
1611             << "%155 = OpLoad %57 %59\n"
1612             << "OpImageWrite %149 %154 %155\n"
1613             << "OpReturn\n"
1614             << "OpFunctionEnd\n"
1615 
1616             // This is traceRaysBottomWrapper, doing the OpTraceRayKHR call.
1617             // We have modified the type so it takes a bare AS as the first argument.
1618             // %25 = OpFunction %2 None %14
1619             << "%25 = OpFunction %2 None %14b\n"
1620 
1621             // Also the type of the first argument here.
1622             // %15 = OpFunctionParameter %7
1623             << "%15 = OpFunctionParameter %6\n"
1624 
1625             << "%16 = OpFunctionParameter %9\n"
1626             << "%17 = OpFunctionParameter %9\n"
1627             << "%18 = OpFunctionParameter %9\n"
1628             << "%19 = OpFunctionParameter %9\n"
1629             << "%20 = OpFunctionParameter %9\n"
1630             << "%21 = OpFunctionParameter %12\n"
1631             << "%22 = OpFunctionParameter %13\n"
1632             << "%23 = OpFunctionParameter %12\n"
1633             << "%24 = OpFunctionParameter %13\n"
1634             << "%26 = OpLabel\n"
1635 
1636             // We no longer need to dereference the pointer here.
1637             // %45 = OpLoad %6 %15
1638 
1639             << "%46 = OpLoad %8 %16\n"
1640             << "%47 = OpLoad %8 %17\n"
1641             << "%48 = OpLoad %8 %18\n"
1642             << "%49 = OpLoad %8 %19\n"
1643             << "%50 = OpLoad %8 %20\n"
1644             << "%51 = OpLoad %11 %21\n"
1645             << "%52 = OpLoad %10 %22\n"
1646             << "%53 = OpLoad %11 %23\n"
1647             << "%54 = OpLoad %10 %24\n"
1648 
1649             // And we can use the first argument here directly.
1650             // OpTraceRayKHR %45 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59
1651             << "OpTraceRayKHR %15 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59\n"
1652 
1653             << "OpReturn\n"
1654             << "OpFunctionEnd\n"
1655 
1656             // This is traceRaysTopWrapper, which calls traceRaysBottomWrapper.
1657             << "%37 = OpFunction %2 None %14\n"
1658 
1659             // First argument, pointer to AS.
1660             << "%27 = OpFunctionParameter %7\n"
1661 
1662             << "%28 = OpFunctionParameter %9\n"
1663             << "%29 = OpFunctionParameter %9\n"
1664             << "%30 = OpFunctionParameter %9\n"
1665             << "%31 = OpFunctionParameter %9\n"
1666             << "%32 = OpFunctionParameter %9\n"
1667             << "%33 = OpFunctionParameter %12\n"
1668             << "%34 = OpFunctionParameter %13\n"
1669             << "%35 = OpFunctionParameter %12\n"
1670             << "%36 = OpFunctionParameter %13\n"
1671             << "%38 = OpLabel\n"
1672             << "%60 = OpVariable %9 Function\n"
1673             << "%62 = OpVariable %9 Function\n"
1674             << "%64 = OpVariable %9 Function\n"
1675             << "%66 = OpVariable %9 Function\n"
1676             << "%68 = OpVariable %9 Function\n"
1677             << "%70 = OpVariable %12 Function\n"
1678             << "%72 = OpVariable %13 Function\n"
1679             << "%74 = OpVariable %12 Function\n"
1680             << "%76 = OpVariable %13 Function\n"
1681 
1682             // Dereference the pointer to pass the AS as the first argument.
1683             << "%27b = OpLoad %6 %27\n"
1684 
1685             << "%61 = OpLoad %8 %28\n"
1686             << "OpStore %60 %61\n"
1687             << "%63 = OpLoad %8 %29\n"
1688             << "OpStore %62 %63\n"
1689             << "%65 = OpLoad %8 %30\n"
1690             << "OpStore %64 %65\n"
1691             << "%67 = OpLoad %8 %31\n"
1692             << "OpStore %66 %67\n"
1693             << "%69 = OpLoad %8 %32\n"
1694             << "OpStore %68 %69\n"
1695             << "%71 = OpLoad %11 %33\n"
1696             << "OpStore %70 %71\n"
1697             << "%73 = OpLoad %10 %34\n"
1698             << "OpStore %72 %73\n"
1699             << "%75 = OpLoad %11 %35\n"
1700             << "OpStore %74 %75\n"
1701             << "%77 = OpLoad %10 %36\n"
1702             << "OpStore %76 %77\n"
1703 
1704             // %2 is void, %25 is traceRaysBottomWrapper and %27 was the first argument.
1705             // We need to pass the loaded AS instead.
1706             // %78 = OpFunctionCall %2 %25 %27 %60 %62 %64 %66 %68 %70 %72 %74 %76
1707             << "%78 = OpFunctionCall %2 %25 %27b %60 %62 %64 %66 %68 %70 %72 %74 %76\n"
1708 
1709             << "OpReturn\n"
1710             << "OpFunctionEnd\n"
1711 
1712             // This is calculateOrigin().
1713             << "%43 = OpFunction %11 None %39\n"
1714             << "%40 = OpFunctionParameter %12\n"
1715             << "%41 = OpFunctionParameter %12\n"
1716             << "%42 = OpFunctionParameter %12\n"
1717             << "%44 = OpLabel\n"
1718             << "%79 = OpLoad %11 %40\n"
1719             << "%85 = OpAccessChain %84 %82 %83\n"
1720             << "%86 = OpLoad %8 %85\n"
1721             << "%87 = OpConvertUToF %10 %86\n"
1722             << "%89 = OpAccessChain %84 %88 %83\n"
1723             << "%90 = OpLoad %8 %89\n"
1724             << "%92 = OpISub %8 %90 %91\n"
1725             << "%93 = OpConvertUToF %10 %92\n"
1726             << "%94 = OpFDiv %10 %87 %93\n"
1727             << "%95 = OpLoad %11 %41\n"
1728             << "%96 = OpVectorTimesScalar %11 %95 %94\n"
1729             << "%97 = OpFAdd %11 %79 %96\n"
1730             << "%98 = OpAccessChain %84 %82 %91\n"
1731             << "%99 = OpLoad %8 %98\n"
1732             << "%100 = OpConvertUToF %10 %99\n"
1733             << "%101 = OpAccessChain %84 %88 %91\n"
1734             << "%102 = OpLoad %8 %101\n"
1735             << "%103 = OpISub %8 %102 %91\n"
1736             << "%104 = OpConvertUToF %10 %103\n"
1737             << "%105 = OpFDiv %10 %100 %104\n"
1738             << "%106 = OpLoad %11 %42\n"
1739             << "%107 = OpVectorTimesScalar %11 %106 %105\n"
1740             << "%108 = OpFAdd %11 %97 %107\n"
1741             << "OpReturnValue %108\n"
1742             << "OpFunctionEnd\n";
1743 
1744         programCollection.spirvAsmSources.add("rgen_depth") << spvBuildOptions << rgen.str();
1745     }
1746 
1747     // chit_depth and miss_depth below have been left untouched.
1748 
1749     {
1750         std::stringstream css;
1751         css << "#version 460 core\n"
1752                "#extension GL_EXT_ray_tracing : require\n"
1753                "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1754                "void main()\n"
1755                "{\n"
1756                "  hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1757                "}\n";
1758 
1759         programCollection.glslSources.add("chit_depth")
1760             << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1761     }
1762 
1763     {
1764         std::stringstream css;
1765         css << "#version 460 core\n"
1766                "#extension GL_EXT_ray_tracing : require\n"
1767                "layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1768                "void main()\n"
1769                "{\n"
1770                "  hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1771                "}\n";
1772 
1773         programCollection.glslSources.add("miss_depth")
1774             << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1775     }
1776 }
1777 
RayTracingASBasicTestInstance(Context & context,const TestParams & data)1778 RayTracingASBasicTestInstance::RayTracingASBasicTestInstance(Context &context, const TestParams &data)
1779     : vkt::TestInstance(context)
1780     , m_data(data)
1781 {
1782 }
1783 
runTest(const uint32_t workerThreadsCount)1784 de::MovePtr<BufferWithMemory> RayTracingASBasicTestInstance::runTest(const uint32_t workerThreadsCount)
1785 {
1786     const InstanceInterface &vki            = m_context.getInstanceInterface();
1787     const DeviceInterface &vkd              = m_context.getDeviceInterface();
1788     const VkDevice device                   = m_context.getDevice();
1789     const VkPhysicalDevice physicalDevice   = m_context.getPhysicalDevice();
1790     const uint32_t queueFamilyIndex         = m_context.getUniversalQueueFamilyIndex();
1791     const VkQueue queue                     = m_context.getUniversalQueue();
1792     Allocator &allocator                    = m_context.getDefaultAllocator();
1793     const uint32_t pixelCount               = m_data.width * m_data.height;
1794     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
1795     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1796     const bool htCopy                       = (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
1797     const bool htSerialize                  = (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
1798 
1799     const Move<VkDescriptorSetLayout> descriptorSetLayout =
1800         DescriptorSetLayoutBuilder()
1801             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1802             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1803             .build(vkd, device);
1804     const Move<VkDescriptorPool> descriptorPool =
1805         DescriptorPoolBuilder()
1806             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1807             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1808             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1809     const Move<VkDescriptorSet> descriptorSet   = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1810     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1811 
1812     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1813     m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
1814     Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1815 
1816     de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
1817     de::MovePtr<BufferWithMemory> hitShaderBindingTable;
1818     de::MovePtr<BufferWithMemory> missShaderBindingTable;
1819     m_data.testConfiguration->initShaderBindingTables(
1820         rayTracingPipeline, m_context, m_data, *pipeline, shaderGroupHandleSize, shaderGroupBaseAlignment,
1821         raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable);
1822 
1823     const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
1824         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
1825                                           shaderGroupHandleSize, shaderGroupHandleSize);
1826     const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
1827         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
1828                                           shaderGroupHandleSize, shaderGroupHandleSize);
1829     const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
1830         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
1831                                           shaderGroupHandleSize, shaderGroupHandleSize);
1832     const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
1833 
1834     const VkFormat imageFormat              = m_data.testConfiguration->getResultImageFormat();
1835     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
1836     const VkImageSubresourceRange imageSubresourceRange =
1837         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1838     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1839         new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1840     const Move<VkImageView> imageView =
1841         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
1842 
1843     const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(
1844         pixelCount * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1845     const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
1846         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1847     const VkBufferImageCopy resultBufferImageRegion =
1848         makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), resultBufferImageSubresourceLayers);
1849     de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
1850         new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1851 
1852     const VkDescriptorImageInfo descriptorImageInfo =
1853         makeDescriptorImageInfo(VK_NULL_HANDLE, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1854 
1855     const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1856     const Move<VkCommandBuffer> cmdBuffer =
1857         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1858 
1859     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
1860     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1861     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
1862     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
1863     std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
1864     std::vector<de::SharedPtr<SerialStorage>> topSerialized;
1865     std::vector<VkDeviceSize> accelerationCompactedSizes;
1866     std::vector<VkDeviceSize> accelerationSerialSizes;
1867     Move<VkQueryPool> m_queryPoolCompact;
1868     Move<VkQueryPool> m_queryPoolSerial;
1869 
1870     beginCommandBuffer(vkd, *cmdBuffer, 0u);
1871     {
1872         const VkImageMemoryBarrier preImageBarrier =
1873             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1874                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
1875         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1876                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1877         const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
1878         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
1879                                &imageSubresourceRange);
1880         const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
1881             VK_ACCESS_TRANSFER_WRITE_BIT,
1882             VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1883             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
1884         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1885                                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1886 
1887         // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
1888         bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1889         bool bottomSerial  = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1890         const bool buildWithoutGeom   = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
1891         const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
1892         const bool topNoPrimitives    = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
1893         const bool inactiveInstances  = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
1894         bottomLevelAccelerationStructures =
1895             m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1896         VkBuildAccelerationStructureFlagsKHR allowCompactionFlag =
1897             VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
1898         VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
1899         VkBuildAccelerationStructureFlagsKHR bottomCompactFlags =
1900             (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
1901         VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
1902         std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
1903         std::vector<VkDeviceSize> bottomBlasCompactSize;
1904         std::vector<VkDeviceSize> bottomBlasSerialSize;
1905 
1906         for (auto &blas : bottomLevelAccelerationStructures)
1907         {
1908             blas->setBuildType(m_data.buildType);
1909             blas->setBuildFlags(bottomBuildFlags);
1910             blas->setUseArrayOfPointers(m_data.bottomUsesAOP);
1911             blas->setCreateGeneric(m_data.bottomGeneric);
1912             blas->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
1913             blas->setBuildWithoutGeometries(buildWithoutGeom);
1914             blas->setBuildWithoutPrimitives(bottomNoPrimitives);
1915             blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
1916             accelerationStructureHandles.push_back(*(blas->getPtr()));
1917         }
1918 
1919         if (m_data.operationType == OP_COMPACT)
1920         {
1921             uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
1922                                       uint32_t(bottomLevelAccelerationStructures.size()) :
1923                                       1u;
1924             if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1925                 m_queryPoolCompact =
1926                     makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
1927             if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1928                 queryAccelerationStructureSize(
1929                     vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
1930                     VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
1931         }
1932         if (m_data.operationType == OP_SERIALIZE)
1933         {
1934             uint32_t queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ?
1935                                       uint32_t(bottomLevelAccelerationStructures.size()) :
1936                                       1u;
1937             if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1938                 m_queryPoolSerial =
1939                     makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
1940             if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1941                 queryAccelerationStructureSize(
1942                     vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
1943                     VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
1944         }
1945 
1946         // 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
1947         if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
1948         {
1949             endCommandBuffer(vkd, *cmdBuffer);
1950 
1951             submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1952 
1953             if (bottomCompact)
1954                 VK_CHECK(vkd.getQueryPoolResults(
1955                     device, *m_queryPoolCompact, 0u, uint32_t(bottomBlasCompactSize.size()),
1956                     sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(),
1957                     sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1958             if (bottomSerial)
1959                 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(bottomBlasSerialSize.size()),
1960                                                  sizeof(VkDeviceSize) * bottomBlasSerialSize.size(),
1961                                                  bottomBlasSerialSize.data(), sizeof(VkDeviceSize),
1962                                                  VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1963 
1964             vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1965             beginCommandBuffer(vkd, *cmdBuffer, 0u);
1966         }
1967 
1968         auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
1969         if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1970         {
1971             switch (m_data.operationType)
1972             {
1973             case OP_COPY:
1974             {
1975                 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1976                 {
1977                     de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1978                     asCopy->setDeferredOperation(htCopy, workerThreadsCount);
1979                     asCopy->setBuildType(m_data.buildType);
1980                     asCopy->setBuildFlags(m_data.buildFlags);
1981                     asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1982                     asCopy->setCreateGeneric(m_data.bottomGeneric);
1983                     asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
1984                     asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1985                     asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1986                     asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
1987                                               bottomLevelAccelerationStructures[i].get(), 0u, 0u);
1988                     bottomLevelAccelerationStructureCopies.push_back(
1989                         de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1990                 }
1991                 break;
1992             }
1993             case OP_COMPACT:
1994             {
1995                 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1996                 {
1997                     de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1998                     asCopy->setBuildType(m_data.buildType);
1999                     asCopy->setBuildFlags(m_data.buildFlags);
2000                     asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2001                     asCopy->setCreateGeneric(m_data.bottomGeneric);
2002                     asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2003                     asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2004                     asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2005                     asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2006                                               bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
2007                     bottomLevelAccelerationStructureCopies.push_back(
2008                         de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2009                 }
2010                 break;
2011             }
2012             case OP_SERIALIZE:
2013             {
2014                 //bottomLevelAccelerationStructureCopies = m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
2015                 for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2016                 {
2017                     de::SharedPtr<SerialStorage> storage(
2018                         new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
2019 
2020                     bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
2021                     bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
2022                     bottomSerialized.push_back(storage);
2023 
2024                     if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2025                     {
2026                         endCommandBuffer(vkd, *cmdBuffer);
2027 
2028                         submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2029 
2030                         vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2031                         beginCommandBuffer(vkd, *cmdBuffer, 0u);
2032                     }
2033 
2034                     de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2035                     asCopy->setBuildType(m_data.buildType);
2036                     asCopy->setBuildFlags(m_data.buildFlags);
2037                     asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2038                     asCopy->setCreateGeneric(m_data.bottomGeneric);
2039                     asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2040                     asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2041                     asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2042                     asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2043                     asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
2044                     bottomLevelAccelerationStructureCopies.push_back(
2045                         de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2046                 }
2047                 break;
2048             }
2049             default:
2050                 DE_ASSERT(false);
2051             }
2052             bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
2053         }
2054 
2055         // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
2056         bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
2057         bool topSerial  = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
2058         VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
2059         VkBuildAccelerationStructureFlagsKHR topBuildFlags   = m_data.buildFlags | topCompactFlags;
2060         std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
2061         std::vector<VkDeviceSize> topBlasCompactSize;
2062         std::vector<VkDeviceSize> topBlasSerialSize;
2063 
2064         topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(
2065             m_context, m_data, *bottomLevelAccelerationStructuresPtr);
2066         topLevelAccelerationStructure->setBuildType(m_data.buildType);
2067         topLevelAccelerationStructure->setBuildFlags(topBuildFlags);
2068         topLevelAccelerationStructure->setBuildWithoutPrimitives(topNoPrimitives);
2069         topLevelAccelerationStructure->setUseArrayOfPointers(m_data.topUsesAOP);
2070         topLevelAccelerationStructure->setCreateGeneric(m_data.topGeneric);
2071         topLevelAccelerationStructure->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2072         topLevelAccelerationStructure->setInactiveInstances(inactiveInstances);
2073         topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
2074         topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr()));
2075 
2076         if (topCompact)
2077             queryAccelerationStructureSize(
2078                 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(),
2079                 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
2080         if (topSerial)
2081             queryAccelerationStructureSize(
2082                 vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(),
2083                 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
2084 
2085         // 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
2086         if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
2087         {
2088             endCommandBuffer(vkd, *cmdBuffer);
2089 
2090             submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2091 
2092             if (topCompact)
2093                 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, uint32_t(topBlasCompactSize.size()),
2094                                                  sizeof(VkDeviceSize) * topBlasCompactSize.size(),
2095                                                  topBlasCompactSize.data(), sizeof(VkDeviceSize),
2096                                                  VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2097             if (topSerial)
2098                 VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, uint32_t(topBlasSerialSize.size()),
2099                                                  sizeof(VkDeviceSize) * topBlasSerialSize.size(),
2100                                                  topBlasSerialSize.data(), sizeof(VkDeviceSize),
2101                                                  VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2102 
2103             vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2104             beginCommandBuffer(vkd, *cmdBuffer, 0u);
2105         }
2106 
2107         const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get();
2108         if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
2109         {
2110             switch (m_data.operationType)
2111             {
2112             case OP_COPY:
2113             {
2114                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2115                 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2116                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2117                 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2118                 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2119                 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2120                 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2121                 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2122                 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2123                 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2124                                                                      topLevelAccelerationStructure.get(), 0u, 0u);
2125                 break;
2126             }
2127             case OP_COMPACT:
2128             {
2129                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2130                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2131                 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2132                 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2133                 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2134                 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2135                 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2136                 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2137                 topLevelAccelerationStructureCopy->createAndCopyFrom(
2138                     vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
2139                 break;
2140             }
2141             case OP_SERIALIZE:
2142             {
2143                 de::SharedPtr<SerialStorage> storage = de::SharedPtr<SerialStorage>(
2144                     new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
2145 
2146                 topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
2147                 topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
2148                 topSerialized.push_back(storage);
2149 
2150                 if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2151                 {
2152                     endCommandBuffer(vkd, *cmdBuffer);
2153 
2154                     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2155 
2156                     vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2157                     beginCommandBuffer(vkd, *cmdBuffer, 0u);
2158                 }
2159 
2160                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2161                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2162                 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2163                 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2164                 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2165                 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2166                 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2167                 topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2168                 topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2169                 topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator,
2170                                                                             storage.get(), 0u);
2171                 break;
2172             }
2173             case OP_UPDATE:
2174             {
2175                 topLevelAccelerationStructureCopy = m_data.testConfiguration->initTopAccelerationStructure(
2176                     m_context, m_data, *bottomLevelAccelerationStructuresPtr);
2177                 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2178                 topLevelAccelerationStructureCopy->create(vkd, device, allocator, 0u, 0u);
2179                 // Update AS based on topLevelAccelerationStructure
2180                 topLevelAccelerationStructureCopy->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2181                 break;
2182             }
2183             case OP_UPDATE_IN_PLACE:
2184             {
2185                 // Update in place
2186                 topLevelAccelerationStructure->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2187                 // Make a coppy
2188                 topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2189                 topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2190                 topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2191                 topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2192                 topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2193                 topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2194                 topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2195                 topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2196                 topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator,
2197                                                                      topLevelAccelerationStructure.get(), 0u, 0u);
2198                 break;
2199             }
2200             default:
2201                 DE_ASSERT(false);
2202             }
2203             topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
2204         }
2205 
2206         const VkMemoryBarrier preTraceMemoryBarrier =
2207             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
2208         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2209                                  VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier);
2210 
2211         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
2212             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
2213             nullptr,                                                           //  const void* pNext;
2214             1u,                                                                //  uint32_t accelerationStructureCount;
2215             topLevelRayTracedPtr->getPtr(), //  const VkAccelerationStructureKHR* pAccelerationStructures;
2216         };
2217 
2218         DescriptorSetUpdateBuilder()
2219             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
2220                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
2221             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
2222                          VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
2223             .update(vkd, device);
2224 
2225         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
2226                                   &descriptorSet.get(), 0, nullptr);
2227 
2228         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
2229 
2230         cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
2231                      &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height, 1);
2232 
2233         const VkMemoryBarrier postTraceMemoryBarrier =
2234             makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2235         const VkMemoryBarrier postCopyMemoryBarrier =
2236             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2237         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
2238                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
2239 
2240         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
2241                                  &resultBufferImageRegion);
2242 
2243         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2244                                  &postCopyMemoryBarrier);
2245     }
2246     endCommandBuffer(vkd, *cmdBuffer);
2247 
2248     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2249 
2250     invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
2251                                 resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(uint32_t));
2252 
2253     return resultBuffer;
2254 }
2255 
iterateNoWorkers(void)2256 bool RayTracingASBasicTestInstance::iterateNoWorkers(void)
2257 {
2258     // run test using arrays of pointers
2259     const de::MovePtr<BufferWithMemory> buffer = runTest(0);
2260 
2261     return m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data);
2262 }
2263 
iterateWithWorkers(void)2264 bool RayTracingASBasicTestInstance::iterateWithWorkers(void)
2265 {
2266     de::MovePtr<BufferWithMemory> singleThreadBufferCPU = runTest(0);
2267     const bool singleThreadValidation =
2268         m_data.testConfiguration->verifyImage(singleThreadBufferCPU.get(), m_context, m_data);
2269 
2270     de::MovePtr<BufferWithMemory> multiThreadBufferCPU = runTest(m_data.workerThreadsCount);
2271     const bool multiThreadValidation =
2272         m_data.testConfiguration->verifyImage(multiThreadBufferCPU.get(), m_context, m_data);
2273 
2274     const uint32_t result = singleThreadValidation && multiThreadValidation;
2275 
2276     return result;
2277 }
2278 
iterate(void)2279 tcu::TestStatus RayTracingASBasicTestInstance::iterate(void)
2280 {
2281     bool result;
2282 
2283     if (m_data.workerThreadsCount != 0)
2284         result = iterateWithWorkers();
2285     else
2286         result = iterateNoWorkers();
2287 
2288     if (result)
2289         return tcu::TestStatus::pass("Pass");
2290     else
2291         return tcu::TestStatus::fail("Fail");
2292 }
2293 
2294 // Tests dynamic indexing of acceleration structures
2295 class RayTracingASDynamicIndexingTestCase : public TestCase
2296 {
2297 public:
2298     RayTracingASDynamicIndexingTestCase(tcu::TestContext &context, const char *name);
2299     ~RayTracingASDynamicIndexingTestCase(void) = default;
2300 
2301     void checkSupport(Context &context) const override;
2302     void initPrograms(SourceCollections &programCollection) const override;
2303     TestInstance *createInstance(Context &context) const override;
2304 };
2305 
2306 class RayTracingASDynamicIndexingTestInstance : public TestInstance
2307 {
2308 public:
2309     RayTracingASDynamicIndexingTestInstance(Context &context);
2310     ~RayTracingASDynamicIndexingTestInstance(void) = default;
2311     tcu::TestStatus iterate(void) override;
2312 };
2313 
RayTracingASDynamicIndexingTestCase(tcu::TestContext & context,const char * name)2314 RayTracingASDynamicIndexingTestCase::RayTracingASDynamicIndexingTestCase(tcu::TestContext &context, const char *name)
2315     : TestCase(context, name)
2316 {
2317 }
2318 
checkSupport(Context & context) const2319 void RayTracingASDynamicIndexingTestCase::checkSupport(Context &context) const
2320 {
2321     commonASTestsCheckSupport(context);
2322     context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
2323 }
2324 
initPrograms(SourceCollections & programCollection) const2325 void RayTracingASDynamicIndexingTestCase::initPrograms(SourceCollections &programCollection) const
2326 {
2327     const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2328     const vk::ShaderBuildOptions glslBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
2329 
2330     // raygen shader is defined in spir-v as it requires possing pointer to TLAS that was read from ssbo;
2331     // original spir-v code was generated using following glsl code but resulting spir-v code was modiifed
2332     //
2333     // #version 460 core
2334     // #extension GL_EXT_ray_tracing : require
2335     // #extension GL_EXT_nonuniform_qualifier : enable
2336     // #define ARRAY_SIZE 500
2337     // layout(location = 0) rayPayloadEXT uvec2 payload;    // offset and flag indicating if we are using descriptors or pointers
2338 
2339     // layout(set = 0, binding = 0) uniform accelerationStructureEXT tlasArray[ARRAY_SIZE];
2340     // layout(set = 0, binding = 1) readonly buffer topLevelASPointers {
2341     //     uvec2 ptr[];
2342     // } tlasPointers;
2343     // layout(set = 0, binding = 2) readonly buffer topLevelASIndices {
2344     //     uint idx[];
2345     // } tlasIndices;
2346     // layout(set = 0, binding = 3, std430) writeonly buffer Result {
2347     //     uint value[];
2348     // } result;
2349 
2350     // void main()
2351     // {
2352     //   float tmin            = 0.0;\n"
2353     //   float tmax            = 2.0;\n"
2354     //   vec3  origin          = vec3(0.25f, 0.5f, 1.0);\n"
2355     //   vec3  direction       = vec3(0.0,0.0,-1.0);\n"
2356     //   uint  activeTlasIndex = gl_LaunchIDEXT.x;\n"
2357     //   uint  activeTlasCount = gl_LaunchSizeEXT.x;\n"
2358     //   uint  tlasIndex       = tlasIndices.idx[nonuniformEXT(activeTlasIndex)];\n"
2359 
2360     //   atomicAdd(result.value[nonuniformEXT(activeTlasIndex)], 2);\n"
2361     //   payload = uvec2(activeTlasIndex + activeTlasCount.x, 0);\n"
2362     //   traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
2363 
2364     //   atomicAdd(result.value[nonuniformEXT(activeTlasIndex + activeTlasCount * 2)], 5);\n"
2365     //   payload = uvec2(activeTlasIndex + activeTlasCount * 3, 1);\n"
2366     //   traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);                // used to generate initial spirv
2367     //   //traceRayEXT(*tlasPointers.ptr[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);    // not available in glsl but should be done in spirv
2368     // };
2369 
2370     const std::string rgenSource =
2371         "OpCapability RayTracingKHR\n"
2372         "OpCapability ShaderNonUniform\n"
2373         "OpExtension \"SPV_EXT_descriptor_indexing\"\n"
2374         "OpExtension \"SPV_KHR_ray_tracing\"\n"
2375         "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2376         "OpMemoryModel Logical GLSL450\n"
2377         "OpEntryPoint RayGenerationKHR %4 \"main\" %27 %33 %var_tlas_indices %var_result %60 %var_as_arr_ptr "
2378         "%var_as_pointers_ssbo\n"
2379         "OpDecorate %27 BuiltIn LaunchIdNV\n"
2380         "OpDecorate %33 BuiltIn LaunchSizeNV\n"
2381         "OpDecorate %37 ArrayStride 4\n"
2382         "OpMemberDecorate %38 0 NonWritable\n"
2383         "OpMemberDecorate %38 0 Offset 0\n"
2384         "OpDecorate %38 Block\n"
2385         "OpDecorate %var_tlas_indices DescriptorSet 0\n"
2386         "OpDecorate %var_tlas_indices Binding 2\n"
2387         "OpDecorate %44 NonUniform\n"
2388         "OpDecorate %46 NonUniform\n"
2389         "OpDecorate %47 NonUniform\n"
2390         "OpDecorate %48 ArrayStride 4\n"
2391         "OpMemberDecorate %49 0 NonReadable\n"
2392         "OpMemberDecorate %49 0 Offset 0\n"
2393         "OpDecorate %49 Block\n"
2394         "OpDecorate %var_result DescriptorSet 0\n"
2395         "OpDecorate %var_result Binding 3\n"
2396         "OpDecorate %53 NonUniform\n"
2397         "OpDecorate %60 Location 0\n"
2398         "OpDecorate %var_as_arr_ptr DescriptorSet 0\n"
2399         "OpDecorate %var_as_arr_ptr Binding 0\n"
2400         "OpDecorate %71 NonUniform\n"
2401         "OpDecorate %73 NonUniform\n"
2402         "OpDecorate %74 NonUniform\n"
2403         "OpDecorate %85 NonUniform\n"
2404         "OpDecorate %as_index NonUniform\n"
2405         "OpDecorate %as_device_addres NonUniform\n"
2406         "OpDecorate %104 ArrayStride 8\n"
2407         "OpMemberDecorate %105 0 NonWritable\n"
2408         "OpMemberDecorate %105 0 Offset 0\n"
2409         "OpDecorate %105 Block\n"
2410         "OpDecorate %var_as_pointers_ssbo DescriptorSet 0\n"
2411         "OpDecorate %var_as_pointers_ssbo Binding 1\n"
2412         // types, constants and variables
2413         "%2 = OpTypeVoid\n"
2414         "%3 = OpTypeFunction %2\n"
2415         "%6 = OpTypeFloat 32\n"
2416         "%7 = OpTypePointer Function %6\n"
2417         "%9 = OpConstant %6 0\n"
2418         "%11 = OpConstant %6 2\n"
2419         "%12 = OpTypeVector %6 3\n"
2420         "%13 = OpTypePointer Function %12\n"
2421         "%15 = OpConstant %6 0.25\n"
2422         "%16 = OpConstant %6 0.5\n"
2423         "%17 = OpConstant %6 1\n"
2424         "%18 = OpConstantComposite %12 %15 %16 %17\n"
2425         "%20 = OpConstant %6 -1\n"
2426         "%21 = OpConstantComposite %12 %9 %9 %20\n"
2427         "%type_uint32 = OpTypeInt 32 0\n"
2428         "%23 = OpTypePointer Function %type_uint32\n"
2429         "%25 = OpTypeVector %type_uint32 3\n"
2430         "%26 = OpTypePointer Input %25\n"
2431         "%27 = OpVariable %26 Input\n"
2432         "%28 = OpConstant %type_uint32 0\n"
2433         "%29 = OpTypePointer Input %type_uint32\n"
2434         "%33 = OpVariable %26 Input\n"
2435         "%37 = OpTypeRuntimeArray %type_uint32\n"
2436         "%38 = OpTypeStruct %37\n"
2437         "%39 = OpTypePointer StorageBuffer %38\n"
2438         "%var_tlas_indices = OpVariable %39 StorageBuffer\n"
2439         "%type_int32 = OpTypeInt 32 1\n"
2440         "%c_int32_0 = OpConstant %type_int32 0\n"
2441         "%45 = OpTypePointer StorageBuffer %type_uint32\n"
2442         "%48 = OpTypeRuntimeArray %type_uint32\n"
2443         "%49 = OpTypeStruct %48\n"
2444         "%50 = OpTypePointer StorageBuffer %49\n"
2445         "%var_result = OpVariable %50 StorageBuffer\n"
2446         "%55 = OpConstant %type_uint32 2\n"
2447         "%56 = OpConstant %type_uint32 1\n"
2448         "%58 = OpTypeVector %type_uint32 2\n"
2449         "%59 = OpTypePointer RayPayloadNV %58\n"
2450         "%60 = OpVariable %59 RayPayloadNV\n"
2451         "%type_as = OpTypeAccelerationStructureKHR\n"
2452         "%66 = OpConstant %type_uint32 500\n"
2453         "%67 = OpTypeArray %type_as %66\n"
2454         "%68 = OpTypePointer UniformConstant %67\n"
2455         "%var_as_arr_ptr = OpVariable %68 UniformConstant\n"
2456         "%72 = OpTypePointer UniformConstant %type_as\n"
2457         "%75 = OpConstant %type_uint32 16\n"
2458         "%76 = OpConstant %type_uint32 255\n"
2459         "%87 = OpConstant %type_uint32 5\n"
2460         "%91 = OpConstant %type_uint32 3\n"
2461 
2462         // <changed_section>
2463         "%104 = OpTypeRuntimeArray %58\n"
2464         "%105 = OpTypeStruct %104\n"
2465         "%106 = OpTypePointer StorageBuffer %105\n"
2466         "%var_as_pointers_ssbo = OpVariable %106 StorageBuffer\n"
2467         "%type_uint64_ssbo_ptr = OpTypePointer StorageBuffer %58\n"
2468         // </changed_section>
2469 
2470         // void main()
2471         "%4 = OpFunction %2 None %3\n"
2472         "%5 = OpLabel\n"
2473         "%8 = OpVariable %7 Function\n"
2474         "%10 = OpVariable %7 Function\n"
2475         "%14 = OpVariable %13 Function\n"
2476         "%19 = OpVariable %13 Function\n"
2477         "%24 = OpVariable %23 Function\n"
2478         "%32 = OpVariable %23 Function\n"
2479         "%36 = OpVariable %23 Function\n"
2480         "OpStore %8 %9\n"
2481         "OpStore %10 %11\n"
2482         "OpStore %14 %18\n"
2483         "OpStore %19 %21\n"
2484         "%30 = OpAccessChain %29 %27 %28\n"
2485         "%31 = OpLoad %type_uint32 %30\n"
2486         "OpStore %24 %31\n"
2487         "%34 = OpAccessChain %29 %33 %28\n"
2488         "%35 = OpLoad %type_uint32 %34\n"
2489         "OpStore %32 %35\n"
2490         "%43 = OpLoad %type_uint32 %24\n"
2491         "%44 = OpCopyObject %type_uint32 %43\n"
2492         "%46 = OpAccessChain %45 %var_tlas_indices %c_int32_0 %44\n"
2493         "%47 = OpLoad %type_uint32 %46\n"
2494         "OpStore %36 %47\n"
2495         // atomicAdd
2496         "%52 = OpLoad %type_uint32 %24\n"
2497         "%53 = OpCopyObject %type_uint32 %52\n"
2498         "%54 = OpAccessChain %45 %var_result %c_int32_0 %53\n"
2499         "%57 = OpAtomicIAdd %type_uint32 %54 %56 %28 %55\n"
2500         // setup payload
2501         "%61 = OpLoad %type_uint32 %24\n"
2502         "%62 = OpLoad %type_uint32 %32\n"
2503         "%63 = OpIAdd %type_uint32 %61 %62\n"
2504         "%64 = OpCompositeConstruct %58 %63 %28\n"
2505         "OpStore %60 %64\n"
2506         // trace rays using tlas from array
2507         "%70 = OpLoad %type_uint32 %36\n"
2508         "%71 = OpCopyObject %type_uint32 %70\n"
2509         "%73 = OpAccessChain %72 %var_as_arr_ptr %71\n"
2510         "%74 = OpLoad %type_as %73\n"
2511         "%77 = OpLoad %12 %14\n"
2512         "%78 = OpLoad %6 %8\n"
2513         "%79 = OpLoad %12 %19\n"
2514         "%80 = OpLoad %6 %10\n"
2515         "OpTraceRayKHR %74 %75 %76 %28 %28 %28 %77 %78 %79 %80 %60\n"
2516         // atomicAdd
2517         "%81 = OpLoad %type_uint32 %24\n"
2518         "%82 = OpLoad %type_uint32 %32\n"
2519         "%83 = OpIMul %type_uint32 %82 %55\n"
2520         "%84 = OpIAdd %type_uint32 %81 %83\n"
2521         "%85 = OpCopyObject %type_uint32 %84\n"
2522         "%86 = OpAccessChain %45 %var_result %c_int32_0 %85\n"
2523         "%88 = OpAtomicIAdd %type_uint32 %86 %56 %28 %87\n"
2524         // setup payload
2525         "%89 = OpLoad %type_uint32 %24\n"
2526         "%90 = OpLoad %type_uint32 %32\n"
2527         "%92 = OpIMul %type_uint32 %90 %91\n"
2528         "%93 = OpIAdd %type_uint32 %89 %92\n"
2529         "%94 = OpCompositeConstruct %58 %93 %56\n"
2530         "OpStore %60 %94\n"
2531         // trace rays using pointers to tlas
2532         "%95 = OpLoad %type_uint32 %36\n"
2533         "%as_index = OpCopyObject %type_uint32 %95\n"
2534 
2535         // <changed_section> OLD
2536         "%as_device_addres_ptr = OpAccessChain %type_uint64_ssbo_ptr %var_as_pointers_ssbo %c_int32_0 "
2537         "%as_index\n"
2538         "%as_device_addres = OpLoad %58 %as_device_addres_ptr\n"
2539         "%as_to_use = OpConvertUToAccelerationStructureKHR %type_as %as_device_addres\n"
2540         // </changed_section>
2541 
2542         "%99 = OpLoad %12 %14\n"
2543         "%100 = OpLoad %6 %8\n"
2544         "%101 = OpLoad %12 %19\n"
2545         "%102 = OpLoad %6 %10\n"
2546         "OpTraceRayKHR %as_to_use %75 %76 %28 %28 %28 %99 %100 %101 %102 %60\n"
2547         "OpReturn\n"
2548         "OpFunctionEnd\n";
2549     programCollection.spirvAsmSources.add("rgen") << rgenSource << spvBuildOptions;
2550 
2551     std::string chitSource = "#version 460 core\n"
2552                              "#extension GL_EXT_ray_tracing : require\n"
2553                              "#extension GL_EXT_nonuniform_qualifier : enable\n"
2554                              "layout(location = 0) rayPayloadInEXT uvec2 payload;\n"
2555                              "\n"
2556                              "layout(set = 0, binding = 3) writeonly buffer Result {\n"
2557                              "    uint value[];\n"
2558                              "} result;\n"
2559                              "void main()\n"
2560                              "{\n"
2561                              // payload.y is 0 or 1 so we will add 3 or 7 (just two prime numbers)
2562                              "    atomicAdd(result.value[nonuniformEXT(payload.x)], 3 + payload.y * 4);\n"
2563                              "}\n";
2564     programCollection.glslSources.add("chit") << glu::ClosestHitSource(chitSource) << glslBuildOptions;
2565 }
2566 
createInstance(Context & context) const2567 TestInstance *RayTracingASDynamicIndexingTestCase::createInstance(Context &context) const
2568 {
2569     return new RayTracingASDynamicIndexingTestInstance(context);
2570 }
2571 
RayTracingASDynamicIndexingTestInstance(Context & context)2572 RayTracingASDynamicIndexingTestInstance::RayTracingASDynamicIndexingTestInstance(Context &context)
2573     : vkt::TestInstance(context)
2574 {
2575 }
2576 
iterate(void)2577 tcu::TestStatus RayTracingASDynamicIndexingTestInstance::iterate(void)
2578 {
2579     const InstanceInterface &vki            = m_context.getInstanceInterface();
2580     const DeviceInterface &vkd              = m_context.getDeviceInterface();
2581     const VkDevice device                   = m_context.getDevice();
2582     const VkPhysicalDevice physicalDevice   = m_context.getPhysicalDevice();
2583     const uint32_t queueFamilyIndex         = m_context.getUniversalQueueFamilyIndex();
2584     const VkQueue queue                     = m_context.getUniversalQueue();
2585     Allocator &allocator                    = m_context.getDefaultAllocator();
2586     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
2587     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
2588     const uint32_t tlasCount                = 500; // changing this will require also changing shaders
2589     const uint32_t activeTlasCount          = 32;  // number of tlas out of <tlasCount> that will be active
2590 
2591     const Move<VkDescriptorSetLayout> descriptorSetLayout =
2592         DescriptorSetLayoutBuilder()
2593             .addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, ALL_RAY_TRACING_STAGES)
2594             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2595                               ALL_RAY_TRACING_STAGES) // pointers to all acceleration structures
2596             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2597                               ALL_RAY_TRACING_STAGES) // ssbo with indices of all acceleration structures
2598             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES) // ssbo with result values
2599             .build(vkd, device);
2600 
2601     const Move<VkDescriptorPool> descriptorPool =
2602         DescriptorPoolBuilder()
2603             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount)
2604             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2605             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2606             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2607             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2608     const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
2609 
2610     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
2611     rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
2612                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
2613     rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
2614                                   createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
2615 
2616     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
2617     Move<VkPipeline> pipeline                   = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
2618     de::MovePtr<BufferWithMemory> raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
2619         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
2620     de::MovePtr<BufferWithMemory> hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
2621         vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
2622 
2623     const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
2624         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
2625                                           shaderGroupHandleSize, shaderGroupHandleSize);
2626     const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2627     const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
2628         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
2629                                           shaderGroupHandleSize, shaderGroupHandleSize);
2630     const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2631 
2632     const VkDeviceSize pointerBufferSize = tlasCount * sizeof(VkDeviceAddress);
2633     const VkBufferCreateInfo pointerBufferCreateInfo =
2634         makeBufferCreateInfo(pointerBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2635     de::MovePtr<BufferWithMemory> pointerBuffer = de::MovePtr<BufferWithMemory>(
2636         new BufferWithMemory(vkd, device, allocator, pointerBufferCreateInfo,
2637                              MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
2638 
2639     const VkDeviceSize indicesBufferSize = activeTlasCount * sizeof(uint32_t);
2640     const VkBufferCreateInfo indicesBufferCreateInfo =
2641         makeBufferCreateInfo(indicesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2642     de::MovePtr<BufferWithMemory> indicesBuffer = de::MovePtr<BufferWithMemory>(
2643         new BufferWithMemory(vkd, device, allocator, indicesBufferCreateInfo, MemoryRequirement::HostVisible));
2644 
2645     const VkDeviceSize resultBufferSize = activeTlasCount * sizeof(uint32_t) * 4;
2646     const VkBufferCreateInfo resultBufferCreateInfo =
2647         makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2648     de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
2649         new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2650 
2651     const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
2652     const Move<VkCommandBuffer> cmdBuffer =
2653         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2654 
2655     de::SharedPtr<BottomLevelAccelerationStructure> blas =
2656         de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
2657     std::vector<de::MovePtr<TopLevelAccelerationStructure>> tlasVect(tlasCount);
2658     std::vector<VkDeviceAddress> tlasPtrVect(tlasCount);
2659     std::vector<VkAccelerationStructureKHR> tlasVkVect;
2660 
2661     // randomly scatter active AS across the range
2662     deRandom rnd;
2663     deRandom_init(&rnd, 123);
2664     std::set<uint32_t> asIndicesSet;
2665     while (asIndicesSet.size() < activeTlasCount)
2666         asIndicesSet.insert(deRandom_getUint32(&rnd) % tlasCount);
2667 
2668     // fill indices buffer
2669     uint32_t helperIndex       = 0;
2670     auto &indicesBufferAlloc   = indicesBuffer->getAllocation();
2671     uint32_t *indicesBufferPtr = reinterpret_cast<uint32_t *>(indicesBufferAlloc.getHostPtr());
2672     std::for_each(asIndicesSet.begin(), asIndicesSet.end(),
2673                   [&helperIndex, indicesBufferPtr](const uint32_t &index) { indicesBufferPtr[helperIndex++] = index; });
2674     vk::flushAlloc(vkd, device, indicesBufferAlloc);
2675 
2676     // clear result buffer
2677     auto &resultBufferAlloc = resultBuffer->getAllocation();
2678     void *resultBufferPtr   = resultBufferAlloc.getHostPtr();
2679     deMemset(resultBufferPtr, 0, static_cast<size_t>(resultBufferSize));
2680     vk::flushAlloc(vkd, device, resultBufferAlloc);
2681 
2682     beginCommandBuffer(vkd, *cmdBuffer, 0u);
2683     {
2684         // build bottom level acceleration structure
2685         blas->setGeometryData(
2686             {
2687                 {0.0, 0.0, 0.0},
2688                 {1.0, 0.0, 0.0},
2689                 {0.0, 1.0, 0.0},
2690             },
2691             true, VK_GEOMETRY_OPAQUE_BIT_KHR);
2692 
2693         blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2694 
2695         // build top level acceleration structures
2696         for (uint32_t tlasIndex = 0; tlasIndex < tlasCount; ++tlasIndex)
2697         {
2698             auto &tlas = tlasVect[tlasIndex];
2699             tlas       = makeTopLevelAccelerationStructure();
2700             tlas->setInstanceCount(1);
2701             tlas->addInstance(blas);
2702             if (!asIndicesSet.count(tlasIndex))
2703             {
2704                 // tlas that are not in asIndicesSet should be empty but it is hard to do
2705                 // that with current cts utils so we are marking them as inactive instead
2706                 tlas->setInactiveInstances(true);
2707             }
2708             tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2709 
2710             // get acceleration structure device address
2711             const VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {
2712                 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, // VkStructureType                sType
2713                 nullptr,        // const void*                    pNext
2714                 *tlas->getPtr() // VkAccelerationStructureKHR    accelerationStructure
2715             };
2716             VkDeviceAddress vkda   = vkd.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
2717             tlasPtrVect[tlasIndex] = vkda;
2718         }
2719 
2720         // fill pointer buffer
2721         vkd.cmdUpdateBuffer(*cmdBuffer, **pointerBuffer, 0, pointerBufferSize, tlasPtrVect.data());
2722 
2723         // wait for data transfers
2724         const VkMemoryBarrier bufferUploadBarrier =
2725             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
2726         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2727                                  VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &bufferUploadBarrier, 1u);
2728 
2729         // wait for as build
2730         const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
2731                                                                  VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
2732         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
2733                                  VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &asBuildBarrier, 1u);
2734 
2735         tlasVkVect.reserve(tlasCount);
2736         for (auto &tlas : tlasVect)
2737             tlasVkVect.push_back(*tlas->getPtr());
2738 
2739         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
2740             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
2741             nullptr,                                                           // const void* pNext;
2742             tlasCount,                                                         // uint32_t accelerationStructureCount;
2743             tlasVkVect.data(), // const VkAccelerationStructureKHR* pAccelerationStructures;
2744         };
2745 
2746         const vk::VkDescriptorBufferInfo pointerBufferInfo =
2747             makeDescriptorBufferInfo(**pointerBuffer, 0u, VK_WHOLE_SIZE);
2748         const vk::VkDescriptorBufferInfo indicesBufferInfo =
2749             makeDescriptorBufferInfo(**indicesBuffer, 0u, VK_WHOLE_SIZE);
2750         const vk::VkDescriptorBufferInfo resultInfo = makeDescriptorBufferInfo(**resultBuffer, 0u, VK_WHOLE_SIZE);
2751 
2752         DescriptorSetUpdateBuilder()
2753             .writeArray(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
2754                         VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount,
2755                         &accelerationStructureWriteDescriptorSet)
2756             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
2757                          VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &pointerBufferInfo)
2758             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u),
2759                          VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indicesBufferInfo)
2760             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u),
2761                          VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo)
2762             .update(vkd, device);
2763 
2764         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
2765                                   &descriptorSet.get(), 0, nullptr);
2766 
2767         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
2768 
2769         cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
2770                      &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, activeTlasCount, 1, 1);
2771 
2772         const VkMemoryBarrier postTraceMemoryBarrier =
2773             makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2774         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
2775                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
2776     }
2777     endCommandBuffer(vkd, *cmdBuffer);
2778 
2779     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2780 
2781     invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
2782                                 resultBuffer->getAllocation().getOffset(), resultBufferSize);
2783 
2784     // verify result buffer
2785     uint32_t failures         = 0;
2786     const uint32_t *resultPtr = reinterpret_cast<uint32_t *>(resultBuffer->getAllocation().getHostPtr());
2787     for (uint32_t index = 0; index < activeTlasCount; ++index)
2788     {
2789         failures += (resultPtr[0 * activeTlasCount + index] != 2) + (resultPtr[1 * activeTlasCount + index] != 3) +
2790                     (resultPtr[2 * activeTlasCount + index] != 5) + (resultPtr[3 * activeTlasCount + index] != 7);
2791     }
2792 
2793     if (failures)
2794         return tcu::TestStatus::fail(de::toString(failures) + " failures, " +
2795                                      de::toString(4 * activeTlasCount - failures) + " are ok");
2796     return tcu::TestStatus::pass("Pass");
2797 }
2798 
2799 // Tests the vkGetDeviceAccelerationStructureKHR routine
2800 class RayTracingDeviceASCompabilityKHRTestInstance : public TestInstance
2801 {
2802 public:
RayTracingDeviceASCompabilityKHRTestInstance(Context & context,const de::SharedPtr<TestParams> params)2803     RayTracingDeviceASCompabilityKHRTestInstance(Context &context, const de::SharedPtr<TestParams> params)
2804         : TestInstance(context)
2805         , m_params(params)
2806     {
2807     }
2808 
2809     tcu::TestStatus iterate(void) override;
2810 
2811 protected:
2812     template <class ASType>
2813     bool performTest(VkCommandPool cmdPool, VkCommandBuffer cmdBuffer,
2814                      const std::vector<de::SharedPtr<ASType>> sourceStructures,
2815                      const std::vector<VkDeviceSize> &copySizes, const std::vector<VkDeviceSize> &compactSizes);
2816 
2817     VkAccelerationStructureCompatibilityKHR getDeviceASCompatibilityKHR(const uint8_t *versionInfoData);
2818     std::string getUUIDsString(const uint8_t *header) const;
2819 
2820 private:
2821     const de::SharedPtr<TestParams> m_params;
2822 };
2823 
2824 // Tests for updating botto-level AS(s) address(es) in top-level AS's header
2825 class RayTracingHeaderBottomAddressTestInstance : public TestInstance
2826 {
2827 public:
RayTracingHeaderBottomAddressTestInstance(Context & context,const de::SharedPtr<TestParams> params)2828     RayTracingHeaderBottomAddressTestInstance(Context &context, const de::SharedPtr<TestParams> params)
2829         : TestInstance(context)
2830         , m_params(params)
2831     {
2832     }
2833     tcu::TestStatus iterate(void) override;
2834 
2835 protected:
2836     de::SharedPtr<TopLevelAccelerationStructure> prepareTopAccelerationStructure(const DeviceInterface &vk,
2837                                                                                  VkDevice device, Allocator &allocator,
2838                                                                                  VkCommandBuffer cmdBuffer);
2839 
2840     bool areAddressesTheSame(const std::vector<uint64_t> &addresses,
2841                              const SerialStorage::AccelerationStructureHeader *header);
2842 
2843     bool areAddressesDifferent(const std::vector<uint64_t> &addresses1, const std::vector<uint64_t> &addresses2);
2844 
2845 private:
2846     const de::SharedPtr<TestParams> m_params;
2847 };
2848 
2849 class RayTracingDeviceASCompabilityKHRTestCase : public TestCase
2850 {
2851 public:
RayTracingDeviceASCompabilityKHRTestCase(tcu::TestContext & ctx,const char * name,const de::SharedPtr<TestParams> params)2852     RayTracingDeviceASCompabilityKHRTestCase(tcu::TestContext &ctx, const char *name,
2853                                              const de::SharedPtr<TestParams> params)
2854         : TestCase(ctx, name)
2855         , m_params(params)
2856     {
2857     }
2858 
2859     void checkSupport(Context &context) const override;
createInstance(Context & context) const2860     TestInstance *createInstance(Context &context) const override
2861     {
2862         return new RayTracingDeviceASCompabilityKHRTestInstance(context, m_params);
2863     }
2864 
2865 private:
2866     de::SharedPtr<TestParams> m_params;
2867 };
2868 
2869 class RayTracingHeaderBottomAddressTestCase : public TestCase
2870 {
2871 public:
RayTracingHeaderBottomAddressTestCase(tcu::TestContext & ctx,const char * name,const de::SharedPtr<TestParams> params)2872     RayTracingHeaderBottomAddressTestCase(tcu::TestContext &ctx, const char *name,
2873                                           const de::SharedPtr<TestParams> params)
2874         : TestCase(ctx, name)
2875         , m_params(params)
2876     {
2877     }
2878 
2879     void checkSupport(Context &context) const override;
createInstance(Context & context) const2880     TestInstance *createInstance(Context &context) const override
2881     {
2882         return new RayTracingHeaderBottomAddressTestInstance(context, m_params);
2883     }
2884 
2885 private:
2886     de::SharedPtr<TestParams> m_params;
2887 };
2888 
checkSupport(Context & context) const2889 void RayTracingDeviceASCompabilityKHRTestCase ::checkSupport(Context &context) const
2890 {
2891     context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2892     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2893 
2894     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
2895         context.getAccelerationStructureFeatures();
2896     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
2897         accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
2898         TCU_THROW(NotSupportedError,
2899                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
2900 
2901     // Check supported vertex format.
2902     checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
2903                                                  m_params->vertexFormat);
2904 }
2905 
checkSupport(Context & context) const2906 void RayTracingHeaderBottomAddressTestCase ::checkSupport(Context &context) const
2907 {
2908     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2909 
2910     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
2911         context.getAccelerationStructureFeatures();
2912     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
2913         accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
2914         TCU_THROW(NotSupportedError,
2915                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
2916 
2917     // Check supported vertex format.
2918     checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(),
2919                                                  m_params->vertexFormat);
2920 }
2921 
getDeviceASCompatibilityKHR(const uint8_t * versionInfoData)2922 VkAccelerationStructureCompatibilityKHR RayTracingDeviceASCompabilityKHRTestInstance::getDeviceASCompatibilityKHR(
2923     const uint8_t *versionInfoData)
2924 {
2925     const VkDevice device      = m_context.getDevice();
2926     const DeviceInterface &vkd = m_context.getDeviceInterface();
2927 
2928     VkAccelerationStructureCompatibilityKHR compability = VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR;
2929 
2930     const VkAccelerationStructureVersionInfoKHR versionInfo = {
2931         VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR, // sType
2932         nullptr,                                                   // pNext
2933         versionInfoData                                            // pVersionData
2934     };
2935 
2936     vkd.getDeviceAccelerationStructureCompatibilityKHR(device, &versionInfo, &compability);
2937 
2938     return compability;
2939 }
2940 
getUUIDsString(const uint8_t * header) const2941 std::string RayTracingDeviceASCompabilityKHRTestInstance::getUUIDsString(const uint8_t *header) const
2942 {
2943     std::stringstream ss;
2944 
2945     int offset         = 0;
2946     const int widths[] = {4, 2, 2, 2, 6};
2947 
2948     for (int h = 0; h < 2; ++h)
2949     {
2950         if (h)
2951             ss << ' ';
2952 
2953         for (int w = 0; w < DE_LENGTH_OF_ARRAY(widths); ++w)
2954         {
2955             if (w)
2956                 ss << '-';
2957 
2958             for (int i = 0; i < widths[w]; ++i)
2959                 ss << std::hex << std::uppercase << static_cast<int>(header[i + offset]);
2960 
2961             offset += widths[w];
2962         }
2963     }
2964 
2965     return ss.str();
2966 }
2967 
iterate(void)2968 tcu::TestStatus RayTracingDeviceASCompabilityKHRTestInstance::iterate(void)
2969 {
2970     const DeviceInterface &vkd      = m_context.getDeviceInterface();
2971     const VkDevice device           = m_context.getDevice();
2972     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2973     const VkQueue queue             = m_context.getUniversalQueue();
2974     Allocator &allocator            = m_context.getDefaultAllocator();
2975 
2976     const Move<VkCommandPool> cmdPool =
2977         createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2978     const Move<VkCommandBuffer> cmdBuffer =
2979         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2980 
2981     bool result = false;
2982 
2983     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomStructures;
2984     std::vector<VkAccelerationStructureKHR> bottomHandles;
2985     std::vector<de::SharedPtr<TopLevelAccelerationStructure>> topStructures;
2986     std::vector<VkAccelerationStructureKHR> topHandles;
2987     Move<VkQueryPool> queryPoolCompact;
2988     Move<VkQueryPool> queryPoolSerial;
2989     std::vector<VkDeviceSize> compactSizes;
2990     std::vector<VkDeviceSize> serialSizes;
2991 
2992     beginCommandBuffer(vkd, *cmdBuffer, 0u);
2993 
2994     bottomStructures = m_params->testConfiguration->initBottomAccelerationStructures(m_context, *m_params);
2995     for (auto &blas : bottomStructures)
2996     {
2997         blas->setBuildType(m_params->buildType);
2998         blas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
2999         blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3000         bottomHandles.push_back(*(blas->getPtr()));
3001     }
3002 
3003     if (m_params->operationTarget == OT_TOP_ACCELERATION)
3004     {
3005         de::MovePtr<TopLevelAccelerationStructure> tlas =
3006             m_params->testConfiguration->initTopAccelerationStructure(m_context, *m_params, bottomStructures);
3007         tlas->setBuildType(m_params->buildType);
3008         tlas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
3009         tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3010         topHandles.push_back(*(tlas->getPtr()));
3011         topStructures.push_back(de::SharedPtr<TopLevelAccelerationStructure>(tlas.release()));
3012     }
3013 
3014     const uint32_t queryCount = uint32_t(
3015         (m_params->operationTarget == OT_BOTTOM_ACCELERATION) ? bottomStructures.size() : topStructures.size());
3016     const std::vector<VkAccelerationStructureKHR> &handles =
3017         (m_params->operationTarget == OT_BOTTOM_ACCELERATION) ? bottomHandles : topHandles;
3018 
3019     // query compact size
3020     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3021         queryPoolCompact =
3022             makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
3023     queryAccelerationStructureSize(vkd, device, *cmdBuffer, handles, m_params->buildType, *queryPoolCompact,
3024                                    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, compactSizes);
3025 
3026     // query serialization size
3027     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3028         queryPoolSerial =
3029             makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
3030     queryAccelerationStructureSize(vkd, device, *cmdBuffer, handles, m_params->buildType, queryPoolSerial.get(),
3031                                    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, serialSizes);
3032 
3033     endCommandBuffer(vkd, *cmdBuffer);
3034     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
3035 
3036     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3037     {
3038         VK_CHECK(vkd.getQueryPoolResults(device, *queryPoolCompact, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3039                                          compactSizes.data(), sizeof(VkDeviceSize),
3040                                          VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3041         VK_CHECK(vkd.getQueryPoolResults(device, *queryPoolSerial, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3042                                          serialSizes.data(), sizeof(VkDeviceSize),
3043                                          VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3044 
3045         vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
3046     }
3047 
3048     if (m_params->operationTarget == OT_BOTTOM_ACCELERATION)
3049         result = performTest<BottomLevelAccelerationStructure>(*cmdPool, *cmdBuffer, bottomStructures, compactSizes,
3050                                                                serialSizes);
3051     else
3052         result =
3053             performTest<TopLevelAccelerationStructure>(*cmdPool, *cmdBuffer, topStructures, compactSizes, serialSizes);
3054 
3055     return result ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
3056 }
3057 
3058 template <class ASType>
performTest(VkCommandPool cmdPool,VkCommandBuffer cmdBuffer,const std::vector<de::SharedPtr<ASType>> sourceStructures,const std::vector<VkDeviceSize> & compactSizes,const std::vector<VkDeviceSize> & serialSizes)3059 bool RayTracingDeviceASCompabilityKHRTestInstance::performTest(
3060     VkCommandPool cmdPool, VkCommandBuffer cmdBuffer, const std::vector<de::SharedPtr<ASType>> sourceStructures,
3061     const std::vector<VkDeviceSize> &compactSizes, const std::vector<VkDeviceSize> &serialSizes)
3062 {
3063     const VkQueue queue        = m_context.getUniversalQueue();
3064     const VkDevice device      = m_context.getDevice();
3065     const DeviceInterface &vkd = m_context.getDeviceInterface();
3066     Allocator &allocator       = m_context.getDefaultAllocator();
3067 
3068     const uint32_t sourceStructuresCount = uint32_t(sourceStructures.size());
3069 
3070     Move<VkQueryPool> queryPoolCompactSerial;
3071     std::vector<VkDeviceSize> compactSerialSizes;
3072 
3073     std::vector<VkAccelerationStructureKHR> compactHandles;
3074     std::vector<de::SharedPtr<ASType>> compactStructures;
3075 
3076     std::vector<de::SharedPtr<SerialStorage>> sourceSerialized;
3077     std::vector<de::SharedPtr<SerialStorage>> compactSerialized;
3078 
3079     // make compact copy of acceleration structure
3080     {
3081         beginCommandBuffer(vkd, cmdBuffer, 0u);
3082 
3083         for (size_t i = 0; i < sourceStructuresCount; ++i)
3084         {
3085             de::MovePtr<ASType> asCopy = makeAccelerationStructure<ASType>();
3086             asCopy->setBuildType(m_params->buildType);
3087             asCopy->createAndCopyFrom(vkd, device, cmdBuffer, allocator, sourceStructures[i].get(), compactSizes[i],
3088                                       0u);
3089             compactHandles.push_back(*(asCopy->getPtr()));
3090             compactStructures.push_back(de::SharedPtr<ASType>(asCopy.release()));
3091         }
3092 
3093         // query serialization size of compact acceleration structures
3094         if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3095             queryPoolCompactSerial = makeQueryPool(
3096                 vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, sourceStructuresCount);
3097         queryAccelerationStructureSize(
3098             vkd, device, cmdBuffer, compactHandles, m_params->buildType, *queryPoolCompactSerial,
3099             VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, compactSerialSizes);
3100 
3101         endCommandBuffer(vkd, cmdBuffer);
3102         submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3103 
3104         if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3105         {
3106             VK_CHECK(vkd.getQueryPoolResults(device, *queryPoolCompactSerial, 0u, sourceStructuresCount,
3107                                              (sourceStructuresCount * sizeof(VkDeviceSize)), compactSerialSizes.data(),
3108                                              sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3109             vkd.resetCommandPool(device, cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
3110         }
3111     }
3112 
3113     // serialize both structures to memory
3114     {
3115         beginCommandBuffer(vkd, cmdBuffer, 0u);
3116 
3117         for (size_t i = 0; i < sourceStructuresCount; ++i)
3118         {
3119             sourceSerialized.push_back(de::SharedPtr<SerialStorage>(
3120                 new SerialStorage(vkd, device, allocator, m_params->buildType, serialSizes[i])));
3121             sourceStructures[i]->serialize(vkd, device, cmdBuffer, sourceSerialized.back().get());
3122 
3123             compactSerialized.push_back(de::SharedPtr<SerialStorage>(
3124                 new SerialStorage(vkd, device, allocator, m_params->buildType, compactSerialSizes[i])));
3125             compactStructures[i]->serialize(vkd, device, cmdBuffer, compactSerialized.back().get());
3126         }
3127 
3128         endCommandBuffer(vkd, cmdBuffer);
3129         submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3130     }
3131 
3132     // verify compatibility
3133     bool result = true;
3134     for (size_t i = 0; result && (i < sourceStructuresCount); ++i)
3135     {
3136         const uint8_t *s_header = static_cast<const uint8_t *>(sourceSerialized[i]->getHostAddressConst().hostAddress);
3137         const uint8_t *c_header = static_cast<const uint8_t *>(compactSerialized[i]->getHostAddressConst().hostAddress);
3138 
3139         const auto s_compability = getDeviceASCompatibilityKHR(s_header);
3140         const auto c_compability = getDeviceASCompatibilityKHR(c_header);
3141 
3142         result &= ((s_compability == c_compability) &&
3143                    (s_compability == VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR));
3144 
3145         if (!result)
3146         {
3147             tcu::TestLog &log = m_context.getTestContext().getLog();
3148 
3149             log << tcu::TestLog::Message << getUUIDsString(s_header) << " serialized AS compability failed"
3150                 << tcu::TestLog::EndMessage;
3151             log << tcu::TestLog::Message << getUUIDsString(c_header) << " compact AS compability failed"
3152                 << tcu::TestLog::EndMessage;
3153         }
3154     }
3155 
3156     return result;
3157 }
3158 
prepareTopAccelerationStructure(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkCommandBuffer cmdBuffer)3159 de::SharedPtr<TopLevelAccelerationStructure> RayTracingHeaderBottomAddressTestInstance::prepareTopAccelerationStructure(
3160     const DeviceInterface &vk, VkDevice device, Allocator &allocator, VkCommandBuffer cmdBuffer)
3161 {
3162     const std::vector<tcu::Vec3> geometryData = {
3163         {0.0, 0.0, 0.0},
3164         {1.0, 0.0, 0.0},
3165         {0.0, 1.0, 0.0},
3166     };
3167 
3168     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottoms;
3169 
3170     if (TopTestType::IDENTICAL_INSTANCES == m_params->topTestType)
3171     {
3172         auto blas = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3173         blas->setBuildType(m_params->buildType);
3174         blas->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3175         blas->createAndBuild(vk, device, cmdBuffer, allocator);
3176         for (uint32_t i = 0; i < m_params->width; ++i)
3177         {
3178             bottoms.emplace_back(blas);
3179         }
3180     }
3181     else if (TopTestType::DIFFERENT_INSTANCES == m_params->topTestType)
3182     {
3183         for (uint32_t i = 0; i < m_params->width; ++i)
3184         {
3185             auto blas =
3186                 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3187             blas->setBuildType(m_params->buildType);
3188             blas->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3189             blas->createAndBuild(vk, device, cmdBuffer, allocator);
3190             bottoms.emplace_back(blas);
3191         }
3192     }
3193     else // TTT_MIX_INSTANCES == m_params->topTestType
3194     {
3195         for (uint32_t i = 0; i < m_params->width; ++i)
3196         {
3197             {
3198                 auto blas1 =
3199                     de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3200                 blas1->setBuildType(m_params->buildType);
3201                 blas1->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3202                 blas1->createAndBuild(vk, device, cmdBuffer, allocator);
3203                 bottoms.emplace_back(blas1);
3204             }
3205 
3206             {
3207                 auto blas2 =
3208                     de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3209                 blas2->setBuildType(m_params->buildType);
3210                 blas2->setGeometryData(geometryData, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3211                 blas2->createAndBuild(vk, device, cmdBuffer, allocator);
3212                 bottoms.emplace_back(blas2);
3213             }
3214         }
3215     }
3216 
3217     const std::size_t instanceCount = bottoms.size();
3218 
3219     de::MovePtr<TopLevelAccelerationStructure> tlas = makeTopLevelAccelerationStructure();
3220     tlas->setBuildType(m_params->buildType);
3221     tlas->setInstanceCount(instanceCount);
3222 
3223     for (std::size_t i = 0; i < instanceCount; ++i)
3224     {
3225         const VkTransformMatrixKHR transformMatrixKHR = {{
3226             //  float matrix[3][4];
3227             {1.0f, 0.0f, 0.0f, (float)i},
3228             {0.0f, 1.0f, 0.0f, (float)i},
3229             {0.0f, 0.0f, 1.0f, 0.0f},
3230         }};
3231         tlas->addInstance(bottoms[i], transformMatrixKHR, 0, m_params->cullMask, 0u,
3232                           getCullFlags((m_params->cullFlags)));
3233     }
3234 
3235     tlas->createAndBuild(vk, device, cmdBuffer, allocator);
3236 
3237     return de::SharedPtr<TopLevelAccelerationStructure>(tlas.release());
3238 }
3239 
iterate(void)3240 tcu::TestStatus RayTracingHeaderBottomAddressTestInstance::iterate(void)
3241 {
3242     const DeviceInterface &vkd = m_context.getDeviceInterface();
3243     const VkDevice device      = m_context.getDevice();
3244     const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3245     const VkQueue queue        = m_context.getUniversalQueue();
3246     Allocator &allocator       = m_context.getDefaultAllocator();
3247 
3248     const Move<VkCommandPool> cmdPool =
3249         createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, familyIndex);
3250     const Move<VkCommandBuffer> cmdBuffer =
3251         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3252 
3253     beginCommandBuffer(vkd, *cmdBuffer, 0);
3254     de::SharedPtr<TopLevelAccelerationStructure> src =
3255         prepareTopAccelerationStructure(vkd, device, allocator, *cmdBuffer);
3256     endCommandBuffer(vkd, *cmdBuffer);
3257     submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3258 
3259     de::MovePtr<TopLevelAccelerationStructure> dst = makeTopLevelAccelerationStructure();
3260 
3261     const std::vector<uint64_t> inAddrs     = src->getSerializingAddresses(vkd, device);
3262     const std::vector<VkDeviceSize> inSizes = src->getSerializingSizes(vkd, device, queue, familyIndex);
3263 
3264     const SerialInfo serialInfo(inAddrs, inSizes);
3265     SerialStorage deepStorage(vkd, device, allocator, m_params->buildType, serialInfo);
3266 
3267     // make deep serialization - top-level AS width bottom-level structures that it owns
3268     vkd.resetCommandBuffer(*cmdBuffer, 0);
3269     beginCommandBuffer(vkd, *cmdBuffer, 0);
3270     src->serialize(vkd, device, *cmdBuffer, &deepStorage);
3271     endCommandBuffer(vkd, *cmdBuffer);
3272     submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3273 
3274     // deserialize all from the previous step to a new top-level AS
3275     // bottom-level structure addresses should be updated when deep data is deserialized
3276     vkd.resetCommandBuffer(*cmdBuffer, 0);
3277     beginCommandBuffer(vkd, *cmdBuffer, 0);
3278     dst->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, &deepStorage);
3279     endCommandBuffer(vkd, *cmdBuffer);
3280     submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3281 
3282     SerialStorage shallowStorage(vkd, device, allocator, m_params->buildType, inSizes[0]);
3283 
3284     // make shallow serialization - only top-level AS without bottom-level structures
3285     vkd.resetCommandBuffer(*cmdBuffer, 0);
3286     beginCommandBuffer(vkd, *cmdBuffer, 0);
3287     dst->serialize(vkd, device, *cmdBuffer, &shallowStorage);
3288     endCommandBuffer(vkd, *cmdBuffer);
3289     submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
3290 
3291     // get data to verification
3292     const std::vector<uint64_t> outAddrs                     = dst->getSerializingAddresses(vkd, device);
3293     const SerialStorage::AccelerationStructureHeader *header = shallowStorage.getASHeader();
3294 
3295     return (areAddressesDifferent(inAddrs, outAddrs) && areAddressesTheSame(outAddrs, header)) ?
3296                tcu::TestStatus::pass("") :
3297                tcu::TestStatus::fail("");
3298 }
3299 
areAddressesTheSame(const std::vector<uint64_t> & addresses,const SerialStorage::AccelerationStructureHeader * header)3300 bool RayTracingHeaderBottomAddressTestInstance::areAddressesTheSame(
3301     const std::vector<uint64_t> &addresses, const SerialStorage::AccelerationStructureHeader *header)
3302 {
3303     const uint32_t cbottoms = uint32_t(addresses.size() - 1);
3304 
3305     // header should contain the same number of handles as serialized/deserialized top-level AS
3306     if (cbottoms != header->handleCount)
3307         return false;
3308 
3309     std::set<uint64_t> refAddrs;
3310     std::set<uint64_t> checkAddrs;
3311 
3312     // distinct, squach and sort address list
3313     for (uint32_t i = 0; i < cbottoms; ++i)
3314     {
3315         refAddrs.insert(addresses[i + 1]);
3316         checkAddrs.insert(header->handleArray[i]);
3317     }
3318 
3319     return std::equal(refAddrs.begin(), refAddrs.end(), checkAddrs.begin());
3320 }
3321 
areAddressesDifferent(const std::vector<uint64_t> & addresses1,const std::vector<uint64_t> & addresses2)3322 bool RayTracingHeaderBottomAddressTestInstance::areAddressesDifferent(const std::vector<uint64_t> &addresses1,
3323                                                                       const std::vector<uint64_t> &addresses2)
3324 {
3325     // the number of addresses must be equal
3326     if (addresses1.size() != addresses2.size())
3327         return false;
3328 
3329     // adresses of top-level AS must differ
3330     if (addresses1[0] == addresses2[0])
3331         return false;
3332 
3333     std::set<uint64_t> addrs1;
3334     std::set<uint64_t> addrs2;
3335     uint32_t matches        = 0;
3336     const uint32_t cbottoms = uint32_t(addresses1.size() - 1);
3337 
3338     for (uint32_t i = 0; i < cbottoms; ++i)
3339     {
3340         addrs1.insert(addresses1[i + 1]);
3341         addrs2.insert(addresses2[i + 1]);
3342     }
3343 
3344     // the first addresses set must not contain any address from the second addresses set
3345     for (auto &addr1 : addrs1)
3346     {
3347         if (addrs2.end() != addrs2.find(addr1))
3348             ++matches;
3349     }
3350 
3351     return (matches == 0);
3352 }
3353 
3354 template <class X, class... Y>
makeShared(Y &&...ctorArgs)3355 inline de::SharedPtr<X> makeShared(Y &&...ctorArgs)
3356 {
3357     return de::SharedPtr<X>(new X(std::forward<Y>(ctorArgs)...));
3358 }
3359 template <class X, class... Y>
makeMovePtr(Y &&...ctorArgs)3360 inline de::MovePtr<X> makeMovePtr(Y &&...ctorArgs)
3361 {
3362     return de::MovePtr<X>(new X(std::forward<Y>(ctorArgs)...));
3363 }
3364 template <class X>
makeSharedFrom(const X & x)3365 inline de::SharedPtr<X> makeSharedFrom(const X &x)
3366 {
3367     return makeShared<X>(x);
3368 }
3369 
3370 struct QueryPoolResultsParams
3371 {
3372     enum class Type
3373     {
3374         StructureSize,
3375         PointerCount
3376     } queryType;
3377     VkAccelerationStructureBuildTypeKHR buildType;
3378     uint32_t blasCount;
3379     bool inVkBuffer;
3380     bool compacted;
3381 };
3382 
3383 typedef de::SharedPtr<const QueryPoolResultsParams> QueryPoolResultsParamsPtr;
3384 
3385 struct ASInterface;
3386 typedef de::SharedPtr<ASInterface> ASInterfacePtr;
3387 
3388 class QueryPoolResultsInstance : public TestInstance
3389 {
3390 public:
3391     using TlasPtr = de::SharedPtr<TopLevelAccelerationStructure>;
3392     using BlasPtr = de::SharedPtr<BottomLevelAccelerationStructure>;
3393 
QueryPoolResultsInstance(Context & context,QueryPoolResultsParamsPtr params)3394     QueryPoolResultsInstance(Context &context, QueryPoolResultsParamsPtr params)
3395         : TestInstance(context)
3396         , m_params(params)
3397     {
3398     }
3399     auto prepareBottomAccStructures(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
3400                                     VkCommandBuffer cmdBuffer) -> std::vector<BlasPtr>;
3401     TlasPtr prepareTopAccStructure(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
3402                                    VkCommandBuffer cmdBuffer, const std::vector<BlasPtr> &bottoms);
3403 
3404 protected:
3405     const QueryPoolResultsParamsPtr m_params;
3406 };
3407 
3408 struct ASInterface
3409 {
~ASInterfacevkt::RayTracing::__anon7ff8e1c10111::ASInterface3410     virtual ~ASInterface()
3411     {
3412     }
3413     virtual VkAccelerationStructureKHR getPtr() const                               = 0;
3414     virtual VkAccelerationStructureBuildSizesInfoKHR getStructureBuildSizes() const = 0;
3415     virtual ASInterfacePtr clone(Context &ctx, VkAccelerationStructureBuildTypeKHR buildType, const VkCommandBuffer cmd,
3416                                  VkDeviceSize size)                                 = 0;
3417 };
3418 
3419 template <class>
3420 struct ASAllocator;
3421 template <>
3422 struct ASAllocator<QueryPoolResultsInstance::TlasPtr>
3423 {
3424     typedef QueryPoolResultsInstance::TlasPtr TlasPtr;
allocvkt::RayTracing::__anon7ff8e1c10111::ASAllocator3425     static TlasPtr alloc()
3426     {
3427         return TlasPtr(makeTopLevelAccelerationStructure().release());
3428     }
3429 };
3430 template <>
3431 struct ASAllocator<QueryPoolResultsInstance::BlasPtr>
3432 {
3433     typedef QueryPoolResultsInstance::BlasPtr BlasPtr;
allocvkt::RayTracing::__anon7ff8e1c10111::ASAllocator3434     static BlasPtr alloc()
3435     {
3436         return BlasPtr(makeBottomLevelAccelerationStructure().release());
3437     }
3438 };
3439 
3440 template <class SharedPtrType>
3441 struct ASInterfaceImpl : ASInterface
3442 {
3443     SharedPtrType m_source;
ASInterfaceImplvkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3444     ASInterfaceImpl(SharedPtrType src) : m_source(src)
3445     {
3446     }
getPtrvkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3447     virtual VkAccelerationStructureKHR getPtr() const override
3448     {
3449         return *m_source->getPtr();
3450     }
getStructureBuildSizesvkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3451     virtual VkAccelerationStructureBuildSizesInfoKHR getStructureBuildSizes() const override
3452     {
3453         return m_source->getStructureBuildSizes();
3454     }
clonevkt::RayTracing::__anon7ff8e1c10111::ASInterfaceImpl3455     virtual ASInterfacePtr clone(Context &ctx, VkAccelerationStructureBuildTypeKHR buildType, const VkCommandBuffer cmd,
3456                                  VkDeviceSize size) override
3457     {
3458         const DeviceInterface &vk = ctx.getDeviceInterface();
3459         const VkDevice device     = ctx.getDevice();
3460         Allocator &allocator      = ctx.getDefaultAllocator();
3461 
3462         auto ptr = ASAllocator<SharedPtrType>::alloc();
3463         ptr->setBuildType(buildType);
3464         ptr->setBuildFlags(m_source->getBuildFlags());
3465         ptr->create(vk, device, allocator, size);
3466         ptr->copyFrom(vk, device, cmd, m_source.get(), false);
3467         return de::SharedPtr<ASInterface>(new ASInterfaceImpl(ptr));
3468     }
3469 };
3470 
3471 template <class SharedPtrType>
makeASInterfacePtr(SharedPtrType asPtr)3472 ASInterfacePtr makeASInterfacePtr(SharedPtrType asPtr)
3473 {
3474     return ASInterfacePtr(new ASInterfaceImpl<SharedPtrType>(asPtr));
3475 }
3476 
3477 class QueryPoolResultsSizeInstance : public QueryPoolResultsInstance
3478 {
3479 public:
QueryPoolResultsSizeInstance(Context & context,QueryPoolResultsParamsPtr params)3480     QueryPoolResultsSizeInstance(Context &context, QueryPoolResultsParamsPtr params)
3481         : QueryPoolResultsInstance(context, params)
3482     {
3483     }
3484     TestStatus iterate(void) override;
3485     auto makeCopyOfStructures(const std::vector<ASInterfacePtr> &structs, const std::vector<VkDeviceSize> sizes)
3486         -> std::vector<ASInterfacePtr>;
3487     auto getStructureSizes(const std::vector<VkAccelerationStructureKHR> &handles) -> std::vector<VkDeviceSize>;
3488 };
3489 
3490 class QueryPoolResultsPointersInstance : public QueryPoolResultsInstance
3491 {
3492 public:
QueryPoolResultsPointersInstance(Context & context,QueryPoolResultsParamsPtr params)3493     QueryPoolResultsPointersInstance(Context &context, QueryPoolResultsParamsPtr params)
3494         : QueryPoolResultsInstance(context, params)
3495     {
3496     }
3497 
3498     TestStatus iterate(void) override;
3499 };
3500 
3501 class QueryPoolResultsCase : public TestCase
3502 {
3503 public:
QueryPoolResultsCase(TestContext & ctx,const char * name,QueryPoolResultsParamsPtr params)3504     QueryPoolResultsCase(TestContext &ctx, const char *name, QueryPoolResultsParamsPtr params)
3505         : TestCase(ctx, name)
3506         , m_params(params)
3507     {
3508     }
3509     void checkSupport(Context &context) const override;
3510     TestInstance *createInstance(Context &context) const override;
3511 
3512     template <class T, class P = T (*)[1], class R = decltype(std::begin(*std::declval<P>()))>
makeStdBeginEnd(void * p,uint32_t n)3513     static auto makeStdBeginEnd(void *p, uint32_t n) -> std::pair<R, R>
3514     {
3515         auto tmp   = std::begin(*P(p));
3516         auto begin = tmp;
3517         std::advance(tmp, n);
3518         return {begin, tmp};
3519     }
3520 
3521 private:
3522     const QueryPoolResultsParamsPtr m_params;
3523 };
3524 
createInstance(Context & context) const3525 TestInstance *QueryPoolResultsCase::createInstance(Context &context) const
3526 {
3527     switch (m_params->queryType)
3528     {
3529     case QueryPoolResultsParams::Type::StructureSize:
3530         return new QueryPoolResultsSizeInstance(context, m_params);
3531     case QueryPoolResultsParams::Type::PointerCount:
3532         return new QueryPoolResultsPointersInstance(context, m_params);
3533     }
3534     TCU_THROW(InternalError, "Unknown test type");
3535     return nullptr;
3536 }
3537 
checkSupport(Context & context) const3538 void QueryPoolResultsCase::checkSupport(Context &context) const
3539 {
3540     context.requireDeviceFunctionality(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
3541     context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
3542 
3543     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
3544         context.getAccelerationStructureFeatures();
3545     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
3546         accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
3547         TCU_THROW(NotSupportedError,
3548                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
3549 
3550     const VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR &maintenance1FeaturesKHR =
3551         context.getRayTracingMaintenance1Features();
3552     if (maintenance1FeaturesKHR.rayTracingMaintenance1 == VK_FALSE)
3553         TCU_THROW(NotSupportedError,
3554                   "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingMaintenance1");
3555 }
3556 
prepareBottomAccStructures(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkCommandBuffer cmdBuffer)3557 auto QueryPoolResultsInstance::prepareBottomAccStructures(const DeviceInterface &vk, VkDevice device,
3558                                                           Allocator &allocator, VkCommandBuffer cmdBuffer)
3559     -> std::vector<BlasPtr>
3560 {
3561     std::vector<Vec3> triangle = {
3562         {0.0, 0.0, 0.0},
3563         {0.5, 0.0, 0.0},
3564         {0.0, 0.5, 0.0},
3565     };
3566 
3567     const uint32_t triangleCount = ((1 + m_params->blasCount) * m_params->blasCount) / 2;
3568     const float angle            = (4.0f * std::acos(0.0f)) / float(triangleCount);
3569     auto rotateCcwZ              = [&](const Vec3 &p, const Vec3 &center) -> tcu::Vec3
3570     {
3571         const float s = std::sin(angle);
3572         const float c = std::cos(angle);
3573         const auto t  = p - center;
3574         return tcu::Vec3(c * t.x() - s * t.y(), s * t.x() + c * t.y(), t.z()) + center;
3575     };
3576     auto nextGeometry = [&]() -> void
3577     {
3578         for (auto &vertex : triangle)
3579             vertex = rotateCcwZ(vertex, Vec3(0.0f, 0.0f, 0.0f));
3580     };
3581 
3582     std::vector<BlasPtr> bottoms(m_params->blasCount);
3583 
3584     for (uint32_t b = 0; b < m_params->blasCount; ++b)
3585     {
3586         BlasPtr blas(makeBottomLevelAccelerationStructure().release());
3587 
3588         blas->setBuildType(m_params->buildType);
3589         if (m_params->compacted)
3590         {
3591             blas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
3592         }
3593         blas->addGeometry(triangle, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3594         for (uint32_t geom = b; geom < m_params->blasCount; ++geom)
3595         {
3596             nextGeometry();
3597             blas->addGeometry(triangle, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
3598         }
3599 
3600         blas->createAndBuild(vk, device, cmdBuffer, allocator);
3601 
3602         bottoms[b] = blas;
3603     }
3604 
3605     return bottoms;
3606 }
3607 
prepareTopAccStructure(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkCommandBuffer cmdBuffer,const std::vector<BlasPtr> & bottoms)3608 auto QueryPoolResultsInstance::prepareTopAccStructure(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
3609                                                       VkCommandBuffer cmdBuffer, const std::vector<BlasPtr> &bottoms)
3610     -> TlasPtr
3611 {
3612     const std::size_t instanceCount = bottoms.size();
3613 
3614     de::MovePtr<TopLevelAccelerationStructure> tlas = makeTopLevelAccelerationStructure();
3615     tlas->setBuildType(m_params->buildType);
3616     if (m_params->compacted)
3617     {
3618         tlas->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
3619     }
3620     tlas->setInstanceCount(instanceCount);
3621 
3622     for (std::size_t i = 0; i < instanceCount; ++i)
3623     {
3624         tlas->addInstance(bottoms[i], identityMatrix3x4, 0, 0xFFu, 0u, VkGeometryInstanceFlagsKHR(0));
3625     }
3626 
3627     tlas->createAndBuild(vk, device, cmdBuffer, allocator);
3628 
3629     return TlasPtr(tlas.release());
3630 }
3631 
getStructureSizes(const std::vector<VkAccelerationStructureKHR> & handles)3632 auto QueryPoolResultsSizeInstance::getStructureSizes(const std::vector<VkAccelerationStructureKHR> &handles)
3633     -> std::vector<VkDeviceSize>
3634 {
3635     const DeviceInterface &vk  = m_context.getDeviceInterface();
3636     const VkDevice device      = m_context.getDevice();
3637     const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3638     const VkQueue queue        = m_context.getUniversalQueue();
3639     Allocator &allocator       = m_context.getDefaultAllocator();
3640 
3641     const Move<VkCommandPool> cmdPool = createCommandPool(vk, device, 0, familyIndex);
3642     const Move<VkCommandBuffer> cmdBuffer =
3643         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3644 
3645     const uint32_t queryCount = static_cast<uint32_t>(handles.size());
3646 
3647     Move<VkQueryPool> queryPoolSize =
3648         makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, queryCount);
3649     Move<VkQueryPool> queryPoolSerial =
3650         makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
3651     Move<VkQueryPool> queryPoolCompact =
3652         m_params->compacted ?
3653             makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount) :
3654             Move<VkQueryPool>();
3655 
3656     de::MovePtr<BufferWithMemory> buffer;
3657     std::vector<VkDeviceSize> sizeSizes(queryCount, 0);
3658     std::vector<VkDeviceSize> serialSizes(queryCount, 0);
3659     std::vector<VkDeviceSize> compactSizes(queryCount, 0);
3660 
3661     if (m_params->inVkBuffer)
3662     {
3663         const auto vci = makeBufferCreateInfo((m_params->compacted ? 3 : 2) * queryCount * sizeof(VkDeviceSize),
3664                                               VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3665         buffer         = makeMovePtr<BufferWithMemory>(vk, device, allocator, vci,
3666                                                MemoryRequirement::Coherent | MemoryRequirement::HostVisible);
3667     }
3668 
3669     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3670     {
3671         beginCommandBuffer(vk, *cmdBuffer, 0);
3672 
3673         vk.cmdResetQueryPool(*cmdBuffer, *queryPoolSize, 0, queryCount);
3674         vk.cmdResetQueryPool(*cmdBuffer, *queryPoolSerial, 0, queryCount);
3675         if (m_params->compacted)
3676         {
3677             vk.cmdResetQueryPool(*cmdBuffer, *queryPoolCompact, 0, queryCount);
3678         }
3679 
3680         vk.cmdWriteAccelerationStructuresPropertiesKHR(
3681             *cmdBuffer, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, *queryPoolSize, 0);
3682         vk.cmdWriteAccelerationStructuresPropertiesKHR(*cmdBuffer, queryCount, handles.data(),
3683                                                        VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR,
3684                                                        *queryPoolSerial, 0);
3685 
3686         if (m_params->compacted)
3687         {
3688             vk.cmdWriteAccelerationStructuresPropertiesKHR(*cmdBuffer, queryCount, handles.data(),
3689                                                            VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
3690                                                            *queryPoolCompact, 0);
3691         }
3692 
3693         if (m_params->inVkBuffer)
3694         {
3695             vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolSize, 0, queryCount, **buffer,
3696                                        (0 * queryCount * sizeof(VkDeviceSize)), sizeof(VkDeviceSize),
3697                                        VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3698             vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolSerial, 0, queryCount, **buffer,
3699                                        (1 * queryCount * sizeof(VkDeviceSize)), sizeof(VkDeviceSize),
3700                                        VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3701             if (m_params->compacted)
3702             {
3703                 vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolCompact, 0, queryCount, **buffer,
3704                                            (2 * queryCount * sizeof(VkDeviceSize)), sizeof(VkDeviceSize),
3705                                            VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3706             }
3707         }
3708         endCommandBuffer(vk, *cmdBuffer);
3709         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3710 
3711         if (m_params->inVkBuffer)
3712         {
3713             Allocation &alloc = buffer->getAllocation();
3714             invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
3715 
3716             uint8_t *ptrSize   = reinterpret_cast<uint8_t *>(alloc.getHostPtr());
3717             uint8_t *ptrSerial = ptrSize + queryCount * sizeof(VkDeviceSize);
3718 
3719             auto rangeSize   = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(ptrSize, queryCount);
3720             auto rangeSerial = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(ptrSerial, queryCount);
3721 
3722             std::copy_n(rangeSize.first, queryCount, sizeSizes.begin());
3723             std::copy_n(rangeSerial.first, queryCount, serialSizes.begin());
3724 
3725             if (m_params->compacted)
3726             {
3727                 auto ptrCompact   = ptrSize + 2 * queryCount * sizeof(VkDeviceSize);
3728                 auto rangeCompact = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(ptrCompact, queryCount);
3729                 std::copy_n(rangeCompact.first, queryCount, compactSizes.begin());
3730             }
3731         }
3732         else
3733         {
3734             VK_CHECK(vk.getQueryPoolResults(device, *queryPoolSize, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3735                                             sizeSizes.data(), sizeof(VkDeviceSize),
3736                                             VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3737             VK_CHECK(vk.getQueryPoolResults(device, *queryPoolSerial, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3738                                             serialSizes.data(), sizeof(VkDeviceSize),
3739                                             VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3740             if (m_params->compacted)
3741             {
3742                 VK_CHECK(vk.getQueryPoolResults(
3743                     device, *queryPoolCompact, 0u, queryCount, queryCount * sizeof(VkDeviceSize), compactSizes.data(),
3744                     sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3745             }
3746         }
3747     }
3748     else
3749     {
3750         vk.writeAccelerationStructuresPropertiesKHR(
3751             device, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR,
3752             queryCount * sizeof(VkDeviceSize), sizeSizes.data(), sizeof(VkDeviceSize));
3753         vk.writeAccelerationStructuresPropertiesKHR(
3754             device, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR,
3755             queryCount * sizeof(VkDeviceSize), serialSizes.data(), sizeof(VkDeviceSize));
3756         if (m_params->compacted)
3757         {
3758             vk.writeAccelerationStructuresPropertiesKHR(
3759                 device, queryCount, handles.data(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
3760                 queryCount * sizeof(VkDeviceSize), compactSizes.data(), sizeof(VkDeviceSize));
3761         }
3762     }
3763 
3764     sizeSizes.insert(sizeSizes.end(), serialSizes.begin(), serialSizes.end());
3765     sizeSizes.insert(sizeSizes.end(), compactSizes.begin(), compactSizes.end());
3766 
3767     return sizeSizes;
3768 }
3769 
makeCopyOfStructures(const std::vector<ASInterfacePtr> & structs,const std::vector<VkDeviceSize> sizes)3770 auto QueryPoolResultsSizeInstance::makeCopyOfStructures(const std::vector<ASInterfacePtr> &structs,
3771                                                         const std::vector<VkDeviceSize> sizes)
3772     -> std::vector<ASInterfacePtr>
3773 {
3774     const DeviceInterface &vk = m_context.getDeviceInterface();
3775     const VkDevice device     = m_context.getDevice();
3776     const VkQueue queue       = m_context.getUniversalQueue();
3777 
3778     Move<VkCommandPool> cmdPool;
3779     Move<VkCommandBuffer> cmdBuffer;
3780 
3781     std::vector<ASInterfacePtr> copies;
3782 
3783     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3784     {
3785         const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3786         cmdPool                    = createCommandPool(vk, device, 0, familyIndex);
3787         cmdBuffer                  = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3788         beginCommandBuffer(vk, *cmdBuffer, 0u);
3789     }
3790 
3791     for (auto begin = structs.begin(), i = begin; i != structs.end(); ++i)
3792     {
3793         copies.push_back((*i)->clone(m_context, m_params->buildType, *cmdBuffer, sizes.at(std::distance(begin, i))));
3794     }
3795 
3796     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3797     {
3798         endCommandBuffer(vk, *cmdBuffer);
3799         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3800     }
3801 
3802     return copies;
3803 }
3804 
iterate(void)3805 TestStatus QueryPoolResultsSizeInstance::iterate(void)
3806 {
3807     const DeviceInterface &vk  = m_context.getDeviceInterface();
3808     const VkDevice device      = m_context.getDevice();
3809     const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3810     const VkQueue queue        = m_context.getUniversalQueue();
3811     Allocator &allocator       = m_context.getDefaultAllocator();
3812 
3813     const Move<VkCommandPool> cmdPool =
3814         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, familyIndex);
3815     const Move<VkCommandBuffer> cmdBuffer =
3816         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3817 
3818     beginCommandBuffer(vk, *cmdBuffer, 0);
3819     const std::vector<BlasPtr> bottoms = prepareBottomAccStructures(vk, device, allocator, *cmdBuffer);
3820     TlasPtr tlas                       = prepareTopAccStructure(vk, device, allocator, *cmdBuffer, bottoms);
3821     endCommandBuffer(vk, *cmdBuffer);
3822     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3823 
3824     const uint32_t queryCount = m_params->blasCount + 1;
3825     std::vector<VkAccelerationStructureKHR> handles(queryCount);
3826     handles[0] = *tlas->getPtr();
3827     std::transform(bottoms.begin(), bottoms.end(), std::next(handles.begin()),
3828                    [](const BlasPtr &blas) { return *blas->getPtr(); });
3829 
3830     // only the first queryCount elements are results from ACCELERATION_STRUCTURE_SIZE queries.
3831     const std::vector<VkDeviceSize> sourceSizes = getStructureSizes(handles);
3832 
3833     std::vector<ASInterfacePtr> sourceStructures;
3834     sourceStructures.push_back(makeASInterfacePtr(tlas));
3835     for (BlasPtr blas : bottoms)
3836         sourceStructures.push_back(makeASInterfacePtr(blas));
3837 
3838     std::vector<ASInterfacePtr> copies = makeCopyOfStructures(sourceStructures, sourceSizes);
3839     std::transform(copies.begin(), copies.end(), handles.begin(),
3840                    [](const ASInterfacePtr &intf) { return intf->getPtr(); });
3841 
3842     const std::vector<VkDeviceSize> copySizes = getStructureSizes(handles);
3843 
3844     // verification
3845     bool pass = true;
3846     for (uint32_t i = 0; pass && i < queryCount; ++i)
3847     {
3848         pass = sourceSizes.at(i) == copySizes.at(i);
3849     }
3850 
3851     return pass ? TestStatus::pass("") : TestStatus::fail("");
3852 }
3853 
iterate(void)3854 TestStatus QueryPoolResultsPointersInstance::iterate(void)
3855 {
3856     const DeviceInterface &vk  = m_context.getDeviceInterface();
3857     const VkDevice device      = m_context.getDevice();
3858     const uint32_t familyIndex = m_context.getUniversalQueueFamilyIndex();
3859     const VkQueue queue        = m_context.getUniversalQueue();
3860     Allocator &allocator       = m_context.getDefaultAllocator();
3861 
3862     const Move<VkCommandPool> cmdPool =
3863         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, familyIndex);
3864     const Move<VkCommandBuffer> cmdBuffer =
3865         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3866 
3867     beginCommandBuffer(vk, *cmdBuffer, 0);
3868     const std::vector<BlasPtr> bottoms = prepareBottomAccStructures(vk, device, allocator, *cmdBuffer);
3869     TlasPtr tlas                       = prepareTopAccStructure(vk, device, allocator, *cmdBuffer, bottoms);
3870     endCommandBuffer(vk, *cmdBuffer);
3871     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3872 
3873     const uint32_t queryCount = m_params->blasCount + 1;
3874     std::vector<VkAccelerationStructureKHR> handles(queryCount);
3875     handles[0] = *tlas.get()->getPtr();
3876     std::transform(bottoms.begin(), bottoms.end(), std::next(handles.begin()),
3877                    [](const BlasPtr &blas) { return *blas.get()->getPtr(); });
3878 
3879     const VkQueryType queryType       = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR;
3880     Move<VkQueryPool> queryPoolCounts = makeQueryPool(vk, device, queryType, queryCount);
3881 
3882     de::MovePtr<BufferWithMemory> buffer;
3883     std::vector<VkDeviceSize> pointerCounts(queryCount, 123u);
3884 
3885     if (m_params->inVkBuffer)
3886     {
3887         const auto vci = makeBufferCreateInfo(queryCount * sizeof(VkDeviceSize), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3888         buffer         = makeMovePtr<BufferWithMemory>(vk, device, allocator, vci,
3889                                                MemoryRequirement::Coherent | MemoryRequirement::HostVisible);
3890     }
3891 
3892     if (m_params->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3893     {
3894         beginCommandBuffer(vk, *cmdBuffer, 0);
3895         vk.cmdResetQueryPool(*cmdBuffer, *queryPoolCounts, 0, queryCount);
3896         vk.cmdWriteAccelerationStructuresPropertiesKHR(*cmdBuffer, queryCount, handles.data(), queryType,
3897                                                        *queryPoolCounts, 0);
3898         if (m_params->inVkBuffer)
3899         {
3900             vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPoolCounts, 0, queryCount, **buffer, 0 /*offset*/,
3901                                        sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3902         }
3903         endCommandBuffer(vk, *cmdBuffer);
3904         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3905 
3906         if (m_params->inVkBuffer)
3907         {
3908             Allocation &alloc = buffer->getAllocation();
3909             invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
3910             auto rangeCounts = QueryPoolResultsCase::makeStdBeginEnd<VkDeviceSize>(alloc.getHostPtr(), queryCount);
3911             std::copy_n(rangeCounts.first, queryCount, pointerCounts.begin());
3912         }
3913         else
3914         {
3915             VK_CHECK(vk.getQueryPoolResults(device, *queryPoolCounts, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
3916                                             pointerCounts.data(), sizeof(VkDeviceSize),
3917                                             VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3918         }
3919     }
3920     else
3921     {
3922         vk.writeAccelerationStructuresPropertiesKHR(device, queryCount, handles.data(), queryType,
3923                                                     queryCount * sizeof(VkDeviceSize), pointerCounts.data(),
3924                                                     sizeof(VkDeviceSize));
3925     }
3926 
3927     // verification
3928     const std::vector<VkDeviceSize> inSizes = tlas->getSerializingSizes(vk, device, queue, familyIndex);
3929     SerialStorage storage(vk, device, allocator, m_params->buildType, inSizes[0]);
3930 
3931     beginCommandBuffer(vk, *cmdBuffer, 0);
3932     tlas->serialize(vk, device, *cmdBuffer, &storage);
3933     endCommandBuffer(vk, *cmdBuffer);
3934     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3935 
3936     const SerialStorage::AccelerationStructureHeader *header = storage.getASHeader();
3937 
3938     bool pass = (header->handleCount == pointerCounts[0]); // must be the same as bottoms.size()
3939     for (uint32_t i = 1; pass && i < queryCount; ++i)
3940     {
3941         pass = (0 == pointerCounts[i]); // bottoms have no chidren
3942     }
3943 
3944     return pass ? TestStatus::pass("") : TestStatus::fail("");
3945 }
3946 
3947 struct CopyWithinPipelineParams
3948 {
3949     enum class Type
3950     {
3951         StageASCopyBit,
3952         StageAllTransferBit,
3953         AccessSBTReadBit
3954     } type;
3955     uint32_t width;
3956     uint32_t height;
3957     VkAccelerationStructureBuildTypeKHR build;
3958 };
3959 typedef de::SharedPtr<const CopyWithinPipelineParams> CopyWithinPipelineParamsPtr;
3960 
3961 class CopyWithinPipelineInstance : public TestInstance
3962 {
3963 public:
3964     using TlasPtr = de::SharedPtr<TopLevelAccelerationStructure>;
3965     using BlasPtr = de::SharedPtr<BottomLevelAccelerationStructure>;
3966 
CopyWithinPipelineInstance(Context & context,CopyWithinPipelineParamsPtr params)3967     CopyWithinPipelineInstance(Context &context, CopyWithinPipelineParamsPtr params)
3968         : TestInstance(context)
3969         , vk(context.getDeviceInterface())
3970         , device(context.getDevice())
3971         , allocator(context.getDefaultAllocator())
3972         , rgenShader(createShaderModule(vk, device, context.getBinaryCollection().get("rgen")))
3973         , chitShader(createShaderModule(vk, device, context.getBinaryCollection().get("chit")))
3974         , missShader(createShaderModule(vk, device, context.getBinaryCollection().get("miss")))
3975         , m_params(params)
3976         , m_format(VK_FORMAT_R32G32B32A32_SFLOAT)
3977     {
3978     }
3979 
3980 protected:
3981     const DeviceInterface &vk;
3982     const VkDevice device;
3983     Allocator &allocator;
3984     Move<VkShaderModule> rgenShader;
3985     Move<VkShaderModule> chitShader;
3986     Move<VkShaderModule> missShader;
3987     CopyWithinPipelineParamsPtr m_params;
3988     VkFormat m_format;
3989 };
3990 
3991 class CopyBlasInstance : public CopyWithinPipelineInstance
3992 {
3993 public:
CopyBlasInstance(Context & context,CopyWithinPipelineParamsPtr params)3994     CopyBlasInstance(Context &context, CopyWithinPipelineParamsPtr params) : CopyWithinPipelineInstance(context, params)
3995     {
3996     }
3997     TestStatus iterate(void) override;
3998     auto getRefImage(BlasPtr blas) const -> de::MovePtr<BufferWithMemory>;
3999 };
4000 
4001 class CopySBTInstance : public CopyWithinPipelineInstance
4002 {
4003 public:
CopySBTInstance(Context & context,CopyWithinPipelineParamsPtr params)4004     CopySBTInstance(Context &context, CopyWithinPipelineParamsPtr params) : CopyWithinPipelineInstance(context, params)
4005     {
4006     }
4007     TestStatus iterate(void) override;
4008     auto getBufferSizeForSBT(const uint32_t &groupCount, const uint32_t &shaderGroupHandleSize,
4009                              const uint32_t &shaderGroupBaseAlignment) const -> VkDeviceSize;
4010     auto getBufferForSBT(const uint32_t &groupCount, const uint32_t &shaderGroupHandleSize,
4011                          const uint32_t &shaderGroupBaseAlignment) const -> de::MovePtr<BufferWithMemory>;
4012 };
4013 
4014 class PipelineStageASCase : public TestCase
4015 {
4016 public:
PipelineStageASCase(TestContext & ctx,const char * name,CopyWithinPipelineParamsPtr params)4017     PipelineStageASCase(TestContext &ctx, const char *name, CopyWithinPipelineParamsPtr params)
4018         : TestCase(ctx, name)
4019         , m_params(params)
4020     {
4021     }
4022     void initPrograms(SourceCollections &programs) const override;
4023     void checkSupport(Context &context) const override;
4024     TestInstance *createInstance(Context &context) const override;
4025 
4026 private:
4027     CopyWithinPipelineParamsPtr m_params;
4028 };
4029 
4030 namespace u
4031 {
4032 namespace details
4033 {
4034 template <class X, class Y>
4035 struct BarrierMaker
4036 {
4037     const X &m_x;
BarrierMakervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4038     BarrierMaker(const X &x) : m_x(x)
4039     {
4040     }
countvkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4041     uint32_t count() const
4042     {
4043         return 1;
4044     }
pointervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4045     const X *pointer() const
4046     {
4047         return &m_x;
4048     }
4049 };
4050 template <class Y>
4051 struct BarrierMaker<std::false_type, Y>
4052 {
BarrierMakervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4053     BarrierMaker(const std::false_type &)
4054     {
4055     }
countvkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4056     uint32_t count() const
4057     {
4058         return 0;
4059     }
pointervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4060     Y *pointer() const
4061     {
4062         return nullptr;
4063     }
4064 };
4065 template <class Z, uint32_t N>
4066 struct BarrierMaker<const Z[N], Z>
4067 {
4068     const Z (&m_a)[N];
BarrierMakervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4069     BarrierMaker(const Z (&a)[N]) : m_a(a)
4070     {
4071     }
countvkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4072     uint32_t count() const
4073     {
4074         return N;
4075     }
pointervkt::RayTracing::__anon7ff8e1c10111::u::details::BarrierMaker4076     const Z *pointer() const
4077     {
4078         return m_a;
4079     }
4080 };
4081 template <class Mem, class Buf, class Img, class Exp>
4082 struct Sel
4083 {
4084     typedef typename std::remove_cv<Mem>::type t_Mem;
4085     typedef typename std::remove_cv<Buf>::type t_Buf;
4086     typedef typename std::remove_cv<Img>::type t_Img;
4087     typedef std::integral_constant<uint32_t, 0> index0;
4088     typedef std::integral_constant<uint32_t, 1> index1;
4089     typedef std::integral_constant<uint32_t, 2> index2;
4090     typedef std::integral_constant<uint32_t, 3> index3;
4091     using isMem = std::is_same<t_Mem, Exp>;
4092     using isBuf = std::is_same<t_Buf, Exp>;
4093     using isImg = std::is_same<t_Img, Exp>;
4094     template <bool B, class T, class F>
4095     using choose = typename std::conditional<B, T, F>::type;
4096     typedef choose<isMem::value, BarrierMaker<Mem, Exp>,
4097                    choose<isBuf::value, BarrierMaker<Buf, Exp>,
4098                           choose<isImg::value, BarrierMaker<Img, Exp>, BarrierMaker<std::false_type, Exp>>>>
4099         type;
4100     typedef choose<isMem::value, index0, choose<isBuf::value, index1, choose<isImg::value, index2, index3>>> index;
4101 };
4102 } // namespace details
4103 constexpr std::false_type NoneBarriers{};
4104 /**
4105  * @brief    Helper function that makes and populates VkDependencyInfoKHR structure.
4106  * @param    barriers1 - any of VkMemoryBarrier2KHR, VkBufferMemoryBarrier2KHR or VkImageMemoryBarrier2KHR (mandatory param)
4107  * @param    barriers2 - any of VkMemoryBarrier2KHR, VkBufferMemoryBarrier2KHR or VkImageMemoryBarrier2KHR (optional param)
4108  * @param    barriers2 - any of VkMemoryBarrier2KHR, VkBufferMemoryBarrier2KHR or VkImageMemoryBarrier2KHR (optional param)
4109  * @note    The order of the parameters does not matter.
4110  */
4111 template <class Barriers1, class Barriers2 = std::false_type, class Barriers3 = std::false_type>
makeDependency(const Barriers1 & barriers1,const Barriers2 & barriers2=NoneBarriers,const Barriers3 & barriers3=NoneBarriers)4112 VkDependencyInfoKHR makeDependency(const Barriers1 &barriers1, const Barriers2 &barriers2 = NoneBarriers,
4113                                    const Barriers3 &barriers3 = NoneBarriers)
4114 {
4115     auto args               = std::forward_as_tuple(barriers1, barriers2, barriers3, std::false_type());
4116     const uint32_t memIndex = details::Sel<Barriers1, Barriers2, Barriers3, VkMemoryBarrier2KHR>::index::value;
4117     const uint32_t bufIndex = details::Sel<Barriers1, Barriers2, Barriers3, VkBufferMemoryBarrier2KHR>::index::value;
4118     const uint32_t imgIndex = details::Sel<Barriers1, Barriers2, Barriers3, VkImageMemoryBarrier2KHR>::index::value;
4119     typedef typename details::Sel<Barriers1, Barriers2, Barriers3, VkMemoryBarrier2KHR>::type memType;
4120     typedef typename details::Sel<Barriers1, Barriers2, Barriers3, VkBufferMemoryBarrier2KHR>::type bufType;
4121     typedef typename details::Sel<Barriers1, Barriers2, Barriers3, VkImageMemoryBarrier2KHR>::type imgType;
4122     return {
4123         VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,       // VkStructureType sType;
4124         nullptr,                                     // const void* pNext;
4125         VK_DEPENDENCY_BY_REGION_BIT,                 // VkDependencyFlags dependencyFlags;
4126         memType(std::get<memIndex>(args)).count(),   // uint32_t memoryBarrierCount;
4127         memType(std::get<memIndex>(args)).pointer(), // const VkMemoryBarrier2KHR* pMemoryBarriers;
4128         bufType(std::get<bufIndex>(args)).count(),   // uint32_t bufferMemoryBarrierCount;
4129         bufType(std::get<bufIndex>(args)).pointer(), // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers;
4130         imgType(std::get<imgIndex>(args)).count(),   // uint32_t imageMemoryBarrierCount;
4131         imgType(std::get<imgIndex>(args)).pointer()  // const VkImageMemoryBarrier2KHR* pImageMemoryBarriers;
4132     };
4133 }
4134 } // namespace u
4135 
createInstance(Context & context) const4136 TestInstance *PipelineStageASCase::createInstance(Context &context) const
4137 {
4138     de::MovePtr<TestInstance> instance;
4139     switch (m_params->type)
4140     {
4141     case CopyWithinPipelineParams::Type::StageASCopyBit:
4142     case CopyWithinPipelineParams::Type::StageAllTransferBit:
4143         instance = makeMovePtr<CopyBlasInstance>(context, m_params);
4144         break;
4145     case CopyWithinPipelineParams::Type::AccessSBTReadBit:
4146         instance = makeMovePtr<CopySBTInstance>(context, m_params);
4147         break;
4148     }
4149     return instance.release();
4150 }
4151 
initPrograms(SourceCollections & programs) const4152 void PipelineStageASCase::initPrograms(SourceCollections &programs) const
4153 {
4154     const vk::ShaderBuildOptions buildOptions(programs.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
4155     const char endl = '\n';
4156 
4157     {
4158         std::stringstream str;
4159         str << "#version 460 core" << endl
4160             << "#extension GL_EXT_ray_tracing : require" << endl
4161             << "layout(location = 0) rayPayloadEXT vec4 payload;" << endl
4162             << "layout(rgba32f, set = 0, binding = 0) uniform image2D result;" << endl
4163             << "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;" << endl
4164             << "void main()" << endl
4165             << "{" << endl
4166             << "  float rx           = (float(gl_LaunchIDEXT.x) + 0.5) / float(gl_LaunchSizeEXT.x);" << endl
4167             << "  float ry           = (float(gl_LaunchIDEXT.y) + 0.5) / float(gl_LaunchSizeEXT.y);" << endl
4168             << "  payload            = vec4(0.5, 0.5, 0.5, 1.0);" << endl
4169             << "  vec3  orig         = vec3(rx, ry, 1.0);" << endl
4170             << "  vec3  dir          = vec3(0.0, 0.0, -1.0);" << endl
4171             << "  traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, 0xFFu, 0, 0, 0, orig, 0.0, dir, 2.0, 0);" << endl
4172             << "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), payload);" << endl
4173             << "}";
4174         str.flush();
4175         programs.glslSources.add("rgen") << glu::RaygenSource(str.str()) << buildOptions;
4176     }
4177 
4178     {
4179         std::stringstream str;
4180         str << "#version 460 core" << endl
4181             << "#extension GL_EXT_ray_tracing : require" << endl
4182             << "layout(location = 0) rayPayloadInEXT vec4 payload;" << endl
4183             << "void main()" << endl
4184             << "{" << endl
4185             << "  payload = vec4(0.0, 1.0, 0.0, 1.0);" << endl
4186             << "}";
4187         str.flush();
4188         programs.glslSources.add("chit") << glu::ClosestHitSource(str.str()) << buildOptions;
4189     }
4190 
4191     {
4192         std::stringstream str;
4193         str << "#version 460 core" << endl
4194             << "#extension GL_EXT_ray_tracing : require" << endl
4195             << "layout(location = 0) rayPayloadInEXT vec4 payload;" << endl
4196             << "void main()" << endl
4197             << "{" << endl
4198             << "  payload = vec4(1.0, 0.0, 0.0, 1.0);" << endl
4199             << "}";
4200         str.flush();
4201         programs.glslSources.add("miss") << glu::MissSource(str.str()) << buildOptions;
4202     }
4203 }
4204 
checkSupport(Context & context) const4205 void PipelineStageASCase::checkSupport(Context &context) const
4206 {
4207     context.requireInstanceFunctionality(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
4208     context.requireDeviceFunctionality(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
4209     context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
4210     context.requireDeviceFunctionality(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
4211     context.requireDeviceFunctionality(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
4212 
4213     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
4214         context.getAccelerationStructureFeatures();
4215     if (m_params->build == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR &&
4216         accelerationStructureFeaturesKHR.accelerationStructureHostCommands == false)
4217         TCU_THROW(NotSupportedError,
4218                   "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands");
4219 
4220     const VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR &maintenance1FeaturesKHR =
4221         context.getRayTracingMaintenance1Features();
4222     if (maintenance1FeaturesKHR.rayTracingMaintenance1 == VK_FALSE)
4223         TCU_THROW(NotSupportedError,
4224                   "Requires VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR::rayTracingMaintenance1");
4225 
4226     const VkPhysicalDeviceSynchronization2FeaturesKHR &synchronization2Features = context.getSynchronization2Features();
4227     if (synchronization2Features.synchronization2 == VK_FALSE)
4228         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceSynchronization2FeaturesKHR::synchronization2");
4229 
4230     if (m_params->type != CopyWithinPipelineParams::Type::AccessSBTReadBit)
4231     {
4232         context.requireDeviceFunctionality(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
4233         const VkPhysicalDevicePushDescriptorPropertiesKHR &pushDescriptorProperties =
4234             context.getPushDescriptorProperties();
4235         if (pushDescriptorProperties.maxPushDescriptors < 32)
4236             TCU_THROW(NotSupportedError, "Requires VK_KHR_push_descriptor extension");
4237     }
4238 }
4239 
getRefImage(BlasPtr blas) const4240 auto CopyBlasInstance::getRefImage(BlasPtr blas) const -> de::MovePtr<BufferWithMemory>
4241 {
4242     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4243     const VkQueue queue             = m_context.getUniversalQueue();
4244 
4245     const de::MovePtr<RayTracingProperties> rtProps =
4246         makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
4247     const uint32_t shaderGroupHandleSize    = rtProps->getShaderGroupHandleSize();
4248     const uint32_t shaderGroupBaseAlignment = rtProps->getShaderGroupBaseAlignment();
4249 
4250     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_params->width, m_params->height, m_format);
4251     const VkImageSubresourceRange imageSubresourceRange =
4252         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4253     const de::MovePtr<ImageWithMemory> image =
4254         makeMovePtr<ImageWithMemory>(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
4255     const Move<VkImageView> view =
4256         makeImageView(vk, device, **image, VK_IMAGE_VIEW_TYPE_2D, m_format, imageSubresourceRange);
4257 
4258     const uint32_t bufferSize = (m_params->width * m_params->height * mapVkFormat(m_format).getPixelSize());
4259     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4260     de::MovePtr<BufferWithMemory> buffer =
4261         makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4262 
4263     const VkImageSubresourceLayers imageSubresourceLayers =
4264         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4265     const VkBufferImageCopy bufferCopyImageRegion =
4266         makeBufferImageCopy(makeExtent3D(m_params->width, m_params->height, 1u), imageSubresourceLayers);
4267 
4268     de::MovePtr<RayTracingPipeline> rtPipeline = makeMovePtr<RayTracingPipeline>();
4269     rtPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, *rgenShader, 0);
4270     rtPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, *chitShader, 1);
4271     rtPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, *missShader, 2);
4272 
4273     const Move<VkDescriptorPool> descriptorPool =
4274         DescriptorPoolBuilder()
4275             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2)
4276             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 2)
4277             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4278     const Move<VkDescriptorSetLayout> descriptorSetLayout =
4279         DescriptorSetLayoutBuilder()
4280             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4281             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4282             .build(vk, device);
4283     const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
4284 
4285     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
4286     Move<VkPipeline> pipeline                   = rtPipeline->createPipeline(vk, device, *pipelineLayout);
4287 
4288     de::MovePtr<BufferWithMemory> rgenSbt = rtPipeline->createShaderBindingTable(
4289         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
4290     VkStridedDeviceAddressRegionKHR rgenRegion = makeStridedDeviceAddressRegionKHR(
4291         getBufferDeviceAddress(vk, device, **rgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4292     de::MovePtr<BufferWithMemory> chitSbt = rtPipeline->createShaderBindingTable(
4293         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
4294     VkStridedDeviceAddressRegionKHR chitRegion = makeStridedDeviceAddressRegionKHR(
4295         getBufferDeviceAddress(vk, device, **chitSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4296     de::MovePtr<BufferWithMemory> missSbt = rtPipeline->createShaderBindingTable(
4297         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
4298     VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(
4299         getBufferDeviceAddress(vk, device, **missSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4300     const VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(VkDeviceAddress(0), 0, 0);
4301 
4302     const VkClearValue clearValue = {{{0.1f, 0.2f, 0.3f, 0.4f}}};
4303 
4304     const VkImageMemoryBarrier2KHR preClearImageImageBarrier = makeImageMemoryBarrier2(
4305         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 0, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4306         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image,
4307         imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4308     const VkImageMemoryBarrier2KHR postClearImageImageBarrier =
4309         makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
4310                                 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_READ_BIT_KHR,
4311                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image,
4312                                 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4313     const VkDependencyInfoKHR preClearImageDependency  = u::makeDependency(preClearImageImageBarrier);
4314     const VkDependencyInfoKHR postClearImageDependency = u::makeDependency(postClearImageImageBarrier);
4315 
4316     const VkImageMemoryBarrier2KHR postTraceRaysImageBarrier = makeImageMemoryBarrier2(
4317         VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_WRITE_BIT_KHR,
4318         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
4319         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4320     const VkImageMemoryBarrier2KHR postCopyImageImageBarrier = makeImageMemoryBarrier2(
4321         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_HOST_BIT_KHR,
4322         VK_ACCESS_2_HOST_READ_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4323         **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4324     const VkDependencyInfoKHR postTraceRaysDependency = u::makeDependency(postTraceRaysImageBarrier);
4325     const VkDependencyInfoKHR postCopyImageDependency = u::makeDependency(postCopyImageImageBarrier);
4326 
4327     const Move<VkCommandPool> cmdPool =
4328         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
4329     const Move<VkCommandBuffer> cmdBuffer =
4330         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4331 
4332     auto tlas = makeTopLevelAccelerationStructure();
4333     tlas->setBuildType(m_params->build);
4334     tlas->setInstanceCount(1);
4335     tlas->addInstance(blas, identityMatrix3x4, 0, (~0u), 0, VkGeometryInstanceFlagsKHR(0));
4336     beginCommandBuffer(vk, *cmdBuffer);
4337     tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4338     endCommandBuffer(vk, *cmdBuffer);
4339     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4340 
4341     const VkDescriptorImageInfo descriptorImageInfo =
4342         makeDescriptorImageInfo(VkSampler(), *view, VK_IMAGE_LAYOUT_GENERAL);
4343     const VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorTlas{
4344         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
4345         nullptr,                                                           //  const void* pNext;
4346         1,                                                                 //  uint32_t accelerationStructureCount;
4347         tlas->getPtr() //  const VkAccelerationStructureKHR* pAccelerationStructures;
4348     };
4349 
4350     DescriptorSetUpdateBuilder()
4351         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
4352                      VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
4353         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
4354                      VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeDescriptorTlas)
4355         .update(vk, device);
4356 
4357     beginCommandBuffer(vk, *cmdBuffer);
4358     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4359     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4360                              &descriptorSet.get(), 0, nullptr);
4361     vk.cmdPipelineBarrier2(*cmdBuffer, &preClearImageDependency);
4362     vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4363                           &imageSubresourceRange);
4364     vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImageDependency);
4365     cmdTraceRays(vk, *cmdBuffer,
4366                  &rgenRegion, // rgen
4367                  &missRegion, // miss
4368                  &chitRegion, // hit
4369                  &callRegion, // call
4370                  m_params->width, m_params->height, 1);
4371     vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4372     vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffer, 1u,
4373                             &bufferCopyImageRegion);
4374     vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4375     endCommandBuffer(vk, *cmdBuffer);
4376     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4377 
4378     invalidateMappedMemoryRange(vk, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(),
4379                                 bufferSize);
4380 
4381     return buffer;
4382 }
4383 
iterate(void)4384 TestStatus CopyBlasInstance::iterate(void)
4385 {
4386     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4387     const VkQueue queue             = m_context.getUniversalQueue();
4388 
4389     const de::MovePtr<RayTracingProperties> rtProps =
4390         makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
4391     const uint32_t shaderGroupHandleSize    = rtProps->getShaderGroupHandleSize();
4392     const uint32_t shaderGroupBaseAlignment = rtProps->getShaderGroupBaseAlignment();
4393 
4394     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_params->width, m_params->height, m_format);
4395     const VkImageSubresourceRange imageSubresourceRange =
4396         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4397     const de::MovePtr<ImageWithMemory> image =
4398         makeMovePtr<ImageWithMemory>(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
4399     const Move<VkImageView> view =
4400         makeImageView(vk, device, **image, VK_IMAGE_VIEW_TYPE_2D, m_format, imageSubresourceRange);
4401 
4402     const uint32_t bufferSize = (m_params->width * m_params->height * mapVkFormat(m_format).getPixelSize());
4403     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4404     de::MovePtr<BufferWithMemory> resultImageBuffer =
4405         makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4406 
4407     const VkImageSubresourceLayers imageSubresourceLayers =
4408         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4409     const VkBufferImageCopy bufferCopyImageRegion =
4410         makeBufferImageCopy(makeExtent3D(m_params->width, m_params->height, 1u), imageSubresourceLayers);
4411 
4412     de::MovePtr<RayTracingPipeline> rtPipeline = makeMovePtr<RayTracingPipeline>();
4413     rtPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, *rgenShader, 0);
4414     rtPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, *chitShader, 1);
4415     rtPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, *missShader, 2);
4416 
4417     const Move<VkDescriptorSetLayout> descriptorSetLayout =
4418         DescriptorSetLayoutBuilder()
4419             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4420             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4421             .build(vk, device, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
4422 
4423     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
4424     Move<VkPipeline> pipeline                   = rtPipeline->createPipeline(vk, device, *pipelineLayout);
4425 
4426     de::MovePtr<BufferWithMemory> rgenSbt = rtPipeline->createShaderBindingTable(
4427         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
4428     VkStridedDeviceAddressRegionKHR rgenRegion = makeStridedDeviceAddressRegionKHR(
4429         getBufferDeviceAddress(vk, device, **rgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4430     de::MovePtr<BufferWithMemory> chitSbt = rtPipeline->createShaderBindingTable(
4431         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
4432     VkStridedDeviceAddressRegionKHR chitRegion = makeStridedDeviceAddressRegionKHR(
4433         getBufferDeviceAddress(vk, device, **chitSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4434     de::MovePtr<BufferWithMemory> missSbt = rtPipeline->createShaderBindingTable(
4435         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
4436     VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(
4437         getBufferDeviceAddress(vk, device, **missSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4438     const VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(VkDeviceAddress(0), 0, 0);
4439 
4440     const VkClearValue clearValue = {{{0.1f, 0.2f, 0.3f, 0.4f}}};
4441 
4442     const VkImageMemoryBarrier2KHR preClearImageImageBarrier = makeImageMemoryBarrier2(
4443         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 0, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4444         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image,
4445         imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4446     const VkImageMemoryBarrier2KHR postClearImageImageBarrier =
4447         makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
4448                                 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_READ_BIT_KHR,
4449                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image,
4450                                 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4451     const VkDependencyInfoKHR preClearImageDependency  = u::makeDependency(preClearImageImageBarrier);
4452     const VkDependencyInfoKHR postClearImageDependency = u::makeDependency(postClearImageImageBarrier);
4453 
4454     const VkImageMemoryBarrier2KHR postTraceRaysImageBarrier = makeImageMemoryBarrier2(
4455         VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_WRITE_BIT_KHR,
4456         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
4457         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4458     const VkImageMemoryBarrier2KHR postCopyImageImageBarrier = makeImageMemoryBarrier2(
4459         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_HOST_BIT_KHR,
4460         VK_ACCESS_2_HOST_READ_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4461         **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4462     const VkDependencyInfoKHR postTraceRaysDependency = u::makeDependency(postTraceRaysImageBarrier);
4463     const VkDependencyInfoKHR postCopyImageDependency = u::makeDependency(postCopyImageImageBarrier);
4464     const VkPipelineStageFlags2KHR srcStageMask     = m_params->type == CopyWithinPipelineParams::Type::StageASCopyBit ?
4465                                                           VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR :
4466                                                           VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR;
4467     const VkMemoryBarrier2KHR copyBlasMemoryBarrier = makeMemoryBarrier2(
4468         srcStageMask, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
4469         VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR);
4470     const VkDependencyInfoKHR copyBlasDependency = u::makeDependency(copyBlasMemoryBarrier);
4471 
4472     const Move<VkCommandPool> cmdPool =
4473         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
4474     const Move<VkCommandBuffer> cmdBuffer =
4475         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4476 
4477     std::vector<VkDeviceSize> blasSize(1);
4478     BlasPtr blas1(makeBottomLevelAccelerationStructure().release());
4479 
4480     // After this block the blas1 stays on device or host respectively to its build type.
4481     // Once it is created it is asked for the serialization size that will be used for a
4482     // creation of an empty blas2. Probably this size will be bigger than it is needed but
4483     // one thing that is important is it must not be less.
4484     {
4485         const VkQueryType query         = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR;
4486         Move<VkQueryPool> queryPoolSize = makeQueryPool(vk, device, query, 1);
4487         beginCommandBuffer(vk, *cmdBuffer);
4488         blas1->setBuildType(m_params->build);
4489         blas1->setGeometryData({{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
4490         blas1->createAndBuild(vk, device, *cmdBuffer, allocator);
4491         queryAccelerationStructureSize(vk, device, *cmdBuffer, {*blas1->getPtr()}, m_params->build, *queryPoolSize,
4492                                        query, 0u, blasSize);
4493         endCommandBuffer(vk, *cmdBuffer);
4494         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4495         if (m_params->build == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
4496         {
4497             VK_CHECK(vk.getQueryPoolResults(device, *queryPoolSize, 0u, 1, sizeof(VkDeviceSize), blasSize.data(),
4498                                             sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
4499         }
4500     }
4501 
4502     de::MovePtr<BufferWithMemory> referenceImageBuffer = getRefImage(blas1);
4503 
4504     // Create blas2 as empty struct
4505     BlasPtr blas2(makeBottomLevelAccelerationStructure().release());
4506     blas2->create(vk, device, allocator, blasSize[0]);
4507 
4508     auto tlas = makeTopLevelAccelerationStructure();
4509     tlas->setBuildType(m_params->build);
4510     tlas->setInstanceCount(1);
4511     tlas->addInstance(blas2, identityMatrix3x4, 0, (~0u), 0, VkGeometryInstanceFlagsKHR(0));
4512 
4513     const VkCopyAccelerationStructureInfoKHR copyBlasInfo{
4514         VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR, // VkStructureType sType;
4515         nullptr,                                                // const void* pNext;
4516         *blas1->getPtr(),                                       // VkAccelerationStructureKHR src;
4517         *blas2->getPtr(),                                       // VkAccelerationStructureKHR dst;
4518         VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR           // VkCopyAccelerationStructureModeKHR mode;
4519     };
4520 
4521     beginCommandBuffer(vk, *cmdBuffer);
4522     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4523 
4524     if (m_params->build == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
4525     {
4526         vk.cmdCopyAccelerationStructureKHR(*cmdBuffer, &copyBlasInfo);
4527         vk.cmdPipelineBarrier2(*cmdBuffer, &copyBlasDependency);
4528     }
4529     else
4530         VK_CHECK(vk.copyAccelerationStructureKHR(device, VK_NULL_HANDLE, &copyBlasInfo));
4531 
4532     tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4533 
4534     const VkDescriptorImageInfo descriptorImageInfo =
4535         makeDescriptorImageInfo(VkSampler(), *view, VK_IMAGE_LAYOUT_GENERAL);
4536     const VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorTlas{
4537         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
4538         nullptr,                                                           //  const void* pNext;
4539         1,                                                                 //  uint32_t accelerationStructureCount;
4540         tlas->getPtr() //  const VkAccelerationStructureKHR* pAccelerationStructures;
4541     };
4542 
4543     DescriptorSetUpdateBuilder()
4544         .writeSingle(VkDescriptorSet(), DescriptorSetUpdateBuilder::Location::binding(0u),
4545                      VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
4546         .writeSingle(VkDescriptorSet(), DescriptorSetUpdateBuilder::Location::binding(1u),
4547                      VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeDescriptorTlas)
4548         .updateWithPush(vk, *cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 0, 2);
4549 
4550     vk.cmdPipelineBarrier2(*cmdBuffer, &preClearImageDependency);
4551     vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4552                           &imageSubresourceRange);
4553     vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImageDependency);
4554 
4555     cmdTraceRays(vk, *cmdBuffer,
4556                  &rgenRegion, // rgen
4557                  &missRegion, // miss
4558                  &chitRegion, // hit
4559                  &callRegion, // call
4560                  m_params->width, m_params->height, 1);
4561 
4562     vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4563     vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultImageBuffer, 1u,
4564                             &bufferCopyImageRegion);
4565     vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4566 
4567     endCommandBuffer(vk, *cmdBuffer);
4568     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4569 
4570     invalidateMappedMemoryRange(vk, device, resultImageBuffer->getAllocation().getMemory(),
4571                                 resultImageBuffer->getAllocation().getOffset(), bufferSize);
4572 
4573     const void *referenceImageData = referenceImageBuffer->getAllocation().getHostPtr();
4574     const void *resultImageData    = resultImageBuffer->getAllocation().getHostPtr();
4575 
4576     return (deMemCmp(referenceImageData, resultImageData, bufferSize) == 0) ?
4577                TestStatus::pass("") :
4578                TestStatus::fail("Reference and result images differ");
4579 }
4580 
getBufferSizeForSBT(const uint32_t & groupCount,const uint32_t & shaderGroupHandleSize,const uint32_t & shaderGroupBaseAlignment) const4581 VkDeviceSize CopySBTInstance::getBufferSizeForSBT(const uint32_t &groupCount, const uint32_t &shaderGroupHandleSize,
4582                                                   const uint32_t &shaderGroupBaseAlignment) const
4583 {
4584     DE_UNREF(shaderGroupBaseAlignment);
4585     return (groupCount * deAlign32(shaderGroupHandleSize, shaderGroupHandleSize));
4586 }
4587 
getBufferForSBT(const uint32_t & groupCount,const uint32_t & shaderGroupHandleSize,const uint32_t & shaderGroupBaseAlignment) const4588 de::MovePtr<BufferWithMemory> CopySBTInstance::getBufferForSBT(const uint32_t &groupCount,
4589                                                                const uint32_t &shaderGroupHandleSize,
4590                                                                const uint32_t &shaderGroupBaseAlignment) const
4591 {
4592     const VkDeviceSize sbtSize = getBufferSizeForSBT(groupCount, shaderGroupHandleSize, shaderGroupBaseAlignment);
4593     const VkBufferUsageFlags sbtFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT |
4594                                         VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
4595                                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
4596     const VkBufferCreateInfo sbtCreateInfo = makeBufferCreateInfo(sbtSize, sbtFlags);
4597     const MemoryRequirement sbtMemRequirements =
4598         MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress;
4599 
4600     return makeMovePtr<BufferWithMemory>(vk, device, allocator, sbtCreateInfo, sbtMemRequirements);
4601 }
4602 
iterate(void)4603 TestStatus CopySBTInstance::iterate(void)
4604 {
4605     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4606     const VkQueue queue             = m_context.getUniversalQueue();
4607 
4608     const de::MovePtr<RayTracingProperties> rtProps =
4609         makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
4610     const uint32_t shaderGroupHandleSize    = rtProps->getShaderGroupHandleSize();
4611     const uint32_t shaderGroupBaseAlignment = rtProps->getShaderGroupBaseAlignment();
4612 
4613     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_params->width, m_params->height, m_format);
4614     const VkImageSubresourceRange imageSubresourceRange =
4615         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4616     const de::MovePtr<ImageWithMemory> image =
4617         makeMovePtr<ImageWithMemory>(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
4618     const Move<VkImageView> view =
4619         makeImageView(vk, device, **image, VK_IMAGE_VIEW_TYPE_2D, m_format, imageSubresourceRange);
4620 
4621     const uint32_t bufferSize = (m_params->width * m_params->height * mapVkFormat(m_format).getPixelSize());
4622     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4623     de::MovePtr<BufferWithMemory> referenceImageBuffer =
4624         makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4625     de::MovePtr<BufferWithMemory> resultImageBuffer =
4626         makeMovePtr<BufferWithMemory>(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
4627 
4628     const VkImageSubresourceLayers imageSubresourceLayers =
4629         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4630     const VkBufferImageCopy bufferCopyImageRegion =
4631         makeBufferImageCopy(makeExtent3D(m_params->width, m_params->height, 1u), imageSubresourceLayers);
4632 
4633     de::MovePtr<RayTracingPipeline> rtPipeline = makeMovePtr<RayTracingPipeline>();
4634     rtPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, *rgenShader, 0);
4635     rtPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, *chitShader, 1);
4636     rtPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, *missShader, 2);
4637 
4638     const Move<VkDescriptorPool> descriptorPool =
4639         DescriptorPoolBuilder()
4640             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
4641             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
4642             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4643     const Move<VkDescriptorSetLayout> descriptorSetLayout =
4644         DescriptorSetLayoutBuilder()
4645             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4646             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4647             .build(vk, device);
4648     const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
4649 
4650     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
4651     Move<VkPipeline> pipeline                   = rtPipeline->createPipeline(vk, device, *pipelineLayout);
4652 
4653     de::MovePtr<BufferWithMemory> sourceRgenSbt = rtPipeline->createShaderBindingTable(
4654         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, VkBufferCreateFlags(0),
4655         VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
4656     VkStridedDeviceAddressRegionKHR sourceRgenRegion = makeStridedDeviceAddressRegionKHR(
4657         getBufferDeviceAddress(vk, device, **sourceRgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4658     de::MovePtr<BufferWithMemory> copyRgenSbt = getBufferForSBT(1, shaderGroupHandleSize, shaderGroupBaseAlignment);
4659     VkStridedDeviceAddressRegionKHR copyRgenRegion = makeStridedDeviceAddressRegionKHR(
4660         getBufferDeviceAddress(vk, device, **copyRgenSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4661     de::MovePtr<BufferWithMemory> chitSbt = rtPipeline->createShaderBindingTable(
4662         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
4663     VkStridedDeviceAddressRegionKHR chitRegion = makeStridedDeviceAddressRegionKHR(
4664         getBufferDeviceAddress(vk, device, **chitSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4665     de::MovePtr<BufferWithMemory> missSbt = rtPipeline->createShaderBindingTable(
4666         vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
4667     VkStridedDeviceAddressRegionKHR missRegion = makeStridedDeviceAddressRegionKHR(
4668         getBufferDeviceAddress(vk, device, **missSbt, 0), shaderGroupHandleSize, shaderGroupHandleSize);
4669     const VkStridedDeviceAddressRegionKHR callRegion = makeStridedDeviceAddressRegionKHR(VkDeviceAddress(0), 0, 0);
4670 
4671     const VkClearValue clearValue = {{{0.1f, 0.2f, 0.3f, 0.4f}}};
4672 
4673     const VkImageMemoryBarrier2KHR preClearImageImageBarrier = makeImageMemoryBarrier2(
4674         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 0, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4675         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image,
4676         imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4677     const VkImageMemoryBarrier2KHR postClearImageImageBarrier =
4678         makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
4679                                 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_READ_BIT_KHR,
4680                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image,
4681                                 imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4682     const VkDependencyInfoKHR preClearImageDependency  = u::makeDependency(preClearImageImageBarrier);
4683     const VkDependencyInfoKHR postClearImageDependency = u::makeDependency(postClearImageImageBarrier);
4684 
4685     const VkImageMemoryBarrier2KHR postTraceRaysImageBarrier = makeImageMemoryBarrier2(
4686         VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_2_SHADER_WRITE_BIT_KHR,
4687         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
4688         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4689     const VkImageMemoryBarrier2KHR postCopyImageImageBarrier = makeImageMemoryBarrier2(
4690         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, VK_PIPELINE_STAGE_2_HOST_BIT_KHR,
4691         VK_ACCESS_2_HOST_READ_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4692         **image, imageSubresourceRange, queueFamilyIndex, queueFamilyIndex);
4693     const VkDependencyInfoKHR postTraceRaysDependency = u::makeDependency(postTraceRaysImageBarrier);
4694     const VkDependencyInfoKHR postCopyImageDependency = u::makeDependency(postCopyImageImageBarrier);
4695 
4696     const Move<VkCommandPool> cmdPool =
4697         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
4698     const Move<VkCommandBuffer> cmdBuffer =
4699         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4700 
4701     auto tlas = makeTopLevelAccelerationStructure();
4702     BlasPtr blas(makeBottomLevelAccelerationStructure().release());
4703     blas->setBuildType(m_params->build);
4704     blas->setGeometryData({{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, true, VK_GEOMETRY_OPAQUE_BIT_KHR);
4705     tlas->setBuildType(m_params->build);
4706     tlas->setInstanceCount(1);
4707     tlas->addInstance(blas, identityMatrix3x4, 0, (~0u), 0, VkGeometryInstanceFlagsKHR(0));
4708     beginCommandBuffer(vk, *cmdBuffer);
4709     blas->createAndBuild(vk, device, *cmdBuffer, allocator);
4710     tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4711     endCommandBuffer(vk, *cmdBuffer);
4712     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4713 
4714     const VkDescriptorImageInfo descriptorImageInfo =
4715         makeDescriptorImageInfo(VkSampler(), *view, VK_IMAGE_LAYOUT_GENERAL);
4716     const VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorTlas{
4717         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
4718         nullptr,                                                           //  const void* pNext;
4719         1,                                                                 //  uint32_t accelerationStructureCount;
4720         tlas->getPtr() //  const VkAccelerationStructureKHR* pAccelerationStructures;
4721     };
4722 
4723     DescriptorSetUpdateBuilder()
4724         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
4725                      VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
4726         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
4727                      VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &writeDescriptorTlas)
4728         .update(vk, device);
4729 
4730     beginCommandBuffer(vk, *cmdBuffer);
4731     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4732     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4733                              &descriptorSet.get(), 0, nullptr);
4734     vk.cmdPipelineBarrier2(*cmdBuffer, &preClearImageDependency);
4735     vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4736                           &imageSubresourceRange);
4737     vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImageDependency);
4738     cmdTraceRays(vk, *cmdBuffer,
4739                  &sourceRgenRegion, // rgen
4740                  &missRegion,       // miss
4741                  &chitRegion,       // hit
4742                  &callRegion,       // call
4743                  m_params->width, m_params->height, 1);
4744     vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4745     vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **referenceImageBuffer, 1u,
4746                             &bufferCopyImageRegion);
4747     vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4748     endCommandBuffer(vk, *cmdBuffer);
4749     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4750 
4751     const VkBufferCopy bufferCopy{0, // VkDeviceSize srcOffset;
4752                                   0, // VkDeviceSize srcOffset;
4753                                   getBufferSizeForSBT(1, shaderGroupHandleSize, shaderGroupBaseAlignment)};
4754     const VkMemoryBarrier2KHR postCopySBTMemoryBarrier = makeMemoryBarrier2(
4755         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, VkAccessFlags2KHR(0), VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR,
4756         VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR);
4757     const VkDependencyInfoKHR postClearImgCopySBTDependency =
4758         u::makeDependency(postCopySBTMemoryBarrier, postClearImageImageBarrier);
4759 
4760     beginCommandBuffer(vk, *cmdBuffer);
4761     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4762     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4763                              &descriptorSet.get(), 0, nullptr);
4764     vk.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4765                           &imageSubresourceRange);
4766     vk.cmdCopyBuffer(*cmdBuffer, **sourceRgenSbt, **copyRgenSbt, 1, &bufferCopy);
4767     vk.cmdPipelineBarrier2(*cmdBuffer, &postClearImgCopySBTDependency);
4768     cmdTraceRays(vk, *cmdBuffer,
4769                  &copyRgenRegion, // rgen
4770                  &missRegion,     // miss
4771                  &chitRegion,     // hit
4772                  &callRegion,     // call
4773                  m_params->width, m_params->height, 1);
4774     vk.cmdPipelineBarrier2(*cmdBuffer, &postTraceRaysDependency);
4775     vk.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultImageBuffer, 1u,
4776                             &bufferCopyImageRegion);
4777     vk.cmdPipelineBarrier2(*cmdBuffer, &postCopyImageDependency);
4778     endCommandBuffer(vk, *cmdBuffer);
4779     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
4780 
4781     invalidateMappedMemoryRange(vk, device, referenceImageBuffer->getAllocation().getMemory(),
4782                                 referenceImageBuffer->getAllocation().getOffset(), bufferSize);
4783     invalidateMappedMemoryRange(vk, device, resultImageBuffer->getAllocation().getMemory(),
4784                                 resultImageBuffer->getAllocation().getOffset(), bufferSize);
4785 
4786     const void *referenceImageDataPtr = referenceImageBuffer->getAllocation().getHostPtr();
4787     const void *resultImageDataPtr    = resultImageBuffer->getAllocation().getHostPtr();
4788 
4789     return (deMemCmp(referenceImageDataPtr, resultImageDataPtr, bufferSize) == 0) ? TestStatus::pass("") :
4790                                                                                     TestStatus::fail("");
4791 }
4792 
4793 class ASUpdateCase : public RayTracingASBasicTestCase
4794 {
4795 public:
4796     ASUpdateCase(tcu::TestContext &context, const char *name, const TestParams &data);
4797     ~ASUpdateCase(void);
4798 
4799     TestInstance *createInstance(Context &context) const override;
4800 };
4801 
4802 class ASUpdateInstance : public RayTracingASBasicTestInstance
4803 {
4804 public:
4805     ASUpdateInstance(Context &context, const TestParams &data);
4806     ~ASUpdateInstance(void) = default;
4807     tcu::TestStatus iterate(void) override;
4808 
4809 private:
4810     TestParams m_data;
4811 };
4812 
ASUpdateCase(tcu::TestContext & context,const char * name,const TestParams & data)4813 ASUpdateCase::ASUpdateCase(tcu::TestContext &context, const char *name, const TestParams &data)
4814     : RayTracingASBasicTestCase(context, name, data)
4815 {
4816 }
4817 
~ASUpdateCase(void)4818 ASUpdateCase::~ASUpdateCase(void)
4819 {
4820 }
4821 
createInstance(Context & context) const4822 TestInstance *ASUpdateCase::createInstance(Context &context) const
4823 {
4824     return new ASUpdateInstance(context, m_data);
4825 }
4826 
ASUpdateInstance(Context & context,const TestParams & data)4827 ASUpdateInstance::ASUpdateInstance(Context &context, const TestParams &data)
4828     : RayTracingASBasicTestInstance(context, data)
4829     , m_data(data)
4830 {
4831 }
4832 
iterate(void)4833 TestStatus ASUpdateInstance::iterate(void)
4834 {
4835     const InstanceInterface &vki            = m_context.getInstanceInterface();
4836     const DeviceInterface &vkd              = m_context.getDeviceInterface();
4837     const VkDevice device                   = m_context.getDevice();
4838     const VkPhysicalDevice physicalDevice   = m_context.getPhysicalDevice();
4839     const uint32_t queueFamilyIndex         = m_context.getUniversalQueueFamilyIndex();
4840     const VkQueue queue                     = m_context.getUniversalQueue();
4841     Allocator &allocator                    = m_context.getDefaultAllocator();
4842     const uint32_t pixelCount               = m_data.width * m_data.height;
4843     const uint32_t shaderGroupHandleSize    = getShaderGroupSize(vki, physicalDevice);
4844     const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
4845 
4846     const Move<VkDescriptorSetLayout> descriptorSetLayout =
4847         DescriptorSetLayoutBuilder()
4848             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
4849             .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
4850             .build(vkd, device);
4851     const Move<VkDescriptorPool> descriptorPool =
4852         DescriptorPoolBuilder()
4853             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
4854             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
4855             .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4856     const Move<VkDescriptorSet> descriptorSet   = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
4857     const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
4858 
4859     de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
4860     m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
4861     Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
4862 
4863     de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
4864     de::MovePtr<BufferWithMemory> hitShaderBindingTable;
4865     de::MovePtr<BufferWithMemory> missShaderBindingTable;
4866     m_data.testConfiguration->initShaderBindingTables(
4867         rayTracingPipeline, m_context, m_data, *pipeline, shaderGroupHandleSize, shaderGroupBaseAlignment,
4868         raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable);
4869 
4870     const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
4871         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
4872                                           shaderGroupHandleSize, shaderGroupHandleSize);
4873     const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
4874         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
4875                                           shaderGroupHandleSize, shaderGroupHandleSize);
4876     const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
4877         makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
4878                                           shaderGroupHandleSize, shaderGroupHandleSize);
4879     const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
4880 
4881     const VkFormat imageFormat              = m_data.testConfiguration->getResultImageFormat();
4882     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
4883     const VkImageSubresourceRange imageSubresourceRange =
4884         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
4885     const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
4886         new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
4887     const Move<VkImageView> imageView =
4888         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
4889 
4890     const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(
4891         pixelCount * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4892     const VkImageSubresourceLayers resultBufferImageSubresourceLayers =
4893         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
4894     const VkBufferImageCopy resultBufferImageRegion =
4895         makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), resultBufferImageSubresourceLayers);
4896     de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(
4897         new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
4898 
4899     const VkDescriptorImageInfo descriptorImageInfo =
4900         makeDescriptorImageInfo(VK_NULL_HANDLE, *imageView, VK_IMAGE_LAYOUT_GENERAL);
4901 
4902     const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
4903     const Move<VkCommandBuffer> cmdBuffer =
4904         allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4905 
4906     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
4907     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
4908     std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
4909     de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
4910     std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
4911     std::vector<de::SharedPtr<SerialStorage>> topSerialized;
4912     std::vector<VkDeviceSize> accelerationCompactedSizes;
4913     std::vector<VkDeviceSize> accelerationSerialSizes;
4914     Move<VkQueryPool> m_queryPoolCompact;
4915     Move<VkQueryPool> m_queryPoolSerial;
4916 
4917     beginCommandBuffer(vkd, *cmdBuffer, 0u);
4918     {
4919         const VkImageMemoryBarrier preImageBarrier =
4920             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
4921                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
4922         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
4923                                       VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
4924         const VkClearValue clearValue = m_data.testConfiguration->getClearValue();
4925         vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
4926                                &imageSubresourceRange);
4927         const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
4928             VK_ACCESS_TRANSFER_WRITE_BIT,
4929             VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
4930             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
4931         cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
4932                                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
4933 
4934         // build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
4935         bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
4936         const bool buildWithoutGeom   = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
4937         const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
4938         const bool topNoPrimitives    = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
4939         const bool inactiveInstances  = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
4940         bottomLevelAccelerationStructures =
4941             m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
4942         VkBuildAccelerationStructureFlagsKHR allowCompactionFlag =
4943             VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
4944         VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
4945         VkBuildAccelerationStructureFlagsKHR bottomCompactFlags =
4946             (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
4947         VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
4948         std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
4949         std::vector<VkDeviceSize> bottomBlasCompactSize;
4950         std::vector<VkDeviceSize> bottomBlasSerialSize;
4951 
4952         for (auto &blas : bottomLevelAccelerationStructures)
4953         {
4954             blas->setBuildType(m_data.buildType);
4955             blas->setBuildFlags(bottomBuildFlags);
4956             blas->setUseArrayOfPointers(m_data.bottomUsesAOP);
4957             blas->setCreateGeneric(m_data.bottomGeneric);
4958             blas->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
4959             blas->setBuildWithoutGeometries(buildWithoutGeom);
4960             blas->setBuildWithoutPrimitives(bottomNoPrimitives);
4961             blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
4962             accelerationStructureHandles.push_back(*(blas->getPtr()));
4963         }
4964 
4965         auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
4966         // build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
4967         bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
4968         VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
4969         VkBuildAccelerationStructureFlagsKHR topBuildFlags   = m_data.buildFlags | topCompactFlags;
4970         std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
4971         std::vector<VkDeviceSize> topBlasCompactSize;
4972         std::vector<VkDeviceSize> topBlasSerialSize;
4973 
4974         topLevelAccelerationStructure = m_data.testConfiguration->initTopAccelerationStructure(
4975             m_context, m_data, *bottomLevelAccelerationStructuresPtr);
4976         topLevelAccelerationStructure->setBuildType(m_data.buildType);
4977         topLevelAccelerationStructure->setBuildFlags(topBuildFlags);
4978         topLevelAccelerationStructure->setBuildWithoutPrimitives(topNoPrimitives);
4979         topLevelAccelerationStructure->setUseArrayOfPointers(m_data.topUsesAOP);
4980         topLevelAccelerationStructure->setCreateGeneric(m_data.topGeneric);
4981         topLevelAccelerationStructure->setCreationBufferUnbounded(m_data.topUnboundedCreation);
4982         topLevelAccelerationStructure->setInactiveInstances(inactiveInstances);
4983         topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
4984         topLevelStructureHandles.push_back(*(topLevelAccelerationStructure->getPtr()));
4985 
4986         const VkMemoryBarrier postBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
4987                                                                    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
4988         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
4989                                  VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postBuildBarrier);
4990 
4991         if (m_data.updateCase == UpdateCase::VERTICES)
4992         {
4993             for (auto &blas : bottomLevelAccelerationStructures)
4994             {
4995                 const std::vector<tcu::Vec3> vertices = {
4996                     tcu::Vec3(0.0f, 0.0f, -0.5f),
4997                     tcu::Vec3(0.5f, 0.0f, -0.5f),
4998                     tcu::Vec3(0.0f, 0.5f, -0.5f),
4999                 };
5000                 const std::vector<uint32_t> indices = {0, 1, 2};
5001                 de::SharedPtr<RaytracedGeometryBase> geometry;
5002                 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, m_data.vertexFormat, m_data.indexType);
5003 
5004                 for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
5005                     geometry->addVertex(*it);
5006 
5007                 if (m_data.indexType != VK_INDEX_TYPE_NONE_KHR)
5008                 {
5009                     for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
5010                         geometry->addIndex(*it);
5011                 }
5012                 blas->updateGeometry(0, geometry);
5013                 blas->build(vkd, device, *cmdBuffer, blas.get());
5014             }
5015         }
5016         else if (m_data.updateCase == UpdateCase::INDICES)
5017         {
5018             for (auto &blas : bottomLevelAccelerationStructures)
5019             {
5020                 const std::vector<tcu::Vec3> vertices = {
5021                     tcu::Vec3(0.0f, 0.0f, 0.0f),  tcu::Vec3(0.5f, 0.0f, 0.0f),  tcu::Vec3(0.0f, 0.5f, 0.0f),
5022                     tcu::Vec3(0.0f, 0.0f, -0.5f), tcu::Vec3(0.5f, 0.0f, -0.5f), tcu::Vec3(0.0f, 0.5f, -0.5f),
5023                 };
5024 
5025                 const std::vector<uint32_t> indices = {3, 4, 5};
5026                 de::SharedPtr<RaytracedGeometryBase> geometry;
5027                 geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, m_data.vertexFormat, m_data.indexType);
5028 
5029                 for (auto it = begin(vertices), eit = end(vertices); it != eit; ++it)
5030                     geometry->addVertex(*it);
5031 
5032                 if (m_data.indexType != VK_INDEX_TYPE_NONE_KHR)
5033                 {
5034                     for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
5035                         geometry->addIndex(*it);
5036                 }
5037                 blas->updateGeometry(0, geometry);
5038                 blas->build(vkd, device, *cmdBuffer, blas.get());
5039             }
5040         }
5041         else if (m_data.updateCase == UpdateCase::TRANSFORM)
5042         {
5043             const VkTransformMatrixKHR translatedMatrix = {
5044                 {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, -0.5f}}};
5045             topLevelAccelerationStructure->updateInstanceMatrix(vkd, device, 0, translatedMatrix);
5046             topLevelAccelerationStructure->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
5047         }
5048 
5049         const TopLevelAccelerationStructure *topLevelRayTracedPtr = topLevelAccelerationStructure.get();
5050         const VkMemoryBarrier preTraceMemoryBarrier =
5051             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
5052                               VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
5053         cmdPipelineMemoryBarrier(
5054             vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
5055             VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier);
5056 
5057         VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
5058             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
5059             nullptr,                                                           //  const void* pNext;
5060             1u,                                                                //  uint32_t accelerationStructureCount;
5061             topLevelRayTracedPtr->getPtr(), //  const VkAccelerationStructureKHR* pAccelerationStructures;
5062         };
5063 
5064         DescriptorSetUpdateBuilder()
5065             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
5066                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
5067             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
5068                          VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
5069             .update(vkd, device);
5070 
5071         vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
5072                                   &descriptorSet.get(), 0, nullptr);
5073 
5074         vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
5075 
5076         cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
5077                      &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height, 1);
5078 
5079         const VkMemoryBarrier postTraceMemoryBarrier =
5080             makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
5081         const VkMemoryBarrier postCopyMemoryBarrier =
5082             makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5083         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
5084                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
5085 
5086         vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u,
5087                                  &resultBufferImageRegion);
5088 
5089         cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
5090                                  &postCopyMemoryBarrier);
5091     }
5092     endCommandBuffer(vkd, *cmdBuffer);
5093 
5094     submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
5095 
5096     invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
5097                                 resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(uint32_t));
5098 
5099     bool result = m_data.testConfiguration->verifyImage(resultBuffer.get(), m_context, m_data);
5100 
5101     if (result)
5102         return tcu::TestStatus::pass("Pass");
5103     else
5104         return tcu::TestStatus::fail("Fail");
5105 }
5106 
5107 } // namespace
5108 
addBasicBuildingTests(tcu::TestCaseGroup * group)5109 void addBasicBuildingTests(tcu::TestCaseGroup *group)
5110 {
5111     struct
5112     {
5113         vk::VkAccelerationStructureBuildTypeKHR buildType;
5114         const char *name;
5115     } buildTypes[] = {
5116         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5117         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5118     };
5119 
5120     struct
5121     {
5122         BottomTestType testType;
5123         bool usesAOP;
5124         const char *name;
5125     } bottomTestTypes[] = {
5126         {BottomTestType::TRIANGLES, false, "triangles"},
5127         {BottomTestType::TRIANGLES, true, "triangles_aop"},
5128         {BottomTestType::AABBS, false, "aabbs"},
5129         {BottomTestType::AABBS, true, "aabbs_aop"},
5130     };
5131 
5132     struct
5133     {
5134         TopTestType testType;
5135         bool usesAOP;
5136         const char *name;
5137     } topTestTypes[] = {
5138         {TopTestType::IDENTICAL_INSTANCES, false, "identical_instances"},
5139         {TopTestType::IDENTICAL_INSTANCES, true, "identical_instances_aop"},
5140         {TopTestType::DIFFERENT_INSTANCES, false, "different_instances"},
5141         {TopTestType::DIFFERENT_INSTANCES, true, "different_instances_aop"},
5142     };
5143 
5144     struct BuildFlagsData
5145     {
5146         VkBuildAccelerationStructureFlagsKHR flags;
5147         const char *name;
5148     };
5149 
5150     BuildFlagsData optimizationTypes[] = {
5151         {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5152         {VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, "fasttrace"},
5153         {VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, "fastbuild"},
5154     };
5155 
5156     BuildFlagsData updateTypes[] = {
5157         {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5158         {VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, "update"},
5159     };
5160 
5161     BuildFlagsData compactionTypes[] = {
5162         {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5163         {VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, "compaction"},
5164     };
5165 
5166     BuildFlagsData lowMemoryTypes[] = {
5167         {VkBuildAccelerationStructureFlagsKHR(0u), "0"},
5168         {VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, "lowmemory"},
5169     };
5170 
5171     struct
5172     {
5173         bool padVertices;
5174         const char *name;
5175     } paddingType[] = {
5176         {false, "nopadding"},
5177         {true, "padded"},
5178     };
5179 
5180     struct
5181     {
5182         bool topGeneric;
5183         bool bottomGeneric;
5184         const char *suffix;
5185     } createGenericParams[] = {
5186         {false, false, ""},
5187         {false, true, "_bottomgeneric"},
5188         {true, false, "_topgeneric"},
5189         {true, true, "_bothgeneric"},
5190     };
5191 
5192     // In order not to create thousands of new test variants for unbound buffer memory on acceleration structure creation, we will
5193     // set these options on some of the tests.
5194     de::ModCounter32 unboundedCreationBottomCounter(3u);
5195     de::ModCounter32 unboundedCreationTopCounter(7u);
5196 
5197     for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5198     {
5199         de::MovePtr<tcu::TestCaseGroup> buildGroup(
5200             new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
5201 
5202         for (size_t bottomNdx = 0; bottomNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++bottomNdx)
5203         {
5204             de::MovePtr<tcu::TestCaseGroup> bottomGroup(
5205                 new tcu::TestCaseGroup(group->getTestContext(), bottomTestTypes[bottomNdx].name));
5206 
5207             for (size_t topNdx = 0; topNdx < DE_LENGTH_OF_ARRAY(topTestTypes); ++topNdx)
5208             {
5209                 de::MovePtr<tcu::TestCaseGroup> topGroup(
5210                     new tcu::TestCaseGroup(group->getTestContext(), topTestTypes[topNdx].name));
5211 
5212                 for (int paddingTypeIdx = 0; paddingTypeIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingTypeIdx)
5213                 {
5214                     de::MovePtr<tcu::TestCaseGroup> paddingGroup(
5215                         new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingTypeIdx].name));
5216 
5217                     for (size_t optimizationNdx = 0; optimizationNdx < DE_LENGTH_OF_ARRAY(optimizationTypes);
5218                          ++optimizationNdx)
5219                     {
5220                         for (size_t updateNdx = 0; updateNdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateNdx)
5221                         {
5222                             for (size_t compactionNdx = 0; compactionNdx < DE_LENGTH_OF_ARRAY(compactionTypes);
5223                                  ++compactionNdx)
5224                             {
5225                                 for (size_t lowMemoryNdx = 0; lowMemoryNdx < DE_LENGTH_OF_ARRAY(lowMemoryTypes);
5226                                      ++lowMemoryNdx)
5227                                 {
5228                                     for (int createGenericIdx = 0;
5229                                          createGenericIdx < DE_LENGTH_OF_ARRAY(createGenericParams); ++createGenericIdx)
5230                                     {
5231                                         std::string testName =
5232                                             std::string(optimizationTypes[optimizationNdx].name) + "_" +
5233                                             std::string(updateTypes[updateNdx].name) + "_" +
5234                                             std::string(compactionTypes[compactionNdx].name) + "_" +
5235                                             std::string(lowMemoryTypes[lowMemoryNdx].name) +
5236                                             std::string(createGenericParams[createGenericIdx].suffix);
5237 
5238                                         const bool unboundedCreationBottom =
5239                                             (static_cast<uint32_t>(unboundedCreationBottomCounter++) == 0u);
5240                                         const bool unboundedCreationTop =
5241                                             (static_cast<uint32_t>(unboundedCreationTopCounter++) == 0u);
5242 
5243                                         TestParams testParams{
5244                                             buildTypes[buildTypeNdx].buildType,
5245                                             VK_FORMAT_R32G32B32_SFLOAT,
5246                                             paddingType[paddingTypeIdx].padVertices,
5247                                             VK_INDEX_TYPE_NONE_KHR,
5248                                             bottomTestTypes[bottomNdx].testType,
5249                                             InstanceCullFlags::NONE,
5250                                             bottomTestTypes[bottomNdx].usesAOP,
5251                                             createGenericParams[createGenericIdx].bottomGeneric,
5252                                             unboundedCreationBottom,
5253                                             topTestTypes[topNdx].testType,
5254                                             topTestTypes[topNdx].usesAOP,
5255                                             createGenericParams[createGenericIdx].topGeneric,
5256                                             unboundedCreationTop,
5257                                             optimizationTypes[optimizationNdx].flags | updateTypes[updateNdx].flags |
5258                                                 compactionTypes[compactionNdx].flags |
5259                                                 lowMemoryTypes[lowMemoryNdx].flags,
5260                                             OT_NONE,
5261                                             OP_NONE,
5262                                             RTAS_DEFAULT_SIZE,
5263                                             RTAS_DEFAULT_SIZE,
5264                                             de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5265                                             0u,
5266                                             EmptyAccelerationStructureCase::NOT_EMPTY,
5267                                             InstanceCustomIndexCase::NONE,
5268                                             false,
5269                                             0xFFu,
5270                                             UpdateCase::NONE,
5271                                         };
5272                                         paddingGroup->addChild(new RayTracingASBasicTestCase(
5273                                             group->getTestContext(), testName.c_str(), testParams));
5274                                     }
5275                                 }
5276                             }
5277                         }
5278                     }
5279                     topGroup->addChild(paddingGroup.release());
5280                 }
5281                 bottomGroup->addChild(topGroup.release());
5282             }
5283             buildGroup->addChild(bottomGroup.release());
5284         }
5285         group->addChild(buildGroup.release());
5286     }
5287 }
5288 
addVertexIndexFormatsTests(tcu::TestCaseGroup * group)5289 void addVertexIndexFormatsTests(tcu::TestCaseGroup *group)
5290 {
5291     struct
5292     {
5293         vk::VkAccelerationStructureBuildTypeKHR buildType;
5294         const char *name;
5295     } buildTypes[] = {
5296         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5297         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5298     };
5299 
5300     const VkFormat vertexFormats[] = {
5301         // Mandatory formats.
5302         VK_FORMAT_R32G32_SFLOAT,
5303         VK_FORMAT_R32G32B32_SFLOAT,
5304         VK_FORMAT_R16G16_SFLOAT,
5305         VK_FORMAT_R16G16B16A16_SFLOAT,
5306         VK_FORMAT_R16G16_SNORM,
5307         VK_FORMAT_R16G16B16A16_SNORM,
5308 
5309         // Additional formats.
5310         VK_FORMAT_R8G8_SNORM,
5311         VK_FORMAT_R8G8B8_SNORM,
5312         VK_FORMAT_R8G8B8A8_SNORM,
5313         VK_FORMAT_R16G16B16_SNORM,
5314         VK_FORMAT_R16G16B16_SFLOAT,
5315         VK_FORMAT_R32G32B32A32_SFLOAT,
5316         VK_FORMAT_R64G64_SFLOAT,
5317         VK_FORMAT_R64G64B64_SFLOAT,
5318         VK_FORMAT_R64G64B64A64_SFLOAT,
5319     };
5320 
5321     struct
5322     {
5323         VkIndexType indexType;
5324         const char *name;
5325     } indexFormats[] = {
5326         {VK_INDEX_TYPE_NONE_KHR, "index_none"},
5327         {VK_INDEX_TYPE_UINT16, "index_uint16"},
5328         {VK_INDEX_TYPE_UINT32, "index_uint32"},
5329     };
5330 
5331     struct
5332     {
5333         bool padVertices;
5334         const char *name;
5335     } paddingType[] = {
5336         {false, "nopadding"},
5337         {true, "padded"},
5338     };
5339 
5340     for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5341     {
5342         de::MovePtr<tcu::TestCaseGroup> buildGroup(
5343             new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
5344 
5345         for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
5346         {
5347             const auto format     = vertexFormats[vertexFormatNdx];
5348             const auto formatName = getFormatSimpleName(format);
5349 
5350             de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(
5351                 new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str()));
5352 
5353             for (int paddingIdx = 0; paddingIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingIdx)
5354             {
5355                 de::MovePtr<tcu::TestCaseGroup> paddingGroup(
5356                     new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingIdx].name));
5357 
5358                 for (size_t indexFormatNdx = 0; indexFormatNdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatNdx)
5359                 {
5360                     TestParams testParams{
5361                         buildTypes[buildTypeNdx].buildType,
5362                         format,
5363                         paddingType[paddingIdx].padVertices,
5364                         indexFormats[indexFormatNdx].indexType,
5365                         BottomTestType::TRIANGLES,
5366                         InstanceCullFlags::NONE,
5367                         false,
5368                         false,
5369                         false,
5370                         TopTestType::IDENTICAL_INSTANCES,
5371                         false,
5372                         false,
5373                         false,
5374                         VkBuildAccelerationStructureFlagsKHR(0u),
5375                         OT_NONE,
5376                         OP_NONE,
5377                         RTAS_DEFAULT_SIZE,
5378                         RTAS_DEFAULT_SIZE,
5379                         de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5380                         0u,
5381                         EmptyAccelerationStructureCase::NOT_EMPTY,
5382                         InstanceCustomIndexCase::NONE,
5383                         false,
5384                         0xFFu,
5385                         UpdateCase::NONE,
5386                     };
5387                     paddingGroup->addChild(new RayTracingASBasicTestCase(
5388                         group->getTestContext(), indexFormats[indexFormatNdx].name, testParams));
5389                 }
5390                 vertexFormatGroup->addChild(paddingGroup.release());
5391             }
5392             buildGroup->addChild(vertexFormatGroup.release());
5393         }
5394         group->addChild(buildGroup.release());
5395     }
5396 }
5397 
addOperationTestsImpl(tcu::TestCaseGroup * group,const uint32_t workerThreads)5398 void addOperationTestsImpl(tcu::TestCaseGroup *group, const uint32_t workerThreads)
5399 {
5400     struct
5401     {
5402         OperationType operationType;
5403         const char *name;
5404     } operationTypes[] = {
5405         {OP_COPY, "copy"},
5406         {OP_COMPACT, "compaction"},
5407         {OP_SERIALIZE, "serialization"},
5408     };
5409 
5410     struct
5411     {
5412         vk::VkAccelerationStructureBuildTypeKHR buildType;
5413         const char *name;
5414     } buildTypes[] = {
5415         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5416         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5417     };
5418 
5419     struct
5420     {
5421         OperationTarget operationTarget;
5422         const char *name;
5423     } operationTargets[] = {
5424         {OT_TOP_ACCELERATION, "top_acceleration_structure"},
5425         {OT_BOTTOM_ACCELERATION, "bottom_acceleration_structure"},
5426     };
5427 
5428     struct
5429     {
5430         BottomTestType testType;
5431         const char *name;
5432     } bottomTestTypes[] = {
5433         {BottomTestType::TRIANGLES, "triangles"},
5434         {BottomTestType::AABBS, "aabbs"},
5435     };
5436 
5437     for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
5438     {
5439         if (workerThreads > 0)
5440             if (operationTypes[operationTypeNdx].operationType != OP_COPY &&
5441                 operationTypes[operationTypeNdx].operationType != OP_SERIALIZE)
5442                 continue;
5443 
5444         de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(
5445             new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name));
5446 
5447         for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5448         {
5449             if (workerThreads > 0 &&
5450                 buildTypes[buildTypeNdx].buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
5451                 continue;
5452 
5453             de::MovePtr<tcu::TestCaseGroup> buildGroup(
5454                 new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
5455 
5456             for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets);
5457                  ++operationTargetNdx)
5458             {
5459                 de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(
5460                     new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name));
5461 
5462                 for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
5463                 {
5464                     TopTestType topTest =
5465                         (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ?
5466                             TopTestType::DIFFERENT_INSTANCES :
5467                             TopTestType::IDENTICAL_INSTANCES;
5468 
5469                     TestParams testParams{
5470                         buildTypes[buildTypeNdx].buildType,
5471                         VK_FORMAT_R32G32B32_SFLOAT,
5472                         false,
5473                         VK_INDEX_TYPE_NONE_KHR,
5474                         bottomTestTypes[testTypeNdx].testType,
5475                         InstanceCullFlags::NONE,
5476                         false,
5477                         false,
5478                         false,
5479                         topTest,
5480                         false,
5481                         false,
5482                         false,
5483                         VkBuildAccelerationStructureFlagsKHR(0u),
5484                         operationTargets[operationTargetNdx].operationTarget,
5485                         operationTypes[operationTypeNdx].operationType,
5486                         RTAS_DEFAULT_SIZE,
5487                         RTAS_DEFAULT_SIZE,
5488                         de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5489                         workerThreads,
5490                         EmptyAccelerationStructureCase::NOT_EMPTY,
5491                         InstanceCustomIndexCase::NONE,
5492                         false,
5493                         0xFFu,
5494                         UpdateCase::NONE,
5495                     };
5496                     operationTargetGroup->addChild(new RayTracingASBasicTestCase(
5497                         group->getTestContext(), bottomTestTypes[testTypeNdx].name, testParams));
5498                 }
5499                 buildGroup->addChild(operationTargetGroup.release());
5500             }
5501             operationTypeGroup->addChild(buildGroup.release());
5502         }
5503         group->addChild(operationTypeGroup.release());
5504     }
5505 }
5506 
addOperationTests(tcu::TestCaseGroup * group)5507 void addOperationTests(tcu::TestCaseGroup *group)
5508 {
5509     addOperationTestsImpl(group, 0);
5510 }
5511 
addHostThreadingOperationTests(tcu::TestCaseGroup * group)5512 void addHostThreadingOperationTests(tcu::TestCaseGroup *group)
5513 {
5514     const uint32_t threads[] = {1, 2, 3, 4, 8, std::numeric_limits<uint32_t>::max()};
5515 
5516     for (size_t threadsNdx = 0; threadsNdx < DE_LENGTH_OF_ARRAY(threads); ++threadsNdx)
5517     {
5518         const std::string groupName =
5519             threads[threadsNdx] != std::numeric_limits<uint32_t>::max() ? de::toString(threads[threadsNdx]) : "max";
5520 
5521         de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), groupName.c_str()));
5522 
5523         addOperationTestsImpl(threadGroup.get(), threads[threadsNdx]);
5524 
5525         group->addChild(threadGroup.release());
5526     }
5527 }
5528 
addFuncArgTests(tcu::TestCaseGroup * group)5529 void addFuncArgTests(tcu::TestCaseGroup *group)
5530 {
5531     const struct
5532     {
5533         vk::VkAccelerationStructureBuildTypeKHR buildType;
5534         const char *name;
5535     } buildTypes[] = {
5536         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5537         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5538     };
5539 
5540     auto &ctx = group->getTestContext();
5541 
5542     for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
5543     {
5544         TestParams testParams{
5545             buildTypes[buildTypeNdx].buildType,
5546             VK_FORMAT_R32G32B32_SFLOAT,
5547             false,
5548             VK_INDEX_TYPE_NONE_KHR,
5549             BottomTestType::TRIANGLES,
5550             InstanceCullFlags::NONE,
5551             false,
5552             false,
5553             false,
5554             TopTestType::IDENTICAL_INSTANCES,
5555             false,
5556             false,
5557             false,
5558             VkBuildAccelerationStructureFlagsKHR(0u),
5559             OT_NONE,
5560             OP_NONE,
5561             RTAS_DEFAULT_SIZE,
5562             RTAS_DEFAULT_SIZE,
5563             de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5564             0u,
5565             EmptyAccelerationStructureCase::NOT_EMPTY,
5566             InstanceCustomIndexCase::NONE,
5567             false,
5568             0xFFu,
5569             UpdateCase::NONE,
5570         };
5571 
5572         group->addChild(new RayTracingASFuncArgTestCase(ctx, buildTypes[buildTypeNdx].name, testParams));
5573     }
5574 }
5575 
addInstanceTriangleCullingTests(tcu::TestCaseGroup * group)5576 void addInstanceTriangleCullingTests(tcu::TestCaseGroup *group)
5577 {
5578     const struct
5579     {
5580         InstanceCullFlags cullFlags;
5581         std::string name;
5582     } cullFlags[] = {
5583         {InstanceCullFlags::NONE, "noflags"},
5584         {InstanceCullFlags::COUNTERCLOCKWISE, "ccw"},
5585         {InstanceCullFlags::CULL_DISABLE, "nocull"},
5586         {InstanceCullFlags::ALL, "ccw_nocull"},
5587     };
5588 
5589     const struct
5590     {
5591         TopTestType topType;
5592         std::string name;
5593     } topType[] = {
5594         {TopTestType::DIFFERENT_INSTANCES, "transformed"}, // Each instance has its own transformation matrix.
5595         {TopTestType::IDENTICAL_INSTANCES, "notransform"}, // "Identical" instances, different geometries.
5596     };
5597 
5598     const struct
5599     {
5600         vk::VkAccelerationStructureBuildTypeKHR buildType;
5601         std::string name;
5602     } buildTypes[] = {
5603         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5604         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5605     };
5606 
5607     const struct
5608     {
5609         VkIndexType indexType;
5610         std::string name;
5611     } indexFormats[] = {
5612         {VK_INDEX_TYPE_NONE_KHR, "index_none"},
5613         {VK_INDEX_TYPE_UINT16, "index_uint16"},
5614         {VK_INDEX_TYPE_UINT32, "index_uint32"},
5615     };
5616 
5617     auto &ctx = group->getTestContext();
5618 
5619     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5620     {
5621         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5622             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5623 
5624         for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
5625         {
5626             de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(
5627                 new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
5628 
5629             for (int topTypeIdx = 0; topTypeIdx < DE_LENGTH_OF_ARRAY(topType); ++topTypeIdx)
5630             {
5631                 for (int cullFlagsIdx = 0; cullFlagsIdx < DE_LENGTH_OF_ARRAY(cullFlags); ++cullFlagsIdx)
5632                 {
5633                     const std::string testName = topType[topTypeIdx].name + "_" + cullFlags[cullFlagsIdx].name;
5634 
5635                     TestParams testParams{
5636                         buildTypes[buildTypeIdx].buildType,
5637                         VK_FORMAT_R32G32B32_SFLOAT,
5638                         false,
5639                         indexFormats[indexFormatIdx].indexType,
5640                         BottomTestType::TRIANGLES,
5641                         cullFlags[cullFlagsIdx].cullFlags,
5642                         false,
5643                         false,
5644                         false,
5645                         topType[topTypeIdx].topType,
5646                         false,
5647                         false,
5648                         false,
5649                         VkBuildAccelerationStructureFlagsKHR(0u),
5650                         OT_NONE,
5651                         OP_NONE,
5652                         RTAS_DEFAULT_SIZE,
5653                         RTAS_DEFAULT_SIZE,
5654                         de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5655                         0u,
5656                         EmptyAccelerationStructureCase::NOT_EMPTY,
5657                         InstanceCustomIndexCase::NONE,
5658                         false,
5659                         0xFFu,
5660                         UpdateCase::NONE,
5661                     };
5662                     indexTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, testName.c_str(), testParams));
5663                 }
5664             }
5665             buildTypeGroup->addChild(indexTypeGroup.release());
5666         }
5667         group->addChild(buildTypeGroup.release());
5668     }
5669 }
5670 
addDynamicIndexingTests(tcu::TestCaseGroup * group)5671 void addDynamicIndexingTests(tcu::TestCaseGroup *group)
5672 {
5673     auto &ctx = group->getTestContext();
5674     group->addChild(new RayTracingASDynamicIndexingTestCase(ctx, "dynamic_indexing"));
5675 }
5676 
addEmptyAccelerationStructureTests(tcu::TestCaseGroup * group)5677 void addEmptyAccelerationStructureTests(tcu::TestCaseGroup *group)
5678 {
5679     const struct
5680     {
5681         vk::VkAccelerationStructureBuildTypeKHR buildType;
5682         std::string name;
5683     } buildTypes[] = {
5684         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5685         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5686     };
5687 
5688     const struct
5689     {
5690         VkIndexType indexType;
5691         std::string name;
5692     } indexFormats[] = {
5693         {VK_INDEX_TYPE_NONE_KHR, "index_none"},
5694         {VK_INDEX_TYPE_UINT16, "index_uint16"},
5695         {VK_INDEX_TYPE_UINT32, "index_uint32"},
5696     };
5697 
5698     const struct
5699     {
5700         EmptyAccelerationStructureCase emptyASCase;
5701         std::string name;
5702     } emptyCases[] = {
5703         {EmptyAccelerationStructureCase::INACTIVE_TRIANGLES, "inactive_triangles"},
5704         {EmptyAccelerationStructureCase::INACTIVE_INSTANCES, "inactive_instances"},
5705         {EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM, "no_geometries_bottom"},
5706         {EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP, "no_primitives_top"},
5707         {EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM, "no_primitives_bottom"},
5708     };
5709 
5710     auto &ctx = group->getTestContext();
5711 
5712     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5713     {
5714         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5715             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5716 
5717         for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
5718         {
5719             de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(
5720                 new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
5721 
5722             for (int emptyCaseIdx = 0; emptyCaseIdx < DE_LENGTH_OF_ARRAY(emptyCases); ++emptyCaseIdx)
5723             {
5724 
5725                 TestParams testParams{
5726                     buildTypes[buildTypeIdx].buildType,
5727                     VK_FORMAT_R32G32B32_SFLOAT,
5728                     false,
5729                     indexFormats[indexFormatIdx].indexType,
5730                     BottomTestType::TRIANGLES,
5731                     InstanceCullFlags::NONE,
5732                     false,
5733                     false,
5734                     false,
5735                     TopTestType::IDENTICAL_INSTANCES,
5736                     false,
5737                     false,
5738                     false,
5739                     VkBuildAccelerationStructureFlagsKHR(0u),
5740                     OT_NONE,
5741                     OP_NONE,
5742                     RTAS_DEFAULT_SIZE,
5743                     RTAS_DEFAULT_SIZE,
5744                     de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5745                     0u,
5746                     emptyCases[emptyCaseIdx].emptyASCase,
5747                     InstanceCustomIndexCase::NONE,
5748                     false,
5749                     0xFFu,
5750                     UpdateCase::NONE,
5751                 };
5752                 indexTypeGroup->addChild(
5753                     new RayTracingASBasicTestCase(ctx, emptyCases[emptyCaseIdx].name.c_str(), testParams));
5754             }
5755             buildTypeGroup->addChild(indexTypeGroup.release());
5756         }
5757         group->addChild(buildTypeGroup.release());
5758     }
5759 }
5760 
addInstanceIndexTests(tcu::TestCaseGroup * group)5761 void addInstanceIndexTests(tcu::TestCaseGroup *group)
5762 {
5763     const struct
5764     {
5765         vk::VkAccelerationStructureBuildTypeKHR buildType;
5766         std::string name;
5767     } buildTypes[] = {
5768         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5769         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5770     };
5771 
5772     const struct
5773     {
5774         InstanceCustomIndexCase customIndexCase;
5775         std::string name;
5776     } customIndexCases[] = {
5777         {InstanceCustomIndexCase::NONE, "no_instance_index"},
5778         {InstanceCustomIndexCase::ANY_HIT, "ahit"},
5779         {InstanceCustomIndexCase::CLOSEST_HIT, "chit"},
5780         {InstanceCustomIndexCase::INTERSECTION, "isec"},
5781     };
5782 
5783     auto &ctx = group->getTestContext();
5784 
5785     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5786     {
5787         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5788             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5789 
5790         for (int customIndexCaseIdx = 0; customIndexCaseIdx < DE_LENGTH_OF_ARRAY(customIndexCases);
5791              ++customIndexCaseIdx)
5792         {
5793             const auto &idxCase = customIndexCases[customIndexCaseIdx].customIndexCase;
5794             const auto bottomGeometryType =
5795                 ((idxCase == InstanceCustomIndexCase::INTERSECTION) ? BottomTestType::AABBS :
5796                                                                       BottomTestType::TRIANGLES);
5797 
5798             TestParams testParams{
5799                 buildTypes[buildTypeIdx].buildType,
5800                 VK_FORMAT_R32G32B32_SFLOAT,
5801                 false,
5802                 VK_INDEX_TYPE_NONE_KHR,
5803                 bottomGeometryType,
5804                 InstanceCullFlags::NONE,
5805                 false,
5806                 false,
5807                 false,
5808                 TopTestType::IDENTICAL_INSTANCES,
5809                 false,
5810                 false,
5811                 false,
5812                 VkBuildAccelerationStructureFlagsKHR(0u),
5813                 OT_NONE,
5814                 OP_NONE,
5815                 RTAS_DEFAULT_SIZE,
5816                 RTAS_DEFAULT_SIZE,
5817                 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5818                 0u,
5819                 EmptyAccelerationStructureCase::NOT_EMPTY,
5820                 customIndexCases[customIndexCaseIdx].customIndexCase,
5821                 false,
5822                 0xFFu,
5823                 UpdateCase::NONE,
5824             };
5825             buildTypeGroup->addChild(
5826                 new RayTracingASBasicTestCase(ctx, customIndexCases[customIndexCaseIdx].name.c_str(), testParams));
5827         }
5828         group->addChild(buildTypeGroup.release());
5829     }
5830 }
5831 
addInstanceUpdateTests(tcu::TestCaseGroup * group)5832 void addInstanceUpdateTests(tcu::TestCaseGroup *group)
5833 {
5834     const struct
5835     {
5836         vk::VkAccelerationStructureBuildTypeKHR buildType;
5837         std::string name;
5838     } buildTypes[] = {
5839         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5840         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5841     };
5842 
5843     struct
5844     {
5845         OperationType operationType;
5846         const char *name;
5847     } operationTypes[] = {
5848         {OP_UPDATE, "update"},
5849         {OP_UPDATE_IN_PLACE, "update_in_place"},
5850     };
5851 
5852     auto &ctx = group->getTestContext();
5853 
5854     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5855     {
5856         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5857             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5858 
5859         for (int operationTypesIdx = 0; operationTypesIdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypesIdx)
5860         {
5861             TestParams testParams{
5862                 buildTypes[buildTypeIdx].buildType,
5863                 VK_FORMAT_R32G32B32_SFLOAT,
5864                 false,
5865                 VK_INDEX_TYPE_NONE_KHR,
5866                 BottomTestType::TRIANGLES,
5867                 InstanceCullFlags::NONE,
5868                 false,
5869                 false,
5870                 false,
5871                 TopTestType::IDENTICAL_INSTANCES,
5872                 false,
5873                 false,
5874                 false,
5875                 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
5876                 OT_TOP_ACCELERATION,
5877                 operationTypes[operationTypesIdx].operationType,
5878                 RTAS_DEFAULT_SIZE,
5879                 RTAS_DEFAULT_SIZE,
5880                 de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
5881                 0u,
5882                 EmptyAccelerationStructureCase::NOT_EMPTY,
5883                 InstanceCustomIndexCase::NONE,
5884                 false,
5885                 0xFFu,
5886                 UpdateCase::NONE,
5887             };
5888             buildTypeGroup->addChild(
5889                 new RayTracingASBasicTestCase(ctx, operationTypes[operationTypesIdx].name, testParams));
5890         }
5891         group->addChild(buildTypeGroup.release());
5892     }
5893 }
5894 
addInstanceRayCullMaskTests(tcu::TestCaseGroup * group)5895 void addInstanceRayCullMaskTests(tcu::TestCaseGroup *group)
5896 {
5897     const struct
5898     {
5899         vk::VkAccelerationStructureBuildTypeKHR buildType;
5900         std::string name;
5901     } buildTypes[] = {
5902         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5903         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5904     };
5905 
5906     const struct
5907     {
5908         InstanceCustomIndexCase customIndexCase;
5909         std::string name;
5910     } customIndexCases[] = {
5911         {InstanceCustomIndexCase::ANY_HIT, "ahit"},
5912         {InstanceCustomIndexCase::CLOSEST_HIT, "chit"},
5913         {InstanceCustomIndexCase::INTERSECTION, "isec"},
5914     };
5915 
5916     const struct
5917     {
5918         uint32_t cullMask;
5919         std::string name;
5920     } cullMask[] = {
5921         {0x000000AAu, "4_bits"},
5922         {0x00000055u, "4_bits_reverse"},
5923         {0xAAAAAAAAu, "16_bits"},
5924         {0x55555555u, "16_bits_reverse"},
5925     };
5926 
5927     auto &ctx = group->getTestContext();
5928 
5929     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
5930     {
5931         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
5932             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
5933 
5934         for (int customIndexCaseIdx = 0; customIndexCaseIdx < DE_LENGTH_OF_ARRAY(customIndexCases);
5935              ++customIndexCaseIdx)
5936         {
5937             de::MovePtr<tcu::TestCaseGroup> customIndexCaseGroup(
5938                 new tcu::TestCaseGroup(ctx, customIndexCases[customIndexCaseIdx].name.c_str()));
5939 
5940             for (int cullMaskIdx = 0; cullMaskIdx < DE_LENGTH_OF_ARRAY(cullMask); ++cullMaskIdx)
5941             {
5942                 const auto &idxCase = customIndexCases[customIndexCaseIdx].customIndexCase;
5943                 const auto bottomGeometryType =
5944                     ((idxCase == InstanceCustomIndexCase::INTERSECTION) ? BottomTestType::AABBS :
5945                                                                           BottomTestType::TRIANGLES);
5946 
5947                 TestParams testParams{
5948                     buildTypes[buildTypeIdx].buildType,
5949                     VK_FORMAT_R32G32B32_SFLOAT,
5950                     false,
5951                     VK_INDEX_TYPE_NONE_KHR,
5952                     bottomGeometryType,
5953                     InstanceCullFlags::NONE,
5954                     false,
5955                     false,
5956                     false,
5957                     TopTestType::IDENTICAL_INSTANCES,
5958                     false,
5959                     false,
5960                     false,
5961                     VkBuildAccelerationStructureFlagsKHR(0u),
5962                     OT_NONE,
5963                     OP_NONE,
5964                     RTAS_DEFAULT_SIZE,
5965                     RTAS_DEFAULT_SIZE,
5966                     de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
5967                     0u,
5968                     EmptyAccelerationStructureCase::NOT_EMPTY,
5969                     customIndexCases[customIndexCaseIdx].customIndexCase,
5970                     true,
5971                     cullMask[cullMaskIdx].cullMask,
5972                     UpdateCase::NONE,
5973                 };
5974                 customIndexCaseGroup->addChild(
5975                     new RayTracingASBasicTestCase(ctx, cullMask[cullMaskIdx].name.c_str(), testParams));
5976             }
5977             buildTypeGroup->addChild(customIndexCaseGroup.release());
5978         }
5979         group->addChild(buildTypeGroup.release());
5980     }
5981 }
5982 
addGetDeviceAccelerationStructureCompabilityTests(tcu::TestCaseGroup * group)5983 void addGetDeviceAccelerationStructureCompabilityTests(tcu::TestCaseGroup *group)
5984 {
5985     struct
5986     {
5987         vk::VkAccelerationStructureBuildTypeKHR buildType;
5988         std::string name;
5989     } const buildTypes[] = {
5990         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
5991         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
5992     };
5993 
5994     struct
5995     {
5996         OperationTarget target;
5997         std::string name;
5998     } const targets[] = {
5999         {OT_TOP_ACCELERATION, "top"},
6000         {OT_BOTTOM_ACCELERATION, "bottom"},
6001     };
6002 
6003     auto &ctx = group->getTestContext();
6004 
6005     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
6006     {
6007         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
6008             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
6009 
6010         for (int targetIdx = 0; targetIdx < DE_LENGTH_OF_ARRAY(targets); ++targetIdx)
6011         {
6012             TestParams testParams{
6013                 buildTypes[buildTypeIdx].buildType, // buildType        - are we making AS on CPU or GPU
6014                 VK_FORMAT_R32G32B32_SFLOAT,         // vertexFormat
6015                 false,                              // padVertices
6016                 VK_INDEX_TYPE_NONE_KHR,             // indexType
6017                 BottomTestType::TRIANGLES,          // bottomTestType    - what kind of geometry is stored in bottom AS
6018                 InstanceCullFlags::NONE,            // cullFlags        - Flags for instances, if needed.
6019                 false, // bottomUsesAOP    - does bottom AS use arrays, or arrays of pointers
6020                 false, // bottomGeneric    - Bottom created as generic AS type.
6021                 false, // bottomUnboundedCreation - Create BLAS using buffers with unbounded memory.
6022                 TopTestType::
6023                     IDENTICAL_INSTANCES, // topTestType        - If instances are identical then bottom geometries must have different vertices/aabbs
6024                 false, // topUsesAOP        - does top AS use arrays, or arrays of pointers
6025                 false, // topGeneric        - Top created as generic AS type.
6026                 false, // topUnboundedCreation - Create TLAS using buffers with unbounded memory.
6027                 VkBuildAccelerationStructureFlagsKHR(0u),                          // buildFlags
6028                 targets[targetIdx].target,                                         // operationTarget
6029                 OP_NONE,                                                           // operationType
6030                 RTAS_DEFAULT_SIZE,                                                 // width
6031                 RTAS_DEFAULT_SIZE,                                                 // height
6032                 de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()), // testConfiguration
6033                 0u,                                                                // workerThreadsCount
6034                 EmptyAccelerationStructureCase::NOT_EMPTY,                         // emptyASCase
6035                 InstanceCustomIndexCase::NONE,                                     // instanceCustomIndexCase
6036                 false,                                                             // useCullMask
6037                 0xFFu,                                                             // cullMask
6038                 UpdateCase::NONE,                                                  // updateCase
6039             };
6040             buildTypeGroup->addChild(new RayTracingDeviceASCompabilityKHRTestCase(
6041                 ctx, targets[targetIdx].name.c_str(), de::SharedPtr<TestParams>(new TestParams(testParams))));
6042         }
6043         group->addChild(buildTypeGroup.release());
6044     }
6045 }
6046 
addUpdateHeaderBottomAddressTests(tcu::TestCaseGroup * group)6047 void addUpdateHeaderBottomAddressTests(tcu::TestCaseGroup *group)
6048 {
6049     struct
6050     {
6051         vk::VkAccelerationStructureBuildTypeKHR buildType;
6052         std::string name;
6053     } const buildTypes[] = {
6054         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu_built"},
6055         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu_built"},
6056     };
6057 
6058     struct
6059     {
6060         TopTestType type;
6061         std::string name;
6062     } const instTypes[] = {
6063         {TopTestType::IDENTICAL_INSTANCES, "the_same_instances"},
6064         {TopTestType::DIFFERENT_INSTANCES, "different_instances"},
6065         {TopTestType::MIX_INSTANCES, "mix_same_diff_instances"},
6066     };
6067 
6068     auto &ctx = group->getTestContext();
6069 
6070     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
6071     {
6072         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
6073             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
6074 
6075         for (int instTypeIdx = 0; instTypeIdx < DE_LENGTH_OF_ARRAY(instTypes); ++instTypeIdx)
6076         {
6077             TestParams testParams{
6078                 buildTypes[buildTypeIdx].buildType,        // buildType
6079                 VK_FORMAT_R32G32B32_SFLOAT,                // vertexFormat
6080                 false,                                     // padVertices
6081                 VK_INDEX_TYPE_NONE_KHR,                    // indexType
6082                 BottomTestType::TRIANGLES,                 // bottomTestType
6083                 InstanceCullFlags::NONE,                   // cullFlags
6084                 false,                                     // bottomUsesAOP
6085                 false,                                     // bottomGeneric
6086                 false,                                     // bottomUnboundedCreation
6087                 instTypes[instTypeIdx].type,               // topTestType
6088                 false,                                     // topUsesAOP
6089                 false,                                     // topGeneric
6090                 false,                                     // topUnboundedCreation
6091                 VkBuildAccelerationStructureFlagsKHR(0u),  // buildFlags
6092                 OT_TOP_ACCELERATION,                       // operationTarget
6093                 OP_NONE,                                   // operationType
6094                 RTAS_DEFAULT_SIZE,                         // width
6095                 RTAS_DEFAULT_SIZE,                         // height
6096                 de::SharedPtr<TestConfiguration>(nullptr), // testConfiguration
6097                 0u,                                        // workerThreadsCount
6098                 EmptyAccelerationStructureCase::NOT_EMPTY, // emptyASCase
6099                 InstanceCustomIndexCase::NONE,             // instanceCustomIndexCase
6100                 false,                                     // useCullMask
6101                 0xFFu,                                     // cullMask
6102                 UpdateCase::NONE,                          // updateCase
6103             };
6104             buildTypeGroup->addChild(new RayTracingHeaderBottomAddressTestCase(
6105                 ctx, instTypes[instTypeIdx].name.c_str(), de::SharedPtr<TestParams>(new TestParams(testParams))));
6106         }
6107         group->addChild(buildTypeGroup.release());
6108     }
6109 }
6110 
addQueryPoolResultsTests(TestCaseGroup * group)6111 void addQueryPoolResultsTests(TestCaseGroup *group)
6112 {
6113     std::pair<VkAccelerationStructureBuildTypeKHR, const char *> const buildTypes[]{
6114         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu"},
6115         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu"},
6116     };
6117 
6118     std::pair<bool, const char *> const storeTypes[]{{false, "memory"}, {true, "buffer"}};
6119 
6120     std::pair<QueryPoolResultsParams::Type, const char *> const queryTypes[]{
6121         {QueryPoolResultsParams::Type::StructureSize, "structure_size"},
6122         {QueryPoolResultsParams::Type::PointerCount, "pointer_count"}};
6123 
6124     std::pair<bool, const char *> const buildWithCompacted[]{{false, "no_compacted"}, {true, "enable_compacted"}};
6125 
6126     auto &testContext = group->getTestContext();
6127     for (const auto &buildType : buildTypes)
6128     {
6129         auto buildTypeGroup = makeMovePtr<TestCaseGroup>(testContext, buildType.second);
6130         for (const auto &compacted : buildWithCompacted)
6131         {
6132             auto buildCompactedGroup = makeMovePtr<TestCaseGroup>(testContext, compacted.second);
6133             for (const auto &storeType : storeTypes)
6134             {
6135                 auto storeTypeGroup = makeMovePtr<TestCaseGroup>(testContext, storeType.second);
6136                 for (const auto &queryType : queryTypes)
6137                 {
6138                     QueryPoolResultsParams p;
6139                     p.buildType  = buildType.first;
6140                     p.inVkBuffer = storeType.first;
6141                     p.queryType  = queryType.first;
6142                     p.blasCount  = 5;
6143                     p.compacted  = compacted.first;
6144 
6145                     storeTypeGroup->addChild(
6146                         new QueryPoolResultsCase(testContext, queryType.second, makeSharedFrom(p)));
6147                 }
6148                 buildCompactedGroup->addChild(storeTypeGroup.release());
6149             }
6150             buildTypeGroup->addChild(buildCompactedGroup.release());
6151         }
6152         group->addChild(buildTypeGroup.release());
6153     }
6154 }
6155 
addCopyWithinPipelineTests(TestCaseGroup * group)6156 void addCopyWithinPipelineTests(TestCaseGroup *group)
6157 {
6158     std::pair<VkAccelerationStructureBuildTypeKHR, const char *> const buildTypes[]{
6159         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu"},
6160         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu"},
6161     };
6162     std::pair<CopyWithinPipelineParams::Type, const char *> const testTypes[]{
6163         {CopyWithinPipelineParams::Type::StageASCopyBit, "stage_as_copy_bit"},
6164         {CopyWithinPipelineParams::Type::StageAllTransferBit, "stage_all_transfer"},
6165         {CopyWithinPipelineParams::Type::AccessSBTReadBit, "access_sbt_read"}};
6166 
6167     auto &testContext = group->getTestContext();
6168     for (const auto &buildType : buildTypes)
6169     {
6170         auto buildTypeGroup = makeMovePtr<TestCaseGroup>(testContext, buildType.second);
6171         for (const auto &testType : testTypes)
6172         {
6173             CopyWithinPipelineParams p;
6174             p.width  = 16;
6175             p.height = 16;
6176             p.build  = buildType.first;
6177             p.type   = testType.first;
6178 
6179             buildTypeGroup->addChild(new PipelineStageASCase(testContext, testType.second, makeSharedFrom(p)));
6180         }
6181         group->addChild(buildTypeGroup.release());
6182     }
6183 }
6184 
addUpdateTests(TestCaseGroup * group)6185 void addUpdateTests(TestCaseGroup *group)
6186 {
6187     const struct
6188     {
6189         vk::VkAccelerationStructureBuildTypeKHR buildType;
6190         std::string name;
6191     } buildTypes[] = {
6192         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, "cpu"},
6193         {VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, "gpu"},
6194     };
6195 
6196     struct
6197     {
6198         UpdateCase updateType;
6199         const char *name;
6200     } updateTypes[] = {
6201         {UpdateCase::VERTICES, "vertices"},
6202         {UpdateCase::INDICES, "indices"},
6203         {UpdateCase::TRANSFORM, "transform"},
6204     };
6205 
6206     auto &ctx = group->getTestContext();
6207 
6208     for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
6209     {
6210         de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(
6211             new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
6212 
6213         for (int updateTypesIdx = 0; updateTypesIdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateTypesIdx)
6214         {
6215             TestParams testParams{
6216                 buildTypes[buildTypeIdx].buildType,
6217                 VK_FORMAT_R32G32B32_SFLOAT,
6218                 false,
6219                 VK_INDEX_TYPE_UINT16,
6220                 BottomTestType::TRIANGLES,
6221                 InstanceCullFlags::NONE,
6222                 false,
6223                 false,
6224                 false,
6225                 TopTestType::IDENTICAL_INSTANCES,
6226                 false,
6227                 false,
6228                 false,
6229                 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
6230                 OT_TOP_ACCELERATION,
6231                 OP_NONE,
6232                 RTAS_DEFAULT_SIZE,
6233                 RTAS_DEFAULT_SIZE,
6234                 de::SharedPtr<TestConfiguration>(new UpdateableASConfiguration()),
6235                 0u,
6236                 EmptyAccelerationStructureCase::NOT_EMPTY,
6237                 InstanceCustomIndexCase::NONE,
6238                 false,
6239                 0xFFu,
6240                 updateTypes[updateTypesIdx].updateType,
6241             };
6242             buildTypeGroup->addChild(new ASUpdateCase(ctx, updateTypes[updateTypesIdx].name, testParams));
6243         }
6244         group->addChild(buildTypeGroup.release());
6245     }
6246 }
6247 
createAccelerationStructuresTests(tcu::TestContext & testCtx)6248 tcu::TestCaseGroup *createAccelerationStructuresTests(tcu::TestContext &testCtx)
6249 {
6250     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "acceleration_structures"));
6251 
6252     // Test building AS with different build types, build flags and geometries/instances using arrays or arrays of pointers
6253     addTestGroup(group.get(), "flags", addBasicBuildingTests);
6254     // Test building AS with different vertex and index formats
6255     addTestGroup(group.get(), "format", addVertexIndexFormatsTests);
6256     // Test copying, compaction and serialization of AS
6257     addTestGroup(group.get(), "operations", addOperationTests);
6258     // Test host threading operations
6259     addTestGroup(group.get(), "host_threading", addHostThreadingOperationTests);
6260     // Test using AS as function argument using both pointers and bare values
6261     addTestGroup(group.get(), "function_argument", addFuncArgTests);
6262     // Test building AS with counterclockwise triangles and/or disabling face culling
6263     addTestGroup(group.get(), "instance_triangle_culling", addInstanceTriangleCullingTests);
6264     // Test for CullMaskKHR builtin as a part of VK_KHR_ray_tracing_maintenance1
6265     addTestGroup(group.get(), "ray_cull_mask", addInstanceRayCullMaskTests);
6266     // Exercise dynamic indexing of acceleration structures
6267     addTestGroup(group.get(), "dynamic_indexing", addDynamicIndexingTests);
6268     // Test building empty acceleration structures using different methods
6269     addTestGroup(group.get(), "empty", addEmptyAccelerationStructureTests);
6270     // Test using different values for the instance index and checking them in shaders
6271     addTestGroup(group.get(), "instance_index", addInstanceIndexTests);
6272     // Test updating instance index using both in-place and separate src/dst acceleration structures
6273     addTestGroup(group.get(), "instance_update", addInstanceUpdateTests);
6274     addTestGroup(group.get(), "device_compability_khr", addGetDeviceAccelerationStructureCompabilityTests);
6275     addTestGroup(group.get(), "header_bottom_address", addUpdateHeaderBottomAddressTests);
6276     // Test for a new VkQueryPool queries for VK_KHR_ray_tracing_maintenance1
6277     addTestGroup(group.get(), "query_pool_results", addQueryPoolResultsTests);
6278     // Tests ACCELLERATION_STRUCTURE_COPY and ACCESS_2_SBT_READ with VK_KHR_ray_tracing_maintenance1
6279     addTestGroup(group.get(), "copy_within_pipeline", addCopyWithinPipelineTests);
6280     // Tests updating AS via replacing vertex/index/transform buffers
6281     addTestGroup(group.get(), "update", addUpdateTests);
6282 
6283     return group.release();
6284 }
6285 
6286 } // namespace RayTracing
6287 
6288 } // namespace vkt
6289