• 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 Misc tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingMiscTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 
27 #include "vkDefs.hpp"
28 
29 #include "vktTestCase.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 
38 #include "vkRayTracingUtil.hpp"
39 
40 #include "deRandom.hpp"
41 #include <algorithm>
42 #include <memory>
43 #include <sstream>
44 
45 namespace vkt
46 {
47 namespace RayTracing
48 {
49 namespace
50 {
51 using namespace vk;
52 using namespace std;
53 
54 enum class BaseType
55 {
56     F32,
57     F64,
58     I8,
59     I16,
60     I32,
61     I64,
62     U8,
63     U16,
64     U32,
65     U64,
66 
67     UNKNOWN
68 };
69 
70 enum class GeometryType
71 {
72     FIRST = 0,
73 
74     AABB = FIRST,
75     TRIANGLES,
76 
77     COUNT,
78 
79     AABB_AND_TRIANGLES, //< Only compatible with ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES AS layout.
80 };
81 
82 enum class MatrixMajorOrder
83 {
84     COLUMN_MAJOR,
85     ROW_MAJOR,
86 
87     UNKNOWN
88 };
89 
90 enum class ShaderGroups
91 {
92     FIRST_GROUP  = 0,
93     RAYGEN_GROUP = FIRST_GROUP,
94     MISS_GROUP,
95     HIT_GROUP,
96 
97     FIRST_CALLABLE_GROUP,
98 };
99 
100 enum class TestType
101 {
102     AABBS_AND_TRIS_IN_ONE_TL,
103     AS_STRESS_TEST,
104     CALLABLE_SHADER_STRESS_DYNAMIC_TEST,
105     CALLABLE_SHADER_STRESS_TEST,
106     CULL_MASK,
107     MAX_RAY_HIT_ATTRIBUTE_SIZE,
108     MAX_RT_INVOCATIONS_SUPPORTED,
109     CULL_MASK_EXTRA_BITS,
110     NO_DUPLICATE_ANY_HIT,
111     REPORT_INTERSECTION_RESULT,
112     RAY_PAYLOAD_IN,
113     RECURSIVE_TRACES_0,
114     RECURSIVE_TRACES_1,
115     RECURSIVE_TRACES_2,
116     RECURSIVE_TRACES_3,
117     RECURSIVE_TRACES_4,
118     RECURSIVE_TRACES_5,
119     RECURSIVE_TRACES_6,
120     RECURSIVE_TRACES_7,
121     RECURSIVE_TRACES_8,
122     RECURSIVE_TRACES_9,
123     RECURSIVE_TRACES_10,
124     RECURSIVE_TRACES_11,
125     RECURSIVE_TRACES_12,
126     RECURSIVE_TRACES_13,
127     RECURSIVE_TRACES_14,
128     RECURSIVE_TRACES_15,
129     RECURSIVE_TRACES_16,
130     RECURSIVE_TRACES_17,
131     RECURSIVE_TRACES_18,
132     RECURSIVE_TRACES_19,
133     RECURSIVE_TRACES_20,
134     RECURSIVE_TRACES_21,
135     RECURSIVE_TRACES_22,
136     RECURSIVE_TRACES_23,
137     RECURSIVE_TRACES_24,
138     RECURSIVE_TRACES_25,
139     RECURSIVE_TRACES_26,
140     RECURSIVE_TRACES_27,
141     RECURSIVE_TRACES_28,
142     RECURSIVE_TRACES_29,
143     SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1,
144     SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2,
145     SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3,
146     SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4,
147     SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5,
148     SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6,
149     SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1,
150     SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2,
151     SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3,
152     SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4,
153     SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5,
154     SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6,
155     SHADER_RECORD_BLOCK_SCALAR_1,
156     SHADER_RECORD_BLOCK_SCALAR_2,
157     SHADER_RECORD_BLOCK_SCALAR_3,
158     SHADER_RECORD_BLOCK_SCALAR_4,
159     SHADER_RECORD_BLOCK_SCALAR_5,
160     SHADER_RECORD_BLOCK_SCALAR_6,
161     SHADER_RECORD_BLOCK_STD430_1,
162     SHADER_RECORD_BLOCK_STD430_2,
163     SHADER_RECORD_BLOCK_STD430_3,
164     SHADER_RECORD_BLOCK_STD430_4,
165     SHADER_RECORD_BLOCK_STD430_5,
166     SHADER_RECORD_BLOCK_STD430_6,
167     IGNORE_ANY_HIT_STATICALLY,
168     IGNORE_ANY_HIT_DYNAMICALLY,
169     TERMINATE_ANY_HIT_STATICALLY,
170     TERMINATE_ANY_HIT_DYNAMICALLY,
171     TERMINATE_INTERSECTION_STATICALLY,
172     TERMINATE_INTERSECTION_DYNAMICALLY,
173     USE_MEMORY_ACCESS,
174 
175     COUNT
176 };
177 
178 enum class VariableType
179 {
180     FIRST,
181 
182     FLOAT = FIRST,
183     VEC2,
184     VEC3,
185     VEC4,
186 
187     MAT2,
188     MAT2X2,
189     MAT2X3,
190     MAT2X4,
191     MAT3,
192     MAT3X2,
193     MAT3X3,
194     MAT3X4,
195     MAT4,
196     MAT4X2,
197     MAT4X3,
198     MAT4X4,
199 
200     INT,
201     IVEC2,
202     IVEC3,
203     IVEC4,
204 
205     INT8,
206     I8VEC2,
207     I8VEC3,
208     I8VEC4,
209 
210     INT16,
211     I16VEC2,
212     I16VEC3,
213     I16VEC4,
214 
215     INT64,
216     I64VEC2,
217     I64VEC3,
218     I64VEC4,
219 
220     UINT,
221     UVEC2,
222     UVEC3,
223     UVEC4,
224 
225     UINT16,
226     U16VEC2,
227     U16VEC3,
228     U16VEC4,
229 
230     UINT64,
231     U64VEC2,
232     U64VEC3,
233     U64VEC4,
234 
235     UINT8,
236     U8VEC2,
237     U8VEC3,
238     U8VEC4,
239 
240     DOUBLE,
241     DVEC2,
242     DVEC3,
243     DVEC4,
244 
245     DMAT2,
246     DMAT2X2,
247     DMAT2X3,
248     DMAT2X4,
249     DMAT3,
250     DMAT3X2,
251     DMAT3X3,
252     DMAT3X4,
253     DMAT4,
254     DMAT4X2,
255     DMAT4X3,
256     DMAT4X4,
257 
258     UNKNOWN,
259     COUNT = UNKNOWN,
260 };
261 
262 enum class AccelerationStructureLayout
263 {
264     FIRST = 0,
265 
266     ONE_TL_ONE_BL_ONE_GEOMETRY = FIRST,
267     ONE_TL_ONE_BL_MANY_GEOMETRIES,
268     ONE_TL_MANY_BLS_ONE_GEOMETRY,
269     ONE_TL_MANY_BLS_MANY_GEOMETRIES,
270 
271     COUNT,
272 
273     ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES
274 };
275 
276 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
277                                               VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
278                                               VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
279 
280 struct CaseDef
281 {
282     TestType type;
283     GeometryType geometryType;
284     AccelerationStructureLayout asLayout;
285 
CaseDefvkt::RayTracing::__anon12c3bfbd0111::CaseDef286     CaseDef() : type(TestType::COUNT), geometryType(GeometryType::COUNT), asLayout(AccelerationStructureLayout::COUNT)
287     {
288         /* Stub */
289     }
290 
CaseDefvkt::RayTracing::__anon12c3bfbd0111::CaseDef291     CaseDef(const TestType &inType)
292         : type(inType)
293         , geometryType(GeometryType::COUNT)
294         , asLayout(AccelerationStructureLayout::COUNT)
295     {
296         /* Stub */
297     }
298 
CaseDefvkt::RayTracing::__anon12c3bfbd0111::CaseDef299     CaseDef(const TestType &inType, const GeometryType &inGeometryType, const AccelerationStructureLayout &inAsLayout)
300         : type(inType)
301         , geometryType(inGeometryType)
302         , asLayout(inAsLayout)
303     {
304         /* Stub */
305     }
306 };
307 
308 /* Helper global functions */
getSuffixForASLayout(const AccelerationStructureLayout & layout)309 static const char *getSuffixForASLayout(const AccelerationStructureLayout &layout)
310 {
311     const char *result = "?!";
312 
313     switch (layout)
314     {
315     case AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY:
316         result = "1TL1BL1G";
317         break;
318     case AccelerationStructureLayout::ONE_TL_ONE_BL_MANY_GEOMETRIES:
319         result = "1TL1BLnG";
320         break;
321     case AccelerationStructureLayout::ONE_TL_MANY_BLS_ONE_GEOMETRY:
322         result = "1TLnBL1G";
323         break;
324     case AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES:
325         result = "1TLnBLnG";
326         break;
327 
328     default:
329     {
330         deAssertFail("This should never happen", __FILE__, __LINE__);
331     }
332     }
333 
334     return result;
335 }
336 
getSuffixForGeometryType(const GeometryType & type)337 static const char *getSuffixForGeometryType(const GeometryType &type)
338 {
339     const char *result = "?!";
340 
341     switch (type)
342     {
343     case GeometryType::AABB:
344         result = "AABB";
345         break;
346     case GeometryType::TRIANGLES:
347         result = "tri";
348         break;
349 
350     default:
351     {
352         deAssertFail("This should never happen", __FILE__, __LINE__);
353     }
354     }
355 
356     return result;
357 }
358 
359 /* Instances and primitives in acceleration structures can have additional information assigned.
360  *
361  * By overriding functions of interest in this class, tests can further customize ASes generated by AS providers.
362  */
363 class ASPropertyProvider
364 {
365 public:
~ASPropertyProvider()366     virtual ~ASPropertyProvider()
367     {
368         /* Stub */
369     }
370 
getCullMask(const uint32_t & nBL,const uint32_t & nInstance) const371     virtual uint8_t getCullMask(const uint32_t &nBL, const uint32_t &nInstance) const
372     {
373         DE_UNREF(nBL);
374         DE_UNREF(nInstance);
375 
376         return 0xFF;
377     }
378 
getInstanceCustomIndex(const uint32_t & nBL,const uint32_t & nInstance) const379     virtual uint32_t getInstanceCustomIndex(const uint32_t &nBL, const uint32_t &nInstance) const
380     {
381         DE_UNREF(nBL);
382         DE_UNREF(nInstance);
383         return 0;
384     }
385 };
386 
387 class IGridASFeedback
388 {
389 public:
~IGridASFeedback()390     virtual ~IGridASFeedback()
391     {
392         /* Stub */
393     }
394 
395     virtual void onCullMaskAssignedToCell(const tcu::UVec3 &cellLocation, const uint8_t &cullMaskAssigned) = 0;
396     virtual void onInstanceCustomIndexAssignedToCell(const tcu::UVec3 &cellLocation,
397                                                      const uint32_t &customIndexAssigned)                  = 0;
398 };
399 
400 /* Acceleration structure data providers.
401  *
402  * These are expected to be reused across different test cases.
403  **/
404 class ASProviderBase
405 {
406 public:
~ASProviderBase()407     virtual ~ASProviderBase()
408     {
409         /* Stub */
410     }
411 
412     virtual std::unique_ptr<TopLevelAccelerationStructure> createTLAS(
413         Context &context, const AccelerationStructureLayout &asLayout, VkCommandBuffer cmdBuffer,
414         const VkGeometryFlagsKHR &bottomLevelGeometryFlags,
415         const ASPropertyProvider *optAsPropertyProviderPtr = nullptr,
416         IGridASFeedback *optASFeedbackPtr                  = nullptr) const = 0;
417     virtual uint32_t getNPrimitives() const                = 0;
418 };
419 
420 /* A 3D grid built of primitives. Size and distribution of the geometry can be configured both at creation time and at a later time. */
421 class GridASProvider : public ASProviderBase
422 {
423 public:
GridASProvider(const tcu::Vec3 & gridStartXYZ,const tcu::Vec3 & gridCellSizeXYZ,const tcu::UVec3 & gridSizeXYZ,const tcu::Vec3 & gridInterCellDeltaXYZ,const GeometryType & geometryType)424     GridASProvider(const tcu::Vec3 &gridStartXYZ, const tcu::Vec3 &gridCellSizeXYZ, const tcu::UVec3 &gridSizeXYZ,
425                    const tcu::Vec3 &gridInterCellDeltaXYZ, const GeometryType &geometryType)
426         : m_geometryType(geometryType)
427         , m_gridCellSizeXYZ(gridCellSizeXYZ)
428         , m_gridInterCellDeltaXYZ(gridInterCellDeltaXYZ)
429         , m_gridSizeXYZ(gridSizeXYZ)
430         , m_gridStartXYZ(gridStartXYZ)
431     {
432         fillVertexVec();
433     }
434 
createTLAS(Context & context,const AccelerationStructureLayout & asLayout,VkCommandBuffer cmdBuffer,const VkGeometryFlagsKHR & bottomLevelGeometryFlags,const ASPropertyProvider * optASPropertyProviderPtr,IGridASFeedback * optASFeedbackPtr) const435     std::unique_ptr<TopLevelAccelerationStructure> createTLAS(Context &context,
436                                                               const AccelerationStructureLayout &asLayout,
437                                                               VkCommandBuffer cmdBuffer,
438                                                               const VkGeometryFlagsKHR &bottomLevelGeometryFlags,
439                                                               const ASPropertyProvider *optASPropertyProviderPtr,
440                                                               IGridASFeedback *optASFeedbackPtr) const final
441     {
442         Allocator &allocator                   = context.getDefaultAllocator();
443         const DeviceInterface &deviceInterface = context.getDeviceInterface();
444         const VkDevice deviceVk                = context.getDevice();
445         const auto nCells                      = m_gridSizeXYZ.x() * m_gridSizeXYZ.y() * m_gridSizeXYZ.z();
446         std::unique_ptr<TopLevelAccelerationStructure> resultPtr;
447         de::MovePtr<TopLevelAccelerationStructure> tlPtr = makeTopLevelAccelerationStructure();
448 
449         DE_ASSERT(((asLayout == AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES) &&
450                    (m_geometryType == GeometryType::AABB_AND_TRIANGLES)) ||
451                   ((asLayout != AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES) &&
452                    (m_geometryType != GeometryType::AABB_AND_TRIANGLES)));
453 
454         switch (asLayout)
455         {
456         case AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY:
457         {
458             DE_ASSERT((m_geometryType == GeometryType::AABB) || (m_geometryType == GeometryType::TRIANGLES));
459 
460             const auto &vertexVec = (m_geometryType == GeometryType::AABB) ? m_aabbVertexVec : m_triVertexVec;
461             const auto cullMask = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getCullMask(0, 0) :
462                                                                           static_cast<uint8_t>(0xFF);
463             const auto instanceCustomIndex =
464                 (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getInstanceCustomIndex(0, 0) : 0;
465 
466             tlPtr->setInstanceCount(1);
467 
468             {
469                 de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
470 
471                 blPtr->setGeometryCount(1u);
472                 blPtr->addGeometry(vertexVec, (m_geometryType == GeometryType::TRIANGLES), bottomLevelGeometryFlags);
473 
474                 blPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
475 
476                 tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release()), identityMatrix3x4,
477                                    instanceCustomIndex, cullMask);
478             }
479 
480             if (optASFeedbackPtr != nullptr)
481             {
482                 for (auto nCell = 0u; nCell < nCells; nCell++)
483                 {
484                     const auto cellX = (((nCell) % m_gridSizeXYZ.x()));
485                     const auto cellY = (((nCell / m_gridSizeXYZ.x()) % m_gridSizeXYZ.y()));
486                     const auto cellZ = (((nCell / m_gridSizeXYZ.x()) / m_gridSizeXYZ.y()) % m_gridSizeXYZ.z());
487 
488                     optASFeedbackPtr->onCullMaskAssignedToCell(tcu::UVec3(cellX, cellY, cellZ), cullMask);
489                     optASFeedbackPtr->onInstanceCustomIndexAssignedToCell(tcu::UVec3(cellX, cellY, cellZ),
490                                                                           instanceCustomIndex);
491                 }
492             }
493 
494             break;
495         }
496 
497         case AccelerationStructureLayout::ONE_TL_ONE_BL_MANY_GEOMETRIES:
498         {
499             DE_ASSERT((m_geometryType == GeometryType::AABB) || (m_geometryType == GeometryType::TRIANGLES));
500 
501             const auto &vertexVec = (m_geometryType == GeometryType::AABB) ? m_aabbVertexVec : m_triVertexVec;
502             const auto nVerticesPerPrimitive =
503                 (m_geometryType == GeometryType::AABB) ? 2u : 12u /* tris */ * 3 /* verts */;
504             const auto cullMask = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getCullMask(0, 0) :
505                                                                           static_cast<uint8_t>(0xFF);
506             const auto instanceCustomIndex =
507                 (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getInstanceCustomIndex(0, 0) : 0;
508 
509             DE_ASSERT((vertexVec.size() % nVerticesPerPrimitive) == 0);
510 
511             tlPtr->setInstanceCount(1);
512 
513             {
514                 de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
515                 const auto nGeometries                              = vertexVec.size() / nVerticesPerPrimitive;
516 
517                 blPtr->setGeometryCount(nGeometries);
518 
519                 for (uint32_t nGeometry = 0; nGeometry < nGeometries; ++nGeometry)
520                 {
521                     std::vector<tcu::Vec3> currentGeometry(nVerticesPerPrimitive);
522 
523                     for (uint32_t nVertex = 0; nVertex < nVerticesPerPrimitive; ++nVertex)
524                     {
525                         currentGeometry.at(nVertex) = vertexVec.at(nGeometry * nVerticesPerPrimitive + nVertex);
526                     }
527 
528                     blPtr->addGeometry(currentGeometry, (m_geometryType == GeometryType::TRIANGLES),
529                                        bottomLevelGeometryFlags);
530                 }
531 
532                 blPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
533 
534                 tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release()), identityMatrix3x4,
535                                    instanceCustomIndex, cullMask);
536             }
537 
538             if (optASFeedbackPtr != nullptr)
539             {
540                 for (auto nCell = 0u; nCell < nCells; nCell++)
541                 {
542                     const auto cellX = (((nCell) % m_gridSizeXYZ.x()));
543                     const auto cellY = (((nCell / m_gridSizeXYZ.x()) % m_gridSizeXYZ.y()));
544                     const auto cellZ = (((nCell / m_gridSizeXYZ.x()) / m_gridSizeXYZ.y()) % m_gridSizeXYZ.z());
545 
546                     optASFeedbackPtr->onCullMaskAssignedToCell(tcu::UVec3(cellX, cellY, cellZ), cullMask);
547                     optASFeedbackPtr->onInstanceCustomIndexAssignedToCell(tcu::UVec3(cellX, cellY, cellZ),
548                                                                           instanceCustomIndex);
549                 }
550             }
551 
552             break;
553         }
554 
555         case AccelerationStructureLayout::ONE_TL_MANY_BLS_ONE_GEOMETRY:
556         {
557             DE_ASSERT((m_geometryType == GeometryType::AABB) || (m_geometryType == GeometryType::TRIANGLES));
558 
559             const auto &vertexVec = (m_geometryType == GeometryType::AABB) ? m_aabbVertexVec : m_triVertexVec;
560             const auto nVerticesPerPrimitive =
561                 (m_geometryType == GeometryType::AABB) ? 2u : 12u /* tris */ * 3 /* verts */;
562             const auto nInstances = vertexVec.size() / nVerticesPerPrimitive;
563 
564             DE_ASSERT((vertexVec.size() % nVerticesPerPrimitive) == 0);
565 
566             tlPtr->setInstanceCount(nInstances);
567 
568             for (uint32_t nInstance = 0; nInstance < nInstances; nInstance++)
569             {
570                 de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
571                 const auto cullMask                                 = (optASPropertyProviderPtr != nullptr) ?
572                                                                           optASPropertyProviderPtr->getCullMask(0, nInstance) :
573                                                                           static_cast<uint8_t>(0xFF);
574                 std::vector<tcu::Vec3> currentInstanceVertexVec;
575                 const auto instanceCustomIndex = (optASPropertyProviderPtr != nullptr) ?
576                                                      optASPropertyProviderPtr->getInstanceCustomIndex(0, nInstance) :
577                                                      0;
578 
579                 for (uint32_t nVertex = 0; nVertex < nVerticesPerPrimitive; ++nVertex)
580                 {
581                     currentInstanceVertexVec.push_back(vertexVec.at(nInstance * nVerticesPerPrimitive + nVertex));
582                 }
583 
584                 blPtr->setGeometryCount(1u);
585                 blPtr->addGeometry(currentInstanceVertexVec, (m_geometryType == GeometryType::TRIANGLES),
586                                    bottomLevelGeometryFlags);
587 
588                 blPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
589 
590                 tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release()), identityMatrix3x4,
591                                    instanceCustomIndex, cullMask);
592 
593                 if (optASFeedbackPtr != nullptr)
594                 {
595                     const auto cellX = (((nInstance) % m_gridSizeXYZ.x()));
596                     const auto cellY = (((nInstance / m_gridSizeXYZ.x()) % m_gridSizeXYZ.y()));
597                     const auto cellZ = (((nInstance / m_gridSizeXYZ.x()) / m_gridSizeXYZ.y()) % m_gridSizeXYZ.z());
598 
599                     optASFeedbackPtr->onCullMaskAssignedToCell(tcu::UVec3(cellX, cellY, cellZ), cullMask);
600                     optASFeedbackPtr->onInstanceCustomIndexAssignedToCell(tcu::UVec3(cellX, cellY, cellZ),
601                                                                           instanceCustomIndex);
602                 }
603             }
604 
605             break;
606         }
607 
608         case AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES:
609         {
610             DE_ASSERT((m_geometryType == GeometryType::AABB) || (m_geometryType == GeometryType::TRIANGLES));
611 
612             const auto &vertexVec = (m_geometryType == GeometryType::AABB) ? m_aabbVertexVec : m_triVertexVec;
613             const auto nVerticesPerPrimitive =
614                 (m_geometryType == GeometryType::AABB) ? 2u : 12u /* tris */ * 3 /* verts */;
615             const auto nPrimitivesDefined = static_cast<uint32_t>(vertexVec.size() / nVerticesPerPrimitive);
616             const auto nPrimitivesPerBLAS = 4;
617             const auto nBottomLevelASes   = nPrimitivesDefined / nPrimitivesPerBLAS;
618 
619             DE_ASSERT((vertexVec.size() % nVerticesPerPrimitive) == 0);
620             DE_ASSERT((nPrimitivesDefined % nPrimitivesPerBLAS) == 0);
621 
622             tlPtr->setInstanceCount(nBottomLevelASes);
623 
624             for (uint32_t nBottomLevelAS = 0; nBottomLevelAS < nBottomLevelASes; nBottomLevelAS++)
625             {
626                 de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
627                 const auto cullMask                                 = (optASPropertyProviderPtr != nullptr) ?
628                                                                           optASPropertyProviderPtr->getCullMask(nBottomLevelAS, 0) :
629                                                                           static_cast<uint8_t>(0xFF);
630                 const auto instanceCustomIndex =
631                     (optASPropertyProviderPtr != nullptr) ?
632                         optASPropertyProviderPtr->getInstanceCustomIndex(nBottomLevelAS, 0) :
633                         0;
634 
635                 blPtr->setGeometryCount(nPrimitivesPerBLAS);
636 
637                 for (uint32_t nGeometry = 0; nGeometry < nPrimitivesPerBLAS; nGeometry++)
638                 {
639                     std::vector<tcu::Vec3> currentVertexVec;
640 
641                     for (uint32_t nVertex = 0; nVertex < nVerticesPerPrimitive; ++nVertex)
642                     {
643                         currentVertexVec.push_back(vertexVec.at(
644                             (nBottomLevelAS * nPrimitivesPerBLAS + nGeometry) * nVerticesPerPrimitive + nVertex));
645                     }
646 
647                     blPtr->addGeometry(currentVertexVec, (m_geometryType == GeometryType::TRIANGLES),
648                                        bottomLevelGeometryFlags);
649                 }
650 
651                 blPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
652                 tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release()), identityMatrix3x4,
653                                    instanceCustomIndex, cullMask);
654 
655                 if (optASFeedbackPtr != nullptr)
656                 {
657                     for (uint32_t cellIndex = nPrimitivesPerBLAS * nBottomLevelAS;
658                          cellIndex < nPrimitivesPerBLAS * (nBottomLevelAS + 1); cellIndex++)
659                     {
660                         const auto cellX = (((cellIndex) % m_gridSizeXYZ.x()));
661                         const auto cellY = (((cellIndex / m_gridSizeXYZ.x()) % m_gridSizeXYZ.y()));
662                         const auto cellZ = (((cellIndex / m_gridSizeXYZ.x()) / m_gridSizeXYZ.y()) % m_gridSizeXYZ.z());
663 
664                         optASFeedbackPtr->onCullMaskAssignedToCell(tcu::UVec3(cellX, cellY, cellZ), cullMask);
665                         optASFeedbackPtr->onInstanceCustomIndexAssignedToCell(tcu::UVec3(cellX, cellY, cellZ),
666                                                                               instanceCustomIndex);
667                     }
668                 }
669             }
670 
671             break;
672         }
673 
674         case AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES:
675         {
676             DE_ASSERT(m_geometryType == GeometryType::AABB_AND_TRIANGLES);
677 
678             const auto nCellsDefined      = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
679             const auto nPrimitivesPerBLAS = 1;
680             const auto nBottomLevelASes   = nCellsDefined / nPrimitivesPerBLAS;
681 
682             DE_ASSERT((nCellsDefined % nPrimitivesPerBLAS) == 0);
683 
684             tlPtr->setInstanceCount(nBottomLevelASes);
685 
686             for (uint32_t nBottomLevelAS = 0; nBottomLevelAS < nBottomLevelASes; nBottomLevelAS++)
687             {
688                 de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
689                 const auto cullMask                                 = (optASPropertyProviderPtr != nullptr) ?
690                                                                           optASPropertyProviderPtr->getCullMask(nBottomLevelAS, 0) :
691                                                                           static_cast<uint8_t>(0xFF);
692                 const auto instanceCustomIndex =
693                     (optASPropertyProviderPtr != nullptr) ?
694                         optASPropertyProviderPtr->getInstanceCustomIndex(nBottomLevelAS, 0) :
695                         0;
696                 const bool usesAABB              = (nBottomLevelAS % 2) == 0;
697                 const auto &vertexVec            = (usesAABB) ? m_aabbVertexVec : m_triVertexVec;
698                 const auto nVerticesPerPrimitive = (usesAABB) ? 2u : 12u /* tris */ * 3 /* verts */;
699 
700                 // For this case, AABBs use the first shader group and triangles use the second shader group in the table.
701                 const auto instanceSBTOffset = (usesAABB ? 0u : 1u);
702 
703                 blPtr->setGeometryCount(nPrimitivesPerBLAS);
704 
705                 for (uint32_t nGeometry = 0; nGeometry < nPrimitivesPerBLAS; nGeometry++)
706                 {
707                     DE_ASSERT((vertexVec.size() % nVerticesPerPrimitive) == 0);
708 
709                     std::vector<tcu::Vec3> currentVertexVec;
710 
711                     for (uint32_t nVertex = 0; nVertex < nVerticesPerPrimitive; ++nVertex)
712                     {
713                         currentVertexVec.push_back(vertexVec.at(
714                             (nBottomLevelAS * nPrimitivesPerBLAS + nGeometry) * nVerticesPerPrimitive + nVertex));
715                     }
716 
717                     blPtr->addGeometry(currentVertexVec, !usesAABB, bottomLevelGeometryFlags);
718                 }
719 
720                 blPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
721 
722                 tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release()), identityMatrix3x4,
723                                    instanceCustomIndex, cullMask, instanceSBTOffset);
724 
725                 if (optASFeedbackPtr != nullptr)
726                 {
727                     for (uint32_t cellIndex = nPrimitivesPerBLAS * nBottomLevelAS;
728                          cellIndex < nPrimitivesPerBLAS * (nBottomLevelAS + 1); cellIndex++)
729                     {
730                         const auto cellX = (((cellIndex) % m_gridSizeXYZ.x()));
731                         const auto cellY = (((cellIndex / m_gridSizeXYZ.x()) % m_gridSizeXYZ.y()));
732                         const auto cellZ = (((cellIndex / m_gridSizeXYZ.x()) / m_gridSizeXYZ.y()) % m_gridSizeXYZ.z());
733 
734                         optASFeedbackPtr->onCullMaskAssignedToCell(tcu::UVec3(cellX, cellY, cellZ), cullMask);
735                         optASFeedbackPtr->onInstanceCustomIndexAssignedToCell(tcu::UVec3(cellX, cellY, cellZ),
736                                                                               instanceCustomIndex);
737                     }
738                 }
739             }
740 
741             break;
742         }
743 
744         default:
745         {
746             deAssertFail("This should never happen", __FILE__, __LINE__);
747         }
748         }
749 
750         tlPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
751 
752         resultPtr = decltype(resultPtr)(tlPtr.release());
753         return resultPtr;
754     }
755 
getNPrimitives() const756     uint32_t getNPrimitives() const final
757     {
758         return m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
759     }
760 
setProperties(const tcu::Vec3 & gridStartXYZ,const tcu::Vec3 & gridCellSizeXYZ,const tcu::UVec3 & gridSizeXYZ,const tcu::Vec3 & gridInterCellDeltaXYZ,const GeometryType & geometryType)761     void setProperties(const tcu::Vec3 &gridStartXYZ, const tcu::Vec3 &gridCellSizeXYZ, const tcu::UVec3 &gridSizeXYZ,
762                        const tcu::Vec3 &gridInterCellDeltaXYZ, const GeometryType &geometryType)
763     {
764         m_gridStartXYZ          = gridStartXYZ;
765         m_gridCellSizeXYZ       = gridCellSizeXYZ;
766         m_gridSizeXYZ           = gridSizeXYZ;
767         m_gridInterCellDeltaXYZ = gridInterCellDeltaXYZ;
768         m_geometryType          = geometryType;
769 
770         fillVertexVec();
771     }
772 
773 private:
fillVertexVec()774     void fillVertexVec()
775     {
776         const auto nCellsNeeded = m_gridSizeXYZ.x() * m_gridSizeXYZ.y() * m_gridSizeXYZ.z();
777 
778         m_aabbVertexVec.clear();
779         m_triVertexVec.clear();
780 
781         for (auto nCell = 0u; nCell < nCellsNeeded; nCell++)
782         {
783             const auto cellX = (((nCell) % m_gridSizeXYZ.x()));
784             const auto cellY = (((nCell / m_gridSizeXYZ.x()) % m_gridSizeXYZ.y()));
785             const auto cellZ = (((nCell / m_gridSizeXYZ.x()) / m_gridSizeXYZ.y()) % m_gridSizeXYZ.z());
786 
787             const auto cellX1Y1Z1 =
788                 tcu::Vec3(m_gridStartXYZ.x() + static_cast<float>(cellX) * m_gridInterCellDeltaXYZ.x(),
789                           m_gridStartXYZ.y() + static_cast<float>(cellY) * m_gridInterCellDeltaXYZ.y(),
790                           m_gridStartXYZ.z() + static_cast<float>(cellZ) * m_gridInterCellDeltaXYZ.z());
791             const auto cellX2Y2Z2 = tcu::Vec3(
792                 m_gridStartXYZ.x() + static_cast<float>(cellX) * m_gridInterCellDeltaXYZ.x() + m_gridCellSizeXYZ.x(),
793                 m_gridStartXYZ.y() + static_cast<float>(cellY) * m_gridInterCellDeltaXYZ.y() + m_gridCellSizeXYZ.y(),
794                 m_gridStartXYZ.z() + static_cast<float>(cellZ) * m_gridInterCellDeltaXYZ.z() + m_gridCellSizeXYZ.z());
795 
796             if (m_geometryType == GeometryType::AABB || m_geometryType == GeometryType::AABB_AND_TRIANGLES)
797             {
798                 /* Cell = AABB of the cell */
799                 m_aabbVertexVec.push_back(cellX1Y1Z1);
800                 m_aabbVertexVec.push_back(cellX2Y2Z2);
801             }
802 
803             if (m_geometryType == GeometryType::AABB_AND_TRIANGLES || m_geometryType == GeometryType::TRIANGLES)
804             {
805                 /* Cell == Six triangles forming a cube
806                  *
807                  * Lower-case characters: vertices with Z == Z2
808                  * Upper-case characters: vertices with Z == Z1
809 
810 
811                         g                h
812 
813 
814                     C              D
815 
816 
817 
818                         e                f
819 
820                     A              B
821 
822 
823                  */
824                 const auto A = tcu::Vec3(cellX1Y1Z1.x(), cellX1Y1Z1.y(), cellX1Y1Z1.z());
825                 const auto B = tcu::Vec3(cellX2Y2Z2.x(), cellX1Y1Z1.y(), cellX1Y1Z1.z());
826                 const auto C = tcu::Vec3(cellX1Y1Z1.x(), cellX2Y2Z2.y(), cellX1Y1Z1.z());
827                 const auto D = tcu::Vec3(cellX2Y2Z2.x(), cellX2Y2Z2.y(), cellX1Y1Z1.z());
828                 const auto E = tcu::Vec3(cellX1Y1Z1.x(), cellX1Y1Z1.y(), cellX2Y2Z2.z());
829                 const auto F = tcu::Vec3(cellX2Y2Z2.x(), cellX1Y1Z1.y(), cellX2Y2Z2.z());
830                 const auto G = tcu::Vec3(cellX1Y1Z1.x(), cellX2Y2Z2.y(), cellX2Y2Z2.z());
831                 const auto H = tcu::Vec3(cellX2Y2Z2.x(), cellX2Y2Z2.y(), cellX2Y2Z2.z());
832 
833                 // Z = Z1 face
834                 m_triVertexVec.push_back(A);
835                 m_triVertexVec.push_back(C);
836                 m_triVertexVec.push_back(D);
837 
838                 m_triVertexVec.push_back(D);
839                 m_triVertexVec.push_back(B);
840                 m_triVertexVec.push_back(A);
841 
842                 // Z = Z2 face
843                 m_triVertexVec.push_back(E);
844                 m_triVertexVec.push_back(H);
845                 m_triVertexVec.push_back(G);
846 
847                 m_triVertexVec.push_back(H);
848                 m_triVertexVec.push_back(E);
849                 m_triVertexVec.push_back(F);
850 
851                 // X = X0 face
852                 m_triVertexVec.push_back(A);
853                 m_triVertexVec.push_back(G);
854                 m_triVertexVec.push_back(C);
855 
856                 m_triVertexVec.push_back(G);
857                 m_triVertexVec.push_back(A);
858                 m_triVertexVec.push_back(E);
859 
860                 // X = X1 face
861                 m_triVertexVec.push_back(B);
862                 m_triVertexVec.push_back(D);
863                 m_triVertexVec.push_back(H);
864 
865                 m_triVertexVec.push_back(H);
866                 m_triVertexVec.push_back(F);
867                 m_triVertexVec.push_back(B);
868 
869                 // Y = Y0 face
870                 m_triVertexVec.push_back(C);
871                 m_triVertexVec.push_back(H);
872                 m_triVertexVec.push_back(D);
873 
874                 m_triVertexVec.push_back(H);
875                 m_triVertexVec.push_back(C);
876                 m_triVertexVec.push_back(G);
877 
878                 // Y = y1 face
879                 m_triVertexVec.push_back(A);
880                 m_triVertexVec.push_back(B);
881                 m_triVertexVec.push_back(E);
882 
883                 m_triVertexVec.push_back(B);
884                 m_triVertexVec.push_back(F);
885                 m_triVertexVec.push_back(E);
886             }
887         }
888     }
889 
890     std::vector<tcu::Vec3> m_aabbVertexVec;
891     std::vector<tcu::Vec3> m_triVertexVec;
892 
893     GeometryType m_geometryType;
894     tcu::Vec3 m_gridCellSizeXYZ;
895     tcu::Vec3 m_gridInterCellDeltaXYZ;
896     tcu::UVec3 m_gridSizeXYZ;
897     tcu::Vec3 m_gridStartXYZ;
898 };
899 
900 /* Provides an AS holding a single {(0, 0, 0), (-1, 1, 0), {1, 1, 0} tri. */
901 class TriASProvider : public ASProviderBase
902 {
903 public:
TriASProvider()904     TriASProvider()
905     {
906         /* Stub*/
907     }
908 
createTLAS(Context & context,const AccelerationStructureLayout &,VkCommandBuffer cmdBuffer,const VkGeometryFlagsKHR & bottomLevelGeometryFlags,const ASPropertyProvider * optASPropertyProviderPtr,IGridASFeedback *) const909     std::unique_ptr<TopLevelAccelerationStructure> createTLAS(Context &context,
910                                                               const AccelerationStructureLayout & /* asLayout */,
911                                                               VkCommandBuffer cmdBuffer,
912                                                               const VkGeometryFlagsKHR &bottomLevelGeometryFlags,
913                                                               const ASPropertyProvider *optASPropertyProviderPtr,
914                                                               IGridASFeedback * /* optASFeedbackPtr */) const final
915     {
916         Allocator &allocator                   = context.getDefaultAllocator();
917         const DeviceInterface &deviceInterface = context.getDeviceInterface();
918         const VkDevice deviceVk                = context.getDevice();
919         std::unique_ptr<TopLevelAccelerationStructure> resultPtr;
920         de::MovePtr<TopLevelAccelerationStructure> tlPtr = makeTopLevelAccelerationStructure();
921 
922         {
923 
924             const auto cullMask = (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getCullMask(0, 0) :
925                                                                           static_cast<uint8_t>(0xFF);
926             const auto instanceCustomIndex =
927                 (optASPropertyProviderPtr != nullptr) ? optASPropertyProviderPtr->getInstanceCustomIndex(0, 0) : 0;
928 
929             tlPtr->setInstanceCount(1);
930 
931             {
932                 de::MovePtr<BottomLevelAccelerationStructure> blPtr = makeBottomLevelAccelerationStructure();
933                 const std::vector<tcu::Vec3> vertexVec = {tcu::Vec3(0, 0, 0), tcu::Vec3(-1, 1, 0), tcu::Vec3(1, 1, 0)};
934 
935                 blPtr->setGeometryCount(1u);
936                 blPtr->addGeometry(vertexVec, true, /* triangles */
937                                    bottomLevelGeometryFlags);
938 
939                 blPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
940 
941                 tlPtr->addInstance(de::SharedPtr<BottomLevelAccelerationStructure>(blPtr.release()), identityMatrix3x4,
942                                    instanceCustomIndex, cullMask);
943             }
944         }
945 
946         tlPtr->createAndBuild(deviceInterface, deviceVk, cmdBuffer, allocator);
947 
948         resultPtr = decltype(resultPtr)(tlPtr.release());
949         return resultPtr;
950     }
951 
getNPrimitives() const952     uint32_t getNPrimitives() const final
953     {
954         return 1;
955     }
956 };
957 
958 /* Test logic providers ==> */
959 class TestBase
960 {
961 public:
~TestBase()962     virtual ~TestBase()
963     {
964         /* Stub */
965     }
966 
967     virtual tcu::UVec3 getDispatchSize() const                                       = 0;
968     virtual uint32_t getResultBufferSize() const                                     = 0;
969     virtual std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const = 0;
970     virtual void resetTLAS()                                                         = 0;
971     virtual void initAS(vkt::Context &context, RayTracingProperties *rtPropertiesPtr,
972                         VkCommandBuffer commandBuffer)                               = 0;
973     virtual void initPrograms(SourceCollections &programCollection) const            = 0;
974     virtual bool verifyResultBuffer(const void *inBufferPtr) const                   = 0;
975 
getAHitShaderCollectionShaderNames() const976     virtual std::vector<std::string> getAHitShaderCollectionShaderNames() const
977     {
978         return {"ahit"};
979     }
980 
getASBindingArraySize() const981     virtual uint32_t getASBindingArraySize() const
982     {
983         return 1u;
984     }
985 
getCallableShaderCollectionNames() const986     virtual std::vector<std::string> getCallableShaderCollectionNames() const
987     {
988         return std::vector<std::string>{};
989     }
990 
getCHitShaderCollectionShaderNames() const991     virtual std::vector<std::string> getCHitShaderCollectionShaderNames() const
992     {
993         return {"chit"};
994     }
995 
getDynamicStackSize(uint32_t maxPipelineRayRecursionDepth) const996     virtual uint32_t getDynamicStackSize(uint32_t maxPipelineRayRecursionDepth) const
997     {
998         DE_ASSERT(false);
999 
1000         DE_UNREF(maxPipelineRayRecursionDepth);
1001 
1002         return 0;
1003     }
1004 
getIntersectionShaderCollectionShaderNames() const1005     virtual std::vector<std::string> getIntersectionShaderCollectionShaderNames() const
1006     {
1007         return {"intersection"};
1008     }
1009 
getMaxRecursionDepthUsed() const1010     virtual uint32_t getMaxRecursionDepthUsed() const
1011     {
1012         return 1;
1013     }
1014 
getMissShaderCollectionShaderNames() const1015     virtual std::vector<std::string> getMissShaderCollectionShaderNames() const
1016     {
1017         return {"miss"};
1018     }
1019 
getNTraceRayInvocationsNeeded() const1020     virtual uint32_t getNTraceRayInvocationsNeeded() const
1021     {
1022         return 1;
1023     }
1024 
getPipelineLayout(const vk::DeviceInterface & deviceInterface,VkDevice deviceVk,VkDescriptorSetLayout descriptorSetLayout)1025     virtual Move<VkPipelineLayout> getPipelineLayout(const vk::DeviceInterface &deviceInterface, VkDevice deviceVk,
1026                                                      VkDescriptorSetLayout descriptorSetLayout)
1027     {
1028         return makePipelineLayout(deviceInterface, deviceVk, descriptorSetLayout);
1029     }
1030 
getResultBufferStartData() const1031     virtual std::vector<uint8_t> getResultBufferStartData() const
1032     {
1033         return std::vector<uint8_t>();
1034     }
1035 
getShaderRecordData(const ShaderGroups &) const1036     virtual const void *getShaderRecordData(const ShaderGroups & /* shaderGroup */) const
1037     {
1038         return nullptr;
1039     }
1040 
getShaderRecordSize(const ShaderGroups &) const1041     virtual uint32_t getShaderRecordSize(const ShaderGroups & /* shaderGroup */) const
1042     {
1043         return 0;
1044     }
1045 
getSpecializationInfoPtr(const VkShaderStageFlagBits &)1046     virtual VkSpecializationInfo *getSpecializationInfoPtr(const VkShaderStageFlagBits & /* shaderStage */)
1047     {
1048         return nullptr;
1049     }
1050 
init(vkt::Context &,RayTracingProperties *)1051     virtual bool init(vkt::Context & /* context    */, RayTracingProperties * /* rtPropsPtr */)
1052     {
1053         return true;
1054     }
1055 
onBeforeCmdTraceRays(const uint32_t &,vkt::Context &,VkCommandBuffer,VkPipelineLayout)1056     virtual void onBeforeCmdTraceRays(const uint32_t & /* nDispatch      */, vkt::Context & /* context        */,
1057                                       VkCommandBuffer /* commandBuffer  */, VkPipelineLayout /* pipelineLayout */)
1058     {
1059         /* Stub */
1060     }
1061 
onShaderStackSizeDiscovered(const VkDeviceSize &,const VkDeviceSize &,const VkDeviceSize &,const VkDeviceSize &,const VkDeviceSize &,const VkDeviceSize &)1062     virtual void onShaderStackSizeDiscovered(const VkDeviceSize & /* raygenShaderStackSize   */,
1063                                              const VkDeviceSize & /* ahitShaderStackSize     */,
1064                                              const VkDeviceSize & /* chitShaderStackSize     */,
1065                                              const VkDeviceSize & /* missShaderStackSize     */,
1066                                              const VkDeviceSize & /* callableShaderStackSize */,
1067                                              const VkDeviceSize & /* isectShaderStackSize    */)
1068     {
1069         /* Stub */
1070     }
1071 
usesDynamicStackSize() const1072     virtual bool usesDynamicStackSize() const
1073     {
1074         return false;
1075     }
1076 };
1077 
1078 class AABBTriTLTest : public TestBase, public ASPropertyProvider
1079 {
1080 public:
AABBTriTLTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout)1081     AABBTriTLTest(const GeometryType &geometryType, const AccelerationStructureLayout &asStructureLayout)
1082         : m_asStructureLayout(asStructureLayout)
1083         , m_geometryType(geometryType)
1084         , m_gridSize(tcu::UVec3(720, 1, 1))
1085         , m_lastCustomInstanceIndexUsed(0)
1086     {
1087     }
1088 
~AABBTriTLTest()1089     ~AABBTriTLTest()
1090     {
1091         /* Stub */
1092     }
1093 
getAHitShaderCollectionShaderNames() const1094     virtual std::vector<std::string> getAHitShaderCollectionShaderNames() const
1095     {
1096         return {"ahit", "ahit"};
1097     }
1098 
getCHitShaderCollectionShaderNames() const1099     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
1100     {
1101         return {};
1102     }
1103 
getInstanceCustomIndex(const uint32_t & nBL,const uint32_t & nInstance) const1104     uint32_t getInstanceCustomIndex(const uint32_t &nBL, const uint32_t &nInstance) const final
1105     {
1106         DE_UNREF(nBL);
1107         DE_UNREF(nInstance);
1108 
1109         return ++m_lastCustomInstanceIndexUsed;
1110     }
1111 
getDispatchSize() const1112     tcu::UVec3 getDispatchSize() const final
1113     {
1114         return tcu::UVec3(m_gridSize[0], m_gridSize[1], m_gridSize[2]);
1115     }
1116 
getResultBufferSize() const1117     uint32_t getResultBufferSize() const final
1118     {
1119         return static_cast<uint32_t>((2 /* nHits, nMisses */ + m_gridSize[0] * m_gridSize[1] * m_gridSize[2] *
1120                                                                    1 /* hit instance custom indices */) *
1121                                      sizeof(uint32_t));
1122     }
1123 
getTLASPtrVecToBind() const1124     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
1125     {
1126         DE_ASSERT(m_tlPtr != nullptr);
1127 
1128         return {m_tlPtr.get()};
1129     }
1130 
resetTLAS()1131     void resetTLAS() final
1132     {
1133         m_tlPtr.reset();
1134     }
1135 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)1136     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
1137                 VkCommandBuffer commandBuffer) final
1138     {
1139         /* Each AS holds a single unit AABB / cube built of tris.
1140          *
1141          * Geometry in the zeroth acceleration structure starts at the origin. Subsequent ASes
1142          * hold geometry that is positioned so that geometry formed by the union of all ASes never
1143          * intersects.
1144          *
1145          * Each raygen shader invocation uses a unique origin+target pair for the traced ray, and
1146          * only one AS is expected to hold geometry that the ray can find intersection for.
1147          * The AS index is stored in the result buffer, which is later verified by the CPU.
1148          *
1149          * Due to the fact AccelerationStructureEXT array indexing must be dynamically uniform and
1150          * it is not guaranteed we can determine workgroup size on VK 1.1-conformant platforms,
1151          * we can only trace rays against the same AS in a single ray trace dispatch.
1152          */
1153         std::unique_ptr<GridASProvider> asProviderPtr(new GridASProvider(tcu::Vec3(0, 0, 0), /* gridStartXYZ          */
1154                                                                          tcu::Vec3(1, 1, 1), /* gridCellSizeXYZ       */
1155                                                                          m_gridSize,
1156                                                                          tcu::Vec3(3, 0, 0), /* gridInterCellDeltaXYZ */
1157                                                                          m_geometryType));
1158 
1159         m_tlPtr = asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer,
1160                                             VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
1161                                             this,     /* optASPropertyProviderPtr */
1162                                             nullptr); /* optASFeedbackPtr            */
1163     }
1164 
initPrograms(SourceCollections & programCollection) const1165     void initPrograms(SourceCollections &programCollection) const final
1166     {
1167         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
1168                                                   0u,    /* flags        */
1169                                                   true); /* allowSpirv14 */
1170 
1171         const char *hitPropsDefinition = "struct HitProps\n"
1172                                          "{\n"
1173                                          "    uint instanceCustomIndex;\n"
1174                                          "};\n";
1175 
1176         {
1177             std::stringstream css;
1178 
1179             css << "#version 460 core\n"
1180                    "\n"
1181                    "#extension GL_EXT_ray_tracing : require\n"
1182                    "\n"
1183                    "hitAttributeEXT vec3 unusedAttribute;\n"
1184                    "\n" +
1185                        de::toString(hitPropsDefinition) +
1186                        "\n"
1187                        "layout(location = 0) rayPayloadInEXT      uint   unusedPayload;\n"
1188                        "layout(set      = 0, binding = 0, std430) buffer result\n"
1189                        "{\n"
1190                        "    uint     nHitsRegistered;\n"
1191                        "    uint     nMissesRegistered;\n"
1192                        "    HitProps hits[];\n"
1193                        "};\n"
1194                        "\n"
1195                        "void main()\n"
1196                        "{\n"
1197                        "    uint nHit = atomicAdd(nHitsRegistered, 1);\n"
1198                        "\n"
1199                        "    hits[nHit].instanceCustomIndex = gl_InstanceCustomIndexEXT;\n"
1200                        "}\n";
1201 
1202             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
1203         }
1204 
1205         {
1206             std::stringstream css;
1207 
1208             css << "#version 460 core\n"
1209                    "\n"
1210                    "#extension GL_EXT_ray_tracing : require\n"
1211                    "\n"
1212                    "hitAttributeEXT vec3 hitAttribute;\n"
1213                    "\n"
1214                    "void main()\n"
1215                    "{\n"
1216                    "    reportIntersectionEXT(0.95f, 0);\n"
1217                    "}\n";
1218 
1219             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
1220         }
1221 
1222         {
1223             std::stringstream css;
1224 
1225             css << "#version 460 core\n"
1226                    "\n"
1227                    "#extension GL_EXT_ray_tracing : require\n"
1228                    "\n" +
1229                        de::toString(hitPropsDefinition) +
1230                        "\n"
1231                        "layout(set = 0, binding = 0, std430) buffer result\n"
1232                        "{\n"
1233                        "    uint     nHitsRegistered;\n"
1234                        "    uint     nMissesRegistered;\n"
1235                        "    HitProps hits[];\n"
1236                        "};\n"
1237                        "\n"
1238                        "layout(location = 0) rayPayloadInEXT uint rayIndex;\n"
1239                        "\n"
1240                        "void main()\n"
1241                        "{\n"
1242                        "    atomicAdd(nMissesRegistered, 1);\n"
1243                        "}\n";
1244 
1245             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
1246         }
1247 
1248         {
1249             std::stringstream css;
1250 
1251             css << "#version 460 core\n"
1252                    "\n"
1253                    "#extension GL_EXT_ray_tracing : require\n"
1254                    "\n"
1255                    "layout(location = 0)              rayPayloadEXT uint               unusedPayload;\n"
1256                    "layout(set      = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
1257                    "\n"
1258                    "void main()\n"
1259                    "{\n"
1260                    "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
1261                    "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
1262                    "    uint  rayFlags     = gl_RayFlagsCullBackFacingTrianglesEXT;\n"
1263                    "    float tmin         = 0.001;\n"
1264                    "    float tmax         = 9.0;\n"
1265                    "\n"
1266                    "    uint  cullMask     = 0xFF;\n"
1267                    "    vec3  cellStartXYZ = vec3(nInvocation * 3.0, 0.0, 0.0);\n"
1268                    "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
1269                    "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
1270                    "    vec3  origin       = target - vec3(0, 2, 0);\n"
1271                    "    vec3  direct       = normalize(target - origin);\n"
1272                    "\n"
1273                    "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, "
1274                    "0);\n"
1275                    "}\n";
1276 
1277             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
1278         }
1279     }
1280 
verifyResultBuffer(const void * resultDataPtr) const1281     bool verifyResultBuffer(const void *resultDataPtr) const final
1282     {
1283         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
1284         bool result                  = false;
1285 
1286         typedef struct
1287         {
1288             uint32_t instanceCustomIndex;
1289         } HitProperties;
1290 
1291         std::map<uint32_t, uint32_t> customInstanceIndexToHitCountMap;
1292         const auto nHitsReported   = *resultU32Ptr;
1293         const auto nMissesReported = *(resultU32Ptr + 1);
1294 
1295         if (nHitsReported != m_gridSize[0] * m_gridSize[1] * m_gridSize[2])
1296         {
1297             goto end;
1298         }
1299 
1300         if (nMissesReported != 0)
1301         {
1302             goto end;
1303         }
1304 
1305         for (uint32_t nHit = 0; nHit < nHitsReported; ++nHit)
1306         {
1307             const HitProperties *hitPropsPtr =
1308                 reinterpret_cast<const HitProperties *>(resultU32Ptr + 2 /* preamble ints */) + nHit;
1309 
1310             customInstanceIndexToHitCountMap[hitPropsPtr->instanceCustomIndex]++;
1311 
1312             if (customInstanceIndexToHitCountMap[hitPropsPtr->instanceCustomIndex] > 1)
1313             {
1314                 goto end;
1315             }
1316         }
1317 
1318         for (uint32_t nInstance = 0; nInstance < nHitsReported; ++nInstance)
1319         {
1320             if (customInstanceIndexToHitCountMap.find(1 + nInstance) == customInstanceIndexToHitCountMap.end())
1321             {
1322                 goto end;
1323             }
1324         }
1325 
1326         result = true;
1327     end:
1328         return result;
1329     }
1330 
1331 private:
1332     const AccelerationStructureLayout m_asStructureLayout;
1333     const GeometryType m_geometryType;
1334 
1335     const tcu::UVec3 m_gridSize;
1336     mutable uint32_t m_lastCustomInstanceIndexUsed;
1337     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
1338 };
1339 
1340 class ASStressTest : public TestBase, public ASPropertyProvider
1341 {
1342 public:
ASStressTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout)1343     ASStressTest(const GeometryType &geometryType, const AccelerationStructureLayout &asStructureLayout)
1344         : m_asStructureLayout(asStructureLayout)
1345         , m_geometryType(geometryType)
1346         , m_lastCustomInstanceIndexUsed(0)
1347         , m_nASesToUse(0)
1348         , m_nMaxASToUse(16u)
1349     {
1350     }
1351 
~ASStressTest()1352     ~ASStressTest()
1353     {
1354         /* Stub */
1355     }
1356 
getASBindingArraySize() const1357     uint32_t getASBindingArraySize() const final
1358     {
1359         DE_ASSERT(m_nASesToUse != 0);
1360 
1361         return m_nASesToUse;
1362     }
1363 
getCHitShaderCollectionShaderNames() const1364     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
1365     {
1366         return {};
1367     }
1368 
getInstanceCustomIndex(const uint32_t & nBL,const uint32_t & nInstance) const1369     uint32_t getInstanceCustomIndex(const uint32_t &nBL, const uint32_t &nInstance) const final
1370     {
1371         DE_UNREF(nBL);
1372         DE_UNREF(nInstance);
1373 
1374         return ++m_lastCustomInstanceIndexUsed;
1375     }
1376 
getDispatchSize() const1377     tcu::UVec3 getDispatchSize() const final
1378     {
1379         return tcu::UVec3(1, 1, 1);
1380     }
1381 
getNTraceRayInvocationsNeeded() const1382     uint32_t getNTraceRayInvocationsNeeded() const final
1383     {
1384         return m_nMaxASToUse;
1385     }
1386 
getResultBufferSize() const1387     uint32_t getResultBufferSize() const final
1388     {
1389         return static_cast<uint32_t>(
1390             (2 /* nHits, nMisses */ + 2 * m_nMaxASToUse /* hit instance custom indices + AS index */) *
1391             sizeof(uint32_t));
1392     }
1393 
getTLASPtrVecToBind() const1394     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
1395     {
1396         std::vector<TopLevelAccelerationStructure *> resultVec;
1397 
1398         DE_ASSERT(m_tlPtrVec.size() != 0);
1399 
1400         for (auto &currentTLPtr : m_tlPtrVec)
1401         {
1402             resultVec.push_back(currentTLPtr.get());
1403         }
1404 
1405         return resultVec;
1406     }
1407 
resetTLAS()1408     void resetTLAS() final
1409     {
1410         for (auto &currentTLPtr : m_tlPtrVec)
1411         {
1412             currentTLPtr.reset();
1413         }
1414     }
1415 
init(vkt::Context &,RayTracingProperties * rtPropertiesPtr)1416     bool init(vkt::Context & /* context    */, RayTracingProperties *rtPropertiesPtr) final
1417     {
1418         /* NOTE: We clamp the number below to a sensible value, in case the implementation has no restrictions on the number of
1419          *         ASes accessible to shaders.
1420          */
1421         m_nASesToUse = std::min(rtPropertiesPtr->getMaxDescriptorSetAccelerationStructures(), m_nMaxASToUse);
1422 
1423         return true;
1424     }
1425 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)1426     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
1427                 VkCommandBuffer commandBuffer) final
1428     {
1429         /* Each AS holds a single unit AABB / cube built of tris.
1430          *
1431          * Geometry in the zeroth acceleration structure starts at the origin. Subsequent ASes
1432          * hold geometry that is positioned so that geometry formed by the union of all ASes never
1433          * intersects.
1434          *
1435          * Each raygen shader invocation uses a unique origin+target pair for the traced ray, and
1436          * only one AS is expected to hold geometry that the ray can find intersection for.
1437          * The AS index is stored in the result buffer, which is later verified by the CPU.
1438          *
1439          * Due to the fact AccelerationStructureEXT array indexing must be dynamically uniform and
1440          * it is not guaranteed we can determine workgroup size on VK 1.1-conformant platforms,
1441          * we can only trace rays against the same AS in a single ray trace dispatch.
1442          */
1443         std::unique_ptr<GridASProvider> asProviderPtr(
1444             new GridASProvider(tcu::Vec3(0, 0, 0),  /* gridStartXYZ          */
1445                                tcu::Vec3(1, 1, 1),  /* gridCellSizeXYZ       */
1446                                tcu::UVec3(1, 1, 1), /* gridSizeXYZ           */
1447                                tcu::Vec3(0, 0, 0),  /* gridInterCellDeltaXYZ */
1448                                m_geometryType));
1449 
1450         for (uint32_t nAS = 0; nAS < m_nASesToUse; ++nAS)
1451         {
1452             const auto origin = tcu::Vec3(3.0f * static_cast<float>(nAS), 0.0f, 0.0f);
1453 
1454             asProviderPtr->setProperties(origin, tcu::Vec3(1, 1, 1), /* gridCellSizeXYZ       */
1455                                          tcu::UVec3(1, 1, 1),        /* gridSizeXYZ           */
1456                                          tcu::Vec3(0, 0, 0),         /* gridInterCellDeltaXYZ */
1457                                          m_geometryType);
1458 
1459             auto tlPtr = asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer,
1460                                                    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
1461                                                    this,     /* optASPropertyProviderPtr */
1462                                                    nullptr); /* optASFeedbackPtr            */
1463 
1464             m_tlPtrVec.push_back(std::move(tlPtr));
1465         }
1466     }
1467 
initPrograms(SourceCollections & programCollection) const1468     void initPrograms(SourceCollections &programCollection) const final
1469     {
1470         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
1471                                                   0u,    /* flags        */
1472                                                   true); /* allowSpirv14 */
1473 
1474         const char *hitPropsDefinition = "struct HitProps\n"
1475                                          "{\n"
1476                                          "    uint instanceCustomIndex;\n"
1477                                          "    uint nAS;\n"
1478                                          "};\n";
1479 
1480         {
1481             std::stringstream css;
1482 
1483             css << "#version 460 core\n"
1484                    "\n"
1485                    "#extension GL_EXT_ray_tracing : require\n"
1486                    "\n"
1487                    "hitAttributeEXT vec3 unusedAttribute;\n"
1488                    "\n" +
1489                        de::toString(hitPropsDefinition) +
1490                        "\n"
1491                        "layout(location = 0) rayPayloadInEXT      uint   nAS;\n"
1492                        "layout(set      = 0, binding = 0, std430) buffer result\n"
1493                        "{\n"
1494                        "    uint     nHitsRegistered;\n"
1495                        "    uint     nMissesRegistered;\n"
1496                        "    HitProps hits[];\n"
1497                        "};\n"
1498                        "\n"
1499                        "void main()\n"
1500                        "{\n"
1501                        "    uint nHit = atomicAdd(nHitsRegistered, 1);\n"
1502                        "\n"
1503                        "    hits[nHit].instanceCustomIndex = gl_InstanceCustomIndexEXT;\n"
1504                        "    hits[nHit].nAS                 = nAS;\n"
1505                        "}\n";
1506 
1507             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
1508         }
1509 
1510         {
1511             std::stringstream css;
1512 
1513             css << "#version 460 core\n"
1514                    "\n"
1515                    "#extension GL_EXT_ray_tracing : require\n"
1516                    "\n"
1517                    "hitAttributeEXT vec3 hitAttribute;\n"
1518                    "\n"
1519                    "void main()\n"
1520                    "{\n"
1521                    "    reportIntersectionEXT(0.95f, 0);\n"
1522                    "}\n";
1523 
1524             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
1525         }
1526 
1527         {
1528             std::stringstream css;
1529 
1530             css << "#version 460 core\n"
1531                    "\n"
1532                    "#extension GL_EXT_ray_tracing : require\n"
1533                    "\n" +
1534                        de::toString(hitPropsDefinition) +
1535                        "\n"
1536                        "layout(set = 0, binding = 0, std430) buffer result\n"
1537                        "{\n"
1538                        "    uint     nHitsRegistered;\n"
1539                        "    uint     nMissesRegistered;\n"
1540                        "    HitProps hits[];\n"
1541                        "};\n"
1542                        "\n"
1543                        "layout(location = 0) rayPayloadInEXT uint rayIndex;\n"
1544                        "\n"
1545                        "void main()\n"
1546                        "{\n"
1547                        "    atomicAdd(nMissesRegistered, 1);\n"
1548                        "}\n";
1549 
1550             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
1551         }
1552 
1553         {
1554             std::stringstream css;
1555 
1556             css << "#version 460 core\n"
1557                    "\n"
1558                    "#extension GL_EXT_ray_tracing : require\n"
1559                    "\n"
1560                    "layout(push_constant) uniform pcUB\n"
1561                    "{\n"
1562                    "    uint nAS;\n"
1563                    "} ub;\n"
1564                    "\n"
1565                    "layout(location = 0)              rayPayloadEXT uint               payload;\n"
1566                    "layout(set      = 0, binding = 1) uniform accelerationStructureEXT accelerationStructures[" +
1567                        de::toString(m_nMaxASToUse) +
1568                        "];\n"
1569                        "\n"
1570                        "void main()\n"
1571                        "{\n"
1572                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
1573                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
1574                        "    uint  rayFlags     = gl_RayFlagsCullBackFacingTrianglesEXT;\n"
1575                        "    float tmin         = 0.001;\n"
1576                        "    float tmax         = 9.0;\n"
1577                        "\n"
1578                        "    uint  cullMask     = 0xFF;\n"
1579                        "    vec3  cellStartXYZ = vec3(ub.nAS * 3.0, 0.0, 0.0);\n"
1580                        "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
1581                        "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
1582                        "    vec3  origin       = target - vec3(0, 2, 0);\n"
1583                        "    vec3  direct       = normalize(target - origin);\n"
1584                        "\n"
1585                        "    payload = ub.nAS;\n"
1586                        "\n"
1587                        "    traceRayEXT(accelerationStructures[ub.nAS], rayFlags, cullMask, 0, 0, 0, origin, tmin, "
1588                        "direct, tmax, 0);\n"
1589                        "}\n";
1590 
1591             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
1592         }
1593     }
1594 
getPipelineLayout(const vk::DeviceInterface & deviceInterface,VkDevice deviceVk,VkDescriptorSetLayout descriptorSetLayout)1595     Move<VkPipelineLayout> getPipelineLayout(const vk::DeviceInterface &deviceInterface, VkDevice deviceVk,
1596                                              VkDescriptorSetLayout descriptorSetLayout) final
1597     {
1598         VkPushConstantRange pushConstantRange;
1599 
1600         pushConstantRange.offset     = 0;
1601         pushConstantRange.size       = sizeof(uint32_t);
1602         pushConstantRange.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
1603 
1604         return makePipelineLayout(deviceInterface, deviceVk, 1, /* setLayoutCount */
1605                                   &descriptorSetLayout, 1,      /* pushRangeCount */
1606                                   &pushConstantRange);
1607     }
1608 
onBeforeCmdTraceRays(const uint32_t & nDispatch,vkt::Context & context,VkCommandBuffer commandBuffer,VkPipelineLayout pipelineLayout)1609     void onBeforeCmdTraceRays(const uint32_t &nDispatch, vkt::Context &context, VkCommandBuffer commandBuffer,
1610                               VkPipelineLayout pipelineLayout) final
1611     {
1612         /* No need for a sync point in-between trace ray commands - all writes are atomic */
1613         VkMemoryBarrier memBarrier;
1614 
1615         memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1616         memBarrier.pNext         = nullptr;
1617         memBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1618         memBarrier.sType         = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1619 
1620         context.getDeviceInterface().cmdPipelineBarrier(
1621             commandBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, /* srcStageMask       */
1622             VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,                /* dstStageMask       */
1623             0,                                                           /* dependencyFlags    */
1624             1,                                                           /* memoryBarrierCount */
1625             &memBarrier, 0,                                              /* bufferMemoryBarrierCount */
1626             nullptr,                                                     /* pBufferMemoryBarriers    */
1627             0,                                                           /* imageMemoryBarrierCount  */
1628             nullptr);                                                    /* pImageMemoryBarriers     */
1629 
1630         context.getDeviceInterface().cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_RAYGEN_BIT_KHR,
1631                                                       0, /* offset */
1632                                                       sizeof(uint32_t), &nDispatch);
1633     }
1634 
verifyResultBuffer(const void * resultDataPtr) const1635     bool verifyResultBuffer(const void *resultDataPtr) const final
1636     {
1637         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
1638         bool result                  = false;
1639 
1640         typedef struct
1641         {
1642             uint32_t instanceCustomIndex;
1643             uint32_t nAS;
1644         } HitProperties;
1645 
1646         const auto nHitsReported   = *resultU32Ptr;
1647         const auto nMissesReported = *(resultU32Ptr + 1);
1648 
1649         if (nHitsReported != m_nMaxASToUse)
1650         {
1651             goto end;
1652         }
1653 
1654         if (nMissesReported != 0)
1655         {
1656             goto end;
1657         }
1658 
1659         for (uint32_t nHit = 0; nHit < nHitsReported; ++nHit)
1660         {
1661             const HitProperties *hitPropsPtr =
1662                 reinterpret_cast<const HitProperties *>(resultU32Ptr + 2 /* preamble ints */) + nHit;
1663 
1664             if (hitPropsPtr->instanceCustomIndex != (nHit + 1))
1665             {
1666                 goto end;
1667             }
1668 
1669             if (hitPropsPtr->nAS != nHit)
1670             {
1671                 goto end;
1672             }
1673         }
1674 
1675         result = true;
1676     end:
1677         return result;
1678     }
1679 
1680 private:
1681     const AccelerationStructureLayout m_asStructureLayout;
1682     const GeometryType m_geometryType;
1683 
1684     mutable uint32_t m_lastCustomInstanceIndexUsed;
1685     uint32_t m_nASesToUse;
1686     std::vector<std::unique_ptr<TopLevelAccelerationStructure>> m_tlPtrVec;
1687 
1688     const uint32_t m_nMaxASToUse;
1689 };
1690 
1691 class CallableShaderStressTest : public TestBase
1692 {
1693 public:
CallableShaderStressTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout,const bool & useDynamicStackSize)1694     CallableShaderStressTest(const GeometryType &geometryType, const AccelerationStructureLayout &asStructureLayout,
1695                              const bool &useDynamicStackSize)
1696         : m_asStructureLayout(asStructureLayout)
1697         , m_geometryType(geometryType)
1698         , m_gridSizeXYZ(tcu::UVec3(128, 1, 1))
1699         , m_nMaxCallableLevels((useDynamicStackSize) ? 8 : 2 /* as per spec */)
1700         , m_useDynamicStackSize(useDynamicStackSize)
1701         , m_ahitShaderStackSize(0)
1702         , m_callableShaderStackSize(0)
1703         , m_chitShaderStackSize(0)
1704         , m_isectShaderStackSize(0)
1705         , m_missShaderStackSize(0)
1706         , m_raygenShaderStackSize(0)
1707     {
1708     }
1709 
~CallableShaderStressTest()1710     ~CallableShaderStressTest()
1711     {
1712         /* Stub */
1713     }
1714 
getCallableShaderCollectionNames() const1715     std::vector<std::string> getCallableShaderCollectionNames() const final
1716     {
1717         std::vector<std::string> resultVec(m_nMaxCallableLevels);
1718 
1719         for (uint32_t nLevel = 0; nLevel < m_nMaxCallableLevels; nLevel++)
1720         {
1721             resultVec.at(nLevel) = "call" + de::toString(nLevel);
1722         }
1723 
1724         return resultVec;
1725     }
1726 
getDispatchSize() const1727     tcu::UVec3 getDispatchSize() const final
1728     {
1729         DE_ASSERT(m_gridSizeXYZ[0] != 0);
1730         DE_ASSERT(m_gridSizeXYZ[1] != 0);
1731         DE_ASSERT(m_gridSizeXYZ[2] != 0);
1732 
1733         return tcu::UVec3(m_gridSizeXYZ[0], m_gridSizeXYZ[1], m_gridSizeXYZ[2]);
1734     }
1735 
getDynamicStackSize(const uint32_t maxPipelineRayRecursionDepth) const1736     uint32_t getDynamicStackSize(const uint32_t maxPipelineRayRecursionDepth) const final
1737     {
1738         uint32_t result                              = 0;
1739         const auto maxStackSpaceNeededForZerothTrace = static_cast<uint32_t>(de::max(
1740             de::max(m_chitShaderStackSize, m_missShaderStackSize), m_isectShaderStackSize + m_ahitShaderStackSize));
1741         const auto maxStackSpaceNeededForNonZerothTraces =
1742             static_cast<uint32_t>(de::max(m_chitShaderStackSize, m_missShaderStackSize));
1743 
1744         DE_ASSERT(m_useDynamicStackSize);
1745 
1746         result = static_cast<uint32_t>(m_raygenShaderStackSize) +
1747                  de::min(1u, maxPipelineRayRecursionDepth) * maxStackSpaceNeededForZerothTrace +
1748                  de::max(0u, maxPipelineRayRecursionDepth - 1) * maxStackSpaceNeededForNonZerothTraces +
1749                  m_nMaxCallableLevels * static_cast<uint32_t>(m_callableShaderStackSize);
1750 
1751         DE_ASSERT(result != 0);
1752         return result;
1753     }
1754 
getResultBufferSize() const1755     uint32_t getResultBufferSize() const final
1756     {
1757         const auto nRaysTraced                          = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
1758         const auto nClosestHitShaderInvocationsExpected = nRaysTraced / 2;
1759         const auto nMissShaderInvocationsExpected       = nRaysTraced / 2;
1760         const auto resultItemSize =
1761             sizeof(uint32_t) * 3 /* shaderStage, nOriginRay, nLevel */ + sizeof(float) * m_nMaxCallableLevels;
1762 
1763         DE_ASSERT((nRaysTraced % 2) == 0);
1764         DE_ASSERT(m_nMaxCallableLevels != 0);
1765         DE_ASSERT(m_gridSizeXYZ[0] != 0);
1766         DE_ASSERT(m_gridSizeXYZ[1] != 0);
1767         DE_ASSERT(m_gridSizeXYZ[2] != 0);
1768 
1769         return static_cast<uint32_t>(
1770             sizeof(uint32_t) /* nItemsStored */ +
1771             (resultItemSize * m_nMaxCallableLevels) *
1772                 (nRaysTraced + nMissShaderInvocationsExpected + nClosestHitShaderInvocationsExpected));
1773     }
1774 
getTLASPtrVecToBind() const1775     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
1776     {
1777         DE_ASSERT(m_tlPtr != nullptr);
1778 
1779         return {m_tlPtr.get()};
1780     }
1781 
init(vkt::Context &,RayTracingProperties * rtPropertiesPtr)1782     bool init(vkt::Context & /* context    */, RayTracingProperties *rtPropertiesPtr) final
1783     {
1784         DE_UNREF(rtPropertiesPtr);
1785         return true;
1786     }
1787 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)1788     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
1789                 VkCommandBuffer commandBuffer) final
1790     {
1791         std::unique_ptr<GridASProvider> asProviderPtr(new GridASProvider(tcu::Vec3(0, 0, 0), /* gridStartXYZ          */
1792                                                                          tcu::Vec3(1, 1, 1), /* gridCellSizeXYZ       */
1793                                                                          m_gridSizeXYZ,
1794                                                                          tcu::Vec3(6, 0, 0), /* gridInterCellDeltaXYZ */
1795                                                                          m_geometryType));
1796 
1797         m_tlPtr =
1798             asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer, 0, /* bottomLevelGeometryFlags */
1799                                       nullptr,                                        /* optASPropertyProviderPtr */
1800                                       nullptr);                                       /* optASFeedbackPtr            */
1801     }
1802 
initPrograms(SourceCollections & programCollection) const1803     void initPrograms(SourceCollections &programCollection) const final
1804     {
1805         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
1806                                                   0u,    /* flags        */
1807                                                   true); /* allowSpirv14 */
1808 
1809         std::vector<std::string> callableDataDefinitions(m_nMaxCallableLevels);
1810         std::vector<std::string> callableDataInDefinitions(m_nMaxCallableLevels);
1811 
1812         for (uint32_t nCallableDataLevel = 0; nCallableDataLevel < m_nMaxCallableLevels; ++nCallableDataLevel)
1813         {
1814             const auto locationsPerCallableData = (3 /* uints */ + (nCallableDataLevel + 1) /* dataChunks */);
1815             const auto callableDataLocation     = locationsPerCallableData * nCallableDataLevel;
1816 
1817             callableDataDefinitions.at(nCallableDataLevel) =
1818                 "layout (location = " + de::toString(callableDataLocation) +
1819                 ") callableDataEXT struct\n"
1820                 "{\n"
1821                 "    uint  shaderStage;\n"
1822                 "    uint  nOriginRay;\n"
1823                 "    uint  nLevel;\n"
1824                 "    float dataChunk[" +
1825                 de::toString(nCallableDataLevel + 1) +
1826                 "];\n"
1827                 "} callableData" +
1828                 de::toString(nCallableDataLevel) + ";\n";
1829 
1830             callableDataInDefinitions.at(nCallableDataLevel) =
1831                 "layout(location = " + de::toString(callableDataLocation) +
1832                 ") callableDataInEXT struct\n"
1833                 "{\n"
1834                 "    uint  shaderStage;\n"
1835                 "    uint  nOriginRay;\n"
1836                 "    uint  nLevel;\n"
1837                 "    float dataChunk[" +
1838                 de::toString(nCallableDataLevel + 1) +
1839                 "];\n"
1840                 "} inData;\n";
1841 
1842             m_callableDataLevelToCallableDataLocation[nCallableDataLevel] = callableDataLocation;
1843         }
1844 
1845         const auto resultBufferDefinition = "struct ResultData\n"
1846                                             "{\n"
1847                                             "    uint  shaderStage;\n"
1848                                             "    uint  nOriginRay;\n"
1849                                             "    uint  nLevel;\n"
1850                                             "    float dataChunk[" +
1851                                             de::toString(m_nMaxCallableLevels) +
1852                                             "];\n"
1853                                             "};\n"
1854                                             "\n"
1855                                             "layout(set = 0, binding = 0, std430) buffer result\n"
1856                                             "{\n"
1857                                             "    uint       nInvocationsRegistered;\n"
1858                                             "    ResultData resultData[];\n"
1859                                             "};\n";
1860 
1861         {
1862             std::stringstream css;
1863 
1864             /* NOTE: executeCallable() is unavailable in ahit stage */
1865             css << "#version 460 core\n"
1866                    "\n"
1867                    "#extension GL_EXT_ray_tracing : require\n"
1868                    "\n"
1869                    "layout(location = 128) rayPayloadInEXT uint unusedPayload;\n"
1870                    "\n"
1871                    "void main()\n"
1872                    "{\n"
1873                    "}\n";
1874 
1875             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
1876         }
1877 
1878         {
1879             std::stringstream css;
1880 
1881             css << "#version 460 core\n"
1882                    "\n"
1883                    "#extension GL_EXT_ray_tracing : require\n"
1884                    "\n"
1885                    "layout(location = 128) rayPayloadInEXT uint rayIndex;\n"
1886                    "\n" +
1887                        de::toString(callableDataDefinitions.at(0)) + de::toString(resultBufferDefinition) +
1888                        "void main()\n"
1889                        "{\n"
1890                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
1891                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
1892                        "\n"
1893                        "    callableData0.shaderStage  = 3;\n"
1894                        "    callableData0.nOriginRay   = nInvocation;\n"
1895                        "    callableData0.nLevel       = 0;\n"
1896                        "    callableData0.dataChunk[0] = float(nInvocation);\n"
1897                        "\n"
1898                        "    executeCallableEXT(0 /* sbtRecordIndex */, " +
1899                        de::toString(m_callableDataLevelToCallableDataLocation.at(0)) +
1900                        ");\n"
1901                        "}\n";
1902 
1903             programCollection.glslSources.add("chit") << glu::ClosestHitSource(css.str()) << buildOptions;
1904         }
1905 
1906         {
1907             std::stringstream css;
1908 
1909             /* NOTE: executeCallable() is unavailable in isect stage */
1910             css << "#version 460 core\n"
1911                    "\n"
1912                    "#extension GL_EXT_ray_tracing : require\n"
1913                    "\n"
1914                    "void main()\n"
1915                    "{\n"
1916                    "    reportIntersectionEXT(0.95f, 0);\n"
1917                    "}\n";
1918 
1919             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
1920         }
1921 
1922         {
1923             std::stringstream css;
1924 
1925             css << "#version 460 core\n"
1926                    "\n"
1927                    "#extension GL_EXT_ray_tracing : require\n"
1928                    "\n" +
1929                        de::toString(callableDataDefinitions.at(0)) + de::toString(resultBufferDefinition) +
1930                        "\n"
1931                        "void main()\n"
1932                        "{\n"
1933                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
1934                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
1935                        "\n"
1936                        "    callableData0.shaderStage  = 2;\n"
1937                        "    callableData0.nOriginRay   = nInvocation;\n"
1938                        "    callableData0.nLevel       = 0;\n"
1939                        "    callableData0.dataChunk[0] = float(nInvocation);\n"
1940                        "\n"
1941                        "    executeCallableEXT(0 /* sbtRecordIndex */, " +
1942                        de::toString(m_callableDataLevelToCallableDataLocation.at(0)) +
1943                        ");\n"
1944                        "}\n";
1945 
1946             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
1947         }
1948 
1949         {
1950             std::stringstream css;
1951 
1952             css << "#version 460 core\n"
1953                    "\n"
1954                    "#extension GL_EXT_ray_tracing : require\n"
1955                    "\n" +
1956                        de::toString(callableDataDefinitions.at(0)) +
1957                        "layout(location = 128)            rayPayloadEXT uint               unusedPayload;\n"
1958                        "layout(set      = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
1959                        "\n"
1960                        "void main()\n"
1961                        "{\n"
1962                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
1963                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
1964                        "    uint  rayFlags     = 0;\n"
1965                        "    float tmin         = 0.001;\n"
1966                        "    float tmax         = 9.0;\n"
1967                        "\n"
1968                        "    uint  cullMask     = 0xFF;\n"
1969                        "    vec3  cellStartXYZ = vec3(nInvocation * 3.0, 0.0, 0.0);\n"
1970                        "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
1971                        "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
1972                        "    vec3  origin       = target - vec3(0, 2, 0);\n"
1973                        "    vec3  direct       = normalize(target - origin);\n"
1974                        "\n"
1975                        "    callableData0.shaderStage  = 0;\n"
1976                        "    callableData0.nOriginRay   = nInvocation;\n"
1977                        "    callableData0.nLevel       = 0;\n"
1978                        "    callableData0.dataChunk[0] = float(nInvocation);\n"
1979                        "\n"
1980                        "    executeCallableEXT(0 /* sbtRecordIndex */, " +
1981                        de::toString(m_callableDataLevelToCallableDataLocation.at(0)) +
1982                        ");\n"
1983                        "\n"
1984                        "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, "
1985                        "tmax, 128);\n"
1986                        "}\n";
1987 
1988             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
1989         }
1990 
1991         for (uint32_t nCallableShader = 0; nCallableShader < m_nMaxCallableLevels; ++nCallableShader)
1992         {
1993             const bool canInvokeExecutable = (nCallableShader != (m_nMaxCallableLevels - 1));
1994             std::stringstream css;
1995 
1996             css << "#version 460 core\n"
1997                    "\n"
1998                    "#extension GL_EXT_ray_tracing : require\n"
1999                    "\n" +
2000                        de::toString(resultBufferDefinition);
2001 
2002             if ((nCallableShader + 1) != m_nMaxCallableLevels)
2003             {
2004                 css << de::toString(callableDataDefinitions.at(nCallableShader + 1));
2005             }
2006 
2007             css << callableDataInDefinitions[nCallableShader] +
2008                        "\n"
2009                        "void main()\n"
2010                        "{\n"
2011                        "    uint nInvocation = atomicAdd(nInvocationsRegistered, 1);\n"
2012                        "\n"
2013                        "    resultData[nInvocation].shaderStage = inData.shaderStage;\n"
2014                        "    resultData[nInvocation].nOriginRay  = inData.nOriginRay;\n"
2015                        "    resultData[nInvocation].nLevel      = inData.nLevel;\n";
2016 
2017             for (uint32_t nLevel = 0; nLevel < nCallableShader + 1; ++nLevel)
2018             {
2019                 css << "    resultData[nInvocation].dataChunk[" + de::toString(nLevel) + "] = inData.dataChunk[" +
2020                            de::toString(nLevel) + "];\n";
2021             }
2022 
2023             if (canInvokeExecutable)
2024             {
2025                 css << "\n"
2026                        "    callableData" +
2027                            de::toString(nCallableShader + 1) +
2028                            ".shaderStage = 1;\n"
2029                            "    callableData" +
2030                            de::toString(nCallableShader + 1) +
2031                            ".nOriginRay  = inData.nOriginRay;\n"
2032                            "    callableData" +
2033                            de::toString(nCallableShader + 1) + ".nLevel      = " + de::toString(nCallableShader) +
2034                            ";\n"
2035                            "\n";
2036 
2037                 for (uint32_t nLevel = 0; nLevel <= nCallableShader + 1; ++nLevel)
2038                 {
2039                     css << "    callableData" + de::toString(nCallableShader + 1) + ".dataChunk[" +
2040                                de::toString(nLevel) + "] = float(inData.nOriginRay + " + de::toString(nLevel) + ");\n";
2041                 }
2042 
2043                 css << "\n"
2044                        "    executeCallableEXT(" +
2045                            de::toString(nCallableShader + 1) + ", " +
2046                            de::toString(m_callableDataLevelToCallableDataLocation[nCallableShader + 1]) + ");\n";
2047             }
2048 
2049             css << "\n"
2050                    "};\n";
2051 
2052             programCollection.glslSources.add("call" + de::toString(nCallableShader))
2053                 << glu::CallableSource(css.str()) << buildOptions;
2054         }
2055     }
2056 
onShaderStackSizeDiscovered(const VkDeviceSize & raygenShaderStackSize,const VkDeviceSize & ahitShaderStackSize,const VkDeviceSize & chitShaderStackSize,const VkDeviceSize & missShaderStackSize,const VkDeviceSize & callableShaderStackSize,const VkDeviceSize & isectShaderStackSize)2057     void onShaderStackSizeDiscovered(const VkDeviceSize &raygenShaderStackSize, const VkDeviceSize &ahitShaderStackSize,
2058                                      const VkDeviceSize &chitShaderStackSize, const VkDeviceSize &missShaderStackSize,
2059                                      const VkDeviceSize &callableShaderStackSize,
2060                                      const VkDeviceSize &isectShaderStackSize) final
2061     {
2062         m_ahitShaderStackSize     = ahitShaderStackSize;
2063         m_callableShaderStackSize = callableShaderStackSize;
2064         m_chitShaderStackSize     = chitShaderStackSize;
2065         m_isectShaderStackSize    = isectShaderStackSize;
2066         m_missShaderStackSize     = missShaderStackSize;
2067         m_raygenShaderStackSize   = raygenShaderStackSize;
2068     }
2069 
resetTLAS()2070     void resetTLAS() final
2071     {
2072         m_tlPtr.reset();
2073     }
2074 
usesDynamicStackSize() const2075     bool usesDynamicStackSize() const final
2076     {
2077         return m_useDynamicStackSize;
2078     }
2079 
verifyResultBuffer(const void * resultDataPtr) const2080     bool verifyResultBuffer(const void *resultDataPtr) const final
2081     {
2082         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
2083         bool result                  = false;
2084         const auto nItemsStored      = *resultU32Ptr;
2085 
2086         /* Convert raw binary data into a human-readable vector representation */
2087         struct ResultItem
2088         {
2089             VkShaderStageFlagBits shaderStage;
2090             uint32_t nLevel;
2091             std::vector<float> dataChunk;
2092 
2093             ResultItem() : shaderStage(VK_SHADER_STAGE_ALL), nLevel(0)
2094             {
2095                 /* Stub */
2096             }
2097         };
2098 
2099         std::map<uint32_t, std::vector<ResultItem>> nRayToResultItemVecMap;
2100 
2101         for (uint32_t nItem = 0; nItem < nItemsStored; ++nItem)
2102         {
2103             const uint32_t *itemDataPtr = resultU32Ptr + 1 /* nItemsStored */ +
2104                                           nItem * (3 /* preamble ints */ + m_nMaxCallableLevels /* received data */);
2105             ResultItem item;
2106             const auto &nOriginRay = *(itemDataPtr + 1);
2107 
2108             item.dataChunk.resize(m_nMaxCallableLevels);
2109 
2110             switch (*itemDataPtr)
2111             {
2112             case 0:
2113                 item.shaderStage = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
2114                 break;
2115             case 1:
2116                 item.shaderStage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;
2117                 break;
2118             case 2:
2119                 item.shaderStage = VK_SHADER_STAGE_MISS_BIT_KHR;
2120                 break;
2121             case 3:
2122                 item.shaderStage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
2123                 break;
2124 
2125             default:
2126             {
2127                 deAssertFail("This should never happen", __FILE__, __LINE__);
2128             }
2129             }
2130 
2131             item.nLevel = *(itemDataPtr + 2);
2132 
2133             memcpy(item.dataChunk.data(), itemDataPtr + 3, m_nMaxCallableLevels * sizeof(float));
2134 
2135             nRayToResultItemVecMap[nOriginRay].push_back(item);
2136         }
2137 
2138         for (uint32_t nRay = 0; nRay < m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2]; ++nRay)
2139         {
2140             /* 1. Make sure each ray generated the anticipated number of stores */
2141             const bool closestHitShaderInvoked            = (nRay % 2) == 0;
2142             const bool missShaderInvoked                  = (nRay % 2) != 0;
2143             const uint32_t nShaderStagesInvokingCallables = 1 + /* raygen */
2144                                                             ((closestHitShaderInvoked) ? 1 : 0) +
2145                                                             ((missShaderInvoked) ? 1 : 0);
2146             auto rayIterator = nRayToResultItemVecMap.find(nRay);
2147 
2148             if (rayIterator == nRayToResultItemVecMap.end())
2149             {
2150                 goto end;
2151             }
2152 
2153             if (rayIterator->second.size() != nShaderStagesInvokingCallables * m_nMaxCallableLevels)
2154             {
2155                 goto end;
2156             }
2157 
2158             /* 2. Make sure each shader stage generated the anticipated number of result items */
2159             {
2160                 uint32_t nCallableShaderStageItemsFound   = 0;
2161                 uint32_t nClosestHitShaderStageItemsFound = 0;
2162                 uint32_t nMissShaderStageItemsFound       = 0;
2163                 uint32_t nRaygenShaderStageItemsFound     = 0;
2164 
2165                 for (const auto &currentItem : rayIterator->second)
2166                 {
2167                     if (currentItem.shaderStage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)
2168                     {
2169                         nRaygenShaderStageItemsFound++;
2170                     }
2171                     else if (currentItem.shaderStage == VK_SHADER_STAGE_CALLABLE_BIT_KHR)
2172                     {
2173                         nCallableShaderStageItemsFound++;
2174                     }
2175                     else if (currentItem.shaderStage == VK_SHADER_STAGE_MISS_BIT_KHR)
2176                     {
2177                         nMissShaderStageItemsFound++;
2178                     }
2179                     else if (currentItem.shaderStage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)
2180                     {
2181                         nClosestHitShaderStageItemsFound++;
2182                     }
2183                     else
2184                     {
2185                         DE_ASSERT(false);
2186                     }
2187                 }
2188 
2189                 if (nRaygenShaderStageItemsFound != 1)
2190                 {
2191                     goto end;
2192                 }
2193 
2194                 /* Even rays hit geometry. Odd ones don't */
2195                 if (!missShaderInvoked)
2196                 {
2197                     if (nClosestHitShaderStageItemsFound == 0)
2198                     {
2199                         goto end;
2200                     }
2201 
2202                     if (nMissShaderStageItemsFound != 0)
2203                     {
2204                         goto end;
2205                     }
2206                 }
2207                 else
2208                 {
2209                     if (nClosestHitShaderStageItemsFound != 0)
2210                     {
2211                         goto end;
2212                     }
2213 
2214                     if (nMissShaderStageItemsFound != 1)
2215                     {
2216                         goto end;
2217                     }
2218                 }
2219 
2220                 if (nCallableShaderStageItemsFound != nShaderStagesInvokingCallables * (m_nMaxCallableLevels - 1))
2221                 {
2222                     goto end;
2223                 }
2224             }
2225 
2226             /* 3. Verify data chunk's correctness */
2227             {
2228                 for (const auto &currentItem : rayIterator->second)
2229                 {
2230                     const auto nValidItemsRequired =
2231                         (currentItem.shaderStage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)      ? 1 :
2232                         (currentItem.shaderStage == VK_SHADER_STAGE_MISS_BIT_KHR)        ? 1 :
2233                         (currentItem.shaderStage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) ? 1 :
2234                                                                                            (currentItem.nLevel + 1);
2235 
2236                     for (uint32_t nItem = 0; nItem < nValidItemsRequired; ++nItem)
2237                     {
2238                         if (fabsf(currentItem.dataChunk.at(nItem) - static_cast<float>(nRay + nItem)) > 1e-3f)
2239                         {
2240                             goto end;
2241                         }
2242                     }
2243                 }
2244             }
2245 
2246             /* 4. Verify all shader levels have been reported for relevant shader stages */
2247             {
2248                 std::map<VkShaderStageFlagBits, std::vector<uint32_t>> shaderStageToLevelVecReportedMap;
2249 
2250                 for (const auto &currentItem : rayIterator->second)
2251                 {
2252                     shaderStageToLevelVecReportedMap[currentItem.shaderStage].push_back(currentItem.nLevel);
2253                 }
2254 
2255                 if (shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_RAYGEN_BIT_KHR).size() != 1 ||
2256                     shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_RAYGEN_BIT_KHR).at(0) != 0)
2257                 {
2258                     goto end;
2259                 }
2260 
2261                 if (closestHitShaderInvoked)
2262                 {
2263                     if (shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR).size() != 1 ||
2264                         shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR).at(0) != 0)
2265                     {
2266                         goto end;
2267                     }
2268                 }
2269                 else
2270                 {
2271                     if (shaderStageToLevelVecReportedMap.find(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) !=
2272                         shaderStageToLevelVecReportedMap.end())
2273                     {
2274                         goto end;
2275                     }
2276                 }
2277 
2278                 if (missShaderInvoked)
2279                 {
2280                     if (shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_MISS_BIT_KHR).size() != 1 ||
2281                         shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_MISS_BIT_KHR).at(0) != 0)
2282                     {
2283                         goto end;
2284                     }
2285                 }
2286                 else
2287                 {
2288                     if (shaderStageToLevelVecReportedMap.find(VK_SHADER_STAGE_MISS_BIT_KHR) !=
2289                         shaderStageToLevelVecReportedMap.end())
2290                     {
2291                         goto end;
2292                     }
2293                 }
2294 
2295                 if (shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_CALLABLE_BIT_KHR).size() !=
2296                     nShaderStagesInvokingCallables * (m_nMaxCallableLevels - 1))
2297                 {
2298                     goto end;
2299                 }
2300 
2301                 for (uint32_t nLevel = 0; nLevel < m_nMaxCallableLevels - 1; ++nLevel)
2302                 {
2303                     const auto &vec  = shaderStageToLevelVecReportedMap.at(VK_SHADER_STAGE_CALLABLE_BIT_KHR);
2304                     auto vecIterator = std::find(vec.begin(), vec.end(), nLevel);
2305 
2306                     if (vecIterator == vec.end())
2307                     {
2308                         goto end;
2309                     }
2310                 }
2311             }
2312         }
2313 
2314         result = true;
2315     end:
2316         return result;
2317     }
2318 
2319 private:
2320     const AccelerationStructureLayout m_asStructureLayout;
2321     const GeometryType m_geometryType;
2322 
2323     const tcu::UVec3 m_gridSizeXYZ;
2324     const uint32_t m_nMaxCallableLevels;
2325     const bool m_useDynamicStackSize;
2326     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
2327 
2328     VkDeviceSize m_ahitShaderStackSize;
2329     VkDeviceSize m_callableShaderStackSize;
2330     VkDeviceSize m_chitShaderStackSize;
2331     VkDeviceSize m_isectShaderStackSize;
2332     VkDeviceSize m_missShaderStackSize;
2333     VkDeviceSize m_raygenShaderStackSize;
2334 
2335     mutable std::map<uint32_t, uint32_t> m_callableDataLevelToCallableDataLocation;
2336 };
2337 
2338 class CullMaskTest : public TestBase, public ASPropertyProvider
2339 {
2340 public:
CullMaskTest(const AccelerationStructureLayout & asLayout,const GeometryType & geometryType,const bool & useExtraCullMaskBits)2341     CullMaskTest(const AccelerationStructureLayout &asLayout, const GeometryType &geometryType,
2342                  const bool &useExtraCullMaskBits)
2343         : m_asLayout(asLayout)
2344         , m_geometryType(geometryType)
2345         , m_nMaxHitsToRegister(256)
2346         , m_nRaysPerInvocation(4)
2347         , m_useExtraCullMaskBits(useExtraCullMaskBits)
2348         , m_lastCustomInstanceIndexUsed(0)
2349         , m_nCullMasksUsed(1)
2350     {
2351         /* Stub */
2352     }
2353 
~CullMaskTest()2354     ~CullMaskTest()
2355     {
2356         /* Stub */
2357     }
2358 
getCHitShaderCollectionShaderNames() const2359     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
2360     {
2361         return {};
2362     }
2363 
getCullMask(const uint32_t & nBL,const uint32_t & nInstance) const2364     uint8_t getCullMask(const uint32_t &nBL, const uint32_t &nInstance) const final
2365     {
2366         DE_UNREF(nBL);
2367         DE_UNREF(nInstance);
2368 
2369         uint8_t result = (m_nCullMasksUsed++) & 0xFF;
2370 
2371         DE_ASSERT(result != 0);
2372         return result;
2373     }
2374 
getInstanceCustomIndex(const uint32_t & nBL,const uint32_t & nInstance) const2375     uint32_t getInstanceCustomIndex(const uint32_t &nBL, const uint32_t &nInstance) const final
2376     {
2377         DE_UNREF(nBL);
2378         DE_UNREF(nInstance);
2379 
2380         /* NOTE: The formula below generates a sequence of unique large values. */
2381         uint32_t result = (m_lastCustomInstanceIndexUsed * 7 + 153325) & ((1 << 24) - 1);
2382 
2383         if (m_instanceCustomIndexVec.size() <= nInstance)
2384         {
2385             m_instanceCustomIndexVec.resize(nInstance + 1);
2386         }
2387 
2388         m_instanceCustomIndexVec[nInstance] = result;
2389         m_lastCustomInstanceIndexUsed       = result;
2390 
2391         return result;
2392     }
2393 
getDispatchSize() const2394     tcu::UVec3 getDispatchSize() const final
2395     {
2396         //< 3*5*17 == 255, which coincidentally is the maximum cull mask value the spec permits.
2397         //<
2398         //< This global WG size is excessively large if m_nRaysPerInvocation > 1 but the raygen shader has
2399         //< a guard condition check that drops extraneous invocations.
2400         return tcu::UVec3(3, 5, 17);
2401     }
2402 
getResultBufferSize() const2403     uint32_t getResultBufferSize() const final
2404     {
2405         return static_cast<uint32_t>((1 + m_nMaxHitsToRegister * 2) * sizeof(uint32_t));
2406     }
2407 
getTLASPtrVecToBind() const2408     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
2409     {
2410         return {m_tlPtr.get()};
2411     }
2412 
resetTLAS()2413     void resetTLAS() final
2414     {
2415         m_tlPtr.reset();
2416     }
2417 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)2418     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
2419                 VkCommandBuffer commandBuffer) final
2420     {
2421         m_asProviderPtr.reset(new GridASProvider(tcu::Vec3(0, 0, 0),          /* gridStartXYZ          */
2422                                                  tcu::Vec3(1, 1, 1),          /* gridCellSizeXYZ       */
2423                                                  tcu::UVec3(3, 5, 17),        /* gridSizeXYZ           */
2424                                                  tcu::Vec3(2.0f, 2.0f, 2.0f), /* gridInterCellDeltaXYZ */
2425                                                  m_geometryType));
2426 
2427         m_tlPtr = m_asProviderPtr->createTLAS(context, m_asLayout, commandBuffer,
2428                                               VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
2429                                               this,     /* optASPropertyProviderPtr */
2430                                               nullptr); /* optASFeedbackPtr         */
2431     }
2432 
initPrograms(SourceCollections & programCollection) const2433     void initPrograms(SourceCollections &programCollection) const final
2434     {
2435         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
2436                                                   0u,    /* flags        */
2437                                                   true); /* allowSpirv14 */
2438 
2439         const char *hitPropsDefinition = "struct HitProps\n"
2440                                          "{\n"
2441                                          "    uint rayIndex;\n"
2442                                          "    uint instanceCustomIndex;\n"
2443                                          "};\n";
2444 
2445         {
2446             std::stringstream css;
2447 
2448             css << "#version 460 core\n"
2449                    "\n"
2450                    "#extension GL_EXT_ray_tracing : require\n"
2451                    "\n"
2452                    "hitAttributeEXT vec3 unusedAttribute;\n"
2453                    "\n" +
2454                        de::toString(hitPropsDefinition) +
2455                        "\n"
2456                        "layout(location = 0) rayPayloadInEXT      uint   nRay;\n"
2457                        "layout(set      = 0, binding = 0, std430) buffer result\n"
2458                        "{\n"
2459                        "    uint     nHitsRegistered;\n"
2460                        "    uint     nMissesRegistered;\n"
2461                        "    HitProps hits[];\n"
2462                        "};\n"
2463                        "\n"
2464                        "void main()\n"
2465                        "{\n"
2466                        "    uint nHit = atomicAdd(nHitsRegistered, 1);\n"
2467                        "\n"
2468                        "    if (nHit < " +
2469                        de::toString(m_nMaxHitsToRegister) +
2470                        ")\n"
2471                        "    {\n"
2472                        "        hits[nHit].rayIndex            = nRay;\n"
2473                        "        hits[nHit].instanceCustomIndex = gl_InstanceCustomIndexEXT;\n"
2474                        "    }\n"
2475                        "}\n";
2476 
2477             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
2478         }
2479 
2480         {
2481             std::stringstream css;
2482 
2483             css << "#version 460 core\n"
2484                    "\n"
2485                    "#extension GL_EXT_ray_tracing : require\n"
2486                    "\n"
2487                    "hitAttributeEXT vec3 hitAttribute;\n"
2488                    "\n"
2489                    "void main()\n"
2490                    "{\n"
2491                    "    reportIntersectionEXT(0.95f, 0);\n"
2492                    "}\n";
2493 
2494             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
2495         }
2496 
2497         {
2498             std::stringstream css;
2499 
2500             css << "#version 460 core\n"
2501                    "\n"
2502                    "#extension GL_EXT_ray_tracing : require\n"
2503                    "\n" +
2504                        de::toString(hitPropsDefinition) +
2505                        "\n"
2506                        "layout(set      = 0, binding = 0, std430) buffer result\n"
2507                        "{\n"
2508                        "    uint     nHitsRegistered;\n"
2509                        "    uint     nMissesRegistered;\n"
2510                        "    HitProps hits[];\n"
2511                        "};\n"
2512                        "\n"
2513                        "layout(location = 0) rayPayloadInEXT uint rayIndex;\n"
2514                        "\n"
2515                        "void main()\n"
2516                        "{\n"
2517                        "    atomicAdd(nMissesRegistered, 1);\n"
2518                        "}\n";
2519 
2520             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
2521         }
2522 
2523         {
2524             std::stringstream css;
2525 
2526             css << "#version 460 core\n"
2527                    "\n"
2528                    "#extension GL_EXT_ray_tracing : require\n"
2529                    "\n"
2530                    "layout(location = 0)              rayPayloadEXT uint               rayIndex;\n"
2531                    "layout(set      = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
2532                    "\n"
2533                    "void main()\n"
2534                    "{\n"
2535                    "    const uint nRaysPerInvocation = " +
2536                        de::toString(m_nRaysPerInvocation) +
2537                        ";\n"
2538                        "\n"
2539                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
2540                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
2541                        "    uint  rayFlags     = gl_RayFlagsCullBackFacingTrianglesEXT;\n"
2542                        "    float tmin         = 0.001;\n"
2543                        "    float tmax         = 4.0;\n"
2544                        "\n"
2545                        "    if (nInvocation >= 256 / nRaysPerInvocation)\n"
2546                        "    {\n"
2547                        "        return;\n"
2548                        "    }\n"
2549                        "\n"
2550                        "    for (uint nRay = 0; nRay < nRaysPerInvocation; ++nRay)\n"
2551                        "    {\n"
2552                        "        uint  cullMask     = 1 + nInvocation * nRaysPerInvocation + nRay;\n";
2553 
2554             if (m_useExtraCullMaskBits)
2555             {
2556                 css << "cullMask |= 0x00FFFFFF;\n";
2557             }
2558 
2559             css << "        uint  nCell        = nInvocation * nRaysPerInvocation + nRay;\n"
2560                    "        uvec3 cellXYZ      = uvec3(nCell % gl_LaunchSizeEXT.x, (nCell / gl_LaunchSizeEXT.x) % "
2561                    "gl_LaunchSizeEXT.y, (nCell / gl_LaunchSizeEXT.x / gl_LaunchSizeEXT.y) % gl_LaunchSizeEXT.z);\n"
2562                    "        vec3  cellStartXYZ = vec3(cellXYZ) * vec3(2.0);\n"
2563                    "        vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
2564                    "        vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
2565                    "        vec3  origin       = target - vec3(1, 1, 1);\n"
2566                    "        vec3  direct       = normalize(target - origin);\n"
2567                    "\n"
2568                    "        if (nCell < 255)\n"
2569                    "        {\n"
2570                    "            rayIndex = nCell;"
2571                    "\n"
2572                    "            traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
2573                    "        }\n"
2574                    "    }\n"
2575                    "}\n";
2576 
2577             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
2578         }
2579     }
2580 
verifyResultBuffer(const void * resultDataPtr) const2581     bool verifyResultBuffer(const void *resultDataPtr) const final
2582     {
2583         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
2584         const auto nHitsReported     = *resultU32Ptr;
2585         const auto nMissesReported   = *(resultU32Ptr + 1);
2586         bool result                  = true;
2587 
2588         // For each traced ray:
2589         //
2590         // 1. Exactly one ahit invocation per ray should be reported.
2591         // 2. All hits reported for a ray R should point to a primitive with a valid custom instance index
2592         // 3. The reported custom instance indices must be valid.
2593         std::map<uint32_t, std::vector<uint32_t>> customInstanceIndexToRayIndexVecMap;
2594         std::map<uint32_t, std::vector<uint32_t>> rayIndexToCustomInstanceIndexVecMap;
2595 
2596         typedef struct
2597         {
2598             uint32_t rayIndex;
2599             uint32_t customInstanceHit;
2600         } HitProperties;
2601 
2602         if (nHitsReported != 0xFF)
2603         {
2604             result = false;
2605 
2606             goto end;
2607         }
2608 
2609         if (nMissesReported != 0)
2610         {
2611             result = false;
2612 
2613             goto end;
2614         }
2615 
2616         for (uint32_t nHit = 0; nHit < nHitsReported; ++nHit)
2617         {
2618             const HitProperties *hitPropsPtr = reinterpret_cast<const HitProperties *>(
2619                 resultU32Ptr + 2 /* preamble ints */ + nHit * 2 /* ints per HitProperties item */);
2620 
2621             customInstanceIndexToRayIndexVecMap[hitPropsPtr->customInstanceHit].push_back(hitPropsPtr->rayIndex);
2622             rayIndexToCustomInstanceIndexVecMap[hitPropsPtr->rayIndex].push_back(hitPropsPtr->customInstanceHit);
2623         }
2624 
2625         if (static_cast<uint32_t>(customInstanceIndexToRayIndexVecMap.size()) != nHitsReported)
2626         {
2627             /* Invalid number of unique custom instance indices reported. */
2628             result = false;
2629 
2630             goto end;
2631         }
2632 
2633         if (static_cast<uint32_t>(rayIndexToCustomInstanceIndexVecMap.size()) != nHitsReported)
2634         {
2635             /* Invalid ray indices reported by ahit invocations */
2636             result = false;
2637 
2638             goto end;
2639         }
2640 
2641         for (const auto &currentItem : customInstanceIndexToRayIndexVecMap)
2642         {
2643             if (currentItem.second.size() != 1)
2644             {
2645                 /* More than one ray associated with the same custom instance index */
2646                 result = false;
2647 
2648                 goto end;
2649             }
2650 
2651             if (currentItem.second.at(0) > 255)
2652             {
2653                 /* Invalid ray index associated with the instance index */
2654                 result = false;
2655 
2656                 goto end;
2657             }
2658 
2659             if (std::find(m_instanceCustomIndexVec.begin(), m_instanceCustomIndexVec.end(), currentItem.first) ==
2660                 m_instanceCustomIndexVec.end())
2661             {
2662                 /* Invalid custom instance index reported for the ray */
2663                 result = false;
2664 
2665                 goto end;
2666             }
2667         }
2668 
2669     end:
2670         return result;
2671     }
2672 
2673 private:
2674     const AccelerationStructureLayout m_asLayout;
2675     const GeometryType m_geometryType;
2676     const uint32_t m_nMaxHitsToRegister;
2677     const uint32_t m_nRaysPerInvocation;
2678     const bool m_useExtraCullMaskBits;
2679 
2680     mutable std::vector<uint32_t> m_instanceCustomIndexVec;
2681     mutable uint32_t m_lastCustomInstanceIndexUsed;
2682     mutable uint32_t m_nCullMasksUsed;
2683 
2684     std::unique_ptr<GridASProvider> m_asProviderPtr;
2685     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
2686 };
2687 
2688 class MAXRayHitAttributeSizeTest : public TestBase
2689 {
2690 public:
MAXRayHitAttributeSizeTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout)2691     MAXRayHitAttributeSizeTest(const GeometryType &geometryType, const AccelerationStructureLayout &asStructureLayout)
2692         : m_asStructureLayout(asStructureLayout)
2693         , m_geometryType(geometryType)
2694         , m_gridSizeXYZ(tcu::UVec3(512, 1, 1))
2695         , m_nRayAttributeU32s(0)
2696     {
2697     }
2698 
~MAXRayHitAttributeSizeTest()2699     ~MAXRayHitAttributeSizeTest()
2700     {
2701         /* Stub */
2702     }
2703 
getDispatchSize() const2704     tcu::UVec3 getDispatchSize() const final
2705     {
2706         DE_ASSERT(m_gridSizeXYZ[0] != 0);
2707         DE_ASSERT(m_gridSizeXYZ[1] != 0);
2708         DE_ASSERT(m_gridSizeXYZ[2] != 0);
2709 
2710         return tcu::UVec3(m_gridSizeXYZ[0], m_gridSizeXYZ[1], m_gridSizeXYZ[2]);
2711     }
2712 
getResultBufferSize() const2713     uint32_t getResultBufferSize() const final
2714     {
2715         DE_ASSERT(m_gridSizeXYZ[0] != 0);
2716         DE_ASSERT(m_gridSizeXYZ[1] != 0);
2717         DE_ASSERT(m_gridSizeXYZ[2] != 0);
2718 
2719         return static_cast<uint32_t>(
2720             (3 /* nAHits, nCHits, nMisses */ + m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2] *
2721                                                    m_nRayAttributeU32s * 2 /* stages where result data is stored */) *
2722             sizeof(uint32_t));
2723     }
2724 
getSpecializationInfoPtr(const VkShaderStageFlagBits & shaderStage)2725     VkSpecializationInfo *getSpecializationInfoPtr(const VkShaderStageFlagBits &shaderStage) final
2726     {
2727         VkSpecializationInfo *resultPtr = nullptr;
2728 
2729         if (shaderStage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR || shaderStage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
2730             shaderStage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR)
2731         {
2732             resultPtr = &m_specializationInfo;
2733         }
2734 
2735         return resultPtr;
2736     }
2737 
getTLASPtrVecToBind() const2738     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
2739     {
2740         DE_ASSERT(m_tlPtr != nullptr);
2741 
2742         return {m_tlPtr.get()};
2743     }
2744 
resetTLAS()2745     void resetTLAS() final
2746     {
2747         m_tlPtr.reset();
2748     }
2749 
init(vkt::Context &,RayTracingProperties * rtPropertiesPtr)2750     bool init(vkt::Context & /* context    */, RayTracingProperties *rtPropertiesPtr) final
2751     {
2752         const auto maxRayHitAttributeSize = rtPropertiesPtr->getMaxRayHitAttributeSize();
2753 
2754         // TODO: If U8s are supported, we could cover the remaining space with these..
2755         m_nRayAttributeU32s = maxRayHitAttributeSize / static_cast<uint32_t>(sizeof(uint32_t));
2756         DE_ASSERT(m_nRayAttributeU32s != 0);
2757 
2758         m_specializationInfoMapEntry.constantID = 1;
2759         m_specializationInfoMapEntry.offset     = 0;
2760         m_specializationInfoMapEntry.size       = sizeof(uint32_t);
2761 
2762         m_specializationInfo.dataSize      = sizeof(uint32_t);
2763         m_specializationInfo.mapEntryCount = 1;
2764         m_specializationInfo.pData         = reinterpret_cast<const void *>(&m_nRayAttributeU32s);
2765         m_specializationInfo.pMapEntries   = &m_specializationInfoMapEntry;
2766 
2767         return true;
2768     }
2769 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)2770     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
2771                 VkCommandBuffer commandBuffer) final
2772     {
2773         std::unique_ptr<GridASProvider> asProviderPtr(new GridASProvider(tcu::Vec3(0, 0, 0), /* gridStartXYZ          */
2774                                                                          tcu::Vec3(1, 1, 1), /* gridCellSizeXYZ       */
2775                                                                          m_gridSizeXYZ,
2776                                                                          tcu::Vec3(6, 0, 0), /* gridInterCellDeltaXYZ */
2777                                                                          m_geometryType));
2778 
2779         m_tlPtr =
2780             asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer, 0, /* bottomLevelGeometryFlags */
2781                                       nullptr,                                        /* optASPropertyProviderPtr */
2782                                       nullptr);                                       /* optASFeedbackPtr         */
2783     }
2784 
initPrograms(SourceCollections & programCollection) const2785     void initPrograms(SourceCollections &programCollection) const final
2786     {
2787         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
2788                                                   0u,    /* flags        */
2789                                                   true); /* allowSpirv14 */
2790 
2791         const char *constantDefinitions = "layout(constant_id = 1) const uint N_UINTS_IN_HIT_ATTRIBUTE = 1;\n";
2792 
2793         const char *hitAttributeDefinition = "\n"
2794                                              "hitAttributeEXT block\n"
2795                                              "{\n"
2796                                              "    uint values[N_UINTS_IN_HIT_ATTRIBUTE];\n"
2797                                              "};\n"
2798                                              "\n";
2799 
2800         const char *resultBufferDefinition = "layout(set      = 0, binding = 0, std430) buffer result\n"
2801                                              "{\n"
2802                                              "    uint nAHitsRegistered;\n"
2803                                              "    uint nCHitsRegistered;\n"
2804                                              "    uint nMissesRegistered;\n"
2805                                              "    uint retrievedValues[N_UINTS_IN_HIT_ATTRIBUTE];\n"
2806                                              "};\n";
2807 
2808         {
2809             std::stringstream css;
2810 
2811             css << "#version 460 core\n"
2812                    "\n"
2813                    "#extension GL_EXT_ray_tracing : require\n"
2814                    "\n" +
2815                        de::toString(constantDefinitions) + de::toString(hitAttributeDefinition) +
2816                        "\n"
2817                        "layout(location = 0) rayPayloadInEXT uint unusedPayload;\n" +
2818                        de::toString(resultBufferDefinition) +
2819                        "\n"
2820                        "void main()\n"
2821                        "{\n"
2822                        "    atomicAdd(nAHitsRegistered, 1);\n"
2823                        "\n"
2824                        "    uint nInvocation = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
2825                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
2826                        "\n"
2827                        "    for (uint nUint = 0; nUint < N_UINTS_IN_HIT_ATTRIBUTE; ++nUint)\n"
2828                        "    {\n"
2829                        "        retrievedValues[(2 * nInvocation + 1) * N_UINTS_IN_HIT_ATTRIBUTE + nUint] = "
2830                        "values[nUint];\n"
2831                        "    }\n"
2832                        "}\n";
2833 
2834             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
2835         }
2836 
2837         {
2838             std::stringstream css;
2839 
2840             css << "#version 460 core\n"
2841                    "\n"
2842                    "#extension GL_EXT_ray_tracing : require\n"
2843                    "\n" +
2844                        de::toString(constantDefinitions) + de::toString(hitAttributeDefinition) +
2845                        de::toString(resultBufferDefinition) +
2846                        "\n"
2847                        "layout(location = 0) rayPayloadInEXT uint rayIndex;\n"
2848                        "\n"
2849                        "void main()\n"
2850                        "{\n"
2851                        "    atomicAdd(nCHitsRegistered, 1);\n"
2852                        "\n"
2853                        "    uint nInvocation = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
2854                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
2855                        "\n"
2856                        "    for (uint nUint = 0; nUint < N_UINTS_IN_HIT_ATTRIBUTE; ++nUint)\n"
2857                        "    {\n"
2858                        "        retrievedValues[(2 * nInvocation + 0) * N_UINTS_IN_HIT_ATTRIBUTE + nUint] = "
2859                        "values[nUint];\n"
2860                        "    }\n"
2861                        "}\n";
2862 
2863             programCollection.glslSources.add("chit") << glu::ClosestHitSource(css.str()) << buildOptions;
2864         }
2865 
2866         {
2867             std::stringstream css;
2868 
2869             css << "#version 460 core\n"
2870                    "\n"
2871                    "#extension GL_EXT_ray_tracing : require\n"
2872                    "\n" +
2873                        de::toString(constantDefinitions) + de::toString(hitAttributeDefinition) +
2874                        de::toString(resultBufferDefinition) +
2875                        "\n"
2876                        "void main()\n"
2877                        "{\n"
2878                        "    uint nInvocation = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
2879                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
2880                        "\n"
2881                        "    for (uint nUint = 0; nUint < N_UINTS_IN_HIT_ATTRIBUTE; ++nUint)\n"
2882                        "    {\n"
2883                        "        values[nUint] = 1 + nInvocation + nUint;\n"
2884                        "    }\n"
2885                        "\n"
2886                        "    reportIntersectionEXT(0.95f, 0);\n"
2887                        "}\n";
2888 
2889             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
2890         }
2891 
2892         {
2893             std::stringstream css;
2894 
2895             css << "#version 460 core\n"
2896                    "\n"
2897                    "#extension GL_EXT_ray_tracing : require\n"
2898                    "\n" +
2899                        de::toString(constantDefinitions) + de::toString(resultBufferDefinition) +
2900                        "\n"
2901                        "void main()\n"
2902                        "{\n"
2903                        "    atomicAdd(nMissesRegistered, 1);\n"
2904                        "}\n";
2905 
2906             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
2907         }
2908 
2909         {
2910             std::stringstream css;
2911 
2912             css << "#version 460 core\n"
2913                    "\n"
2914                    "#extension GL_EXT_ray_tracing : require\n"
2915                    "\n"
2916                    "layout(location = 0)              rayPayloadEXT uint               unusedPayload;\n"
2917                    "layout(set      = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
2918                    "\n"
2919                    "void main()\n"
2920                    "{\n"
2921                    "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
2922                    "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
2923                    "    uint  rayFlags     = 0;\n"
2924                    "    float tmin         = 0.001;\n"
2925                    "    float tmax         = 9.0;\n"
2926                    "\n"
2927                    "    uint  cullMask     = 0xFF;\n"
2928                    "    vec3  cellStartXYZ = vec3(nInvocation * 3.0, 0.0, 0.0);\n"
2929                    "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
2930                    "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
2931                    "    vec3  origin       = target - vec3(0, 2, 0);\n"
2932                    "    vec3  direct       = normalize(target - origin);\n"
2933                    "\n"
2934                    "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, "
2935                    "0);\n"
2936                    "}\n";
2937 
2938             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
2939         }
2940     }
2941 
verifyResultBuffer(const void * resultDataPtr) const2942     bool verifyResultBuffer(const void *resultDataPtr) const final
2943     {
2944         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
2945         bool result                  = false;
2946 
2947         const auto nAHitsReported    = *resultU32Ptr;
2948         const auto nCHitsRegistered  = *(resultU32Ptr + 1);
2949         const auto nMissesRegistered = *(resultU32Ptr + 2);
2950 
2951         if (nAHitsReported != m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2] / 2)
2952         {
2953             goto end;
2954         }
2955 
2956         if (nCHitsRegistered != nAHitsReported)
2957         {
2958             goto end;
2959         }
2960 
2961         if (nMissesRegistered != nAHitsReported)
2962         {
2963             goto end;
2964         }
2965 
2966         for (uint32_t nHit = 0; nHit < nAHitsReported; ++nHit)
2967         {
2968             const uint32_t *ahitValues = resultU32Ptr + 3 /* preamble ints */ + (2 * nHit + 0) * m_nRayAttributeU32s;
2969             const uint32_t *chitValues = resultU32Ptr + 3 /* preamble ints */ + (2 * nHit + 1) * m_nRayAttributeU32s;
2970             const bool missExpected    = (nHit % 2) != 0;
2971 
2972             for (uint32_t nValue = 0; nValue < m_nRayAttributeU32s; ++nValue)
2973             {
2974                 if (!missExpected)
2975                 {
2976                     if (ahitValues[nValue] != 1 + nHit + nValue)
2977                     {
2978                         goto end;
2979                     }
2980 
2981                     if (chitValues[nValue] != 1 + nHit + nValue)
2982                     {
2983                         goto end;
2984                     }
2985                 }
2986                 else
2987                 {
2988                     if (ahitValues[nValue] != 0)
2989                     {
2990                         goto end;
2991                     }
2992 
2993                     if (chitValues[nValue] != 0)
2994                     {
2995                         goto end;
2996                     }
2997                 }
2998             }
2999         }
3000 
3001         result = true;
3002     end:
3003         return result;
3004     }
3005 
3006 private:
3007     const AccelerationStructureLayout m_asStructureLayout;
3008     const GeometryType m_geometryType;
3009 
3010     const tcu::UVec3 m_gridSizeXYZ;
3011     uint32_t m_nRayAttributeU32s;
3012     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
3013 
3014     VkSpecializationInfo m_specializationInfo;
3015     VkSpecializationMapEntry m_specializationInfoMapEntry;
3016 };
3017 
3018 class MAXRTInvocationsSupportedTest : public TestBase, public ASPropertyProvider, public IGridASFeedback
3019 {
3020 public:
MAXRTInvocationsSupportedTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout)3021     MAXRTInvocationsSupportedTest(const GeometryType &geometryType,
3022                                   const AccelerationStructureLayout &asStructureLayout)
3023         : m_asStructureLayout(asStructureLayout)
3024         , m_geometryType(geometryType)
3025         , m_lastCustomInstanceIndexUsed(0)
3026         , m_nMaxCells(8 * 8 * 8)
3027     {
3028     }
3029 
~MAXRTInvocationsSupportedTest()3030     ~MAXRTInvocationsSupportedTest()
3031     {
3032         /* Stub */
3033     }
3034 
getCHitShaderCollectionShaderNames() const3035     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
3036     {
3037         return {};
3038     }
3039 
getInstanceCustomIndex(const uint32_t & nBL,const uint32_t & nInstance) const3040     uint32_t getInstanceCustomIndex(const uint32_t &nBL, const uint32_t &nInstance) const final
3041     {
3042         DE_UNREF(nBL);
3043         DE_UNREF(nInstance);
3044 
3045         return ++m_lastCustomInstanceIndexUsed;
3046     }
3047 
getDispatchSize() const3048     tcu::UVec3 getDispatchSize() const final
3049     {
3050         DE_ASSERT(m_gridSizeXYZ[0] != 0);
3051         DE_ASSERT(m_gridSizeXYZ[1] != 0);
3052         DE_ASSERT(m_gridSizeXYZ[2] != 0);
3053 
3054         return tcu::UVec3(m_gridSizeXYZ[0], m_gridSizeXYZ[1], m_gridSizeXYZ[2]);
3055     }
3056 
getResultBufferSize() const3057     uint32_t getResultBufferSize() const final
3058     {
3059         DE_ASSERT(m_gridSizeXYZ[0] != 0);
3060         DE_ASSERT(m_gridSizeXYZ[1] != 0);
3061         DE_ASSERT(m_gridSizeXYZ[2] != 0);
3062 
3063         return static_cast<uint32_t>((2 /* nHits, nMisses */ + m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2] *
3064                                                                    1 /* hit instance custom index */) *
3065                                      sizeof(uint32_t));
3066     }
3067 
getTLASPtrVecToBind() const3068     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
3069     {
3070         DE_ASSERT(m_tlPtr != nullptr);
3071 
3072         return {m_tlPtr.get()};
3073     }
3074 
init(vkt::Context & context,RayTracingProperties * rtPropertiesPtr)3075     bool init(vkt::Context &context, RayTracingProperties *rtPropertiesPtr) final
3076     {
3077         m_context = &context;
3078         /* NOTE: In order to avoid running into a situation where the test attempts to create a buffer of size larger than permitted by Vulkan,
3079          *       we limit the maximum number of testable invocations to 2^29 on 64bit CTS build and driver or to 2^27 on 32bit */
3080         const auto maxComputeWorkGroupCount        = context.getDeviceProperties().limits.maxComputeWorkGroupCount;
3081         const auto maxComputeWorkGroupSize         = context.getDeviceProperties().limits.maxComputeWorkGroupSize;
3082         const uint64_t maxGlobalRTWorkGroupSize[3] = {
3083             static_cast<uint64_t>(maxComputeWorkGroupCount[0]) * static_cast<uint64_t>(maxComputeWorkGroupSize[0]),
3084             static_cast<uint64_t>(maxComputeWorkGroupCount[1]) * static_cast<uint64_t>(maxComputeWorkGroupSize[1]),
3085             static_cast<uint64_t>(maxComputeWorkGroupCount[2]) * static_cast<uint64_t>(maxComputeWorkGroupSize[2])};
3086         const auto maxRayDispatchInvocationCount =
3087             de::min(static_cast<uint64_t>(rtPropertiesPtr->getMaxRayDispatchInvocationCount()),
3088 #if (DE_PTR_SIZE == 4)
3089                     static_cast<uint64_t>(1ULL << 27));
3090 #else
3091                     static_cast<uint64_t>(1ULL << 29));
3092 #endif
3093 
3094         m_gridSizeXYZ[0] =
3095             de::max(1u, static_cast<uint32_t>((maxRayDispatchInvocationCount) % maxGlobalRTWorkGroupSize[0]));
3096         m_gridSizeXYZ[1] = de::max(1u, static_cast<uint32_t>((maxRayDispatchInvocationCount / m_gridSizeXYZ[0]) %
3097                                                              maxGlobalRTWorkGroupSize[1]));
3098         m_gridSizeXYZ[2] =
3099             de::max(1u, static_cast<uint32_t>((maxRayDispatchInvocationCount / m_gridSizeXYZ[0] / m_gridSizeXYZ[1]) %
3100                                               maxGlobalRTWorkGroupSize[2]));
3101 
3102         /* TODO: The simple formulas above may need to be improved to handle your implementation correctly */
3103         DE_ASSERT(m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2] == maxRayDispatchInvocationCount);
3104 
3105         return true;
3106     }
3107 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)3108     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
3109                 VkCommandBuffer commandBuffer) final
3110     {
3111         std::unique_ptr<GridASProvider> asProviderPtr(
3112             new GridASProvider(tcu::Vec3(0, 0, 0),    /* gridStartXYZ          */
3113                                tcu::Vec3(1, 1, 1),    /* gridCellSizeXYZ       */
3114                                tcu::UVec3(512, 1, 1), /* gridSizeXYZ           */
3115                                tcu::Vec3(3, 0, 0),    /* gridInterCellDeltaXYZ */
3116                                m_geometryType));
3117 
3118         m_tlPtr = asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer,
3119                                             VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
3120                                             this,  /* optASPropertyProviderPtr */
3121                                             this); /* optASFeedbackPtr            */
3122     }
3123 
initPrograms(SourceCollections & programCollection) const3124     void initPrograms(SourceCollections &programCollection) const final
3125     {
3126         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
3127                                                   0u,    /* flags        */
3128                                                   true); /* allowSpirv14 */
3129 
3130         const char *hitPropsDefinition = "struct HitProps\n"
3131                                          "{\n"
3132                                          "    uint instanceCustomIndex;\n"
3133                                          "};\n";
3134 
3135         {
3136             std::stringstream css;
3137 
3138             css << "#version 460 core\n"
3139                    "\n"
3140                    "#extension GL_EXT_ray_tracing : require\n"
3141                    "\n"
3142                    "hitAttributeEXT vec3 unusedAttribute;\n"
3143                    "\n" +
3144                        de::toString(hitPropsDefinition) +
3145                        "\n"
3146                        "layout(location = 0) rayPayloadInEXT      uint   unusedPayload;\n"
3147                        "layout(set      = 0, binding = 0, std430) buffer result\n"
3148                        "{\n"
3149                        "    uint     nHitsRegistered;\n"
3150                        "    uint     nMissesRegistered;\n"
3151                        "    HitProps hits[];\n"
3152                        "};\n"
3153                        "\n"
3154                        "void main()\n"
3155                        "{\n"
3156                        "    atomicAdd(nHitsRegistered, 1);\n"
3157                        "\n"
3158                        "    uint nInvocation = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
3159                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3160                        "\n"
3161                        "    hits[nInvocation].instanceCustomIndex = gl_InstanceCustomIndexEXT;\n"
3162                        "}\n";
3163 
3164             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
3165         }
3166 
3167         {
3168             std::stringstream css;
3169 
3170             css << "#version 460 core\n"
3171                    "\n"
3172                    "#extension GL_EXT_ray_tracing : require\n"
3173                    "\n"
3174                    "hitAttributeEXT vec3 hitAttribute;\n"
3175                    "\n"
3176                    "void main()\n"
3177                    "{\n"
3178                    "    reportIntersectionEXT(0.95f, 0);\n"
3179                    "}\n";
3180 
3181             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
3182         }
3183 
3184         {
3185             std::stringstream css;
3186 
3187             css << "#version 460 core\n"
3188                    "\n"
3189                    "#extension GL_EXT_ray_tracing : require\n"
3190                    "\n" +
3191                        de::toString(hitPropsDefinition) +
3192                        "\n"
3193                        "layout(set = 0, binding = 0, std430) buffer result\n"
3194                        "{\n"
3195                        "    uint     nHitsRegistered;\n"
3196                        "    uint     nMissesRegistered;\n"
3197                        "    HitProps hits[];\n"
3198                        "};\n"
3199                        "\n"
3200                        "layout(location = 0) rayPayloadInEXT uint rayIndex;\n"
3201                        "\n"
3202                        "void main()\n"
3203                        "{\n"
3204                        "    atomicAdd(nMissesRegistered, 1);\n"
3205                        "}\n";
3206 
3207             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
3208         }
3209 
3210         {
3211             std::stringstream css;
3212 
3213             css << "#version 460 core\n"
3214                    "\n"
3215                    "#extension GL_EXT_ray_tracing : require\n"
3216                    "\n"
3217                    "layout(location = 0)              rayPayloadEXT uint               unusedPayload;\n"
3218                    "layout(set      = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
3219                    "\n"
3220                    "void main()\n"
3221                    "{\n"
3222                    "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
3223                    "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3224                    "    uint  rayFlags     = 0;\n"
3225                    "    float tmin         = 0.001;\n"
3226                    "    float tmax         = 2.1;\n"
3227                    "\n"
3228                    "    uint  cullMask     = 0xFF;\n"
3229                    "    vec3  cellStartXYZ = vec3( (nInvocation % " +
3230                        de::toString(m_nMaxCells) +
3231                        ") * 3, 0.0, 0.0);\n"
3232                        "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
3233                        "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
3234                        "    vec3  origin       = target - vec3(0, 2, 0);\n"
3235                        "    vec3  direct       = normalize(target - origin);\n"
3236                        "\n"
3237                        "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, "
3238                        "tmax, 0);\n"
3239                        "}\n";
3240 
3241             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
3242         }
3243     }
3244 
resetTLAS()3245     void resetTLAS() final
3246     {
3247         m_tlPtr.reset();
3248     }
3249 
verifyResultBuffer(const void * resultDataPtr) const3250     bool verifyResultBuffer(const void *resultDataPtr) const final
3251     {
3252         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
3253         bool result                  = false;
3254 
3255         typedef struct
3256         {
3257             uint32_t instanceCustomIndex;
3258         } HitProperties;
3259 
3260         const auto nHitsReported   = *resultU32Ptr;
3261         const auto nMissesReported = *(resultU32Ptr + 1);
3262 
3263         if (nHitsReported != m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2])
3264         {
3265             goto end;
3266         }
3267 
3268         if (nMissesReported != 0)
3269         {
3270             goto end;
3271         }
3272 
3273         for (uint32_t nRay = 0; nRay < nHitsReported; ++nRay)
3274         {
3275             // Touch watch dog every 100000 loops to avoid timeout issue.
3276             if (nRay > 0 && (nRay % 100000 == 0))
3277                 m_context->getTestContext().touchWatchdog();
3278             const HitProperties *hitPropsPtr =
3279                 reinterpret_cast<const HitProperties *>(resultU32Ptr + 2 /* preamble ints */) + nRay;
3280 
3281             if (m_nRayToInstanceIndexExpected.at(nRay % m_nMaxCells) != hitPropsPtr->instanceCustomIndex)
3282             {
3283                 goto end;
3284             }
3285         }
3286 
3287         result = true;
3288     end:
3289         return result;
3290     }
3291 
3292 private:
onCullMaskAssignedToCell(const tcu::UVec3 & cellLocation,const uint8_t & cullMaskAssigned)3293     void onCullMaskAssignedToCell(const tcu::UVec3 &cellLocation, const uint8_t &cullMaskAssigned)
3294     {
3295         /* Dont'care */
3296         DE_UNREF(cellLocation);
3297         DE_UNREF(cullMaskAssigned);
3298     }
3299 
onInstanceCustomIndexAssignedToCell(const tcu::UVec3 & cellLocation,const uint32_t & customIndexAssigned)3300     void onInstanceCustomIndexAssignedToCell(const tcu::UVec3 &cellLocation, const uint32_t &customIndexAssigned)
3301     {
3302         DE_ASSERT(cellLocation[1] == 0);
3303         DE_ASSERT(cellLocation[2] == 0);
3304 
3305         m_nRayToInstanceIndexExpected[cellLocation[0]] = customIndexAssigned;
3306     }
3307 
3308     vkt::Context *m_context;
3309     const AccelerationStructureLayout m_asStructureLayout;
3310     const GeometryType m_geometryType;
3311 
3312     tcu::UVec3 m_gridSizeXYZ;
3313     mutable uint32_t m_lastCustomInstanceIndexUsed;
3314     const uint32_t m_nMaxCells;
3315     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
3316 
3317     std::map<uint32_t, uint32_t> m_nRayToInstanceIndexExpected;
3318 };
3319 
3320 class NoDuplicateAnyHitTest : public TestBase
3321 {
3322 public:
NoDuplicateAnyHitTest(const AccelerationStructureLayout & asLayout,const GeometryType & geometryType)3323     NoDuplicateAnyHitTest(const AccelerationStructureLayout &asLayout, const GeometryType &geometryType)
3324         : m_asLayout(asLayout)
3325         , m_geometryType(geometryType)
3326         , m_gridSizeXYZ(tcu::UVec3(4, 4, 4))
3327         , m_nRaysToTrace(32)
3328     {
3329         /* Stub */
3330     }
3331 
~NoDuplicateAnyHitTest()3332     ~NoDuplicateAnyHitTest()
3333     {
3334         /* Stub */
3335     }
3336 
getCHitShaderCollectionShaderNames() const3337     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
3338     {
3339         return {};
3340     }
3341 
getDispatchSize() const3342     tcu::UVec3 getDispatchSize() const final
3343     {
3344         return tcu::UVec3(4, 4, m_nRaysToTrace / (4 * 4) + 1);
3345     }
3346 
getResultBufferSize() const3347     uint32_t getResultBufferSize() const final
3348     {
3349         const auto nPrimitives = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
3350 
3351         return static_cast<uint32_t>((2 /* nHits, nMisses */ + 3 * nPrimitives /* instancePrimitiveIDPairsUsed */) *
3352                                      sizeof(uint32_t) * m_nRaysToTrace);
3353     }
3354 
getTLASPtrVecToBind() const3355     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
3356     {
3357         return {m_tlPtr.get()};
3358     }
3359 
resetTLAS()3360     void resetTLAS() final
3361     {
3362         m_tlPtr.reset();
3363     }
3364 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)3365     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
3366                 VkCommandBuffer commandBuffer) final
3367     {
3368         m_asProviderPtr.reset(new GridASProvider(tcu::Vec3(0, 0, 0),                         /* gridStartXYZ          */
3369                                                  tcu::Vec3(1, 1, 1),                         /* gridCellSizeXYZ       */
3370                                                  m_gridSizeXYZ, tcu::Vec3(2.0f, 2.0f, 2.0f), /* gridInterCellDeltaXYZ */
3371                                                  m_geometryType));
3372 
3373         m_tlPtr = m_asProviderPtr->createTLAS(context, m_asLayout, commandBuffer,
3374                                               VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
3375                                               nullptr,  /* optASPropertyProviderPtr */
3376                                               nullptr); /* optASFedbackPtr          */
3377     }
3378 
initPrograms(SourceCollections & programCollection) const3379     void initPrograms(SourceCollections &programCollection) const final
3380     {
3381         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
3382                                                   0u,    /* flags        */
3383                                                   true); /* allowSpirv14 */
3384 
3385         const auto nTotalPrimitives        = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
3386         const auto hitPropertiesDefinition = "struct HitProperties\n"
3387                                              "{\n"
3388                                              "    uint nHitsRegistered;\n"
3389                                              "     uint nMissRegistered;\n"
3390                                              "    uint instancePrimitiveIDPairsUsed[3 * " +
3391                                              de::toString(nTotalPrimitives) +
3392                                              "];\n"
3393                                              "};\n";
3394 
3395         {
3396             std::stringstream css;
3397 
3398             css << "#version 460 core\n"
3399                    "\n"
3400                    "#extension GL_EXT_ray_tracing : require\n"
3401                    "\n"
3402                    "hitAttributeEXT vec3 unusedAttribute;\n"
3403                    "\n" +
3404                        hitPropertiesDefinition +
3405                        "\n"
3406                        "layout(location = 0) rayPayloadInEXT      vec3 unusedPayload;\n"
3407                        "layout(set      = 0, binding = 0, std430) buffer result\n"
3408                        "{\n"
3409                        "    HitProperties rayToHitProps["
3410                 << de::toString(m_nRaysToTrace)
3411                 << "];\n"
3412                    "};\n"
3413                    "\n"
3414                    "void main()\n"
3415                    "{\n"
3416                    "    uint nRay            = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
3417                    "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3418                    "    uint nHitsRegistered = atomicAdd(rayToHitProps[nRay].nHitsRegistered, 1);\n"
3419                    "\n"
3420                    "    rayToHitProps[nRay].instancePrimitiveIDPairsUsed[3 * nHitsRegistered + 0] = 1 + "
3421                    "gl_InstanceID;\n"
3422                    "    rayToHitProps[nRay].instancePrimitiveIDPairsUsed[3 * nHitsRegistered + 1] = 1 + "
3423                    "gl_PrimitiveID;\n"
3424                    "    rayToHitProps[nRay].instancePrimitiveIDPairsUsed[3 * nHitsRegistered + 2] = 1 + "
3425                    "gl_GeometryIndexEXT;\n"
3426                    "}\n";
3427 
3428             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
3429         }
3430 
3431         {
3432             std::stringstream css;
3433 
3434             css << "#version 460 core\n"
3435                    "\n"
3436                    "#extension GL_EXT_ray_tracing : require\n"
3437                    "\n"
3438                    "hitAttributeEXT vec3 hitAttribute;\n"
3439                    "\n"
3440                    "void main()\n"
3441                    "{\n"
3442                    "    reportIntersectionEXT(0.95f, 0);\n"
3443                    "}\n";
3444 
3445             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
3446         }
3447 
3448         {
3449             std::stringstream css;
3450 
3451             css << "#version 460 core\n"
3452                    "\n"
3453                    "#extension GL_EXT_ray_tracing : require\n"
3454                    "\n" +
3455                        hitPropertiesDefinition +
3456                        "layout(location = 0) rayPayloadInEXT      vec3   unusedPayload;\n"
3457                        "layout(set      = 0, binding = 0, std430) buffer result\n"
3458                        "{\n"
3459                        "    HitProperties rayToHitProps["
3460                 << de::toString(m_nRaysToTrace)
3461                 << "];\n"
3462                    "};\n"
3463                    "\n"
3464                    "void main()\n"
3465                    "{\n"
3466                    "    uint nRay = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + gl_LaunchIDEXT.y * "
3467                    "gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3468                    "\n"
3469                    "    atomicAdd(rayToHitProps[nRay].nMissRegistered, 1);\n"
3470                    "}\n";
3471 
3472             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
3473         }
3474 
3475         {
3476             std::stringstream css;
3477 
3478             css << "#version 460 core\n"
3479                    "\n"
3480                    "#extension GL_EXT_ray_tracing : require\n"
3481                    "\n" +
3482                        hitPropertiesDefinition +
3483                        "layout(location = 0)              rayPayloadEXT vec3                     unusedPayload;\n"
3484                        "layout(set      = 0, binding = 1) uniform       accelerationStructureEXT topLevelAS;\n"
3485                        "\n"
3486                        "void main()\n"
3487                        "{\n"
3488                        "    uint  nInvocation = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
3489                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3490                        "    uint  rayFlags    = 0;\n"
3491                        "    uint  cullMask    = 0xFF;\n"
3492                        "    float tmin        = 0.001;\n"
3493                        "    float tmax        = 9.0;\n"
3494                        "    vec3  origin      = vec3(4,                                  4,                            "
3495                        "      4);\n"
3496                        "    vec3  target      = vec3(float(gl_LaunchIDEXT.x * 2) + 0.5f, float(gl_LaunchIDEXT.y * 2) + "
3497                        "0.5f, float(gl_LaunchIDEXT.z * 2) + 0.5f);\n"
3498                        "    vec3  direct      = normalize(target - origin);\n"
3499                        "\n"
3500                        "    if (nInvocation >= "
3501                 << m_nRaysToTrace
3502                 << ")\n"
3503                    "    {\n"
3504                    "        return;\n"
3505                    "    }\n"
3506                    "\n"
3507                    "    traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
3508                    "}\n";
3509 
3510             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
3511         }
3512     }
3513 
verifyResultBuffer(const void * resultDataPtr) const3514     bool verifyResultBuffer(const void *resultDataPtr) const final
3515     {
3516         const auto nTotalPrimitives = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
3517         bool result                 = true;
3518 
3519         for (uint32_t nRay = 0; nRay < m_nRaysToTrace; ++nRay)
3520         {
3521             std::vector<std::tuple<uint32_t, uint32_t, uint32_t>> tupleVec;
3522             const auto rayProps = reinterpret_cast<const uint32_t *>(resultDataPtr) + (2 + 3 * nTotalPrimitives) * nRay;
3523 
3524             // 1. At least one ahit invocation must have been made.
3525             if (rayProps[0] == 0)
3526             {
3527                 result = false;
3528 
3529                 goto end;
3530             }
3531 
3532             // 2. It's OK for each ray to intersect many AABBs, but no AABB should have had >1 ahit invocation fired.
3533             for (uint32_t nPrimitive = 0; nPrimitive < nTotalPrimitives; nPrimitive++)
3534             {
3535                 const auto instanceID    = rayProps[2 /* nHits, nMissesRegistered */ + 3 * nPrimitive + 0];
3536                 const auto primitiveID   = rayProps[2 /* nHits, nMissesRegistered */ + 3 * nPrimitive + 1];
3537                 const auto geometryIndex = rayProps[2 /* nHits, nMissesRegistered */ + 3 * nPrimitive + 2];
3538 
3539                 const auto currentTuple =
3540                     std::tuple<uint32_t, uint32_t, uint32_t>(instanceID, primitiveID, geometryIndex);
3541 
3542                 if (instanceID != 0 || primitiveID != 0 || geometryIndex != 0)
3543                 {
3544                     if (std::find(tupleVec.begin(), tupleVec.end(), currentTuple) != tupleVec.end())
3545                     {
3546                         result = false;
3547 
3548                         goto end;
3549                     }
3550 
3551                     tupleVec.push_back(currentTuple);
3552                 }
3553             }
3554 
3555             // 3. None of the traced rays should have triggered the miss shader invocation.
3556             if (rayProps[1] != 0)
3557             {
3558                 result = false;
3559 
3560                 goto end;
3561             }
3562         }
3563 
3564     end:
3565         return result;
3566     }
3567 
3568 private:
3569     const AccelerationStructureLayout m_asLayout;
3570     const GeometryType m_geometryType;
3571     const tcu::UVec3 m_gridSizeXYZ;
3572     const uint32_t m_nRaysToTrace;
3573 
3574     std::unique_ptr<GridASProvider> m_asProviderPtr;
3575     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
3576 };
3577 
3578 const std::vector<VariableType> g_ShaderRecordBlockTestVars1 = {
3579     VariableType::FLOAT, VariableType::VEC2,   VariableType::VEC3,   VariableType::VEC4,
3580 
3581     VariableType::MAT2,  VariableType::MAT2X2, VariableType::MAT2X3, VariableType::MAT2X4,
3582     VariableType::MAT3,  VariableType::MAT3X2, VariableType::MAT3X3, VariableType::MAT3X4,
3583     VariableType::MAT4,  VariableType::MAT4X2, VariableType::MAT4X3, VariableType::MAT4X4,
3584 
3585     VariableType::INT,   VariableType::IVEC2,  VariableType::IVEC3,  VariableType::IVEC4,
3586 
3587     VariableType::UINT,  VariableType::UVEC2,  VariableType::UVEC3,  VariableType::UVEC4,
3588 };
3589 
3590 const std::vector<VariableType> g_ShaderRecordBlockTestVars2 = {
3591     VariableType::DOUBLE, VariableType::DVEC2,   VariableType::DVEC3,   VariableType::DVEC4,
3592 
3593     VariableType::DMAT2,  VariableType::DMAT2X2, VariableType::DMAT2X3, VariableType::DMAT2X4, VariableType::DMAT3,
3594 };
3595 
3596 const std::vector<VariableType> g_ShaderRecordBlockTestVars3 = {
3597     VariableType::DMAT3X2, VariableType::DMAT3X3, VariableType::DMAT3X4, VariableType::DMAT4,
3598     VariableType::DMAT4X2, VariableType::DMAT4X3, VariableType::DMAT4X4,
3599 };
3600 
3601 const std::vector<VariableType> g_ShaderRecordBlockTestVars4 = {
3602     VariableType::VEC3,   VariableType::VEC4,
3603 
3604     VariableType::INT16,  VariableType::I16VEC2, VariableType::I16VEC3, VariableType::I16VEC4,
3605 
3606     VariableType::MAT3X3, VariableType::MAT3X4,  VariableType::MAT4X3,
3607 
3608     VariableType::UINT16, VariableType::U16VEC2, VariableType::U16VEC3, VariableType::U16VEC4,
3609 };
3610 
3611 const std::vector<VariableType> g_ShaderRecordBlockTestVars5 = {
3612     VariableType::VEC3,   VariableType::VEC4,
3613 
3614     VariableType::INT64,  VariableType::I64VEC2, VariableType::I64VEC3, VariableType::I64VEC4,
3615 
3616     VariableType::MAT3X3, VariableType::MAT3X4,  VariableType::MAT4X3,
3617 
3618     VariableType::UINT64, VariableType::U64VEC2, VariableType::U64VEC3, VariableType::U64VEC4,
3619 };
3620 
3621 const std::vector<VariableType> g_ShaderRecordBlockTestVars6 = {
3622     VariableType::VEC3,   VariableType::VEC4,
3623 
3624     VariableType::INT8,   VariableType::I8VEC2, VariableType::I8VEC3, VariableType::I8VEC4,
3625 
3626     VariableType::MAT3X3, VariableType::MAT3X4, VariableType::MAT4X3,
3627 
3628     VariableType::UINT8,  VariableType::U8VEC2, VariableType::U8VEC3, VariableType::U8VEC4,
3629 };
3630 
3631 class ShaderRecordBlockTest : public TestBase
3632 {
3633 public:
ShaderRecordBlockTest(const TestType & testType,const std::vector<VariableType> & varTypesToTest)3634     ShaderRecordBlockTest(const TestType &testType, const std::vector<VariableType> &varTypesToTest)
3635         : m_gridSizeXYZ(tcu::UVec3(2, 2, 2))
3636         , m_testType(testType)
3637         , m_varTypesToTest(varTypesToTest)
3638         , m_resultBufferSize(0)
3639         , m_shaderRecordSize(0)
3640     {
3641         initTestItems();
3642     }
3643 
~ShaderRecordBlockTest()3644     ~ShaderRecordBlockTest()
3645     {
3646         /* Stub */
3647     }
3648 
getDispatchSize() const3649     tcu::UVec3 getDispatchSize() const final
3650     {
3651         return tcu::UVec3(3, 1, 1);
3652     }
3653 
getResultBufferSize() const3654     uint32_t getResultBufferSize() const final
3655     {
3656         return m_resultBufferSize;
3657     }
3658 
getShaderRecordData(const ShaderGroups & shaderGroup) const3659     const void *getShaderRecordData(const ShaderGroups &shaderGroup) const final
3660     {
3661         return (shaderGroup == ShaderGroups::HIT_GROUP)  ? m_shaderGroupToRecordDataMap.at(shaderGroup).data() :
3662                (shaderGroup == ShaderGroups::MISS_GROUP) ? m_shaderGroupToRecordDataMap.at(shaderGroup).data() :
3663                                                            nullptr;
3664     }
3665 
getShaderRecordSize(const ShaderGroups & shaderGroup) const3666     uint32_t getShaderRecordSize(const ShaderGroups &shaderGroup) const final
3667     {
3668         DE_ASSERT(m_shaderRecordSize != 0);
3669 
3670         return ((shaderGroup == ShaderGroups::HIT_GROUP) || (shaderGroup == ShaderGroups::MISS_GROUP)) ?
3671                    m_shaderRecordSize :
3672                    0;
3673     }
3674 
getTLASPtrVecToBind() const3675     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
3676     {
3677         return {m_tlPtr.get()};
3678     }
3679 
getVarsToTest(const TestType & testType)3680     static std::vector<VariableType> getVarsToTest(const TestType &testType)
3681     {
3682         return ((testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1) ||
3683                 (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1) ||
3684                 (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_1) ||
3685                 (testType == TestType::SHADER_RECORD_BLOCK_STD430_1)) ?
3686                    g_ShaderRecordBlockTestVars1 :
3687                ((testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2) ||
3688                 (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2) ||
3689                 (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_2) ||
3690                 (testType == TestType::SHADER_RECORD_BLOCK_STD430_2)) ?
3691                    g_ShaderRecordBlockTestVars2 :
3692                ((testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3) ||
3693                 (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3) ||
3694                 (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_3) ||
3695                 (testType == TestType::SHADER_RECORD_BLOCK_STD430_3)) ?
3696                    g_ShaderRecordBlockTestVars3 :
3697                ((testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4) ||
3698                 (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4) ||
3699                 (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_4) ||
3700                 (testType == TestType::SHADER_RECORD_BLOCK_STD430_4)) ?
3701                    g_ShaderRecordBlockTestVars4 :
3702                ((testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5) ||
3703                 (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5) ||
3704                 (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_5) ||
3705                 (testType == TestType::SHADER_RECORD_BLOCK_STD430_5)) ?
3706                    g_ShaderRecordBlockTestVars5 :
3707                    g_ShaderRecordBlockTestVars6;
3708     }
3709 
resetTLAS()3710     void resetTLAS() final
3711     {
3712         m_tlPtr.reset();
3713     }
3714 
init(vkt::Context &,RayTracingProperties *)3715     bool init(vkt::Context & /* context */, RayTracingProperties * /* rtPropsPtr */) final
3716     {
3717         // Cache required result buffer size.
3718         {
3719             uint32_t largestBaseTypeSizeUsed = 0;
3720             const auto &lastItem             = m_testItems.items.back();
3721             const uint32_t nResultBytesPerShaderStage =
3722                 lastItem.resultBufferProps.bufferOffset + lastItem.arraySize * lastItem.resultBufferProps.arrayStride;
3723             const VkShaderStageFlagBits shaderStages[] = {
3724                 VK_SHADER_STAGE_MISS_BIT_KHR,
3725                 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
3726                 VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
3727                 VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
3728             };
3729 
3730             m_shaderRecordSize =
3731                 lastItem.inputBufferProps.bufferOffset + lastItem.arraySize * lastItem.inputBufferProps.arrayStride;
3732 
3733             for (const auto &currentTestItem : m_testItems.items)
3734             {
3735                 const auto baseType      = getBaseType(currentTestItem.type);
3736                 const auto componentSize = getComponentSizeBytes(baseType);
3737 
3738                 largestBaseTypeSizeUsed = de::max(componentSize, largestBaseTypeSizeUsed);
3739             }
3740 
3741             for (const auto &currentShaderStage : shaderStages)
3742             {
3743                 m_shaderStageToResultBufferOffset[currentShaderStage] = m_resultBufferSize;
3744 
3745                 m_resultBufferSize =
3746                     de::roundUp(m_resultBufferSize, static_cast<uint32_t>(sizeof(largestBaseTypeSizeUsed)));
3747                 m_resultBufferSize += nResultBytesPerShaderStage;
3748             }
3749         }
3750 
3751         return true;
3752     }
3753 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)3754     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
3755                 VkCommandBuffer commandBuffer) final
3756     {
3757         m_asProviderPtr.reset(new GridASProvider(tcu::Vec3(0, 0, 0),                         /* gridStartXYZ          */
3758                                                  tcu::Vec3(1, 1, 1),                         /* gridCellSizeXYZ       */
3759                                                  m_gridSizeXYZ, tcu::Vec3(2.0f, 2.0f, 2.0f), /* gridInterCellDeltaXYZ */
3760                                                  GeometryType::AABB));
3761 
3762         m_tlPtr = m_asProviderPtr->createTLAS(context, AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES,
3763                                               commandBuffer, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
3764                                               nullptr,  /* optASPropertyProviderPtr */
3765                                               nullptr); /* optASFedbackPtr          */
3766     }
3767 
initPrograms(SourceCollections & programCollection) const3768     void initPrograms(SourceCollections &programCollection) const final
3769     {
3770         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
3771                                                   0u,    /* flags        */
3772                                                   true); /* allowSpirv14 */
3773 
3774         const bool isSTD430Test         = isExplicitSTD430OffsetTest(m_testType) || isSTD430LayoutTest(m_testType);
3775         const bool requires16BitStorage = usesI16(m_testType) || usesU16(m_testType);
3776         const bool requires8BitStorage  = usesI8(m_testType) || usesU8(m_testType);
3777         const bool requiresInt64        = usesI64(m_testType) || usesU64(m_testType);
3778         const bool usesExplicitOffsets =
3779             isExplicitScalarOffsetTest(m_testType) || isExplicitSTD430OffsetTest(m_testType);
3780         const auto inputBlockVariablesGLSL =
3781             getGLSLForStructItem(m_testItems, usesExplicitOffsets, true /* targetsInputBuffer            */);
3782         const auto outputStructVariablesGLSL =
3783             getGLSLForStructItem(m_testItems, false, /* includeOffsetLayoutQualifier */
3784                                  false /* targetsInputBuffer            */);
3785 
3786         const auto inputBufferGLSL = "layout (" + std::string((!isSTD430Test) ? "scalar, " : "std430, ") +
3787                                      "shaderRecordEXT) buffer ib\n"
3788                                      "{\n" +
3789                                      inputBlockVariablesGLSL + "} inputBuffer;\n";
3790         const auto outputBufferGLSL = "struct OutputData\n"
3791                                       "{\n" +
3792                                       outputStructVariablesGLSL +
3793                                       "};\n"
3794                                       "\n"
3795                                       "layout (std430, set = 0, binding = 0) buffer ob\n"
3796                                       "{\n"
3797                                       "    OutputData results[4];\n"
3798                                       "};\n";
3799 
3800         std::string preamble;
3801 
3802         {
3803             std::stringstream css;
3804 
3805             css << "#version 460 core\n"
3806                    "\n"
3807                    "#extension GL_EXT_ray_tracing : require\n";
3808 
3809             if (!isSTD430Test)
3810             {
3811                 css << "#extension GL_EXT_scalar_block_layout : require\n";
3812             }
3813 
3814             if (requires16BitStorage)
3815             {
3816                 css << "#extension GL_EXT_shader_16bit_storage : require\n";
3817             }
3818 
3819             if (requires8BitStorage)
3820             {
3821                 css << "#extension GL_EXT_shader_8bit_storage : require\n";
3822             }
3823 
3824             if (requiresInt64)
3825             {
3826                 css << "#extension GL_ARB_gpu_shader_int64 : require\n";
3827             }
3828 
3829             preamble = css.str();
3830         }
3831 
3832         {
3833             std::stringstream css;
3834 
3835             css << preamble
3836                 << "\n"
3837                    "                     hitAttributeEXT vec3 unusedAttribute;\n"
3838                    "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
3839                    "\n" +
3840                        inputBufferGLSL + outputBufferGLSL +
3841                        "\n"
3842                        "void main()\n"
3843                        "{\n" +
3844                        getGLSLForSetters(m_testItems, 3) + "}\n";
3845 
3846             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
3847         }
3848 
3849         {
3850             std::stringstream css;
3851 
3852             css << preamble
3853                 << "\n"
3854                    "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n" +
3855                        inputBufferGLSL + outputBufferGLSL +
3856                        "\n"
3857                        "void main()\n"
3858                        "{\n" +
3859                        getGLSLForSetters(m_testItems, 1) + "}\n";
3860 
3861             programCollection.glslSources.add("chit") << glu::ClosestHitSource(css.str()) << buildOptions;
3862         }
3863 
3864         {
3865             std::stringstream css;
3866 
3867             css << preamble
3868                 << "\n"
3869                    "hitAttributeEXT vec3 hitAttribute;\n"
3870                    "\n" +
3871                        inputBufferGLSL + outputBufferGLSL +
3872                        "\n"
3873                        "void main()\n"
3874                        "{\n" +
3875                        getGLSLForSetters(m_testItems, 2) +
3876                        "\n"
3877                        "    reportIntersectionEXT(0.95f, 0);\n"
3878                        "}\n";
3879 
3880             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
3881         }
3882 
3883         {
3884             std::stringstream css;
3885 
3886             css << preamble
3887                 << "\n"
3888                    "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n"
3889                    "\n" +
3890                        inputBufferGLSL + outputBufferGLSL +
3891                        "\n"
3892                        "void main()\n"
3893                        "{\n"
3894                        "    uint nRay = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + gl_LaunchIDEXT.y "
3895                        "* gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3896                        "\n" +
3897                        getGLSLForSetters(m_testItems, 0) + "}\n";
3898 
3899             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
3900         }
3901 
3902         {
3903             std::stringstream css;
3904 
3905             css << preamble
3906                 << "layout(location = 0)                      rayPayloadEXT vec3       unusedPayload;\n"
3907                    "layout(set      = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
3908                    "\n"
3909                    "void main()\n"
3910                    "{\n"
3911                    "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
3912                    "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
3913                    "    uint  rayFlags     = 0;\n"
3914                    "    float tmin         = 0.001;\n"
3915                    "    float tmax         = 9.0;\n"
3916                    "\n"
3917                    "    uint  cullMask     = 0xFF;\n"
3918                    "    vec3  cellStartXYZ = vec3(nInvocation * 2.0, 0.0, 0.0);\n"
3919                    "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
3920                    "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
3921                    "    vec3  origin       = target - vec3(0, 2, 0);\n"
3922                    "    vec3  direct       = normalize(target - origin);\n"
3923                    "\n"
3924                    "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, "
3925                    "0);\n"
3926                    "}\n";
3927 
3928             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
3929         }
3930     }
3931 
isExplicitScalarOffsetTest(const TestType & testType)3932     static bool isExplicitScalarOffsetTest(const TestType &testType)
3933     {
3934         return (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1) ||
3935                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2) ||
3936                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3) ||
3937                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4) ||
3938                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5) ||
3939                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6);
3940     }
3941 
isExplicitSTD430OffsetTest(const TestType & testType)3942     static bool isExplicitSTD430OffsetTest(const TestType &testType)
3943     {
3944         return (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1) ||
3945                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2) ||
3946                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3) ||
3947                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4) ||
3948                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5) ||
3949                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6);
3950     }
3951 
isScalarLayoutTest(const TestType & testType)3952     static bool isScalarLayoutTest(const TestType &testType)
3953     {
3954         return (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_1) ||
3955                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_2) ||
3956                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_3) ||
3957                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_4) ||
3958                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_5) ||
3959                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_6);
3960     }
3961 
isSTD430LayoutTest(const TestType & testType)3962     static bool isSTD430LayoutTest(const TestType &testType)
3963     {
3964         return (testType == TestType::SHADER_RECORD_BLOCK_STD430_1) ||
3965                (testType == TestType::SHADER_RECORD_BLOCK_STD430_2) ||
3966                (testType == TestType::SHADER_RECORD_BLOCK_STD430_3) ||
3967                (testType == TestType::SHADER_RECORD_BLOCK_STD430_4) ||
3968                (testType == TestType::SHADER_RECORD_BLOCK_STD430_5) ||
3969                (testType == TestType::SHADER_RECORD_BLOCK_STD430_6);
3970     }
3971 
isTest(const TestType & testType)3972     static bool isTest(const TestType &testType)
3973     {
3974         return (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1) ||
3975                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2) ||
3976                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3) ||
3977                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4) ||
3978                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5) ||
3979                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6) ||
3980                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1) ||
3981                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2) ||
3982                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3) ||
3983                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4) ||
3984                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5) ||
3985                (testType == TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6) ||
3986                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_1) ||
3987                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_2) ||
3988                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_3) ||
3989                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_4) ||
3990                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_5) ||
3991                (testType == TestType::SHADER_RECORD_BLOCK_SCALAR_6) ||
3992                (testType == TestType::SHADER_RECORD_BLOCK_STD430_1) ||
3993                (testType == TestType::SHADER_RECORD_BLOCK_STD430_2) ||
3994                (testType == TestType::SHADER_RECORD_BLOCK_STD430_3) ||
3995                (testType == TestType::SHADER_RECORD_BLOCK_STD430_4) ||
3996                (testType == TestType::SHADER_RECORD_BLOCK_STD430_5) ||
3997                (testType == TestType::SHADER_RECORD_BLOCK_STD430_6);
3998     }
3999 
usesF64(const TestType & testType)4000     static bool usesF64(const TestType &testType)
4001     {
4002         const auto tested_var_types = getVarsToTest(testType);
4003         const bool has_f64 =
4004             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DOUBLE) != tested_var_types.end();
4005         const bool has_f64vec2 =
4006             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DVEC2) != tested_var_types.end();
4007         const bool has_f64vec3 =
4008             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DVEC3) != tested_var_types.end();
4009         const bool has_f64vec4 =
4010             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DVEC4) != tested_var_types.end();
4011         const bool has_f64mat2 =
4012             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DMAT2) != tested_var_types.end();
4013         const bool has_f64mat3 =
4014             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DMAT3) != tested_var_types.end();
4015         const bool has_f64mat4 =
4016             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::DMAT4) != tested_var_types.end();
4017 
4018         return (has_f64 || has_f64vec2 || has_f64vec3 || has_f64vec4 || has_f64mat2 || has_f64mat3 || has_f64mat4);
4019     }
4020 
usesI8(const TestType & testType)4021     static bool usesI8(const TestType &testType)
4022     {
4023         const auto tested_var_types = getVarsToTest(testType);
4024         const bool has_i8 =
4025             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::INT8) != tested_var_types.end();
4026         const bool has_i8vec2 =
4027             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I8VEC2) != tested_var_types.end();
4028         const bool has_i8vec3 =
4029             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I8VEC3) != tested_var_types.end();
4030         const bool has_i8vec4 =
4031             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I8VEC4) != tested_var_types.end();
4032 
4033         return (has_i8 || has_i8vec2 || has_i8vec3 || has_i8vec4);
4034     }
4035 
usesI16(const TestType & testType)4036     static bool usesI16(const TestType &testType)
4037     {
4038         const auto tested_var_types = getVarsToTest(testType);
4039         const bool has_i16 =
4040             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::INT16) != tested_var_types.end();
4041         const bool has_i16vec2 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I16VEC2) !=
4042                                  tested_var_types.end();
4043         const bool has_i16vec3 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I16VEC3) !=
4044                                  tested_var_types.end();
4045         const bool has_i16vec4 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I16VEC4) !=
4046                                  tested_var_types.end();
4047 
4048         return (has_i16 || has_i16vec2 || has_i16vec3 || has_i16vec4);
4049     }
4050 
usesI64(const TestType & testType)4051     static bool usesI64(const TestType &testType)
4052     {
4053         const auto tested_var_types = getVarsToTest(testType);
4054         const bool has_i64 =
4055             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::INT64) != tested_var_types.end();
4056         const bool has_i64vec2 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I64VEC2) !=
4057                                  tested_var_types.end();
4058         const bool has_i64vec3 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I64VEC3) !=
4059                                  tested_var_types.end();
4060         const bool has_i64vec4 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::I64VEC4) !=
4061                                  tested_var_types.end();
4062 
4063         return (has_i64 || has_i64vec2 || has_i64vec3 || has_i64vec4);
4064     }
4065 
usesU8(const TestType & testType)4066     static bool usesU8(const TestType &testType)
4067     {
4068         const auto tested_var_types = getVarsToTest(testType);
4069         const bool has_u8 =
4070             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::UINT8) != tested_var_types.end();
4071         const bool has_u8vec2 =
4072             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U8VEC2) != tested_var_types.end();
4073         const bool has_u8vec3 =
4074             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U8VEC3) != tested_var_types.end();
4075         const bool has_u8vec4 =
4076             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U8VEC4) != tested_var_types.end();
4077 
4078         return (has_u8 || has_u8vec2 || has_u8vec3 || has_u8vec4);
4079     }
4080 
usesU16(const TestType & testType)4081     static bool usesU16(const TestType &testType)
4082     {
4083         const auto tested_var_types = getVarsToTest(testType);
4084         const bool has_u16 =
4085             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::UINT16) != tested_var_types.end();
4086         const bool has_u16vec2 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U16VEC2) !=
4087                                  tested_var_types.end();
4088         const bool has_u16vec3 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U16VEC3) !=
4089                                  tested_var_types.end();
4090         const bool has_u16vec4 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U16VEC4) !=
4091                                  tested_var_types.end();
4092 
4093         return (has_u16 || has_u16vec2 || has_u16vec3 || has_u16vec4);
4094     }
4095 
usesU64(const TestType & testType)4096     static bool usesU64(const TestType &testType)
4097     {
4098         const auto tested_var_types = getVarsToTest(testType);
4099         const bool has_u64 =
4100             std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::UINT64) != tested_var_types.end();
4101         const bool has_u64vec2 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U64VEC2) !=
4102                                  tested_var_types.end();
4103         const bool has_u64vec3 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U64VEC3) !=
4104                                  tested_var_types.end();
4105         const bool has_u64vec4 = std::find(tested_var_types.begin(), tested_var_types.end(), VariableType::U64VEC4) !=
4106                                  tested_var_types.end();
4107 
4108         return (has_u64 || has_u64vec2 || has_u64vec3 || has_u64vec4);
4109     }
4110 
verifyResultBuffer(const void * resultBufferDataPtr) const4111     bool verifyResultBuffer(const void *resultBufferDataPtr) const final
4112     {
4113         bool result = false;
4114 
4115         for (const auto &iterator : m_shaderStageToResultBufferOffset)
4116         {
4117             const auto currentShaderStage = iterator.first;
4118             const auto shaderGroup        = ((currentShaderStage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR) ||
4119                                       (currentShaderStage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) ||
4120                                       (currentShaderStage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) ?
4121                                                 ShaderGroups::HIT_GROUP :
4122                                                 ShaderGroups::MISS_GROUP;
4123             const auto resultStartOffset  = iterator.second;
4124 
4125             if (currentShaderStage != VK_SHADER_STAGE_MISS_BIT_KHR)
4126                 continue;
4127 
4128             for (const auto &currentItem : m_testItems.items)
4129             {
4130                 const auto baseDataType      = getBaseType(currentItem.type);
4131                 const auto componentSize     = getComponentSizeBytes(baseDataType);
4132                 const auto &expectedDataVec  = currentItem.shaderGroupToRecordDataMap.at(shaderGroup);
4133                 auto expectedDataPtr         = reinterpret_cast<const uint8_t *>(expectedDataVec.data());
4134                 const auto isMatrixType      = isMatrix(currentItem.type);
4135                 const auto nComponents       = getNComponents(currentItem.type);
4136                 const uint8_t *resultDataPtr = reinterpret_cast<const uint8_t *>(resultBufferDataPtr) +
4137                                                resultStartOffset + currentItem.resultBufferProps.bufferOffset;
4138 
4139                 for (uint32_t nArrayItem = 0; nArrayItem < currentItem.arraySize; ++nArrayItem)
4140                 {
4141                     for (uint32_t nComponent = 0; nComponent < nComponents; ++nComponent)
4142                     {
4143                         const auto expectedComponentDataPtr =
4144                             expectedDataPtr +
4145                             ((!isMatrixType) ? componentSize * nComponent :
4146                                                currentItem.inputBufferProps.matrixElementStartOffsets.at(nComponent));
4147                         const auto resultComponentDataPtr =
4148                             resultDataPtr +
4149                             ((!isMatrixType) ? componentSize * nComponent :
4150                                                currentItem.resultBufferProps.matrixElementStartOffsets.at(nComponent));
4151 
4152                         switch (baseDataType)
4153                         {
4154                         case BaseType::F32:
4155                         {
4156                             if (fabs(*reinterpret_cast<const float *>(resultComponentDataPtr) -
4157                                      *reinterpret_cast<const float *>(expectedComponentDataPtr)) > 1e-3f)
4158                             {
4159                                 goto end;
4160                             }
4161 
4162                             break;
4163                         }
4164 
4165                         case BaseType::F64:
4166                         {
4167                             if (fabs(*reinterpret_cast<const double *>(resultComponentDataPtr) -
4168                                      *reinterpret_cast<const double *>(expectedComponentDataPtr)) > 1e-3)
4169                             {
4170                                 goto end;
4171                             }
4172 
4173                             break;
4174                         }
4175 
4176                         case BaseType::I8:
4177                         {
4178                             if (*reinterpret_cast<const int8_t *>(resultComponentDataPtr) !=
4179                                 *reinterpret_cast<const int8_t *>(expectedComponentDataPtr))
4180                             {
4181                                 goto end;
4182                             }
4183 
4184                             break;
4185                         }
4186 
4187                         case BaseType::I16:
4188                         {
4189                             if (*reinterpret_cast<const int16_t *>(resultComponentDataPtr) !=
4190                                 *reinterpret_cast<const int16_t *>(expectedComponentDataPtr))
4191                             {
4192                                 goto end;
4193                             }
4194 
4195                             break;
4196                         }
4197 
4198                         case BaseType::I32:
4199                         {
4200                             if (*reinterpret_cast<const int32_t *>(resultComponentDataPtr) !=
4201                                 *reinterpret_cast<const int32_t *>(expectedComponentDataPtr))
4202                             {
4203                                 goto end;
4204                             }
4205 
4206                             break;
4207                         }
4208 
4209                         case BaseType::I64:
4210                         {
4211                             if (*reinterpret_cast<const int64_t *>(resultComponentDataPtr) !=
4212                                 *reinterpret_cast<const int64_t *>(expectedComponentDataPtr))
4213                             {
4214                                 goto end;
4215                             }
4216 
4217                             break;
4218                         }
4219 
4220                         case BaseType::U8:
4221                         {
4222                             if (*reinterpret_cast<const uint8_t *>(resultComponentDataPtr) !=
4223                                 *reinterpret_cast<const uint8_t *>(expectedComponentDataPtr))
4224                             {
4225                                 goto end;
4226                             }
4227 
4228                             break;
4229                         }
4230 
4231                         case BaseType::U16:
4232                         {
4233                             if (*reinterpret_cast<const uint16_t *>(resultComponentDataPtr) !=
4234                                 *reinterpret_cast<const uint16_t *>(expectedComponentDataPtr))
4235                             {
4236                                 goto end;
4237                             }
4238 
4239                             break;
4240                         }
4241 
4242                         case BaseType::U32:
4243                         {
4244                             if (*reinterpret_cast<const uint32_t *>(resultComponentDataPtr) !=
4245                                 *reinterpret_cast<const uint32_t *>(expectedComponentDataPtr))
4246                             {
4247                                 goto end;
4248                             }
4249 
4250                             break;
4251                         }
4252 
4253                         case BaseType::U64:
4254                         {
4255                             if (*reinterpret_cast<const uint64_t *>(resultComponentDataPtr) !=
4256                                 *reinterpret_cast<const uint64_t *>(expectedComponentDataPtr))
4257                             {
4258                                 goto end;
4259                             }
4260 
4261                             break;
4262                         }
4263 
4264                         default:
4265                         {
4266                             DE_ASSERT(false);
4267                         }
4268                         }
4269                     }
4270 
4271                     expectedDataPtr += currentItem.inputBufferProps.arrayStride;
4272                     resultDataPtr += currentItem.resultBufferProps.arrayStride;
4273                 }
4274             }
4275         }
4276 
4277         result = true;
4278     end:
4279         return result;
4280     }
4281 
4282 private:
4283     typedef struct Item
4284     {
4285         struct BufferProps
4286         {
4287             uint32_t arrayStride;
4288             uint32_t bufferOffset;
4289             std::vector<uint32_t> matrixElementStartOffsets; //< Holds offsets to consecutive matrix element values.
4290 
BufferPropsvkt::RayTracing::__anon12c3bfbd0111::ShaderRecordBlockTest::Item::BufferProps4291             BufferProps() : arrayStride(0), bufferOffset(0xFFFFFFFF)
4292             {
4293                 /* Stub */
4294             }
4295         };
4296 
4297         BufferProps inputBufferProps;
4298         BufferProps resultBufferProps;
4299 
4300         uint32_t arraySize;
4301         MatrixMajorOrder matrixOrder;
4302         std::string name;
4303         VariableType type;
4304 
4305         std::map<ShaderGroups, std::vector<uint8_t>> shaderGroupToRecordDataMap;
4306 
Itemvkt::RayTracing::__anon12c3bfbd0111::ShaderRecordBlockTest::Item4307         Item() : arraySize(0), matrixOrder(MatrixMajorOrder::UNKNOWN), type(VariableType::UNKNOWN)
4308         {
4309             /* Stub */
4310         }
4311     } Item;
4312 
4313     struct StructItem
4314     {
4315         std::vector<Item> items;
4316     };
4317 
4318     // Private functions
getBaseType(const VariableType & type) const4319     BaseType getBaseType(const VariableType &type) const
4320     {
4321         auto result = BaseType::UNKNOWN;
4322 
4323         switch (type)
4324         {
4325         case VariableType::FLOAT:
4326         case VariableType::MAT2:
4327         case VariableType::MAT2X2:
4328         case VariableType::MAT2X3:
4329         case VariableType::MAT2X4:
4330         case VariableType::MAT3:
4331         case VariableType::MAT3X2:
4332         case VariableType::MAT3X3:
4333         case VariableType::MAT3X4:
4334         case VariableType::MAT4:
4335         case VariableType::MAT4X2:
4336         case VariableType::MAT4X3:
4337         case VariableType::MAT4X4:
4338         case VariableType::VEC2:
4339         case VariableType::VEC3:
4340         case VariableType::VEC4:
4341         {
4342             result = BaseType::F32;
4343 
4344             break;
4345         }
4346 
4347         case VariableType::DOUBLE:
4348         case VariableType::DMAT2:
4349         case VariableType::DMAT2X2:
4350         case VariableType::DMAT2X3:
4351         case VariableType::DMAT2X4:
4352         case VariableType::DMAT3:
4353         case VariableType::DMAT3X2:
4354         case VariableType::DMAT3X3:
4355         case VariableType::DMAT3X4:
4356         case VariableType::DMAT4:
4357         case VariableType::DMAT4X2:
4358         case VariableType::DMAT4X3:
4359         case VariableType::DMAT4X4:
4360         case VariableType::DVEC2:
4361         case VariableType::DVEC3:
4362         case VariableType::DVEC4:
4363         {
4364             result = BaseType::F64;
4365 
4366             break;
4367         }
4368 
4369         case VariableType::INT16:
4370         case VariableType::I16VEC2:
4371         case VariableType::I16VEC3:
4372         case VariableType::I16VEC4:
4373         {
4374             result = BaseType::I16;
4375 
4376             break;
4377         }
4378 
4379         case VariableType::INT:
4380         case VariableType::IVEC2:
4381         case VariableType::IVEC3:
4382         case VariableType::IVEC4:
4383         {
4384             result = BaseType::I32;
4385 
4386             break;
4387         }
4388 
4389         case VariableType::INT64:
4390         case VariableType::I64VEC2:
4391         case VariableType::I64VEC3:
4392         case VariableType::I64VEC4:
4393         {
4394             result = BaseType::I64;
4395 
4396             break;
4397         }
4398 
4399         case VariableType::INT8:
4400         case VariableType::I8VEC2:
4401         case VariableType::I8VEC3:
4402         case VariableType::I8VEC4:
4403         {
4404             result = BaseType::I8;
4405 
4406             break;
4407         }
4408 
4409         case VariableType::UINT16:
4410         case VariableType::U16VEC2:
4411         case VariableType::U16VEC3:
4412         case VariableType::U16VEC4:
4413         {
4414             result = BaseType::U16;
4415 
4416             break;
4417         }
4418 
4419         case VariableType::UINT:
4420         case VariableType::UVEC2:
4421         case VariableType::UVEC3:
4422         case VariableType::UVEC4:
4423         {
4424             result = BaseType::U32;
4425 
4426             break;
4427         }
4428 
4429         case VariableType::UINT64:
4430         case VariableType::U64VEC2:
4431         case VariableType::U64VEC3:
4432         case VariableType::U64VEC4:
4433         {
4434             result = BaseType::U64;
4435 
4436             break;
4437         }
4438 
4439         case VariableType::UINT8:
4440         case VariableType::U8VEC2:
4441         case VariableType::U8VEC3:
4442         case VariableType::U8VEC4:
4443         {
4444             result = BaseType::U8;
4445 
4446             break;
4447         }
4448 
4449         default:
4450         {
4451             DE_ASSERT(false);
4452         }
4453         }
4454 
4455         return result;
4456     }
4457 
getComponentSizeBytes(const BaseType & type) const4458     uint32_t getComponentSizeBytes(const BaseType &type) const
4459     {
4460         uint32_t result = 0;
4461 
4462         switch (type)
4463         {
4464         case BaseType::I8:
4465         case BaseType::U8:
4466         {
4467             result = 1;
4468 
4469             break;
4470         }
4471 
4472         case BaseType::I16:
4473         case BaseType::U16:
4474         {
4475             result = 2;
4476 
4477             break;
4478         }
4479 
4480         case BaseType::F32:
4481         case BaseType::I32:
4482         case BaseType::U32:
4483         {
4484             result = 4;
4485 
4486             break;
4487         }
4488 
4489         case BaseType::F64:
4490         case BaseType::I64:
4491         case BaseType::U64:
4492         {
4493             result = 8;
4494 
4495             break;
4496         }
4497 
4498         default:
4499         {
4500             DE_ASSERT(false);
4501         }
4502         }
4503 
4504         return result;
4505     }
4506 
getGLSLForSetters(const StructItem & item,const uint32_t & nResultArrayItem) const4507     std::string getGLSLForSetters(const StructItem &item, const uint32_t &nResultArrayItem) const
4508     {
4509         std::string result;
4510 
4511         for (const auto &currentItem : item.items)
4512         {
4513             if (currentItem.arraySize > 1)
4514             {
4515                 result += "for (uint nArrayItem = 0; nArrayItem < " + de::toString(currentItem.arraySize) +
4516                           "; ++nArrayItem)\n"
4517                           "{\n";
4518             }
4519 
4520             result += "results[" + de::toString(nResultArrayItem) + "]." + currentItem.name;
4521 
4522             if (currentItem.arraySize > 1)
4523             {
4524                 result += "[nArrayItem]";
4525             }
4526 
4527             result += " = inputBuffer." + currentItem.name;
4528 
4529             if (currentItem.arraySize > 1)
4530             {
4531                 result += "[nArrayItem]";
4532             }
4533 
4534             result += ";\n";
4535 
4536             if (currentItem.arraySize > 1)
4537             {
4538                 result += "}\n";
4539             }
4540         }
4541 
4542         return result;
4543     }
4544 
getGLSLForStructItem(const StructItem & item,const bool & includeOffsetLayoutQualifier,const bool & targetsInputBuffer) const4545     std::string getGLSLForStructItem(const StructItem &item, const bool &includeOffsetLayoutQualifier,
4546                                      const bool &targetsInputBuffer) const
4547     {
4548         std::string result;
4549 
4550         for (const auto &currentItem : item.items)
4551         {
4552             const bool needsMatrixOrderQualifier = (currentItem.matrixOrder == MatrixMajorOrder::ROW_MAJOR);
4553             const auto variableTypeGLSL          = getVariableTypeGLSLType(currentItem.type);
4554             uint32_t nLayoutQualifiersUsed       = 0;
4555             const uint32_t nLayoutQualifierUses =
4556                 ((includeOffsetLayoutQualifier) ? 1 : 0) + ((needsMatrixOrderQualifier) ? 1 : 0);
4557             const bool usesLayoutQualifiers = (nLayoutQualifierUses > 0);
4558 
4559             if (usesLayoutQualifiers)
4560             {
4561                 result += "layout(";
4562             }
4563 
4564             if (includeOffsetLayoutQualifier)
4565             {
4566                 result += "offset = " + de::toString((targetsInputBuffer) ? currentItem.inputBufferProps.bufferOffset :
4567                                                                             currentItem.resultBufferProps.bufferOffset);
4568 
4569                 if ((++nLayoutQualifiersUsed) != nLayoutQualifierUses)
4570                 {
4571                     result += ", ";
4572                 }
4573             }
4574 
4575             if (needsMatrixOrderQualifier)
4576             {
4577                 result += ((currentItem.matrixOrder == MatrixMajorOrder::COLUMN_MAJOR) ? "column_major" : "row_major");
4578 
4579                 if ((++nLayoutQualifiersUsed) != nLayoutQualifierUses)
4580                 {
4581                     result += ", ";
4582                 }
4583             }
4584 
4585             if (usesLayoutQualifiers)
4586             {
4587                 result += ") ";
4588             }
4589 
4590             result += variableTypeGLSL + std::string(" ") + currentItem.name;
4591 
4592             if (currentItem.arraySize != 1)
4593             {
4594                 result += "[" + de::toString(currentItem.arraySize) + "]";
4595             }
4596 
4597             result += ";\n";
4598         }
4599 
4600         return result;
4601     }
4602 
getMatrixSize(const VariableType & type) const4603     tcu::UVec2 getMatrixSize(const VariableType &type) const
4604     {
4605         auto result = tcu::UVec2();
4606 
4607         switch (type)
4608         {
4609         case VariableType::DMAT2:
4610         case VariableType::DMAT2X2:
4611         case VariableType::MAT2:
4612         case VariableType::MAT2X2:
4613         {
4614             result = tcu::UVec2(2, 2);
4615 
4616             break;
4617         }
4618 
4619         case VariableType::DMAT2X3:
4620         case VariableType::MAT2X3:
4621         {
4622             result = tcu::UVec2(2, 3);
4623 
4624             break;
4625         }
4626 
4627         case VariableType::DMAT2X4:
4628         case VariableType::MAT2X4:
4629         {
4630             result = tcu::UVec2(2, 4);
4631 
4632             break;
4633         }
4634 
4635         case VariableType::DMAT3:
4636         case VariableType::DMAT3X3:
4637         case VariableType::MAT3:
4638         case VariableType::MAT3X3:
4639         {
4640             result = tcu::UVec2(3, 3);
4641 
4642             break;
4643         }
4644 
4645         case VariableType::DMAT3X2:
4646         case VariableType::MAT3X2:
4647         {
4648             result = tcu::UVec2(3, 2);
4649 
4650             break;
4651         }
4652 
4653         case VariableType::DMAT3X4:
4654         case VariableType::MAT3X4:
4655         {
4656             result = tcu::UVec2(3, 4);
4657 
4658             break;
4659         }
4660 
4661         case VariableType::DMAT4:
4662         case VariableType::DMAT4X4:
4663         case VariableType::MAT4:
4664         case VariableType::MAT4X4:
4665         {
4666             result = tcu::UVec2(4, 4);
4667 
4668             break;
4669         }
4670 
4671         case VariableType::DMAT4X2:
4672         case VariableType::MAT4X2:
4673         {
4674             result = tcu::UVec2(4, 2);
4675 
4676             break;
4677         }
4678 
4679         case VariableType::DMAT4X3:
4680         case VariableType::MAT4X3:
4681         {
4682             result = tcu::UVec2(4, 3);
4683 
4684             break;
4685         }
4686 
4687         default:
4688         {
4689             DE_ASSERT(false);
4690 
4691             break;
4692         }
4693         }
4694 
4695         return result;
4696     }
4697 
getNComponents(const VariableType & type) const4698     uint32_t getNComponents(const VariableType &type) const
4699     {
4700         uint32_t result = 0;
4701 
4702         switch (type)
4703         {
4704         case VariableType::DOUBLE:
4705         case VariableType::FLOAT:
4706         case VariableType::INT8:
4707         case VariableType::INT16:
4708         case VariableType::INT64:
4709         case VariableType::INT:
4710         case VariableType::UINT:
4711         case VariableType::UINT8:
4712         case VariableType::UINT16:
4713         case VariableType::UINT64:
4714         {
4715             result = 1;
4716 
4717             break;
4718         }
4719 
4720         case VariableType::DVEC2:
4721         case VariableType::I8VEC2:
4722         case VariableType::I16VEC2:
4723         case VariableType::I64VEC2:
4724         case VariableType::IVEC2:
4725         case VariableType::U8VEC2:
4726         case VariableType::U16VEC2:
4727         case VariableType::U64VEC2:
4728         case VariableType::UVEC2:
4729         case VariableType::VEC2:
4730         {
4731             result = 2;
4732 
4733             break;
4734         }
4735 
4736         case VariableType::DVEC3:
4737         case VariableType::I8VEC3:
4738         case VariableType::I16VEC3:
4739         case VariableType::I64VEC3:
4740         case VariableType::IVEC3:
4741         case VariableType::U8VEC3:
4742         case VariableType::U16VEC3:
4743         case VariableType::U64VEC3:
4744         case VariableType::UVEC3:
4745         case VariableType::VEC3:
4746         {
4747             result = 3;
4748 
4749             break;
4750         }
4751 
4752         case VariableType::DMAT2:
4753         case VariableType::DMAT2X2:
4754         case VariableType::DVEC4:
4755         case VariableType::I8VEC4:
4756         case VariableType::I16VEC4:
4757         case VariableType::I64VEC4:
4758         case VariableType::IVEC4:
4759         case VariableType::MAT2:
4760         case VariableType::MAT2X2:
4761         case VariableType::U8VEC4:
4762         case VariableType::U16VEC4:
4763         case VariableType::U64VEC4:
4764         case VariableType::UVEC4:
4765         case VariableType::VEC4:
4766         {
4767             result = 4;
4768 
4769             break;
4770         }
4771 
4772         case VariableType::DMAT2X3:
4773         case VariableType::DMAT3X2:
4774         case VariableType::MAT2X3:
4775         case VariableType::MAT3X2:
4776         {
4777             result = 6;
4778 
4779             break;
4780         }
4781 
4782         case VariableType::DMAT2X4:
4783         case VariableType::DMAT4X2:
4784         case VariableType::MAT2X4:
4785         case VariableType::MAT4X2:
4786         {
4787             result = 8;
4788 
4789             break;
4790         }
4791 
4792         case VariableType::DMAT3:
4793         case VariableType::DMAT3X3:
4794         case VariableType::MAT3:
4795         case VariableType::MAT3X3:
4796         {
4797             result = 9;
4798 
4799             break;
4800         }
4801 
4802         case VariableType::DMAT3X4:
4803         case VariableType::DMAT4X3:
4804         case VariableType::MAT3X4:
4805         case VariableType::MAT4X3:
4806         {
4807             result = 12;
4808 
4809             break;
4810         }
4811 
4812         case VariableType::DMAT4:
4813         case VariableType::DMAT4X4:
4814         case VariableType::MAT4:
4815         case VariableType::MAT4X4:
4816         {
4817             result = 16;
4818 
4819             break;
4820         }
4821 
4822         default:
4823         {
4824             DE_ASSERT(false);
4825         }
4826         }
4827 
4828         return result;
4829     }
4830 
getNMatrixColumns(const VariableType & type) const4831     uint32_t getNMatrixColumns(const VariableType &type) const
4832     {
4833         uint32_t result = 0;
4834 
4835         switch (type)
4836         {
4837         case VariableType::DMAT2:
4838         case VariableType::DMAT2X2:
4839         case VariableType::DMAT2X3:
4840         case VariableType::DMAT2X4:
4841         case VariableType::MAT2:
4842         case VariableType::MAT2X2:
4843         case VariableType::MAT2X3:
4844         case VariableType::MAT2X4:
4845         {
4846             result = 2;
4847 
4848             break;
4849         }
4850 
4851         case VariableType::DMAT3:
4852         case VariableType::DMAT3X2:
4853         case VariableType::DMAT3X3:
4854         case VariableType::DMAT3X4:
4855         case VariableType::MAT3:
4856         case VariableType::MAT3X2:
4857         case VariableType::MAT3X4:
4858         case VariableType::MAT3X3:
4859         {
4860             result = 3;
4861 
4862             break;
4863         }
4864 
4865         case VariableType::DMAT4X2:
4866         case VariableType::MAT4X2:
4867         case VariableType::DMAT4X3:
4868         case VariableType::MAT4X3:
4869         case VariableType::DMAT4X4:
4870         case VariableType::DMAT4:
4871         case VariableType::MAT4X4:
4872         case VariableType::MAT4:
4873         {
4874             result = 4;
4875 
4876             break;
4877         }
4878 
4879         default:
4880         {
4881             DE_ASSERT(false);
4882         }
4883         }
4884 
4885         return result;
4886     }
4887 
getNMatrixRows(const VariableType & type) const4888     uint32_t getNMatrixRows(const VariableType &type) const
4889     {
4890         uint32_t result = 0;
4891 
4892         switch (type)
4893         {
4894         case VariableType::DMAT2:
4895         case VariableType::DMAT2X2:
4896         case VariableType::DMAT3X2:
4897         case VariableType::DMAT4X2:
4898         case VariableType::MAT2:
4899         case VariableType::MAT2X2:
4900         case VariableType::MAT3X2:
4901         case VariableType::MAT4X2:
4902         {
4903             result = 2;
4904 
4905             break;
4906         }
4907 
4908         case VariableType::DMAT2X3:
4909         case VariableType::DMAT3:
4910         case VariableType::DMAT3X3:
4911         case VariableType::DMAT4X3:
4912         case VariableType::MAT2X3:
4913         case VariableType::MAT3:
4914         case VariableType::MAT3X3:
4915         case VariableType::MAT4X3:
4916         {
4917             result = 3;
4918 
4919             break;
4920         }
4921 
4922         case VariableType::DMAT2X4:
4923         case VariableType::DMAT3X4:
4924         case VariableType::DMAT4:
4925         case VariableType::DMAT4X4:
4926         case VariableType::MAT2X4:
4927         case VariableType::MAT3X4:
4928         case VariableType::MAT4:
4929         case VariableType::MAT4X4:
4930         {
4931             result = 4;
4932 
4933             break;
4934         }
4935 
4936         default:
4937         {
4938             DE_ASSERT(false);
4939         }
4940         }
4941 
4942         return result;
4943     }
4944 
getVariableTypeGLSLType(const VariableType & type) const4945     const char *getVariableTypeGLSLType(const VariableType &type) const
4946     {
4947         const char *resultPtr = "!?";
4948 
4949         switch (type)
4950         {
4951         case VariableType::DOUBLE:
4952             resultPtr = "double";
4953             break;
4954         case VariableType::DMAT2:
4955             resultPtr = "dmat2";
4956             break;
4957         case VariableType::DMAT2X2:
4958             resultPtr = "dmat2x2";
4959             break;
4960         case VariableType::DMAT2X3:
4961             resultPtr = "dmat2x3";
4962             break;
4963         case VariableType::DMAT2X4:
4964             resultPtr = "dmat2x4";
4965             break;
4966         case VariableType::DMAT3:
4967             resultPtr = "dmat3";
4968             break;
4969         case VariableType::DMAT3X2:
4970             resultPtr = "dmat3x2";
4971             break;
4972         case VariableType::DMAT3X3:
4973             resultPtr = "dmat3x3";
4974             break;
4975         case VariableType::DMAT3X4:
4976             resultPtr = "dmat3x4";
4977             break;
4978         case VariableType::DMAT4:
4979             resultPtr = "dmat4";
4980             break;
4981         case VariableType::DMAT4X2:
4982             resultPtr = "dmat4x2";
4983             break;
4984         case VariableType::DMAT4X3:
4985             resultPtr = "dmat4x3";
4986             break;
4987         case VariableType::DMAT4X4:
4988             resultPtr = "dmat4x4";
4989             break;
4990         case VariableType::DVEC2:
4991             resultPtr = "dvec2";
4992             break;
4993         case VariableType::DVEC3:
4994             resultPtr = "dvec3";
4995             break;
4996         case VariableType::DVEC4:
4997             resultPtr = "dvec4";
4998             break;
4999         case VariableType::FLOAT:
5000             resultPtr = "float";
5001             break;
5002         case VariableType::INT16:
5003             resultPtr = "int16_t";
5004             break;
5005         case VariableType::INT64:
5006             resultPtr = "int64_t";
5007             break;
5008         case VariableType::INT8:
5009             resultPtr = "int8_t";
5010             break;
5011         case VariableType::INT:
5012             resultPtr = "int";
5013             break;
5014         case VariableType::I16VEC2:
5015             resultPtr = "i16vec2";
5016             break;
5017         case VariableType::I16VEC3:
5018             resultPtr = "i16vec3";
5019             break;
5020         case VariableType::I16VEC4:
5021             resultPtr = "i16vec4";
5022             break;
5023         case VariableType::I64VEC2:
5024             resultPtr = "i64vec2";
5025             break;
5026         case VariableType::I64VEC3:
5027             resultPtr = "i64vec3";
5028             break;
5029         case VariableType::I64VEC4:
5030             resultPtr = "i64vec4";
5031             break;
5032         case VariableType::I8VEC2:
5033             resultPtr = "i8vec2";
5034             break;
5035         case VariableType::I8VEC3:
5036             resultPtr = "i8vec3";
5037             break;
5038         case VariableType::I8VEC4:
5039             resultPtr = "i8vec4";
5040             break;
5041         case VariableType::IVEC2:
5042             resultPtr = "ivec2";
5043             break;
5044         case VariableType::IVEC3:
5045             resultPtr = "ivec3";
5046             break;
5047         case VariableType::IVEC4:
5048             resultPtr = "ivec4";
5049             break;
5050         case VariableType::MAT2:
5051             resultPtr = "mat2";
5052             break;
5053         case VariableType::MAT2X2:
5054             resultPtr = "mat2x2";
5055             break;
5056         case VariableType::MAT2X3:
5057             resultPtr = "mat2x3";
5058             break;
5059         case VariableType::MAT2X4:
5060             resultPtr = "mat2x4";
5061             break;
5062         case VariableType::MAT3:
5063             resultPtr = "mat3";
5064             break;
5065         case VariableType::MAT3X2:
5066             resultPtr = "mat3x2";
5067             break;
5068         case VariableType::MAT3X3:
5069             resultPtr = "mat3x3";
5070             break;
5071         case VariableType::MAT3X4:
5072             resultPtr = "mat3x4";
5073             break;
5074         case VariableType::MAT4:
5075             resultPtr = "mat4";
5076             break;
5077         case VariableType::MAT4X2:
5078             resultPtr = "mat4x2";
5079             break;
5080         case VariableType::MAT4X3:
5081             resultPtr = "mat4x3";
5082             break;
5083         case VariableType::MAT4X4:
5084             resultPtr = "mat4x4";
5085             break;
5086         case VariableType::UINT16:
5087             resultPtr = "uint16_t";
5088             break;
5089         case VariableType::UINT64:
5090             resultPtr = "uint64_t";
5091             break;
5092         case VariableType::UINT8:
5093             resultPtr = "uint8_t";
5094             break;
5095         case VariableType::UINT:
5096             resultPtr = "uint";
5097             break;
5098         case VariableType::U16VEC2:
5099             resultPtr = "u16vec2";
5100             break;
5101         case VariableType::U16VEC3:
5102             resultPtr = "u16vec3";
5103             break;
5104         case VariableType::U16VEC4:
5105             resultPtr = "u16vec4";
5106             break;
5107         case VariableType::U64VEC2:
5108             resultPtr = "u64vec2";
5109             break;
5110         case VariableType::U64VEC3:
5111             resultPtr = "u64vec3";
5112             break;
5113         case VariableType::U64VEC4:
5114             resultPtr = "u64vec4";
5115             break;
5116         case VariableType::U8VEC2:
5117             resultPtr = "u8vec2";
5118             break;
5119         case VariableType::U8VEC3:
5120             resultPtr = "u8vec3";
5121             break;
5122         case VariableType::U8VEC4:
5123             resultPtr = "u8vec4";
5124             break;
5125         case VariableType::UVEC2:
5126             resultPtr = "uvec2";
5127             break;
5128         case VariableType::UVEC3:
5129             resultPtr = "uvec3";
5130             break;
5131         case VariableType::UVEC4:
5132             resultPtr = "uvec4";
5133             break;
5134         case VariableType::VEC2:
5135             resultPtr = "vec2";
5136             break;
5137         case VariableType::VEC3:
5138             resultPtr = "vec3";
5139             break;
5140         case VariableType::VEC4:
5141             resultPtr = "vec4";
5142             break;
5143 
5144         default:
5145         {
5146             DE_ASSERT(false);
5147         }
5148         }
5149 
5150         return resultPtr;
5151     }
5152 
initTestItems()5153     void initTestItems()
5154     {
5155         de::Random randomNumberGenerator(13567);
5156         const uint32_t testArraySizes[] = {3, 7, 5};
5157 
5158         const ShaderGroups shaderGroups[] = {
5159             ShaderGroups::HIT_GROUP,
5160             ShaderGroups::MISS_GROUP,
5161         };
5162 
5163         const auto nTestArraySizes = sizeof(testArraySizes) / sizeof(testArraySizes[0]);
5164 
5165         for (const auto &currentVariableType : m_varTypesToTest)
5166         {
5167             const auto currentArraySize =
5168                 testArraySizes[static_cast<uint32_t>(m_testItems.items.size()) % nTestArraySizes];
5169             Item newItem;
5170 
5171             newItem.arraySize = currentArraySize;
5172             newItem.name      = "var" + de::toString(m_testItems.items.size());
5173             newItem.type      = currentVariableType;
5174 
5175             // TODO: glslang issue.
5176             // newItem.matrixOrder = static_cast<MatrixMajorOrder>(static_cast<uint32_t>(m_testItems.items.size() ) % static_cast<uint32_t>(MatrixMajorOrder::UNKNOWN) );
5177 
5178             newItem.matrixOrder = MatrixMajorOrder::COLUMN_MAJOR;
5179 
5180             m_testItems.items.push_back(newItem);
5181         }
5182 
5183         // Determine start offsets for matrix elements.
5184         //
5185         // Note: result buffer aways uses std430 layout.
5186         setSTD430MatrixElementOffsets(m_testItems, false /* updateInputBufferProps */);
5187         setSTD430ArrayStrides(m_testItems, false /* updateInputBufferProps */);
5188         setSTD430BufferOffsets(m_testItems, false /* updateInputBufferProps */);
5189 
5190         switch (m_testType)
5191         {
5192         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1:
5193         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2:
5194         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3:
5195         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4:
5196         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5:
5197         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6:
5198         {
5199             setExplicitScalarOffsetMatrixElementOffsets(m_testItems, true /* updateInputBufferProps */);
5200 
5201             break;
5202         }
5203 
5204         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1:
5205         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2:
5206         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3:
5207         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4:
5208         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5:
5209         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6:
5210         {
5211             setExplicitSTD430OffsetMatrixElementOffsets(m_testItems, true /* updateInputBufferProps */);
5212 
5213             break;
5214         }
5215 
5216         case TestType::SHADER_RECORD_BLOCK_SCALAR_1:
5217         case TestType::SHADER_RECORD_BLOCK_SCALAR_2:
5218         case TestType::SHADER_RECORD_BLOCK_SCALAR_3:
5219         case TestType::SHADER_RECORD_BLOCK_SCALAR_4:
5220         case TestType::SHADER_RECORD_BLOCK_SCALAR_5:
5221         case TestType::SHADER_RECORD_BLOCK_SCALAR_6:
5222         {
5223             setScalarMatrixElementOffsets(m_testItems, true /* updateInputBufferProps */);
5224 
5225             break;
5226         }
5227 
5228         case TestType::SHADER_RECORD_BLOCK_STD430_1:
5229         case TestType::SHADER_RECORD_BLOCK_STD430_2:
5230         case TestType::SHADER_RECORD_BLOCK_STD430_3:
5231         case TestType::SHADER_RECORD_BLOCK_STD430_4:
5232         case TestType::SHADER_RECORD_BLOCK_STD430_5:
5233         case TestType::SHADER_RECORD_BLOCK_STD430_6:
5234         {
5235             setSTD430MatrixElementOffsets(m_testItems, true /* updateInputBufferProps */);
5236 
5237             break;
5238         }
5239 
5240         default:
5241         {
5242             DE_ASSERT(false);
5243         }
5244         }
5245 
5246         // Configure array strides for the variables.
5247         switch (m_testType)
5248         {
5249         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1:
5250         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2:
5251         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3:
5252         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4:
5253         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5:
5254         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6:
5255         {
5256             setExplicitScalarOffsetArrayStrides(m_testItems, true /* updateInputBufferProps */);
5257 
5258             break;
5259         }
5260 
5261         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1:
5262         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2:
5263         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3:
5264         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4:
5265         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5:
5266         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6:
5267         {
5268             setExplicitSTD430OffsetArrayStrides(m_testItems, true /* updateInputBufferProps */);
5269 
5270             break;
5271         }
5272 
5273         case TestType::SHADER_RECORD_BLOCK_SCALAR_1:
5274         case TestType::SHADER_RECORD_BLOCK_SCALAR_2:
5275         case TestType::SHADER_RECORD_BLOCK_SCALAR_3:
5276         case TestType::SHADER_RECORD_BLOCK_SCALAR_4:
5277         case TestType::SHADER_RECORD_BLOCK_SCALAR_5:
5278         case TestType::SHADER_RECORD_BLOCK_SCALAR_6:
5279         {
5280             setScalarArrayStrides(m_testItems, true /* updateInputBufferProps */);
5281 
5282             break;
5283         }
5284 
5285         case TestType::SHADER_RECORD_BLOCK_STD430_1:
5286         case TestType::SHADER_RECORD_BLOCK_STD430_2:
5287         case TestType::SHADER_RECORD_BLOCK_STD430_3:
5288         case TestType::SHADER_RECORD_BLOCK_STD430_4:
5289         case TestType::SHADER_RECORD_BLOCK_STD430_5:
5290         case TestType::SHADER_RECORD_BLOCK_STD430_6:
5291         {
5292             setSTD430ArrayStrides(m_testItems, true /* updateInputBufferProps */);
5293 
5294             break;
5295         }
5296 
5297         default:
5298         {
5299             DE_ASSERT(false);
5300         }
5301         }
5302 
5303         // Configure buffer offsets for the variables.
5304         switch (m_testType)
5305         {
5306         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1:
5307         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2:
5308         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3:
5309         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4:
5310         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5:
5311         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6:
5312         {
5313             setExplicitScalarOffsetBufferOffsets(m_testItems, true /* updateInputBufferProps */);
5314 
5315             break;
5316         }
5317 
5318         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1:
5319         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2:
5320         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3:
5321         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4:
5322         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5:
5323         case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6:
5324         {
5325             setExplicitSTD430OffsetBufferOffsets(m_testItems, true /* updateInputBufferProps */);
5326 
5327             break;
5328         }
5329 
5330         case TestType::SHADER_RECORD_BLOCK_SCALAR_1:
5331         case TestType::SHADER_RECORD_BLOCK_SCALAR_2:
5332         case TestType::SHADER_RECORD_BLOCK_SCALAR_3:
5333         case TestType::SHADER_RECORD_BLOCK_SCALAR_4:
5334         case TestType::SHADER_RECORD_BLOCK_SCALAR_5:
5335         case TestType::SHADER_RECORD_BLOCK_SCALAR_6:
5336         {
5337             setScalarBufferOffsets(m_testItems, true /* updateInputBufferProps */);
5338 
5339             break;
5340         }
5341 
5342         case TestType::SHADER_RECORD_BLOCK_STD430_1:
5343         case TestType::SHADER_RECORD_BLOCK_STD430_2:
5344         case TestType::SHADER_RECORD_BLOCK_STD430_3:
5345         case TestType::SHADER_RECORD_BLOCK_STD430_4:
5346         case TestType::SHADER_RECORD_BLOCK_STD430_5:
5347         case TestType::SHADER_RECORD_BLOCK_STD430_6:
5348         {
5349             setSTD430BufferOffsets(m_testItems, true /* updateInputBufferProps */);
5350 
5351             break;
5352         }
5353 
5354         default:
5355         {
5356             DE_ASSERT(false);
5357         }
5358         }
5359 
5360         // Bake data to be used in the tested buffer.
5361         for (auto &currentTestItem : m_testItems.items)
5362         {
5363             const auto baseType           = getBaseType(currentTestItem.type);
5364             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5365             const bool isMatrixType       = isMatrix(currentTestItem.type);
5366             const auto nComponents        = getNComponents(currentTestItem.type);
5367             const auto nBytesNeeded       = currentTestItem.arraySize * currentTestItem.inputBufferProps.arrayStride;
5368 
5369             for (const auto &currentShaderGroup : shaderGroups)
5370             {
5371                 auto &currentDataVec = currentTestItem.shaderGroupToRecordDataMap[currentShaderGroup];
5372 
5373                 currentDataVec.resize(nBytesNeeded);
5374 
5375                 for (uint32_t nArrayItem = 0; nArrayItem < currentTestItem.arraySize; ++nArrayItem)
5376                 {
5377                     uint8_t *currentItemDataPtr =
5378                         currentDataVec.data() + nArrayItem * currentTestItem.inputBufferProps.arrayStride;
5379 
5380                     for (uint32_t nComponent = 0; nComponent < nComponents; ++nComponent)
5381                     {
5382                         switch (baseType)
5383                         {
5384                         case BaseType::F32:
5385                         {
5386                             DE_ASSERT(currentItemDataPtr + sizeof(float) <=
5387                                       currentDataVec.data() + currentDataVec.size());
5388 
5389                             *reinterpret_cast<float *>(currentItemDataPtr) = randomNumberGenerator.getFloat();
5390 
5391                             break;
5392                         }
5393 
5394                         case BaseType::F64:
5395                         {
5396                             DE_ASSERT(currentItemDataPtr + sizeof(double) <=
5397                                       currentDataVec.data() + currentDataVec.size());
5398 
5399                             *reinterpret_cast<double *>(currentItemDataPtr) = randomNumberGenerator.getDouble();
5400 
5401                             break;
5402                         }
5403 
5404                         case BaseType::I8:
5405                         {
5406                             DE_ASSERT(currentItemDataPtr + sizeof(int8_t) <=
5407                                       currentDataVec.data() + currentDataVec.size());
5408 
5409                             *reinterpret_cast<int8_t *>(currentItemDataPtr) =
5410                                 static_cast<int8_t>(randomNumberGenerator.getInt(-128, 127));
5411 
5412                             break;
5413                         }
5414 
5415                         case BaseType::I16:
5416                         {
5417                             DE_ASSERT(currentItemDataPtr + sizeof(int16_t) <=
5418                                       currentDataVec.data() + currentDataVec.size());
5419 
5420                             *reinterpret_cast<int16_t *>(currentItemDataPtr) =
5421                                 static_cast<int16_t>(randomNumberGenerator.getInt(-32768, 32767));
5422 
5423                             break;
5424                         }
5425 
5426                         case BaseType::I32:
5427                         {
5428                             DE_ASSERT(currentItemDataPtr + sizeof(int32_t) <=
5429                                       currentDataVec.data() + currentDataVec.size());
5430 
5431                             *reinterpret_cast<int32_t *>(currentItemDataPtr) = randomNumberGenerator.getInt(
5432                                 static_cast<int>(-2147483648LL), static_cast<int>(2147483647LL));
5433 
5434                             break;
5435                         }
5436 
5437                         case BaseType::I64:
5438                         {
5439                             DE_ASSERT(currentItemDataPtr + sizeof(int64_t) <=
5440                                       currentDataVec.data() + currentDataVec.size());
5441 
5442                             *reinterpret_cast<int64_t *>(currentItemDataPtr) = randomNumberGenerator.getInt64();
5443 
5444                             break;
5445                         }
5446 
5447                         case BaseType::U8:
5448                         {
5449                             DE_ASSERT(currentItemDataPtr + sizeof(uint8_t) <=
5450                                       currentDataVec.data() + currentDataVec.size());
5451 
5452                             *reinterpret_cast<uint8_t *>(currentItemDataPtr) = randomNumberGenerator.getUint8();
5453 
5454                             break;
5455                         }
5456 
5457                         case BaseType::U16:
5458                         {
5459                             DE_ASSERT(currentItemDataPtr + sizeof(uint16_t) <=
5460                                       currentDataVec.data() + currentDataVec.size());
5461 
5462                             *reinterpret_cast<uint16_t *>(currentItemDataPtr) = randomNumberGenerator.getUint16();
5463 
5464                             break;
5465                         }
5466 
5467                         case BaseType::U32:
5468                         {
5469                             DE_ASSERT(currentItemDataPtr + sizeof(uint32_t) <=
5470                                       currentDataVec.data() + currentDataVec.size());
5471 
5472                             *reinterpret_cast<uint32_t *>(currentItemDataPtr) = randomNumberGenerator.getUint32();
5473 
5474                             break;
5475                         }
5476 
5477                         case BaseType::U64:
5478                         {
5479                             DE_ASSERT(currentItemDataPtr + sizeof(uint64_t) <=
5480                                       currentDataVec.data() + currentDataVec.size());
5481 
5482                             *reinterpret_cast<uint64_t *>(currentItemDataPtr) = randomNumberGenerator.getUint64();
5483 
5484                             break;
5485                         }
5486 
5487                         default:
5488                         {
5489                             DE_ASSERT(false);
5490                         }
5491                         }
5492 
5493                         if (isMatrixType)
5494                         {
5495                             if (nComponent != (nComponents - 1))
5496                             {
5497                                 const auto delta =
5498                                     currentTestItem.inputBufferProps.matrixElementStartOffsets.at(nComponent + 1) -
5499                                     currentTestItem.inputBufferProps.matrixElementStartOffsets.at(nComponent + 0);
5500 
5501                                 DE_ASSERT(delta >= componentSizeBytes);
5502 
5503                                 currentItemDataPtr += delta;
5504                             }
5505                         }
5506                         else
5507                         {
5508                             currentItemDataPtr += componentSizeBytes;
5509                         }
5510                     }
5511                 }
5512             }
5513         }
5514 
5515         // Merge individual member data into coalesced buffers.
5516         for (const auto &currentShaderGroup : shaderGroups)
5517         {
5518             auto &resultVec = m_shaderGroupToRecordDataMap[currentShaderGroup];
5519 
5520             {
5521                 const auto &lastItem = m_testItems.items.back();
5522 
5523                 resultVec.resize(lastItem.inputBufferProps.bufferOffset +
5524                                  lastItem.shaderGroupToRecordDataMap.at(currentShaderGroup).size());
5525             }
5526 
5527             for (const auto &currentVariable : m_testItems.items)
5528             {
5529                 const auto &currentVariableDataVec = currentVariable.shaderGroupToRecordDataMap.at(currentShaderGroup);
5530 
5531                 DE_ASSERT(resultVec.size() >=
5532                           currentVariable.inputBufferProps.bufferOffset + currentVariableDataVec.size());
5533 
5534                 memcpy(resultVec.data() + currentVariable.inputBufferProps.bufferOffset, currentVariableDataVec.data(),
5535                        currentVariableDataVec.size());
5536             }
5537         }
5538     }
5539 
isMatrix(const VariableType & type) const5540     bool isMatrix(const VariableType &type) const
5541     {
5542         bool result = false;
5543 
5544         switch (type)
5545         {
5546         case VariableType::DMAT2:
5547         case VariableType::DMAT2X2:
5548         case VariableType::DMAT2X3:
5549         case VariableType::DMAT2X4:
5550         case VariableType::DMAT3:
5551         case VariableType::DMAT3X2:
5552         case VariableType::DMAT3X3:
5553         case VariableType::DMAT3X4:
5554         case VariableType::DMAT4:
5555         case VariableType::DMAT4X2:
5556         case VariableType::DMAT4X3:
5557         case VariableType::DMAT4X4:
5558         case VariableType::MAT2:
5559         case VariableType::MAT2X2:
5560         case VariableType::MAT2X3:
5561         case VariableType::MAT2X4:
5562         case VariableType::MAT3:
5563         case VariableType::MAT3X2:
5564         case VariableType::MAT3X3:
5565         case VariableType::MAT3X4:
5566         case VariableType::MAT4:
5567         case VariableType::MAT4X2:
5568         case VariableType::MAT4X3:
5569         case VariableType::MAT4X4:
5570         {
5571             result = true;
5572 
5573             break;
5574         }
5575 
5576         case VariableType::DOUBLE:
5577         case VariableType::DVEC2:
5578         case VariableType::DVEC3:
5579         case VariableType::DVEC4:
5580         case VariableType::FLOAT:
5581         case VariableType::INT8:
5582         case VariableType::INT64:
5583         case VariableType::INT16:
5584         case VariableType::INT:
5585         case VariableType::I16VEC2:
5586         case VariableType::I16VEC3:
5587         case VariableType::I16VEC4:
5588         case VariableType::I64VEC2:
5589         case VariableType::I64VEC3:
5590         case VariableType::I64VEC4:
5591         case VariableType::I8VEC2:
5592         case VariableType::I8VEC3:
5593         case VariableType::I8VEC4:
5594         case VariableType::IVEC2:
5595         case VariableType::IVEC3:
5596         case VariableType::IVEC4:
5597         case VariableType::UINT8:
5598         case VariableType::UINT64:
5599         case VariableType::UINT16:
5600         case VariableType::UINT:
5601         case VariableType::U16VEC2:
5602         case VariableType::U16VEC3:
5603         case VariableType::U16VEC4:
5604         case VariableType::U64VEC2:
5605         case VariableType::U64VEC3:
5606         case VariableType::U64VEC4:
5607         case VariableType::U8VEC2:
5608         case VariableType::U8VEC3:
5609         case VariableType::U8VEC4:
5610         case VariableType::UVEC2:
5611         case VariableType::UVEC3:
5612         case VariableType::UVEC4:
5613         case VariableType::VEC2:
5614         case VariableType::VEC3:
5615         case VariableType::VEC4:
5616         {
5617             result = false;
5618 
5619             break;
5620         }
5621 
5622         default:
5623         {
5624             DE_ASSERT(false);
5625         }
5626         }
5627 
5628         return result;
5629     }
5630 
setExplicitScalarOffsetArrayStrides(StructItem & inputStruct,const bool & updateInputBufferProps)5631     void setExplicitScalarOffsetArrayStrides(StructItem &inputStruct, const bool &updateInputBufferProps)
5632     {
5633         return setScalarArrayStrides(inputStruct, updateInputBufferProps);
5634     }
5635 
setExplicitScalarOffsetBufferOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5636     void setExplicitScalarOffsetBufferOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5637     {
5638         uint32_t nBytesConsumed = 0;
5639 
5640         for (auto &currentItem : inputStruct.items)
5641         {
5642             const auto baseType = getBaseType(currentItem.type);
5643             auto &bufferProps = (updateInputBufferProps) ? currentItem.inputBufferProps : currentItem.resultBufferProps;
5644             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5645             const auto isMatrixVariable   = isMatrix(currentItem.type);
5646             const auto nComponents        = getNComponents(currentItem.type);
5647 
5648             bufferProps.bufferOffset = de::roundUp(nBytesConsumed, componentSizeBytes * 2);
5649 
5650             if (isMatrixVariable)
5651             {
5652                 nBytesConsumed = bufferProps.bufferOffset + currentItem.arraySize * bufferProps.arrayStride;
5653             }
5654             else
5655             {
5656                 nBytesConsumed = bufferProps.bufferOffset + currentItem.arraySize * componentSizeBytes * nComponents;
5657             }
5658         }
5659     }
5660 
setExplicitScalarOffsetElementOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5661     void setExplicitScalarOffsetElementOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5662     {
5663         return setScalarMatrixElementOffsets(inputStruct, updateInputBufferProps);
5664     }
5665 
setExplicitScalarOffsetMatrixElementOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5666     void setExplicitScalarOffsetMatrixElementOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5667     {
5668         return setScalarMatrixElementOffsets(inputStruct, updateInputBufferProps);
5669     }
5670 
setExplicitSTD430OffsetArrayStrides(StructItem & inputStruct,const bool & updateInputBufferProps)5671     void setExplicitSTD430OffsetArrayStrides(StructItem &inputStruct, const bool &updateInputBufferProps)
5672     {
5673         return setSTD430ArrayStrides(inputStruct, updateInputBufferProps);
5674     }
5675 
setExplicitSTD430OffsetBufferOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5676     void setExplicitSTD430OffsetBufferOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5677     {
5678         uint32_t nBytesConsumed = 0;
5679 
5680         for (auto &currentItem : inputStruct.items)
5681         {
5682             const auto baseType = getBaseType(currentItem.type);
5683             auto &bufferProps = (updateInputBufferProps) ? currentItem.inputBufferProps : currentItem.resultBufferProps;
5684             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5685             const auto isMatrixVariable   = isMatrix(currentItem.type);
5686             const auto nComponents        = getNComponents(currentItem.type);
5687             uint32_t requiredAlignment    = 0;
5688 
5689             uint32_t nMatrixRows = 0;
5690 
5691             if (isMatrixVariable)
5692             {
5693                 nMatrixRows = getNMatrixRows(currentItem.type);
5694 
5695                 if (nMatrixRows == 3)
5696                 {
5697                     nMatrixRows = 4;
5698                 }
5699 
5700                 requiredAlignment = nMatrixRows * componentSizeBytes;
5701             }
5702             else if (nComponents == 1)
5703             {
5704                 DE_ASSERT((baseType == BaseType::F32) || (baseType == BaseType::F64) || (baseType == BaseType::I16) ||
5705                           (baseType == BaseType::I32) || (baseType == BaseType::I64) || (baseType == BaseType::I8) ||
5706                           (baseType == BaseType::U16) || (baseType == BaseType::U32) || (baseType == BaseType::U64) ||
5707                           (baseType == BaseType::U8));
5708 
5709                 requiredAlignment = componentSizeBytes;
5710             }
5711             else if (nComponents == 2)
5712             {
5713                 requiredAlignment = 2 * componentSizeBytes;
5714             }
5715             else
5716             {
5717                 requiredAlignment = 4 * componentSizeBytes;
5718             }
5719 
5720             bufferProps.bufferOffset = de::roundUp(nBytesConsumed, requiredAlignment * 2);
5721 
5722             if (isMatrixVariable)
5723             {
5724                 nBytesConsumed = bufferProps.bufferOffset + currentItem.arraySize * bufferProps.arrayStride;
5725             }
5726             else
5727             {
5728                 nBytesConsumed = bufferProps.bufferOffset +
5729                                  currentItem.arraySize * componentSizeBytes * ((nComponents == 3) ? 4 : nComponents);
5730             }
5731         }
5732     }
5733 
setExplicitSTD430OffsetElementOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5734     void setExplicitSTD430OffsetElementOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5735     {
5736         return setSTD430MatrixElementOffsets(inputStruct, updateInputBufferProps);
5737     }
5738 
setExplicitSTD430OffsetMatrixElementOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5739     void setExplicitSTD430OffsetMatrixElementOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5740     {
5741         return setSTD430MatrixElementOffsets(inputStruct, updateInputBufferProps);
5742     }
5743 
setSTD430ArrayStrides(StructItem & inputStruct,const bool & updateInputBufferProps)5744     void setSTD430ArrayStrides(StructItem &inputStruct, const bool &updateInputBufferProps)
5745     {
5746         for (auto &currentItem : inputStruct.items)
5747         {
5748             const auto baseType = getBaseType(currentItem.type);
5749             auto &bufferProps = (updateInputBufferProps) ? currentItem.inputBufferProps : currentItem.resultBufferProps;
5750             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5751             const auto isMatrixVariable   = isMatrix(currentItem.type);
5752             const auto nComponents        = getNComponents(currentItem.type);
5753             uint32_t requiredStride       = 0;
5754 
5755             if (isMatrixVariable)
5756             {
5757                 auto nMatrixColumns = getNMatrixColumns(currentItem.type);
5758                 auto nMatrixRows    = getNMatrixRows(currentItem.type);
5759 
5760                 if (nMatrixRows == 3)
5761                 {
5762                     nMatrixRows = 4;
5763                 }
5764 
5765                 requiredStride = nMatrixRows * nMatrixColumns * componentSizeBytes;
5766             }
5767             else
5768             {
5769                 requiredStride = componentSizeBytes * ((nComponents == 3) ? 4 : nComponents);
5770             }
5771 
5772             bufferProps.arrayStride = requiredStride;
5773         }
5774     }
5775 
setSTD430BufferOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5776     void setSTD430BufferOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5777     {
5778         uint32_t nBytesConsumed = 0;
5779 
5780         for (auto &currentItem : inputStruct.items)
5781         {
5782             const auto baseType = getBaseType(currentItem.type);
5783             auto &bufferProps = (updateInputBufferProps) ? currentItem.inputBufferProps : currentItem.resultBufferProps;
5784             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5785             const auto isMatrixVariable   = isMatrix(currentItem.type);
5786             const auto nComponents        = getNComponents(currentItem.type);
5787             uint32_t requiredAlignment    = 0;
5788 
5789             uint32_t nMatrixRows = 0;
5790 
5791             if (isMatrixVariable)
5792             {
5793                 nMatrixRows = getNMatrixRows(currentItem.type);
5794 
5795                 if (nMatrixRows == 3)
5796                 {
5797                     nMatrixRows = 4;
5798                 }
5799 
5800                 requiredAlignment = nMatrixRows * componentSizeBytes;
5801             }
5802             else if (nComponents == 1)
5803             {
5804                 DE_ASSERT((baseType == BaseType::F32) || (baseType == BaseType::F64) || (baseType == BaseType::I16) ||
5805                           (baseType == BaseType::I32) || (baseType == BaseType::I64) || (baseType == BaseType::I8) ||
5806                           (baseType == BaseType::U16) || (baseType == BaseType::U32) || (baseType == BaseType::U64) ||
5807                           (baseType == BaseType::U8));
5808 
5809                 requiredAlignment = componentSizeBytes;
5810             }
5811             else if (nComponents == 2)
5812             {
5813                 requiredAlignment = 2 * componentSizeBytes;
5814             }
5815             else
5816             {
5817                 requiredAlignment = 4 * componentSizeBytes;
5818             }
5819 
5820             bufferProps.bufferOffset = de::roundUp(nBytesConsumed, requiredAlignment);
5821 
5822             if (isMatrixVariable)
5823             {
5824                 nBytesConsumed = bufferProps.bufferOffset + currentItem.arraySize * bufferProps.arrayStride;
5825             }
5826             else
5827             {
5828                 nBytesConsumed = bufferProps.bufferOffset +
5829                                  currentItem.arraySize * componentSizeBytes * ((nComponents == 3) ? 4 : nComponents);
5830             }
5831         }
5832     }
5833 
setScalarArrayStrides(StructItem & inputStruct,const bool & updateInputBufferProps)5834     void setScalarArrayStrides(StructItem &inputStruct, const bool &updateInputBufferProps)
5835     {
5836         for (auto &currentItem : inputStruct.items)
5837         {
5838             const auto baseType = getBaseType(currentItem.type);
5839             auto &bufferProps = (updateInputBufferProps) ? currentItem.inputBufferProps : currentItem.resultBufferProps;
5840             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5841             const auto isMatrixVariable   = isMatrix(currentItem.type);
5842             const auto nComponents        = getNComponents(currentItem.type);
5843 
5844             if (isMatrixVariable)
5845             {
5846                 auto nMatrixColumns = getNMatrixColumns(currentItem.type);
5847                 auto nMatrixRows    = getNMatrixRows(currentItem.type);
5848 
5849                 bufferProps.arrayStride = nMatrixRows * nMatrixColumns * componentSizeBytes;
5850             }
5851             else
5852             {
5853                 bufferProps.arrayStride = componentSizeBytes * nComponents;
5854             }
5855         }
5856     }
5857 
setScalarBufferOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5858     void setScalarBufferOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5859     {
5860         uint32_t nBytesConsumed = 0;
5861 
5862         for (auto &currentItem : inputStruct.items)
5863         {
5864             const auto baseType = getBaseType(currentItem.type);
5865             auto &bufferProps = (updateInputBufferProps) ? currentItem.inputBufferProps : currentItem.resultBufferProps;
5866             const auto componentSizeBytes = getComponentSizeBytes(baseType);
5867             const auto isMatrixVariable   = isMatrix(currentItem.type);
5868             const auto nComponents        = getNComponents(currentItem.type);
5869 
5870             bufferProps.bufferOffset = de::roundUp(nBytesConsumed, componentSizeBytes);
5871 
5872             if (isMatrixVariable)
5873             {
5874                 nBytesConsumed = bufferProps.bufferOffset + currentItem.arraySize * bufferProps.arrayStride;
5875             }
5876             else
5877             {
5878                 nBytesConsumed = bufferProps.bufferOffset + currentItem.arraySize * componentSizeBytes * nComponents;
5879             }
5880         }
5881     }
5882 
setScalarMatrixElementOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5883     void setScalarMatrixElementOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5884     {
5885         for (auto &currentVariable : inputStruct.items)
5886         {
5887             if (isMatrix(currentVariable.type))
5888             {
5889                 auto &bufferProps =
5890                     (updateInputBufferProps) ? currentVariable.inputBufferProps : currentVariable.resultBufferProps;
5891                 const auto componentSizeBytes       = getComponentSizeBytes(getBaseType(currentVariable.type));
5892                 uint32_t currentMatrixElementOffset = 0;
5893                 const auto nMatrixColumns           = getNMatrixColumns(currentVariable.type);
5894                 const auto nMatrixRows              = getNMatrixRows(currentVariable.type);
5895 
5896                 for (uint32_t nMatrixColumn = 0; nMatrixColumn < nMatrixColumns; ++nMatrixColumn)
5897                 {
5898                     currentMatrixElementOffset =
5899                         de::roundUp(nMatrixRows * componentSizeBytes * nMatrixColumn, componentSizeBytes);
5900 
5901                     for (uint32_t nMatrixRow = 0; nMatrixRow < nMatrixRows; ++nMatrixRow)
5902                     {
5903                         bufferProps.matrixElementStartOffsets.push_back(currentMatrixElementOffset);
5904 
5905                         currentMatrixElementOffset += componentSizeBytes;
5906                     }
5907                 }
5908             }
5909         }
5910     }
5911 
setSTD430MatrixElementOffsets(StructItem & inputStruct,const bool & updateInputBufferProps)5912     void setSTD430MatrixElementOffsets(StructItem &inputStruct, const bool &updateInputBufferProps)
5913     {
5914         for (auto &currentVariable : inputStruct.items)
5915         {
5916             if (isMatrix(currentVariable.type))
5917             {
5918                 auto &bufferProps =
5919                     (updateInputBufferProps) ? currentVariable.inputBufferProps : currentVariable.resultBufferProps;
5920                 const auto componentSizeBytes       = getComponentSizeBytes(getBaseType(currentVariable.type));
5921                 uint32_t currentMatrixElementOffset = 0;
5922                 auto nMatrixColumns                 = getNMatrixColumns(currentVariable.type);
5923                 auto nMatrixRows                    = getNMatrixRows(currentVariable.type);
5924 
5925                 if (currentVariable.matrixOrder == MatrixMajorOrder::COLUMN_MAJOR)
5926                 {
5927                     for (uint32_t nMatrixColumn = 0; nMatrixColumn < nMatrixColumns; ++nMatrixColumn)
5928                     {
5929                         currentMatrixElementOffset = de::roundUp(
5930                             static_cast<uint32_t>(nMatrixRows * componentSizeBytes * nMatrixColumn),
5931                             static_cast<uint32_t>(((nMatrixRows == 3) ? 4 : nMatrixRows) * componentSizeBytes));
5932 
5933                         for (uint32_t nMatrixRow = 0; nMatrixRow < nMatrixRows; ++nMatrixRow)
5934                         {
5935                             bufferProps.matrixElementStartOffsets.push_back(currentMatrixElementOffset);
5936 
5937                             currentMatrixElementOffset += componentSizeBytes;
5938                         }
5939                     }
5940                 }
5941                 else
5942                 {
5943                     // TODO
5944                     DE_ASSERT(false);
5945                 }
5946             }
5947         }
5948     }
5949 
5950     // Private variables
5951     const tcu::UVec3 m_gridSizeXYZ;
5952     const TestType m_testType;
5953     const std::vector<VariableType> m_varTypesToTest;
5954 
5955     uint32_t m_resultBufferSize;
5956     uint32_t m_shaderRecordSize;
5957     StructItem m_testItems;
5958 
5959     std::map<ShaderGroups, std::vector<uint8_t>> m_shaderGroupToRecordDataMap;
5960     std::map<VkShaderStageFlagBits, uint32_t> m_shaderStageToResultBufferOffset;
5961     std::unique_ptr<GridASProvider> m_asProviderPtr;
5962     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
5963 };
5964 
5965 class RecursiveTracesTest : public TestBase
5966 {
5967 public:
RecursiveTracesTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout,const uint32_t & depthToUse)5968     RecursiveTracesTest(const GeometryType &geometryType, const AccelerationStructureLayout &asStructureLayout,
5969                         const uint32_t &depthToUse)
5970         : m_asStructureLayout(asStructureLayout)
5971         , m_geometryType(geometryType)
5972         , m_depthToUse(depthToUse)
5973         , m_nRaysToTest(512)
5974         , m_maxResultBufferSizePermitted(512 * 1024768)
5975     {
5976         const auto nItemsExpectedPerRay         = static_cast<uint32_t>((1 << (m_depthToUse + 0)) - 1);
5977         const auto nItemsExpectedPerRayInclRgen = static_cast<uint32_t>((1 << (m_depthToUse + 1)) - 1);
5978 
5979         m_nResultItemsExpected     = nItemsExpectedPerRayInclRgen * m_nRaysToTest;
5980         m_nCHitInvocationsExpected = nItemsExpectedPerRay * m_nRaysToTest;
5981         m_nMissInvocationsExpected = nItemsExpectedPerRay * m_nRaysToTest;
5982 
5983         {
5984             const uint32_t nPreambleBytes = sizeof(uint32_t) * 3;
5985             const uint32_t resultItemSize = sizeof(uint32_t) * 4;
5986 
5987             m_nMaxResultItemsPermitted = (m_maxResultBufferSizePermitted - nPreambleBytes) / resultItemSize;
5988         }
5989     }
5990 
~RecursiveTracesTest()5991     ~RecursiveTracesTest()
5992     {
5993         /* Stub */
5994     }
5995 
getAHitShaderCollectionShaderNames() const5996     std::vector<std::string> getAHitShaderCollectionShaderNames() const final
5997     {
5998         return m_ahitShaderNameVec;
5999     }
6000 
getCHitShaderCollectionShaderNames() const6001     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
6002     {
6003         return m_chitShaderNameVec;
6004     }
6005 
getDispatchSize() const6006     tcu::UVec3 getDispatchSize() const final
6007     {
6008         DE_ASSERT(m_nRaysToTest != 0);
6009 
6010         return tcu::UVec3(m_nRaysToTest, 1u, 1u);
6011     }
6012 
getIntersectionShaderCollectionShaderNames() const6013     std::vector<std::string> getIntersectionShaderCollectionShaderNames() const final
6014     {
6015         const auto nIntersectionShaders =
6016             ((m_geometryType == GeometryType::AABB) || (m_geometryType == GeometryType::AABB_AND_TRIANGLES)) ?
6017                 m_depthToUse :
6018                 0;
6019 
6020         return std::vector<std::string>(nIntersectionShaders, {"intersection0"});
6021     }
6022 
getMaxRecursionDepthUsed() const6023     uint32_t getMaxRecursionDepthUsed() const final
6024     {
6025         return m_depthToUse;
6026     }
6027 
getMissShaderCollectionShaderNames() const6028     std::vector<std::string> getMissShaderCollectionShaderNames() const final
6029     {
6030         return m_missShaderNameVec;
6031     }
6032 
getResultBufferSize() const6033     uint32_t getResultBufferSize() const final
6034     {
6035         DE_ASSERT(m_depthToUse < 30); //< due to how nItemsExpectedPerRay is stored.
6036         DE_ASSERT(m_nRaysToTest != 0);
6037 
6038         /* NOTE: A single item is generated by rgen shader stage which is invoked once per each initial ray.
6039          *
6040          *       Each ray at level N generates two result items.
6041          *
6042          *       Thus, for a single initial traced ray, we need sum(2^depth)=2^(depth+1)-1 items.
6043          */
6044         const auto nItemsExpectedPerRay = static_cast<uint32_t>((1 << (m_depthToUse + 1)) - 1);
6045         const auto nResultItemsExpected = de::min(nItemsExpectedPerRay * m_nRaysToTest, m_nMaxResultItemsPermitted);
6046         const auto resultItemSize =
6047             static_cast<uint32_t>(sizeof(uint32_t) * 4 /* nOriginRay, stage, depth, parentResultItem */);
6048 
6049         return static_cast<uint32_t>(sizeof(uint32_t) * 3 /* nItemsRegistered, nCHitInvocations, nMissInvocations */) +
6050                nResultItemsExpected * resultItemSize;
6051     }
6052 
getSpecializationInfoPtr(const VkShaderStageFlagBits & shaderStage)6053     VkSpecializationInfo *getSpecializationInfoPtr(const VkShaderStageFlagBits &shaderStage) final
6054     {
6055         VkSpecializationInfo *resultPtr = nullptr;
6056 
6057         if (shaderStage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR || shaderStage == VK_SHADER_STAGE_MISS_BIT_KHR)
6058         {
6059             resultPtr = &m_specializationInfo;
6060         }
6061 
6062         return resultPtr;
6063     }
6064 
getTLASPtrVecToBind() const6065     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
6066     {
6067         DE_ASSERT(m_tlPtr != nullptr);
6068 
6069         return {m_tlPtr.get()};
6070     }
6071 
init(vkt::Context &,RayTracingProperties *)6072     bool init(vkt::Context & /* context    */, RayTracingProperties * /* rtPropsPtr */) final
6073     {
6074         m_specializationEntry.constantID = 1;
6075         m_specializationEntry.offset     = 0;
6076         m_specializationEntry.size       = sizeof(uint32_t);
6077 
6078         m_specializationInfo.dataSize      = sizeof(uint32_t);
6079         m_specializationInfo.mapEntryCount = 1;
6080         m_specializationInfo.pData         = &m_depthToUse;
6081         m_specializationInfo.pMapEntries   = &m_specializationEntry;
6082 
6083         return true;
6084     }
6085 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)6086     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
6087                 VkCommandBuffer commandBuffer) final
6088     {
6089         std::unique_ptr<GridASProvider> asProviderPtr(new GridASProvider(tcu::Vec3(0, 0, 0), /* gridStartXYZ          */
6090                                                                          tcu::Vec3(1, 1, 1), /* gridCellSizeXYZ       */
6091                                                                          tcu::UVec3(1, 1, 1),
6092                                                                          tcu::Vec3(2, 0, 2), /* gridInterCellDeltaXYZ */
6093                                                                          m_geometryType));
6094 
6095         m_tlPtr =
6096             asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer, 0, /* bottomLevelGeometryFlags */
6097                                       nullptr,                                        /* optASPropertyProviderPtr */
6098                                       nullptr);                                       /* optASFeedbackPtr         */
6099     }
6100 
initPrograms(SourceCollections & programCollection) const6101     void initPrograms(SourceCollections &programCollection) const final
6102     {
6103         const auto nLocationsPerPayload = 3; /* 3 scalar uints */
6104 
6105         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
6106                                                   0u,    /* flags        */
6107                                                   true); /* allowSpirv14 */
6108 
6109         std::vector<std::string> rayPayloadDefinitionVec(m_depthToUse);
6110         std::vector<std::string> rayPayloadInDefinitionVec(m_depthToUse);
6111 
6112         for (uint32_t nLevel = 0; nLevel < m_depthToUse; ++nLevel)
6113         {
6114             rayPayloadDefinitionVec.at(nLevel) = "layout(location = " + de::toString(nLocationsPerPayload * nLevel) +
6115                                                  ") rayPayloadEXT block\n"
6116                                                  "{\n"
6117                                                  "    uint currentDepth;\n"
6118                                                  "    uint currentNOriginRay;\n"
6119                                                  "    uint currentResultItem;\n"
6120                                                  "};\n";
6121 
6122             rayPayloadInDefinitionVec.at(nLevel) = "layout(location = " + de::toString(nLocationsPerPayload * nLevel) +
6123                                                    ") rayPayloadInEXT block\n"
6124                                                    "{\n"
6125                                                    "    uint parentDepth;\n"
6126                                                    "    uint parentNOriginRay;\n"
6127                                                    "    uint parentResultItem;\n"
6128                                                    "};\n";
6129         }
6130 
6131         const std::string constantVariableDefinition =
6132             "layout(constant_id = 1) const uint MAX_RECURSIVE_DEPTH = " + de::toString(m_depthToUse) + ";\n";
6133 
6134         const char *resultBufferDefinition = "struct ResultData\n"
6135                                              "{\n"
6136                                              "    uint nOriginRay;\n"
6137                                              "    uint shaderStage;\n"
6138                                              "    uint depth;\n"
6139                                              "    uint callerResultItem;\n"
6140                                              "};\n"
6141                                              "\n"
6142                                              "layout(set = 0, binding = 0, std430) buffer result\n"
6143                                              "{\n"
6144                                              "    uint       nItemsStored;\n"
6145                                              "    uint       nCHitInvocations;\n"
6146                                              "    uint       nMissInvocations;\n"
6147                                              "    ResultData resultItems[];\n"
6148                                              "};\n";
6149 
6150         {
6151             m_ahitShaderNameVec.resize(m_depthToUse);
6152 
6153             for (uint32_t nLevel = 0; nLevel < m_depthToUse; ++nLevel)
6154             {
6155                 std::stringstream css;
6156 
6157                 css << "#version 460 core\n"
6158                        "\n"
6159                        "#extension GL_EXT_ray_tracing : require\n"
6160                        "\n" +
6161                            de::toString(resultBufferDefinition) + rayPayloadInDefinitionVec.at(nLevel) +
6162                            "\n"
6163                            "void main()\n"
6164                            "{\n"
6165                            /* Stub - don't care */
6166                            "}\n";
6167 
6168                 m_ahitShaderNameVec.at(nLevel) = std::string("ahit") + de::toString(nLevel);
6169 
6170                 programCollection.glslSources.add(m_ahitShaderNameVec.at(nLevel))
6171                     << glu::AnyHitSource(css.str()) << buildOptions;
6172             }
6173         }
6174 
6175         {
6176             m_chitShaderNameVec.resize(m_depthToUse);
6177 
6178             for (uint32_t nLevel = 0; nLevel < m_depthToUse; ++nLevel)
6179             {
6180                 std::stringstream css;
6181                 const bool shouldTraceRays = (nLevel != (m_depthToUse - 1));
6182 
6183                 css << "#version 460 core\n"
6184                        "\n"
6185                        "#extension GL_EXT_ray_tracing : require\n"
6186                        "\n"
6187                        "layout(set = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
6188                        "\n" +
6189                            constantVariableDefinition + de::toString(resultBufferDefinition) +
6190                            de::toString(rayPayloadInDefinitionVec.at(nLevel));
6191 
6192                 if (shouldTraceRays)
6193                 {
6194                     css << rayPayloadDefinitionVec.at(nLevel + 1);
6195                 }
6196 
6197                 css << "\n"
6198                        "void main()\n"
6199                        "{\n"
6200                        "    uint nItem = atomicAdd(nItemsStored, 1);\n"
6201                        "\n"
6202                        "    atomicAdd(nCHitInvocations, 1);\n"
6203                        "\n"
6204                        "    if (nItem < " +
6205                            de::toString(m_nMaxResultItemsPermitted) +
6206                            ")\n"
6207                            "    {\n"
6208                            "        resultItems[nItem].callerResultItem = parentResultItem;\n"
6209                            "        resultItems[nItem].depth            = parentDepth;\n"
6210                            "        resultItems[nItem].nOriginRay       = parentNOriginRay;\n"
6211                            "        resultItems[nItem].shaderStage      = 1;\n"
6212                            "    }\n"
6213                            "\n";
6214 
6215                 if (shouldTraceRays)
6216                 {
6217                     css << "    if (parentDepth < MAX_RECURSIVE_DEPTH - 1)\n"
6218                            "    {\n"
6219                            "        currentDepth      = parentDepth + 1;\n"
6220                            "        currentNOriginRay = parentNOriginRay;\n"
6221                            "        currentResultItem = nItem;\n"
6222                            "\n"
6223                            "        vec3  cellStartXYZ  = vec3(0.0, 0.0, 0.0);\n"
6224                            "        vec3  cellEndXYZ    = cellStartXYZ + vec3(1.0);\n"
6225                            "        vec3  targetHit     = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
6226                            "        vec3  targetMiss    = targetHit + vec3(0, 10, 0);\n"
6227                            "        vec3  origin        = targetHit - vec3(1, 0,  0);\n"
6228                            "        vec3  directionHit  = normalize(targetHit  - origin);\n"
6229                            "        vec3  directionMiss = normalize(targetMiss - origin);\n"
6230                            "        uint  rayFlags      = 0;\n"
6231                            "        uint  cullMask      = 0xFF;\n"
6232                            "        float tmin          = 0.001;\n"
6233                            "        float tmax          = 5.0;\n"
6234                            "\n"
6235                            "        traceRayEXT(accelerationStructure, rayFlags, cullMask, " +
6236                                de::toString(nLevel + 1) + ", 0, 0, origin, tmin, directionHit,  tmax, " +
6237                                de::toString(nLocationsPerPayload * (nLevel + 1)) +
6238                                ");\n"
6239                                "        traceRayEXT(accelerationStructure, rayFlags, cullMask, " +
6240                                de::toString(nLevel + 1) + ", 0, 0, origin, tmin, directionMiss, tmax, " +
6241                                de::toString(nLocationsPerPayload * (nLevel + 1)) +
6242                                ");\n"
6243                                "    }\n"
6244                                "\n";
6245                 }
6246 
6247                 css << "}\n";
6248 
6249                 m_chitShaderNameVec.at(nLevel) = std::string("chit") + de::toString(nLevel);
6250 
6251                 programCollection.glslSources.add(m_chitShaderNameVec.at(nLevel))
6252                     << glu::ClosestHitSource(css.str()) << buildOptions;
6253             }
6254         }
6255 
6256         {
6257             std::stringstream css;
6258 
6259             css << "#version 460 core\n"
6260                    "\n"
6261                    "#extension GL_EXT_ray_tracing : require\n"
6262                    "\n"
6263                    "void main()\n"
6264                    "{\n"
6265                    "    reportIntersectionEXT(0.95f, 0);\n"
6266                    "}\n";
6267 
6268             // There is stack caching code that assumes it knows which shader groups are what, but that doesn't apply to
6269             // this test. The other hit group shaders don't hit this issue because they don't use the canonical name, so
6270             // de-canonicalize the name to work around that
6271             programCollection.glslSources.add("intersection0") << glu::IntersectionSource(css.str()) << buildOptions;
6272         }
6273 
6274         {
6275             m_missShaderNameVec.resize(m_depthToUse);
6276 
6277             for (uint32_t nLevel = 0; nLevel < m_depthToUse; ++nLevel)
6278             {
6279                 std::stringstream css;
6280                 const bool shouldTraceRays = (nLevel != (m_depthToUse - 1));
6281 
6282                 css << "#version 460 core\n"
6283                        "\n"
6284                        "#extension GL_EXT_ray_tracing : require\n"
6285                        "\n"
6286                        "layout(set = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
6287                        "\n" +
6288                            constantVariableDefinition + de::toString(resultBufferDefinition) +
6289                            de::toString(rayPayloadInDefinitionVec.at(nLevel));
6290 
6291                 if (shouldTraceRays)
6292                 {
6293                     css << rayPayloadDefinitionVec.at(nLevel + 1);
6294                 }
6295 
6296                 css << "\n"
6297                        "void main()\n"
6298                        "{\n"
6299                        "    uint nItem = atomicAdd(nItemsStored, 1);\n"
6300                        "\n"
6301                        "    atomicAdd(nMissInvocations, 1);\n"
6302                        "\n"
6303                        "    if (nItem < " +
6304                            de::toString(m_nMaxResultItemsPermitted) +
6305                            ")\n"
6306                            "    {\n"
6307                            "        resultItems[nItem].depth            = parentDepth;\n"
6308                            "        resultItems[nItem].nOriginRay       = parentNOriginRay;\n"
6309                            "        resultItems[nItem].callerResultItem = parentResultItem;\n"
6310                            "        resultItems[nItem].shaderStage      = 2;\n"
6311                            "    }\n"
6312                            "\n";
6313 
6314                 if (shouldTraceRays)
6315                 {
6316                     css << "    if (parentDepth < MAX_RECURSIVE_DEPTH - 1)\n"
6317                            "    {\n"
6318                            "        currentDepth      = parentDepth + 1;\n"
6319                            "        currentNOriginRay = parentNOriginRay;\n"
6320                            "        currentResultItem = nItem;\n"
6321                            "\n"
6322                            "        vec3  cellStartXYZ  = vec3(0.0, 0.0, 0.0);\n"
6323                            "        vec3  cellEndXYZ    = cellStartXYZ + vec3(1.0);\n"
6324                            "        vec3  targetHit     = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
6325                            "        vec3  targetMiss    = targetHit + vec3(0, 10, 0);\n"
6326                            "        vec3  origin        = targetHit - vec3(1, 0,  0);\n"
6327                            "        vec3  directionHit  = normalize(targetHit  - origin);\n"
6328                            "        vec3  directionMiss = normalize(targetMiss - origin);\n"
6329                            "\n"
6330                            "        uint  rayFlags      = 0;\n"
6331                            "        uint  cullMask      = 0xFF;\n"
6332                            "        float tmin          = 0.001;\n"
6333                            "        float tmax          = 5.0;\n"
6334                            "\n"
6335                            "        traceRayEXT(accelerationStructure, rayFlags, cullMask, " +
6336                                de::toString(nLevel + 1) + ", 0, 0, origin, tmin, directionHit,  tmax, " +
6337                                de::toString(nLocationsPerPayload * (nLevel + 1)) +
6338                                ");\n"
6339                                "        traceRayEXT(accelerationStructure, rayFlags, cullMask, " +
6340                                de::toString(nLevel + 1) + ", 0, 0, origin, tmin, directionMiss, tmax, " +
6341                                de::toString(nLocationsPerPayload * (nLevel + 1)) +
6342                                ");\n"
6343                                "    }\n";
6344                 }
6345 
6346                 css << "}\n";
6347 
6348                 m_missShaderNameVec.at(nLevel) = "miss" + de::toString(nLevel);
6349 
6350                 programCollection.glslSources.add(m_missShaderNameVec.at(nLevel))
6351                     << glu::MissSource(css.str()) << buildOptions;
6352             }
6353         }
6354 
6355         {
6356             const std::string rayPayloadDefinition = ((m_depthToUse == 0u) ? "" : rayPayloadDefinitionVec.at(0));
6357 
6358             std::stringstream css;
6359 
6360             css << "#version 460 core\n"
6361                    "\n"
6362                    "#extension GL_EXT_ray_tracing : require\n"
6363                    "\n"
6364                    "layout(set = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
6365                    "\n" +
6366                        de::toString(resultBufferDefinition) + rayPayloadDefinition +
6367                        "void main()\n"
6368                        "{\n"
6369                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
6370                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
6371                        "    uint  rayFlags     = 0;\n"
6372                        "    float tmin         = 0.001;\n"
6373                        "    float tmax         = 9.0;\n"
6374                        "\n"
6375                        "    uint  cullMask      = 0xFF;\n"
6376                        "    vec3  cellStartXYZ  = vec3(0.0, 0.0, 0.0);\n"
6377                        "    vec3  cellEndXYZ    = cellStartXYZ + vec3(1.0);\n"
6378                        "    vec3  targetHit     = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
6379                        "    vec3  targetMiss    = targetHit + vec3(0, 10, 0);\n"
6380                        "    vec3  origin        = targetHit - vec3(1, 0,  0);\n"
6381                        "    vec3  directionHit  = normalize(targetHit  - origin);\n"
6382                        "    vec3  directionMiss = normalize(targetMiss - origin);\n"
6383                        "\n"
6384                        "    uint nItem = atomicAdd(nItemsStored, 1);\n"
6385                        "\n"
6386                        "    if (nItem < " +
6387                        de::toString(m_nMaxResultItemsPermitted) +
6388                        ")\n"
6389                        "    {\n"
6390                        "        resultItems[nItem].callerResultItem = 0xFFFFFFFF;\n"
6391                        "        resultItems[nItem].depth            = 0;\n"
6392                        "        resultItems[nItem].nOriginRay       = nInvocation;\n"
6393                        "        resultItems[nItem].shaderStage      = 3;\n"
6394                        "    }\n"
6395                        "\n" +
6396                        ((m_depthToUse == 0u) ? "" :
6397                                                "    currentDepth      = 0;\n"
6398                                                "    currentNOriginRay = nInvocation;\n"
6399                                                "    currentResultItem = nItem;\n"
6400                                                "\n"
6401                                                "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, "
6402                                                "origin, tmin, directionHit,  tmax, 0);\n"
6403                                                "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, "
6404                                                "origin, tmin, directionMiss, tmax, 0);\n") +
6405                        "}\n";
6406 
6407             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
6408         }
6409     }
6410 
resetTLAS()6411     void resetTLAS() final
6412     {
6413         m_tlPtr.reset();
6414     }
6415 
verifyResultBuffer(const void * resultDataPtr) const6416     bool verifyResultBuffer(const void *resultDataPtr) const final
6417     {
6418         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
6419         bool result                  = false;
6420         auto nItemsStored            = *resultU32Ptr;
6421         const auto nCHitInvocations  = *(resultU32Ptr + 1);
6422         const auto nMissInvocations  = *(resultU32Ptr + 2);
6423         const bool doFullCheck       = (m_nResultItemsExpected < m_nMaxResultItemsPermitted);
6424 
6425         struct ResultItem
6426         {
6427             uint32_t depth;
6428             uint32_t nOriginRay;
6429             uint32_t nParentNode;
6430 
6431             VkShaderStageFlagBits stage;
6432 
6433             ResultItem *childCHitNodePtr;
6434             ResultItem *childMissNodePtr;
6435 
6436             ResultItem()
6437                 : depth(0xFFFFFFFFu)
6438                 , nOriginRay(0xFFFFFFFFu)
6439                 , nParentNode(0xFFFFFFFFu)
6440                 , stage(VK_SHADER_STAGE_ALL)
6441                 , childCHitNodePtr(nullptr)
6442                 , childMissNodePtr(nullptr)
6443             {
6444                 /* Stub */
6445             }
6446         };
6447 
6448         std::map<uint32_t, ResultItem *> nItemToResultItemPtrMap;
6449         std::map<uint32_t, std::vector<std::unique_ptr<ResultItem>>> nRayToResultItemPtrVecMap;
6450         std::map<uint32_t, std::map<uint32_t, std::vector<ResultItem *>>> nRayToNLevelToResultItemPtrVecMap;
6451 
6452         if (doFullCheck)
6453         {
6454             if (nItemsStored != m_nResultItemsExpected)
6455             {
6456                 goto end;
6457             }
6458         }
6459         else
6460         {
6461             // Test shaders always use an atomic add to obtain a unique index, at which they should write the result item.
6462             // Hence, the value we read back from the result buffer's preamble does not actually indicate how many items
6463             // are available for reading, since a partial (!= full) check implies our result buffer only contains a fraction
6464             // of all expected items (since more items would simply not fit in).
6465             //
6466             // Make sure to use a correct value in subsequent checks.
6467             if (nItemsStored < m_nResultItemsExpected)
6468             {
6469                 goto end;
6470             }
6471 
6472             nItemsStored = m_nMaxResultItemsPermitted;
6473         }
6474 
6475         if (nCHitInvocations != m_nCHitInvocationsExpected)
6476         {
6477             goto end;
6478         }
6479 
6480         if (nMissInvocations != m_nMissInvocationsExpected)
6481         {
6482             goto end;
6483         }
6484 
6485         /* Convert an array of result items, stored in undefined order, to a representation we can easily verify */
6486         for (uint32_t nItem = 0; nItem < nItemsStored; ++nItem)
6487         {
6488             const uint32_t *currentItemU32Ptr = resultU32Ptr +
6489                                                 3 /* nItemsRegistered, nCHitInvocations, nMissInvocations*/ +
6490                                                 4 /* items per result item */ * nItem;
6491             std::unique_ptr<ResultItem> resultItemPtr;
6492 
6493             resultItemPtr.reset(new ResultItem());
6494 
6495             resultItemPtr->depth       = *(currentItemU32Ptr + 2);
6496             resultItemPtr->nOriginRay  = *(currentItemU32Ptr + 0);
6497             resultItemPtr->nParentNode = *(currentItemU32Ptr + 3);
6498 
6499             switch (*(currentItemU32Ptr + 1))
6500             {
6501             case 1:
6502                 resultItemPtr->stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
6503                 break;
6504             case 2:
6505                 resultItemPtr->stage = VK_SHADER_STAGE_MISS_BIT_KHR;
6506                 break;
6507             case 3:
6508                 resultItemPtr->stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
6509                 break;
6510 
6511             default:
6512             {
6513                 /* This should never happen */
6514                 DE_ASSERT(false);
6515 
6516                 goto end;
6517             }
6518             }
6519 
6520             if (resultItemPtr->depth >= m_depthToUse && m_depthToUse > 0u)
6521             {
6522                 DE_ASSERT(resultItemPtr->depth < m_depthToUse);
6523 
6524                 goto end;
6525             }
6526 
6527             if (resultItemPtr->nOriginRay >= m_nRaysToTest)
6528             {
6529                 DE_ASSERT(resultItemPtr->nOriginRay < m_nRaysToTest);
6530 
6531                 goto end;
6532             }
6533 
6534             nItemToResultItemPtrMap[nItem] = resultItemPtr.get();
6535 
6536             nRayToNLevelToResultItemPtrVecMap[resultItemPtr->nOriginRay][resultItemPtr->depth].push_back(
6537                 resultItemPtr.get());
6538             nRayToResultItemPtrVecMap[resultItemPtr->nOriginRay].push_back(std::move(resultItemPtr));
6539         }
6540 
6541         if (doFullCheck)
6542         {
6543             for (const auto &iterator1 : nRayToNLevelToResultItemPtrVecMap)
6544             {
6545                 const auto &currentNLevelToResultItemPtrVecMap = iterator1.second;
6546                 uint32_t nRayGenShaderResultItemsFound         = 0;
6547 
6548                 for (const auto &iterator2 : currentNLevelToResultItemPtrVecMap)
6549                 {
6550                     const auto &currentResultItemPtrVec = iterator2.second;
6551 
6552                     for (const auto &currentResultItemPtr : currentResultItemPtrVec)
6553                     {
6554                         if (currentResultItemPtr->stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)
6555                         {
6556                             if (currentResultItemPtr->nParentNode != 0xFFFFFFFF)
6557                             {
6558                                 DE_ASSERT(currentResultItemPtr->nParentNode == 0xFFFFFFFF);
6559 
6560                                 goto end;
6561                             }
6562 
6563                             nRayGenShaderResultItemsFound++;
6564                         }
6565                         else if (currentResultItemPtr->stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)
6566                         {
6567                             DE_ASSERT(currentResultItemPtr->nParentNode < nItemsStored);
6568 
6569                             auto parentNodePtr = nItemToResultItemPtrMap.at(currentResultItemPtr->nParentNode);
6570 
6571                             if (parentNodePtr->childCHitNodePtr != nullptr)
6572                             {
6573                                 DE_ASSERT(parentNodePtr->childCHitNodePtr == nullptr);
6574 
6575                                 goto end;
6576                             }
6577 
6578                             parentNodePtr->childCHitNodePtr = currentResultItemPtr;
6579                         }
6580                         else
6581                         {
6582                             DE_ASSERT(currentResultItemPtr->stage == VK_SHADER_STAGE_MISS_BIT_KHR);
6583                             DE_ASSERT(currentResultItemPtr->nParentNode < nItemsStored);
6584 
6585                             auto parentNodePtr = nItemToResultItemPtrMap.at(currentResultItemPtr->nParentNode);
6586 
6587                             if (parentNodePtr->childMissNodePtr != nullptr)
6588                             {
6589                                 DE_ASSERT(parentNodePtr->childMissNodePtr == nullptr);
6590 
6591                                 goto end;
6592                             }
6593 
6594                             parentNodePtr->childMissNodePtr = currentResultItemPtr;
6595                         }
6596                     }
6597                 }
6598 
6599                 if (nRayGenShaderResultItemsFound != 1)
6600                 {
6601                     DE_ASSERT(nRayGenShaderResultItemsFound == 1);
6602 
6603                     goto end;
6604                 }
6605             }
6606         }
6607 
6608         // 1. Verify all nodes that are not leaves have both child nodes attached, and that leaf nodes do not have any children assigned.
6609         if (doFullCheck)
6610         {
6611             for (const auto &iterator1 : nRayToNLevelToResultItemPtrVecMap)
6612             {
6613                 const auto &currentNLevelToResultItemPtrVecMap = iterator1.second;
6614 
6615                 for (const auto &iterator2 : currentNLevelToResultItemPtrVecMap)
6616                 {
6617                     const auto &currentNLevel           = iterator2.first;
6618                     const auto &currentResultItemPtrVec = iterator2.second;
6619 
6620                     for (const auto &currentResultItemPtr : currentResultItemPtrVec)
6621                     {
6622                         if (currentResultItemPtr->stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ||
6623                             currentNLevel != m_depthToUse - 1)
6624                         {
6625                             if (currentResultItemPtr->childCHitNodePtr == nullptr && m_depthToUse > 0u)
6626                             {
6627                                 DE_ASSERT(currentResultItemPtr->childCHitNodePtr != nullptr);
6628 
6629                                 goto end;
6630                             }
6631 
6632                             if (currentResultItemPtr->childMissNodePtr == nullptr && m_depthToUse > 0u)
6633                             {
6634                                 DE_ASSERT(currentResultItemPtr->childMissNodePtr != nullptr);
6635 
6636                                 goto end;
6637                             }
6638                         }
6639                         else
6640                         {
6641                             if (currentResultItemPtr->childCHitNodePtr != nullptr)
6642                             {
6643                                 DE_ASSERT(currentResultItemPtr->childCHitNodePtr == nullptr);
6644 
6645                                 goto end;
6646                             }
6647 
6648                             if (currentResultItemPtr->childMissNodePtr != nullptr)
6649                             {
6650                                 DE_ASSERT(currentResultItemPtr->childMissNodePtr == nullptr);
6651 
6652                                 goto end;
6653                             }
6654                         }
6655                     }
6656                 }
6657             }
6658         }
6659 
6660         // 2. Verify depth level is correct for each node.
6661         for (const auto &iterator1 : nRayToNLevelToResultItemPtrVecMap)
6662         {
6663             const auto &currentNLevelToResultItemPtrVecMap = iterator1.second;
6664 
6665             for (const auto &iterator2 : currentNLevelToResultItemPtrVecMap)
6666             {
6667                 const auto &currentNLevel           = iterator2.first;
6668                 const auto &currentResultItemPtrVec = iterator2.second;
6669 
6670                 for (const auto &currentResultItemPtr : currentResultItemPtrVec)
6671                 {
6672                     if (currentResultItemPtr->stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)
6673                     {
6674                         if (currentResultItemPtr->depth != 0)
6675                         {
6676                             DE_ASSERT(currentResultItemPtr->depth == 0);
6677 
6678                             goto end;
6679                         }
6680                     }
6681                     else if (currentResultItemPtr->depth != currentNLevel)
6682                     {
6683                         DE_ASSERT(currentResultItemPtr->depth == currentNLevel);
6684 
6685                         goto end;
6686                     }
6687                 }
6688             }
6689         }
6690 
6691         // 3. Verify child node ptrs point to nodes that are assigned correct shader stage.
6692         for (const auto &iterator : nItemToResultItemPtrMap)
6693         {
6694             const auto &currentResultItemPtr = iterator.second;
6695 
6696             if (currentResultItemPtr->childCHitNodePtr != nullptr &&
6697                 currentResultItemPtr->childCHitNodePtr->stage != VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)
6698             {
6699                 DE_ASSERT(currentResultItemPtr->childCHitNodePtr->stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
6700 
6701                 goto end;
6702             }
6703 
6704             if (currentResultItemPtr->childMissNodePtr != nullptr &&
6705                 currentResultItemPtr->childMissNodePtr->stage != VK_SHADER_STAGE_MISS_BIT_KHR)
6706             {
6707                 DE_ASSERT(currentResultItemPtr->childMissNodePtr->stage = VK_SHADER_STAGE_MISS_BIT_KHR);
6708 
6709                 goto end;
6710             }
6711         }
6712 
6713         // 4. Verify nodes hold correct ray index.
6714         for (const auto &iterator : nRayToResultItemPtrVecMap)
6715         {
6716             const auto &currentNRay = iterator.first;
6717 
6718             for (const auto &currentResultItemPtr : iterator.second)
6719             {
6720                 if (currentResultItemPtr->nOriginRay != currentNRay)
6721                 {
6722                     DE_ASSERT(currentResultItemPtr->nOriginRay == currentNRay);
6723 
6724                     goto end;
6725                 }
6726             }
6727         }
6728 
6729         // 5. Verify child nodes are assigned correct depth levels.
6730         for (const auto &iterator1 : nRayToNLevelToResultItemPtrVecMap)
6731         {
6732             const auto &currentNLevelToResultItemPtrVecMap = iterator1.second;
6733 
6734             for (const auto &iterator2 : currentNLevelToResultItemPtrVecMap)
6735             {
6736                 const auto &currentNLevel           = iterator2.first;
6737                 const auto &currentResultItemPtrVec = iterator2.second;
6738 
6739                 for (const auto &currentResultItemPtr : currentResultItemPtrVec)
6740                 {
6741                     const auto expectedChildNodeDepth =
6742                         (currentResultItemPtr->stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR) ?
6743                             0 :
6744                             currentResultItemPtr->depth + 1;
6745 
6746                     if (currentResultItemPtr->depth != currentNLevel)
6747                     {
6748                         DE_ASSERT(currentResultItemPtr->depth == currentNLevel);
6749 
6750                         goto end;
6751                     }
6752 
6753                     if (currentResultItemPtr->childCHitNodePtr != nullptr &&
6754                         currentResultItemPtr->childCHitNodePtr->depth != expectedChildNodeDepth)
6755                     {
6756                         DE_ASSERT(currentResultItemPtr->childCHitNodePtr->depth == expectedChildNodeDepth);
6757 
6758                         goto end;
6759                     }
6760 
6761                     if (currentResultItemPtr->childMissNodePtr != nullptr &&
6762                         currentResultItemPtr->childMissNodePtr->depth != expectedChildNodeDepth)
6763                     {
6764                         DE_ASSERT(currentResultItemPtr->childMissNodePtr->depth == expectedChildNodeDepth);
6765 
6766                         goto end;
6767                     }
6768                 }
6769             }
6770         }
6771 
6772         // 6. Verify that RT shader stages were invoked for all anticipated recursion levels.
6773         if (doFullCheck)
6774         {
6775             for (const auto &iterator1 : nRayToNLevelToResultItemPtrVecMap)
6776             {
6777                 for (uint32_t nLevel = 0; nLevel < m_depthToUse; nLevel++)
6778                 {
6779                     if (iterator1.second.find(nLevel) == iterator1.second.end())
6780                     {
6781                         DE_ASSERT(false);
6782 
6783                         goto end;
6784                     }
6785                 }
6786             }
6787         }
6788 
6789         result = true;
6790     end:
6791         return result;
6792     }
6793 
6794 private:
6795     const AccelerationStructureLayout m_asStructureLayout;
6796     const GeometryType m_geometryType;
6797 
6798     uint32_t m_depthToUse;
6799     uint32_t m_nMaxResultItemsPermitted;
6800     const uint32_t m_nRaysToTest;
6801     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
6802 
6803     VkSpecializationInfo m_specializationInfo;
6804     VkSpecializationMapEntry m_specializationEntry;
6805 
6806     mutable std::vector<std::string> m_ahitShaderNameVec;
6807     mutable std::vector<std::string> m_chitShaderNameVec;
6808     mutable std::vector<std::string> m_missShaderNameVec;
6809 
6810     uint32_t m_nCHitInvocationsExpected;
6811     uint32_t m_nMissInvocationsExpected;
6812     uint32_t m_nResultItemsExpected;
6813 
6814     const uint32_t m_maxResultBufferSizePermitted;
6815 };
6816 
6817 // Test the return value of reportIntersectionEXT
6818 class ReportIntersectionResultTest : public TestBase
6819 {
6820 public:
ReportIntersectionResultTest(const AccelerationStructureLayout & asLayout,const GeometryType & geometryType)6821     ReportIntersectionResultTest(const AccelerationStructureLayout &asLayout, const GeometryType &geometryType)
6822         : m_asLayout(asLayout)
6823         , m_geometryType(geometryType)
6824         , m_gridSizeXYZ(tcu::UVec3(4, 4, 1))
6825         , m_nRaysToTrace(16)
6826     {
6827     }
6828 
getCHitShaderCollectionShaderNames() const6829     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
6830     {
6831         return {};
6832     }
6833 
getDispatchSize() const6834     tcu::UVec3 getDispatchSize() const final
6835     {
6836         return m_gridSizeXYZ;
6837     }
6838 
getResultBufferSize() const6839     uint32_t getResultBufferSize() const final
6840     {
6841         return static_cast<uint32_t>(2u * sizeof(uint32_t) * m_nRaysToTrace);
6842     }
6843 
getTLASPtrVecToBind() const6844     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
6845     {
6846         return {m_tlPtr.get()};
6847     }
6848 
resetTLAS()6849     void resetTLAS() final
6850     {
6851         m_tlPtr.reset();
6852     }
6853 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)6854     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
6855                 VkCommandBuffer commandBuffer) final
6856     {
6857         m_asProviderPtr.reset(new GridASProvider(tcu::Vec3(0, 0, 0),                         // gridStartXYZ
6858                                                  tcu::Vec3(1, 1, 1),                         // gridCellSizeXYZ
6859                                                  m_gridSizeXYZ, tcu::Vec3(2.0f, 2.0f, 2.0f), // gridInterCellDeltaXYZ
6860                                                  m_geometryType));
6861 
6862         m_tlPtr = m_asProviderPtr->createTLAS(context, m_asLayout, commandBuffer, 0u,
6863                                               nullptr,  // optASPropertyProviderPtr
6864                                               nullptr); // optASFedbackPtr
6865     }
6866 
initPrograms(SourceCollections & programCollection) const6867     void initPrograms(SourceCollections &programCollection) const final
6868     {
6869         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
6870         const std::string hitPropertiesDefinition  = "struct HitProperties\n"
6871                                                      "{\n"
6872                                                      "    uint nHitsRejected;\n"
6873                                                      "    uint nHitsAccepteded;\n"
6874                                                      "};\n";
6875         const std::string hitPropertiesDeclaration = "layout(set = 0, binding = 0, std430) buffer result\n"
6876                                                      "{\n"
6877                                                      "    HitProperties rayToHitProps[" +
6878                                                      de::toString(m_nRaysToTrace) +
6879                                                      "];\n"
6880                                                      "};\n";
6881 
6882         programCollection.glslSources.add("ahit")
6883             << glu::AnyHitSource(std::string() +
6884                                  "#version 460 core\n"
6885                                  "\n"
6886                                  "#extension GL_EXT_ray_tracing : require\n"
6887                                  "\n"
6888                                  "hitAttributeEXT vec3 unusedAttribute;\n"
6889                                  "\n" +
6890                                  hitPropertiesDefinition +
6891                                  "\n"
6892                                  "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n" +
6893                                  hitPropertiesDeclaration +
6894                                  "\n"
6895                                  "void main()\n"
6896                                  "{\n"
6897                                  "    uint nRay = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
6898                                  "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
6899                                  "    if ((gl_RayTmaxEXT > 0.6) && (gl_RayTmaxEXT < 0.8))\n"
6900                                  "    {\n"
6901                                  "        atomicAdd(rayToHitProps[nRay].nHitsRejected, 1);\n"
6902                                  "        ignoreIntersectionEXT;\n" // reportIntersectionEXT should return false
6903                                  "    }\n"
6904                                  "    else if ((gl_RayTmaxEXT > 0.1) && (gl_RayTmaxEXT < 0.3))\n"
6905                                  "    {\n"
6906                                  "        atomicAdd(rayToHitProps[nRay].nHitsAccepteded, 1);\n"
6907                                  "    }\n"
6908                                  "}\n")
6909             << buildOptions;
6910 
6911         programCollection.glslSources.add("intersection")
6912             << glu::IntersectionSource("#version 460 core\n"
6913                                        "#extension GL_EXT_ray_tracing : require\n"
6914                                        "\n"
6915                                        "hitAttributeEXT vec3 hitAttribute;\n"
6916                                        "\n"
6917                                        "void main()\n"
6918                                        "{\n"
6919                                        "    bool resultThatShouldBeRejected = reportIntersectionEXT(0.7f, 0);\n"
6920                                        "    if (resultThatShouldBeRejected)\n"
6921                                        "        reportIntersectionEXT(0.7f, 0);\n"
6922                                        "    else\n"
6923                                        "    {\n"
6924                                        "         bool resultThatShouldBeAccepted = reportIntersectionEXT(0.2f, 0);\n"
6925                                        "         if (!resultThatShouldBeAccepted)\n"
6926                                        "             reportIntersectionEXT(0.2f, 0);\n"
6927                                        "    }\n"
6928                                        "}\n")
6929             << buildOptions;
6930 
6931         programCollection.glslSources.add("miss")
6932             << glu::MissSource(std::string() +
6933                                "#version 460 core\n"
6934                                "\n"
6935                                "#extension GL_EXT_ray_tracing : require\n"
6936                                "\n" +
6937                                hitPropertiesDefinition + "layout(location = 0) rayPayloadInEXT vec3 unusedPayload;\n" +
6938                                hitPropertiesDeclaration +
6939                                "\n"
6940                                "void main()\n"
6941                                "{\n"
6942                                "}\n")
6943             << buildOptions;
6944 
6945         programCollection.glslSources.add("rgen")
6946             << glu::RaygenSource(
6947                    "#version 460 core\n"
6948                    "\n"
6949                    "#extension GL_EXT_ray_tracing : require\n"
6950                    "\n" +
6951                    hitPropertiesDefinition +
6952                    "layout(location = 0)              rayPayloadEXT vec3                     unusedPayload;\n"
6953                    "layout(set      = 0, binding = 1) uniform       accelerationStructureEXT topLevelAS;\n"
6954                    "\n"
6955                    "void main()\n"
6956                    "{\n"
6957                    "    uint  rayFlags    = 0;\n"
6958                    "    uint  cullMask    = 0xFF;\n"
6959                    "    float tmin        = 0.001;\n"
6960                    "    float tmax        = 9.0;\n"
6961                    "    vec3  origin      = vec3(4, 4, 4);\n"
6962                    "    vec3  target      = vec3(float(gl_LaunchIDEXT.x * 2) + 0.5f, float(gl_LaunchIDEXT.y * 2) + "
6963                    "0.5f, float(gl_LaunchIDEXT.z * 2) + 0.5f);\n"
6964                    "    vec3  direct      = normalize(target - origin);\n"
6965                    "\n"
6966                    "    traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
6967                    "}\n")
6968             << buildOptions;
6969     }
6970 
verifyResultBuffer(const void * resultDataPtr) const6971     bool verifyResultBuffer(const void *resultDataPtr) const final
6972     {
6973         for (uint32_t nRay = 0; nRay < m_nRaysToTrace; ++nRay)
6974         {
6975             const uint32_t *rayProps = reinterpret_cast<const uint32_t *>(resultDataPtr) + 2 * nRay;
6976             if ((rayProps[0] != 1) || (rayProps[1] != 1))
6977                 return false;
6978         }
6979         return true;
6980     }
6981 
6982 private:
6983     const AccelerationStructureLayout m_asLayout;
6984     const GeometryType m_geometryType;
6985     const tcu::UVec3 m_gridSizeXYZ;
6986     const uint32_t m_nRaysToTrace;
6987 
6988     std::unique_ptr<GridASProvider> m_asProviderPtr;
6989     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
6990 };
6991 
6992 class RayPayloadInTest : public TestBase
6993 {
6994 public:
RayPayloadInTest(const GeometryType & geometryType,const AccelerationStructureLayout & asStructureLayout)6995     RayPayloadInTest(const GeometryType &geometryType, const AccelerationStructureLayout &asStructureLayout)
6996         : m_asStructureLayout(asStructureLayout)
6997         , m_geometryType(geometryType)
6998         , m_gridSizeXYZ(tcu::UVec3(512, 1, 1))
6999         , m_nRayPayloadU32s(512)
7000     {
7001     }
7002 
~RayPayloadInTest()7003     ~RayPayloadInTest()
7004     {
7005         /* Stub */
7006     }
7007 
getDispatchSize() const7008     tcu::UVec3 getDispatchSize() const final
7009     {
7010         DE_ASSERT(m_gridSizeXYZ[0] != 0);
7011         DE_ASSERT(m_gridSizeXYZ[1] != 0);
7012         DE_ASSERT(m_gridSizeXYZ[2] != 0);
7013 
7014         return tcu::UVec3(m_gridSizeXYZ[0], m_gridSizeXYZ[1], m_gridSizeXYZ[2]);
7015     }
7016 
getResultBufferSize() const7017     uint32_t getResultBufferSize() const final
7018     {
7019         DE_ASSERT(m_gridSizeXYZ[0] != 0);
7020         DE_ASSERT(m_gridSizeXYZ[1] != 0);
7021         DE_ASSERT(m_gridSizeXYZ[2] != 0);
7022         DE_ASSERT(m_nRayPayloadU32s != 0);
7023 
7024         const auto nRays = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
7025 
7026         DE_ASSERT(nRays != 0);
7027         DE_ASSERT((nRays % 2) == 0);
7028 
7029         const auto nMissShaderInvocationsExpected = nRays / 2;
7030         const auto nAHitShaderInvocationsExpected = nRays / 2;
7031         const auto nCHitShaderInvocationsExpected = nAHitShaderInvocationsExpected;
7032         const auto nResultStoresExpected =
7033             nMissShaderInvocationsExpected + nAHitShaderInvocationsExpected + nCHitShaderInvocationsExpected;
7034 
7035         return static_cast<uint32_t>((1 /* nItems */ + m_nRayPayloadU32s * nResultStoresExpected) * sizeof(uint32_t));
7036     }
7037 
getSpecializationInfoPtr(const VkShaderStageFlagBits & shaderStage)7038     VkSpecializationInfo *getSpecializationInfoPtr(const VkShaderStageFlagBits &shaderStage) final
7039     {
7040         VkSpecializationInfo *resultPtr = nullptr;
7041 
7042         if (shaderStage == VK_SHADER_STAGE_MISS_BIT_KHR || shaderStage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
7043             shaderStage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR || shaderStage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)
7044         {
7045             resultPtr = &m_specializationInfo;
7046         }
7047 
7048         return resultPtr;
7049     }
7050 
getTLASPtrVecToBind() const7051     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
7052     {
7053         DE_ASSERT(m_tlPtr != nullptr);
7054 
7055         return {m_tlPtr.get()};
7056     }
7057 
init(vkt::Context &,RayTracingProperties *)7058     bool init(vkt::Context & /* context           */, RayTracingProperties * /* rtPropertiesPtr */) final
7059     {
7060         m_specializationInfoMapEntry.constantID = 1;
7061         m_specializationInfoMapEntry.offset     = 0;
7062         m_specializationInfoMapEntry.size       = sizeof(uint32_t);
7063 
7064         m_specializationInfo.dataSize      = sizeof(uint32_t);
7065         m_specializationInfo.mapEntryCount = 1;
7066         m_specializationInfo.pData         = reinterpret_cast<const void *>(&m_nRayPayloadU32s);
7067         m_specializationInfo.pMapEntries   = &m_specializationInfoMapEntry;
7068 
7069         return true;
7070     }
7071 
resetTLAS()7072     void resetTLAS() final
7073     {
7074         m_tlPtr.reset();
7075     }
7076 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)7077     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
7078                 VkCommandBuffer commandBuffer) final
7079     {
7080         std::unique_ptr<GridASProvider> asProviderPtr(new GridASProvider(tcu::Vec3(0, 0, 0), /* gridStartXYZ          */
7081                                                                          tcu::Vec3(1, 1, 1), /* gridCellSizeXYZ       */
7082                                                                          m_gridSizeXYZ,
7083                                                                          tcu::Vec3(6, 0, 0), /* gridInterCellDeltaXYZ */
7084                                                                          m_geometryType));
7085 
7086         m_tlPtr = asProviderPtr->createTLAS(context, m_asStructureLayout, commandBuffer,
7087                                             VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, nullptr, nullptr);
7088     }
7089 
initPrograms(SourceCollections & programCollection) const7090     void initPrograms(SourceCollections &programCollection) const final
7091     {
7092         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
7093                                                   0u,    /* flags        */
7094                                                   true); /* allowSpirv14 */
7095 
7096         const char *constantDefinitions = "layout(constant_id = 1) const uint N_UINTS_IN_RAY_PAYLOAD = 1;\n";
7097 
7098         const char *rayPayloadDefinition = "\n"
7099                                            "layout(location = 0) rayPayloadEXT block\n"
7100                                            "{\n"
7101                                            "    uint values[N_UINTS_IN_RAY_PAYLOAD];\n"
7102                                            "};\n"
7103                                            "\n";
7104 
7105         const char *rayPayloadInDefinition = "\n"
7106                                              "layout(location = 0) rayPayloadInEXT block\n"
7107                                              "{\n"
7108                                              "    uint values[N_UINTS_IN_RAY_PAYLOAD];\n"
7109                                              "};\n"
7110                                              "\n";
7111 
7112         const char *resultBufferDefinition = "layout(set      = 0, binding = 0, std430) buffer result\n"
7113                                              "{\n"
7114                                              "    uint nItemsStored;\n"
7115                                              "    uint resultValues[];\n"
7116                                              "};\n";
7117 
7118         {
7119             std::stringstream css;
7120 
7121             css << "#version 460 core\n"
7122                    "\n"
7123                    "#extension GL_EXT_ray_tracing : require\n"
7124                    "\n" +
7125                        de::toString(constantDefinitions) + de::toString(resultBufferDefinition) +
7126                        de::toString(rayPayloadInDefinition) +
7127                        "\n"
7128                        "void main()\n"
7129                        "{\n"
7130                        "    uint nItem = atomicAdd(nItemsStored, 1);\n"
7131                        "\n"
7132                        "    for (uint nUint = 0; nUint < N_UINTS_IN_RAY_PAYLOAD; ++nUint)\n"
7133                        "    {\n"
7134                        "        resultValues[nItem * N_UINTS_IN_RAY_PAYLOAD + nUint] = values[nUint];\n"
7135                        "    }\n"
7136                        "}\n";
7137 
7138             programCollection.glslSources.add("ahit") << glu::AnyHitSource(css.str()) << buildOptions;
7139         }
7140 
7141         {
7142             std::stringstream css;
7143 
7144             css << "#version 460 core\n"
7145                    "\n"
7146                    "#extension GL_EXT_ray_tracing : require\n"
7147                    "\n" +
7148                        de::toString(constantDefinitions) + de::toString(resultBufferDefinition) +
7149                        de::toString(rayPayloadInDefinition) +
7150                        "\n"
7151                        "void main()\n"
7152                        "{\n"
7153                        "    uint nItem = atomicAdd(nItemsStored, 1);\n"
7154                        "\n"
7155                        "    for (uint nUint = 0; nUint < N_UINTS_IN_RAY_PAYLOAD; ++nUint)\n"
7156                        "    {\n"
7157                        "        resultValues[nItem * N_UINTS_IN_RAY_PAYLOAD + nUint] = values[nUint];\n"
7158                        "    }\n"
7159                        "}\n";
7160 
7161             programCollection.glslSources.add("chit") << glu::ClosestHitSource(css.str()) << buildOptions;
7162         }
7163 
7164         {
7165             std::stringstream css;
7166 
7167             css << "#version 460 core\n"
7168                    "\n"
7169                    "#extension GL_EXT_ray_tracing : require\n"
7170                    "\n"
7171                    "void main()\n"
7172                    "{\n"
7173                    "    reportIntersectionEXT(0.95f, 0);\n"
7174                    "}\n";
7175 
7176             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
7177         }
7178 
7179         {
7180             std::stringstream css;
7181 
7182             css << "#version 460 core\n"
7183                    "\n"
7184                    "#extension GL_EXT_ray_tracing : require\n"
7185                    "\n" +
7186                        de::toString(constantDefinitions) + de::toString(resultBufferDefinition) +
7187                        de::toString(rayPayloadInDefinition) +
7188                        "\n"
7189                        "void main()\n"
7190                        "{\n"
7191                        "    uint nItem = atomicAdd(nItemsStored, 1);\n"
7192                        "\n"
7193                        "    for (uint nUint = 0; nUint < N_UINTS_IN_RAY_PAYLOAD; ++nUint)\n"
7194                        "    {\n"
7195                        "        resultValues[nItem * N_UINTS_IN_RAY_PAYLOAD + nUint] = values[nUint];\n"
7196                        "    }\n"
7197                        "}\n";
7198 
7199             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
7200         }
7201 
7202         {
7203             std::stringstream css;
7204 
7205             css << "#version 460 core\n"
7206                    "\n"
7207                    "#extension GL_EXT_ray_tracing : require\n"
7208                    "\n"
7209                    "layout(set = 0, binding = 1) uniform accelerationStructureEXT accelerationStructure;\n"
7210                    "\n" +
7211                        de::toString(constantDefinitions) + de::toString(rayPayloadDefinition) +
7212                        "void main()\n"
7213                        "{\n"
7214                        "    uint  nInvocation  = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
7215                        "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
7216                        "    uint  rayFlags     = 0;\n"
7217                        "    float tmin         = 0.001;\n"
7218                        "    float tmax         = 2.1;\n"
7219                        "\n"
7220                        "    uint  cullMask     = 0xFF;\n"
7221                        "    vec3  cellStartXYZ = vec3(nInvocation * 3.0, 0.0, 0.0);\n"
7222                        "    vec3  cellEndXYZ   = cellStartXYZ + vec3(1.0);\n"
7223                        "    vec3  target       = mix(cellStartXYZ, cellEndXYZ, vec3(0.5) );\n"
7224                        "    vec3  origin       = target - vec3(0, 2, 0);\n"
7225                        "    vec3  direct       = normalize(target - origin);\n"
7226                        "\n"
7227                        "    for (uint nUint = 0; nUint < N_UINTS_IN_RAY_PAYLOAD; ++nUint)\n"
7228                        "    {\n"
7229                        "        values[nUint] = (1 + nUint);\n"
7230                        "    }\n"
7231                        "\n"
7232                        "    traceRayEXT(accelerationStructure, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, "
7233                        "tmax, 0);\n"
7234                        "}\n";
7235 
7236             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
7237         }
7238     }
7239 
verifyResultBuffer(const void * resultDataPtr) const7240     bool verifyResultBuffer(const void *resultDataPtr) const final
7241     {
7242         const uint32_t *resultU32Ptr = reinterpret_cast<const uint32_t *>(resultDataPtr);
7243         bool result                  = false;
7244 
7245         const auto nItemsStored                   = *resultU32Ptr;
7246         const auto nRays                          = m_gridSizeXYZ[0] * m_gridSizeXYZ[1] * m_gridSizeXYZ[2];
7247         const auto nMissShaderInvocationsExpected = nRays / 2;
7248         const auto nAHitShaderInvocationsExpected = nRays / 2;
7249         const auto nCHitShaderInvocationsExpected = nAHitShaderInvocationsExpected;
7250         const auto nResultStoresExpected =
7251             nMissShaderInvocationsExpected + nAHitShaderInvocationsExpected + nCHitShaderInvocationsExpected;
7252 
7253         if (nItemsStored != nResultStoresExpected)
7254         {
7255             goto end;
7256         }
7257 
7258         for (uint32_t nItem = 0; nItem < nItemsStored; ++nItem)
7259         {
7260             const auto resultItemDataPtr = resultU32Ptr + 1 /* nItemsStored */ + nItem * m_nRayPayloadU32s;
7261 
7262             for (uint32_t nValue = 0; nValue < m_nRayPayloadU32s; ++nValue)
7263             {
7264                 if (resultItemDataPtr[nValue] != (1 + nValue))
7265                 {
7266                     goto end;
7267                 }
7268             }
7269         }
7270 
7271         result = true;
7272     end:
7273         return result;
7274     }
7275 
7276 private:
7277     const AccelerationStructureLayout m_asStructureLayout;
7278     const GeometryType m_geometryType;
7279 
7280     const tcu::UVec3 m_gridSizeXYZ;
7281     uint32_t m_nRayPayloadU32s;
7282     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
7283 
7284     VkSpecializationInfo m_specializationInfo;
7285     VkSpecializationMapEntry m_specializationInfoMapEntry;
7286 };
7287 
7288 class TerminationTest : public TestBase
7289 {
7290 public:
7291     enum class Mode
7292     {
7293         IGNORE_ANY_HIT_STATICALLY,
7294         IGNORE_ANY_HIT_DYNAMICALLY,
7295         TERMINATE_ANY_HIT_STATICALLY,
7296         TERMINATE_ANY_HIT_DYNAMICALLY,
7297         TERMINATE_INTERSECTION_STATICALLY,
7298         TERMINATE_INTERSECTION_DYNAMICALLY,
7299 
7300         UNKNOWN
7301     };
7302 
getModeFromTestType(const TestType & testType)7303     static Mode getModeFromTestType(const TestType &testType)
7304     {
7305         Mode result = Mode::UNKNOWN;
7306 
7307         switch (testType)
7308         {
7309         case TestType::IGNORE_ANY_HIT_DYNAMICALLY:
7310             result = Mode::IGNORE_ANY_HIT_DYNAMICALLY;
7311             break;
7312         case TestType::IGNORE_ANY_HIT_STATICALLY:
7313             result = Mode::IGNORE_ANY_HIT_STATICALLY;
7314             break;
7315         case TestType::TERMINATE_ANY_HIT_DYNAMICALLY:
7316             result = Mode::TERMINATE_ANY_HIT_DYNAMICALLY;
7317             break;
7318         case TestType::TERMINATE_ANY_HIT_STATICALLY:
7319             result = Mode::TERMINATE_ANY_HIT_STATICALLY;
7320             break;
7321         case TestType::TERMINATE_INTERSECTION_DYNAMICALLY:
7322             result = Mode::TERMINATE_INTERSECTION_DYNAMICALLY;
7323             break;
7324         case TestType::TERMINATE_INTERSECTION_STATICALLY:
7325             result = Mode::TERMINATE_INTERSECTION_STATICALLY;
7326             break;
7327 
7328         default:
7329         {
7330             DE_ASSERT(false && "This should never happen");
7331         }
7332         }
7333 
7334         return result;
7335     }
7336 
TerminationTest(const Mode & mode)7337     TerminationTest(const Mode &mode) : m_mode(mode)
7338     {
7339         /* Stub */
7340     }
7341 
~TerminationTest()7342     ~TerminationTest()
7343     {
7344         /* Stub */
7345     }
7346 
getCHitShaderCollectionShaderNames() const7347     std::vector<std::string> getCHitShaderCollectionShaderNames() const final
7348     {
7349         return {};
7350     }
7351 
getDispatchSize() const7352     tcu::UVec3 getDispatchSize() const final
7353     {
7354         return tcu::UVec3(1, 1, 1);
7355     }
7356 
getResultBufferStartData() const7357     std::vector<uint8_t> getResultBufferStartData() const final
7358     {
7359         auto resultU8Vec      = std::vector<uint8_t>(getResultBufferSize());
7360         auto resultU32DataPtr = reinterpret_cast<uint32_t *>(resultU8Vec.data());
7361 
7362         memset(resultU8Vec.data(), 0, resultU8Vec.size());
7363 
7364         if (m_mode == Mode::IGNORE_ANY_HIT_DYNAMICALLY || m_mode == Mode::TERMINATE_ANY_HIT_DYNAMICALLY)
7365         {
7366             resultU32DataPtr[2] = 1;
7367         }
7368         else if (m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY)
7369         {
7370             resultU32DataPtr[3] = 1;
7371         }
7372 
7373         return resultU8Vec;
7374     }
7375 
getResultBufferSize() const7376     uint32_t getResultBufferSize() const final
7377     {
7378         const uint32_t nExtraUints =
7379             (m_mode == Mode::IGNORE_ANY_HIT_DYNAMICALLY || m_mode == Mode::TERMINATE_ANY_HIT_DYNAMICALLY ||
7380              m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY) ?
7381                 1 :
7382                 0;
7383         const uint32_t nResultUints =
7384             (m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY || m_mode == Mode::TERMINATE_INTERSECTION_STATICALLY) ?
7385                 3 :
7386                 2;
7387 
7388         return static_cast<uint32_t>(sizeof(uint32_t)) * (nExtraUints + nResultUints);
7389     }
7390 
getTLASPtrVecToBind() const7391     std::vector<TopLevelAccelerationStructure *> getTLASPtrVecToBind() const final
7392     {
7393         return {m_tlPtr.get()};
7394     }
7395 
resetTLAS()7396     void resetTLAS() final
7397     {
7398         m_tlPtr.reset();
7399     }
7400 
initAS(vkt::Context & context,RayTracingProperties *,VkCommandBuffer commandBuffer)7401     void initAS(vkt::Context &context, RayTracingProperties * /* rtPropertiesPtr */,
7402                 VkCommandBuffer commandBuffer) final
7403     {
7404         if (m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY || m_mode == Mode::TERMINATE_INTERSECTION_STATICALLY)
7405         {
7406             const tcu::Vec3 gridCellSizeXYZ       = tcu::Vec3(2, 1, 1);
7407             const tcu::Vec3 gridInterCellDeltaXYZ = tcu::Vec3(3, 3, 3);
7408             const tcu::UVec3 gridSizeXYZ          = tcu::UVec3(1, 1, 1);
7409             const tcu::Vec3 gridStartXYZ          = tcu::Vec3(-1, -1, -1);
7410 
7411             m_asProviderPtr.reset(new GridASProvider(gridStartXYZ, gridCellSizeXYZ, gridSizeXYZ, gridInterCellDeltaXYZ,
7412                                                      GeometryType::AABB));
7413         }
7414         else
7415         {
7416             m_asProviderPtr.reset(new TriASProvider());
7417         }
7418 
7419         m_tlPtr = m_asProviderPtr->createTLAS(context, AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY,
7420                                               commandBuffer, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
7421                                               nullptr,  /* optASPropertyProviderPtr */
7422                                               nullptr); /* optASFedbackPtr          */
7423     }
7424 
initPrograms(SourceCollections & programCollection) const7425     void initPrograms(SourceCollections &programCollection) const final
7426     {
7427         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4,
7428                                                   0u,    /* flags        */
7429                                                   true); /* allowSpirv14 */
7430 
7431         const std::string resultBufferSizeString = de::toString(getResultBufferSize() / sizeof(uint32_t));
7432 
7433         {
7434             std::string aHitShader;
7435 
7436             switch (m_mode)
7437             {
7438             case Mode::IGNORE_ANY_HIT_DYNAMICALLY:
7439             {
7440                 aHitShader = "#version 460 core\n"
7441                              "\n"
7442                              "#extension GL_EXT_ray_tracing : require\n"
7443                              "\n"
7444                              "hitAttributeEXT vec3 unusedAttribute;\n"
7445                              "\n"
7446                              "layout(location = 0) rayPayloadInEXT      vec3 unusedPayload;\n"
7447                              "layout(set      = 0, binding = 0, std430) buffer result\n"
7448                              "{\n"
7449                              "    uint resultData[" +
7450                              resultBufferSizeString +
7451                              "];\n"
7452                              "};\n"
7453                              "\n"
7454                              "void ignoreIntersectionWrapper()\n"
7455                              "{\n"
7456                              "    ignoreIntersectionEXT;\n"
7457                              "}\n"
7458                              "\n"
7459                              "void main()\n"
7460                              "{\n"
7461                              "\n"
7462                              "    if (resultData[2] == 1)\n"
7463                              "    {\n"
7464                              "        ignoreIntersectionWrapper();\n"
7465                              "    }\n"
7466                              "\n"
7467                              "    resultData[0] = 1;\n"
7468                              "}\n";
7469 
7470                 break;
7471             }
7472 
7473             case Mode::IGNORE_ANY_HIT_STATICALLY:
7474             {
7475                 aHitShader = "#version 460 core\n"
7476                              "\n"
7477                              "#extension GL_EXT_ray_tracing : require\n"
7478                              "\n"
7479                              "hitAttributeEXT vec3 unusedAttribute;\n"
7480                              "\n"
7481                              "layout(location = 0) rayPayloadInEXT      vec3 unusedPayload;\n"
7482                              "layout(set      = 0, binding = 0, std430) buffer result\n"
7483                              "{\n"
7484                              "    uint resultData[" +
7485                              resultBufferSizeString +
7486                              "];\n"
7487                              "};\n"
7488                              "\n"
7489                              "void ignoreIntersectionWrapper()\n"
7490                              "{\n"
7491                              "    ignoreIntersectionEXT;\n"
7492                              "}\n"
7493                              "\n"
7494                              "void main()\n"
7495                              "{\n"
7496                              "    ignoreIntersectionWrapper();\n"
7497                              "\n"
7498                              "    resultData[0] = 1;\n"
7499                              "}\n";
7500 
7501                 break;
7502             }
7503 
7504             case Mode::TERMINATE_ANY_HIT_DYNAMICALLY:
7505             {
7506                 aHitShader = "#version 460 core\n"
7507                              "\n"
7508                              "#extension GL_EXT_ray_tracing : require\n"
7509                              "\n"
7510                              "hitAttributeEXT vec3 unusedAttribute;\n"
7511                              "\n"
7512                              "layout(location = 0) rayPayloadInEXT      vec3 unusedPayload;\n"
7513                              "layout(set      = 0, binding = 0, std430) buffer result\n"
7514                              "{\n"
7515                              "    uint resultData[" +
7516                              resultBufferSizeString +
7517                              "];\n"
7518                              "};\n"
7519                              "\n"
7520                              "void terminateRayWrapper()\n"
7521                              "{\n"
7522                              "    terminateRayEXT;\n"
7523                              "}\n"
7524                              "\n"
7525                              "void main()\n"
7526                              "{\n"
7527                              "    if (resultData[2] == 1)\n"
7528                              "    {\n"
7529                              "        terminateRayWrapper();\n"
7530                              "    }\n"
7531                              "\n"
7532                              "    resultData[0] = 1;\n"
7533                              "}\n";
7534 
7535                 break;
7536             }
7537 
7538             case Mode::TERMINATE_ANY_HIT_STATICALLY:
7539             case Mode::TERMINATE_INTERSECTION_STATICALLY:
7540             {
7541                 aHitShader = "#version 460 core\n"
7542                              "\n"
7543                              "#extension GL_EXT_ray_tracing : require\n"
7544                              "\n"
7545                              "hitAttributeEXT vec3 unusedAttribute;\n"
7546                              "\n"
7547                              "layout(location = 0) rayPayloadInEXT      vec3 unusedPayload;\n"
7548                              "layout(set      = 0, binding = 0, std430) buffer result\n"
7549                              "{\n"
7550                              "    uint resultData[" +
7551                              resultBufferSizeString +
7552                              "];\n"
7553                              "};\n"
7554                              "\n"
7555                              "void terminateRayWrapper()\n"
7556                              "{\n"
7557                              "    terminateRayEXT;\n"
7558                              "}\n"
7559                              "\n"
7560                              "void main()\n"
7561                              "{\n"
7562                              "    terminateRayWrapper();\n"
7563                              "\n"
7564                              "    resultData[0] = 1;\n"
7565                              "}\n";
7566 
7567                 break;
7568             }
7569 
7570             case Mode::TERMINATE_INTERSECTION_DYNAMICALLY:
7571             {
7572                 aHitShader = "#version 460 core\n"
7573                              "\n"
7574                              "#extension GL_EXT_ray_tracing : require\n"
7575                              "\n"
7576                              "hitAttributeEXT vec3 unusedAttribute;\n"
7577                              "\n"
7578                              "layout(location = 0) rayPayloadInEXT      vec3 unusedPayload;\n"
7579                              "layout(set      = 0, binding = 0, std430) buffer result\n"
7580                              "{\n"
7581                              "    uint resultData[" +
7582                              resultBufferSizeString +
7583                              "];\n"
7584                              "};\n"
7585                              "\n"
7586                              "void terminateRayWrapper()\n"
7587                              "{\n"
7588                              "    terminateRayEXT;\n"
7589                              "}\n"
7590                              "\n"
7591                              "void main()\n"
7592                              "{\n"
7593                              "    if (resultData[3] == 1)\n"
7594                              "    {\n"
7595                              "        terminateRayWrapper();\n"
7596                              "    }\n"
7597                              "\n"
7598                              "    resultData[0] = 1;\n"
7599                              "}\n";
7600 
7601                 break;
7602             }
7603 
7604             default:
7605             {
7606                 DE_ASSERT(false);
7607             }
7608             }
7609 
7610             programCollection.glslSources.add("ahit") << glu::AnyHitSource(aHitShader) << buildOptions;
7611         }
7612 
7613         if (m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY || m_mode == Mode::TERMINATE_INTERSECTION_STATICALLY)
7614         {
7615             std::stringstream css;
7616 
7617             css << "#version 460 core\n"
7618                    "\n"
7619                    "#extension GL_EXT_ray_tracing : require\n"
7620                    "\n"
7621                    "hitAttributeEXT vec3 hitAttribute;\n"
7622                    "\n"
7623                    "layout(set = 0, binding = 0, std430) buffer result\n"
7624                    "{\n"
7625                    "    uint resultData[4];\n"
7626                    "};\n"
7627                    "\n"
7628                    "void generateIntersection()\n"
7629                    "{\n"
7630                    "    reportIntersectionEXT(0.95f, 0);\n"
7631                    "}\n"
7632                    "\n"
7633                    "void main()\n"
7634                    "{\n";
7635 
7636             if (m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY)
7637             {
7638                 css << "    if (resultData[3] == 1)\n"
7639                        "    {\n";
7640             }
7641 
7642             css << "    generateIntersection();\n";
7643 
7644             if (m_mode == Mode::TERMINATE_INTERSECTION_DYNAMICALLY)
7645             {
7646                 css << "    }\n";
7647             }
7648 
7649             css << "\n"
7650                    "    resultData[2] = 1;\n"
7651                    "}\n";
7652 
7653             programCollection.glslSources.add("intersection") << glu::IntersectionSource(css.str()) << buildOptions;
7654         }
7655 
7656         {
7657             std::stringstream css;
7658 
7659             css << "#version 460 core\n"
7660                    "\n"
7661                    "#extension GL_EXT_ray_tracing : require\n"
7662                    "\n"
7663                    "layout(location = 0) rayPayloadInEXT      vec3   unusedPayload;\n"
7664                    "layout(set      = 0, binding = 0, std430) buffer result\n"
7665                    "{\n"
7666                    "    uint resultData[2];\n"
7667                    "};\n"
7668                    "\n"
7669                    "void main()\n"
7670                    "{\n"
7671                    "    resultData[1] = 1;\n"
7672                    "}\n";
7673 
7674             programCollection.glslSources.add("miss") << glu::MissSource(css.str()) << buildOptions;
7675         }
7676 
7677         {
7678             std::stringstream css;
7679 
7680             css << "#version 460 core\n"
7681                    "\n"
7682                    "#extension GL_EXT_ray_tracing : require\n"
7683                    "\n"
7684                    "layout(location = 0)              rayPayloadEXT vec3                     unusedPayload;\n"
7685                    "layout(set      = 0, binding = 1) uniform       accelerationStructureEXT topLevelAS;\n"
7686                    "\n"
7687                    "void main()\n"
7688                    "{\n"
7689                    "    uint  nInvocation = gl_LaunchIDEXT.z * gl_LaunchSizeEXT.x * gl_LaunchSizeEXT.y + "
7690                    "gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x;\n"
7691                    "    uint  rayFlags    = 0;\n"
7692                    "    uint  cullMask    = 0xFF;\n"
7693                    "    float tmin        = 0.001;\n"
7694                    "    float tmax        = 9.0;\n"
7695                    "    vec3  origin      = vec3(-1,  -1,  -1);\n"
7696                    "    vec3  target      = vec3(0.0, 0.5,  0);\n"
7697                    "    vec3  direct      = normalize(target - origin);\n"
7698                    "\n"
7699                    "    traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
7700                    "}\n";
7701 
7702             programCollection.glslSources.add("rgen") << glu::RaygenSource(css.str()) << buildOptions;
7703         }
7704     }
7705 
verifyResultBuffer(const void * resultDataPtr) const7706     bool verifyResultBuffer(const void *resultDataPtr) const final
7707     {
7708         const uint32_t *resultU32DataPtr = reinterpret_cast<const uint32_t *>(resultDataPtr);
7709         bool result                      = false;
7710 
7711         switch (m_mode)
7712         {
7713         case Mode::IGNORE_ANY_HIT_DYNAMICALLY:
7714         case Mode::IGNORE_ANY_HIT_STATICALLY:
7715         {
7716             if (resultU32DataPtr[0] != 0 || resultU32DataPtr[1] != 1)
7717             {
7718                 goto end;
7719             }
7720 
7721             result = true;
7722 
7723             break;
7724         }
7725 
7726         case Mode::TERMINATE_ANY_HIT_DYNAMICALLY:
7727         case Mode::TERMINATE_ANY_HIT_STATICALLY:
7728         {
7729             if (resultU32DataPtr[0] != 0 || resultU32DataPtr[1] != 0)
7730             {
7731                 goto end;
7732             }
7733 
7734             result = true;
7735 
7736             break;
7737         }
7738 
7739         case Mode::TERMINATE_INTERSECTION_DYNAMICALLY:
7740         case Mode::TERMINATE_INTERSECTION_STATICALLY:
7741         {
7742             if (resultU32DataPtr[0] != 0 || resultU32DataPtr[1] != 0 || resultU32DataPtr[2] != 0)
7743             {
7744                 goto end;
7745             }
7746 
7747             result = true;
7748 
7749             break;
7750         }
7751 
7752         default:
7753         {
7754             TCU_FAIL("This should never be reached");
7755         }
7756         }
7757 
7758     end:
7759         return result;
7760     }
7761 
7762 private:
7763     std::unique_ptr<ASProviderBase> m_asProviderPtr;
7764     const Mode m_mode;
7765     std::unique_ptr<TopLevelAccelerationStructure> m_tlPtr;
7766 };
7767 
7768 /* Generic misc test instance */
7769 class RayTracingMiscTestInstance : public TestInstance
7770 {
7771 public:
7772     RayTracingMiscTestInstance(Context &context, const CaseDef &data, TestBase *testPtr);
7773     ~RayTracingMiscTestInstance(void);
7774 
7775     tcu::TestStatus iterate(void);
7776 
7777 protected:
7778     void checkSupport(void) const;
7779     de::MovePtr<BufferWithMemory> runTest(void);
7780 
7781 private:
7782     CaseDef m_data;
7783 
7784     de::MovePtr<RayTracingProperties> m_rayTracingPropsPtr;
7785     TestBase *m_testPtr;
7786 };
7787 
RayTracingMiscTestInstance(Context & context,const CaseDef & data,TestBase * testPtr)7788 RayTracingMiscTestInstance::RayTracingMiscTestInstance(Context &context, const CaseDef &data, TestBase *testPtr)
7789     : vkt::TestInstance(context)
7790     , m_data(data)
7791     , m_rayTracingPropsPtr(makeRayTracingProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
7792     , m_testPtr(testPtr)
7793 {
7794     m_testPtr->init(m_context, m_rayTracingPropsPtr.get());
7795 }
7796 
~RayTracingMiscTestInstance(void)7797 RayTracingMiscTestInstance::~RayTracingMiscTestInstance(void)
7798 {
7799     /* Stub */
7800 }
7801 
checkSupport(void) const7802 void RayTracingMiscTestInstance::checkSupport(void) const
7803 {
7804     if (m_testPtr->getResultBufferSize() > m_context.getDeviceVulkan11Properties().maxMemoryAllocationSize)
7805         TCU_THROW(NotSupportedError,
7806                   "VkPhysicalDeviceVulkan11Properties::maxMemoryAllocationSize too small, allocation might fail");
7807 }
7808 
runTest(void)7809 de::MovePtr<BufferWithMemory> RayTracingMiscTestInstance::runTest(void)
7810 {
7811     const DeviceInterface &deviceInterface = m_context.getDeviceInterface();
7812     const VkDevice deviceVk                = m_context.getDevice();
7813 
7814     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
7815     const VkQueue queueVk           = m_context.getUniversalQueue();
7816     Allocator &allocator            = m_context.getDefaultAllocator();
7817 
7818     de::MovePtr<BufferWithMemory> resultBufferPtr;
7819 
7820     // Determine group indices
7821     const auto ahitCollectionShaderNameVec         = m_testPtr->getAHitShaderCollectionShaderNames();
7822     const auto chitCollectionShaderNameVec         = m_testPtr->getCHitShaderCollectionShaderNames();
7823     const auto intersectionCollectionShaderNameVec = m_testPtr->getIntersectionShaderCollectionShaderNames();
7824     const auto missCollectionShaderNameVec         = m_testPtr->getMissShaderCollectionShaderNames();
7825 
7826     const uint32_t nRaygenGroups = 1;
7827     const uint32_t nMissGroups   = static_cast<uint32_t>(missCollectionShaderNameVec.size());
7828     const uint32_t nHitGroups    = de::max(de::max(static_cast<uint32_t>(ahitCollectionShaderNameVec.size()),
7829                                                    static_cast<uint32_t>(chitCollectionShaderNameVec.size())),
7830                                            static_cast<uint32_t>(intersectionCollectionShaderNameVec.size()));
7831 
7832     const uint32_t raygenGroupIndex = 0;
7833     const uint32_t missGroupIndex   = nRaygenGroups;
7834     const uint32_t hitGroupIndex    = missGroupIndex + nMissGroups;
7835 
7836     const auto callableShaderCollectionNames = m_testPtr->getCallableShaderCollectionNames();
7837     auto &collection                         = m_context.getBinaryCollection();
7838     const auto resultBufferSize              = m_testPtr->getResultBufferSize();
7839 
7840     const Move<VkDescriptorSetLayout> descriptorSetLayoutPtr =
7841         DescriptorSetLayoutBuilder()
7842             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES)
7843             .addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, m_testPtr->getASBindingArraySize(),
7844                              ALL_RAY_TRACING_STAGES)
7845             .build(deviceInterface, deviceVk);
7846 
7847     const Move<VkDescriptorPool> descriptorPoolPtr =
7848         DescriptorPoolBuilder()
7849             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
7850             .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, m_testPtr->getASBindingArraySize())
7851             .build(deviceInterface, deviceVk, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); /* maxSets */
7852 
7853     const Move<VkDescriptorSet> descriptorSetPtr =
7854         makeDescriptorSet(deviceInterface, deviceVk, *descriptorPoolPtr, *descriptorSetLayoutPtr);
7855 
7856     const Move<VkPipelineLayout> pipelineLayoutPtr =
7857         m_testPtr->getPipelineLayout(deviceInterface, deviceVk, descriptorSetLayoutPtr.get());
7858 
7859     const Move<VkCommandPool> cmdPoolPtr = createCommandPool(deviceInterface, deviceVk, 0, /* pCreateInfo */
7860                                                              queueFamilyIndex);
7861 
7862     const Move<VkCommandBuffer> cmdBufferPtr =
7863         allocateCommandBuffer(deviceInterface, deviceVk, *cmdPoolPtr, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
7864 
7865     Move<VkPipeline> pipelineVkPtr;
7866     de::MovePtr<RayTracingPipeline> rayTracingPipelinePtr = de::newMovePtr<RayTracingPipeline>();
7867 
7868     {
7869         Move<VkShaderModule> raygenShader =
7870             createShaderModule(deviceInterface, deviceVk, collection.get("rgen"), 0); /* flags */
7871 
7872         rayTracingPipelinePtr->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, makeVkSharedPtr(raygenShader),
7873                                          raygenGroupIndex,
7874                                          m_testPtr->getSpecializationInfoPtr(VK_SHADER_STAGE_RAYGEN_BIT_KHR));
7875     }
7876 
7877     {
7878         for (uint32_t nMissShaderName = 0; nMissShaderName < static_cast<uint32_t>(missCollectionShaderNameVec.size());
7879              nMissShaderName++)
7880         {
7881             const auto &currentMissShaderName = missCollectionShaderNameVec.at(nMissShaderName);
7882             Move<VkShaderModule> missShader =
7883                 createShaderModule(deviceInterface, deviceVk, collection.get(currentMissShaderName), 0); /* flags */
7884 
7885             rayTracingPipelinePtr->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, makeVkSharedPtr(missShader),
7886                                              missGroupIndex + nMissShaderName,
7887                                              m_testPtr->getSpecializationInfoPtr(VK_SHADER_STAGE_MISS_BIT_KHR));
7888         }
7889     }
7890 
7891     {
7892         for (uint32_t nAHitShaderName = 0; nAHitShaderName < static_cast<uint32_t>(ahitCollectionShaderNameVec.size());
7893              nAHitShaderName++)
7894         {
7895             const auto &currentAHitShaderName = ahitCollectionShaderNameVec.at(nAHitShaderName);
7896             Move<VkShaderModule> anyHitShader =
7897                 createShaderModule(deviceInterface, deviceVk, collection.get(currentAHitShaderName), 0); /* flags */
7898 
7899             rayTracingPipelinePtr->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR, makeVkSharedPtr(anyHitShader),
7900                                              hitGroupIndex + nAHitShaderName,
7901                                              m_testPtr->getSpecializationInfoPtr(VK_SHADER_STAGE_ANY_HIT_BIT_KHR));
7902         }
7903 
7904         for (uint32_t nCHitShaderName = 0; nCHitShaderName < static_cast<uint32_t>(chitCollectionShaderNameVec.size());
7905              nCHitShaderName++)
7906         {
7907             const auto &currentCHitShaderName = chitCollectionShaderNameVec.at(nCHitShaderName);
7908             Move<VkShaderModule> closestHitShader =
7909                 createShaderModule(deviceInterface, deviceVk, collection.get(currentCHitShaderName), 0); /* flags */
7910 
7911             rayTracingPipelinePtr->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, makeVkSharedPtr(closestHitShader),
7912                                              hitGroupIndex + nCHitShaderName,
7913                                              m_testPtr->getSpecializationInfoPtr(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR));
7914         }
7915 
7916         if (m_data.geometryType == GeometryType::AABB || m_data.geometryType == GeometryType::AABB_AND_TRIANGLES)
7917         {
7918             for (uint32_t nIntersectionShaderName = 0;
7919                  nIntersectionShaderName < static_cast<uint32_t>(intersectionCollectionShaderNameVec.size());
7920                  nIntersectionShaderName++)
7921             {
7922                 const auto &currentIntersectionShaderName =
7923                     intersectionCollectionShaderNameVec.at(nIntersectionShaderName);
7924                 Move<VkShaderModule> intersectionShader = createShaderModule(
7925                     deviceInterface, deviceVk, collection.get(currentIntersectionShaderName), 0); /* flags */
7926 
7927                 rayTracingPipelinePtr->addShader(
7928                     VK_SHADER_STAGE_INTERSECTION_BIT_KHR, makeVkSharedPtr(intersectionShader),
7929                     hitGroupIndex + nIntersectionShaderName,
7930                     m_testPtr->getSpecializationInfoPtr(VK_SHADER_STAGE_INTERSECTION_BIT_KHR));
7931             }
7932         }
7933 
7934         for (uint32_t nCallableShader = 0;
7935              nCallableShader < static_cast<uint32_t>(callableShaderCollectionNames.size()); ++nCallableShader)
7936         {
7937             const auto &currentCallableShaderName = callableShaderCollectionNames.at(nCallableShader);
7938             Move<VkShaderModule> callableShader =
7939                 createShaderModule(deviceInterface, deviceVk, collection.get(currentCallableShaderName), 0); /* flags */
7940 
7941             rayTracingPipelinePtr->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR, makeVkSharedPtr(callableShader),
7942                                              static_cast<uint32_t>(ShaderGroups::FIRST_CALLABLE_GROUP) +
7943                                                  nCallableShader,
7944                                              m_testPtr->getSpecializationInfoPtr(VK_SHADER_STAGE_CALLABLE_BIT_KHR));
7945         }
7946 
7947         if (m_testPtr->usesDynamicStackSize())
7948         {
7949             rayTracingPipelinePtr->addDynamicState(VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR);
7950         }
7951 
7952         rayTracingPipelinePtr->setMaxRecursionDepth(m_testPtr->getMaxRecursionDepthUsed());
7953 
7954         pipelineVkPtr = rayTracingPipelinePtr->createPipeline(deviceInterface, deviceVk, *pipelineLayoutPtr);
7955     }
7956 
7957     /* Cache shader stack size info */
7958     {
7959         VkDeviceSize ahitShaderStackSize     = 0;
7960         VkDeviceSize callableShaderStackSize = 0;
7961         VkDeviceSize chitShaderStackSize     = 0;
7962         VkDeviceSize isectShaderStackSize    = 0;
7963         VkDeviceSize missShaderStackSize     = 0;
7964         VkDeviceSize raygenShaderStackSize   = 0;
7965 
7966         raygenShaderStackSize = deviceInterface.getRayTracingShaderGroupStackSizeKHR(
7967             deviceVk, *pipelineVkPtr, static_cast<uint32_t>(ShaderGroups::RAYGEN_GROUP),
7968             VK_SHADER_GROUP_SHADER_GENERAL_KHR);
7969 
7970         if (collection.contains("ahit"))
7971         {
7972             ahitShaderStackSize = deviceInterface.getRayTracingShaderGroupStackSizeKHR(
7973                 deviceVk, *pipelineVkPtr, static_cast<uint32_t>(ShaderGroups::HIT_GROUP),
7974                 VK_SHADER_GROUP_SHADER_ANY_HIT_KHR);
7975         }
7976 
7977         if (collection.contains("chit"))
7978         {
7979             chitShaderStackSize = deviceInterface.getRayTracingShaderGroupStackSizeKHR(
7980                 deviceVk, *pipelineVkPtr, static_cast<uint32_t>(ShaderGroups::HIT_GROUP),
7981                 VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR);
7982         }
7983 
7984         if (m_data.geometryType == GeometryType::AABB || m_data.geometryType == GeometryType::AABB_AND_TRIANGLES)
7985         {
7986             if (collection.contains("intersection"))
7987             {
7988                 isectShaderStackSize = deviceInterface.getRayTracingShaderGroupStackSizeKHR(
7989                     deviceVk, *pipelineVkPtr, static_cast<uint32_t>(ShaderGroups::HIT_GROUP),
7990                     VK_SHADER_GROUP_SHADER_INTERSECTION_KHR);
7991             }
7992         }
7993 
7994         if (nMissGroups > 0u)
7995         {
7996             missShaderStackSize = deviceInterface.getRayTracingShaderGroupStackSizeKHR(
7997                 deviceVk, *pipelineVkPtr, static_cast<uint32_t>(ShaderGroups::MISS_GROUP),
7998                 VK_SHADER_GROUP_SHADER_GENERAL_KHR);
7999         }
8000 
8001         for (uint32_t nCallableShader = 0;
8002              nCallableShader < static_cast<uint32_t>(callableShaderCollectionNames.size()); ++nCallableShader)
8003         {
8004             callableShaderStackSize += deviceInterface.getRayTracingShaderGroupStackSizeKHR(
8005                 deviceVk, *pipelineVkPtr, static_cast<uint32_t>(ShaderGroups::FIRST_CALLABLE_GROUP) + nCallableShader,
8006                 VK_SHADER_GROUP_SHADER_GENERAL_KHR);
8007         }
8008 
8009         m_testPtr->onShaderStackSizeDiscovered(raygenShaderStackSize, ahitShaderStackSize, chitShaderStackSize,
8010                                                missShaderStackSize, callableShaderStackSize, isectShaderStackSize);
8011     }
8012 
8013     auto callableShaderBindingTablePtr = de::MovePtr<BufferWithMemory>();
8014 
8015     if (callableShaderCollectionNames.size() != 0)
8016     {
8017         callableShaderBindingTablePtr = rayTracingPipelinePtr->createShaderBindingTable(
8018             deviceInterface, deviceVk, *pipelineVkPtr, allocator, m_rayTracingPropsPtr->getShaderGroupHandleSize(),
8019             m_rayTracingPropsPtr->getShaderGroupBaseAlignment(),
8020             static_cast<uint32_t>(ShaderGroups::FIRST_CALLABLE_GROUP),
8021             static_cast<uint32_t>(callableShaderCollectionNames.size()), /* groupCount                  */
8022             0u,                                                          /* additionalBufferCreateFlags */
8023             0u,                                                          /* additionalBufferUsageFlags  */
8024             MemoryRequirement::Any, 0u,                                  /* opaqueCaptureAddress       */
8025             0u,                                                          /* shaderBindingTableOffset   */
8026             m_testPtr->getShaderRecordSize(ShaderGroups::FIRST_CALLABLE_GROUP));
8027     }
8028 
8029     const auto raygenShaderBindingTablePtr = rayTracingPipelinePtr->createShaderBindingTable(
8030         deviceInterface, deviceVk, *pipelineVkPtr, allocator, m_rayTracingPropsPtr->getShaderGroupHandleSize(),
8031         m_rayTracingPropsPtr->getShaderGroupBaseAlignment(), raygenGroupIndex,
8032         nRaygenGroups,              /* groupCount                  */
8033         0u,                         /* additionalBufferCreateFlags */
8034         0u,                         /* additionalBufferUsageFlags  */
8035         MemoryRequirement::Any, 0u, /* opaqueCaptureAddress        */
8036         0u);                        /* shaderBindingTableOffset    */
8037 
8038     auto missShaderBindingTablePtr = de::MovePtr<BufferWithMemory>();
8039     if (nMissGroups > 0u)
8040     {
8041         const void *missShaderBindingGroupShaderRecordDataPtr =
8042             m_testPtr->getShaderRecordData(ShaderGroups::MISS_GROUP);
8043         missShaderBindingTablePtr = rayTracingPipelinePtr->createShaderBindingTable(
8044             deviceInterface, deviceVk, *pipelineVkPtr, allocator, m_rayTracingPropsPtr->getShaderGroupHandleSize(),
8045             m_rayTracingPropsPtr->getShaderGroupBaseAlignment(), missGroupIndex,
8046             nMissGroups,                /* groupCount                  */
8047             0u,                         /* additionalBufferCreateFlags */
8048             0u,                         /* additionalBufferUsageFlags  */
8049             MemoryRequirement::Any, 0u, /* opaqueCaptureAddress       */
8050             0u,                         /* shaderBindingTableOffset   */
8051             m_testPtr->getShaderRecordSize(ShaderGroups::MISS_GROUP), &missShaderBindingGroupShaderRecordDataPtr);
8052     }
8053 
8054     auto hitShaderBindingTablePtr = de::MovePtr<BufferWithMemory>();
8055     if (nHitGroups > 0u)
8056     {
8057         const void *hitShaderBindingGroupShaderRecordDataPtr = m_testPtr->getShaderRecordData(ShaderGroups::HIT_GROUP);
8058         hitShaderBindingTablePtr                             = rayTracingPipelinePtr->createShaderBindingTable(
8059             deviceInterface, deviceVk, *pipelineVkPtr, allocator, m_rayTracingPropsPtr->getShaderGroupHandleSize(),
8060             m_rayTracingPropsPtr->getShaderGroupBaseAlignment(), hitGroupIndex,
8061             nHitGroups,                 /* groupCount                  */
8062             0u,                         /* additionalBufferCreateFlags */
8063             0u,                         /* additionalBufferUsageFlags  */
8064             MemoryRequirement::Any, 0u, /* opaqueCaptureAddress       */
8065             0u,                         /* shaderBindingTableOffset   */
8066             m_testPtr->getShaderRecordSize(ShaderGroups::HIT_GROUP), &hitShaderBindingGroupShaderRecordDataPtr);
8067     }
8068 
8069     {
8070         const auto resultBufferCreateInfo = makeBufferCreateInfo(
8071             resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
8072         const auto resultBufferDataVec = m_testPtr->getResultBufferStartData();
8073 
8074         resultBufferPtr = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
8075             deviceInterface, deviceVk, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
8076 
8077         if (resultBufferDataVec.size() > 0)
8078         {
8079             DE_ASSERT(static_cast<uint32_t>(resultBufferDataVec.size()) == resultBufferSize);
8080 
8081             memcpy(resultBufferPtr->getAllocation().getHostPtr(), resultBufferDataVec.data(),
8082                    resultBufferDataVec.size());
8083 
8084             flushAlloc(deviceInterface, deviceVk, resultBufferPtr->getAllocation());
8085         }
8086     }
8087 
8088     beginCommandBuffer(deviceInterface, *cmdBufferPtr, 0u /* flags */);
8089     {
8090         m_testPtr->initAS(m_context, m_rayTracingPropsPtr.get(), *cmdBufferPtr);
8091 
8092         std::vector<TopLevelAccelerationStructure *> tlasPtrVec = m_testPtr->getTLASPtrVecToBind();
8093         std::vector<VkAccelerationStructureKHR> tlasVkVec;
8094 
8095         for (auto &currentTLASPtr : tlasPtrVec)
8096         {
8097             tlasVkVec.push_back(*currentTLASPtr->getPtr());
8098         }
8099 
8100         if (m_testPtr->getResultBufferStartData().size() == 0)
8101         {
8102             deviceInterface.cmdFillBuffer(*cmdBufferPtr, **resultBufferPtr, 0, /* dstOffset */
8103                                           VK_WHOLE_SIZE, 0);                   /* data */
8104 
8105             {
8106                 const auto postFillBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, /* srcAccessMask */
8107                                                                      VK_ACCESS_SHADER_WRITE_BIT,   /* dstAccessMask */
8108                                                                      **resultBufferPtr, 0,         /* offset */
8109                                                                      VK_WHOLE_SIZE);
8110 
8111                 cmdPipelineBufferMemoryBarrier(deviceInterface, *cmdBufferPtr,
8112                                                VK_PIPELINE_STAGE_TRANSFER_BIT,               /* srcStageMask */
8113                                                VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, /* dstStageMask */
8114                                                &postFillBarrier);
8115             }
8116         }
8117 
8118         {
8119             VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
8120                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, //  VkStructureType sType;
8121                 DE_NULL,                                                           //  const void* pNext;
8122                 static_cast<uint32_t>(tlasVkVec.size()), //  uint32_t accelerationStructureCount;
8123                 tlasVkVec.data(),                        //  const VkAccelerationStructureKHR* pAccelerationStructures;
8124             };
8125 
8126             const auto descriptorResultBufferInfo = makeDescriptorBufferInfo(**resultBufferPtr, 0, /* offset */
8127                                                                              resultBufferSize);
8128 
8129             DescriptorSetUpdateBuilder()
8130                 .writeSingle(*descriptorSetPtr, DescriptorSetUpdateBuilder::Location::binding(0u),
8131                              VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorResultBufferInfo)
8132                 .writeArray(*descriptorSetPtr, DescriptorSetUpdateBuilder::Location::binding(1u),
8133                             VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, static_cast<uint32_t>(tlasVkVec.size()),
8134                             &accelerationStructureWriteDescriptorSet)
8135                 .update(deviceInterface, deviceVk);
8136         }
8137 
8138         deviceInterface.cmdBindDescriptorSets(*cmdBufferPtr, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayoutPtr,
8139                                               0,                          /* firstSet           */
8140                                               1,                          /* descriptorSetCount */
8141                                               &descriptorSetPtr.get(), 0, /* dynamicOffsetCount */
8142                                               DE_NULL);                   /* pDynamicOffsets    */
8143 
8144         deviceInterface.cmdBindPipeline(*cmdBufferPtr, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineVkPtr);
8145 
8146         {
8147             const auto preTraceMemoryBarrier =
8148                 (m_data.type == TestType::USE_MEMORY_ACCESS) ?
8149                     makeMemoryBarrier(VK_ACCESS_MEMORY_WRITE_BIT, /* srcAccessMask */
8150                                       VK_ACCESS_MEMORY_READ_BIT)  /* dstAccessMask */
8151                     :
8152                     makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, /* srcAccessMask */
8153                                       VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR); /* dstAccessMask */
8154 
8155             cmdPipelineMemoryBarrier(deviceInterface, *cmdBufferPtr,
8156                                      VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, /* srcStageMask */
8157                                      VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,           /* dstStageMask */
8158                                      &preTraceMemoryBarrier);
8159         }
8160 
8161         {
8162             const auto nTraceRaysInvocationsNeeded = m_testPtr->getNTraceRayInvocationsNeeded();
8163             const auto handleSize                  = m_rayTracingPropsPtr->getShaderGroupHandleSize();
8164             const auto missStride =
8165                 de::roundUp(handleSize + m_testPtr->getShaderRecordSize(ShaderGroups::MISS_GROUP), handleSize);
8166             const auto hitStride =
8167                 de::roundUp(handleSize + m_testPtr->getShaderRecordSize(ShaderGroups::HIT_GROUP), handleSize);
8168             const auto callStride = de::roundUp(
8169                 handleSize + m_testPtr->getShaderRecordSize(ShaderGroups::FIRST_CALLABLE_GROUP), handleSize);
8170             const auto raygenShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(
8171                 getBufferDeviceAddress(deviceInterface, deviceVk, raygenShaderBindingTablePtr->get(), 0 /* offset */),
8172                 handleSize, handleSize);
8173             const auto missShaderBindingTableRegion =
8174                 ((nMissGroups > 0u) ? makeStridedDeviceAddressRegionKHR(
8175                                           getBufferDeviceAddress(deviceInterface, deviceVk,
8176                                                                  missShaderBindingTablePtr->get(), 0 /* offset */),
8177                                           missStride, missStride * nMissGroups) :
8178                                       makeStridedDeviceAddressRegionKHR(DE_NULL, 0, /* stride */
8179                                                                         0 /* size   */));
8180             const auto hitShaderBindingTableRegion =
8181                 ((nHitGroups > 0u) ? makeStridedDeviceAddressRegionKHR(
8182                                          getBufferDeviceAddress(deviceInterface, deviceVk,
8183                                                                 hitShaderBindingTablePtr->get(), 0 /* offset */),
8184                                          hitStride, hitStride * nHitGroups) :
8185                                      makeStridedDeviceAddressRegionKHR(DE_NULL, 0, /* stride */
8186                                                                        0 /* size   */));
8187 
8188             const auto callableShaderBindingTableRegion =
8189                 (callableShaderCollectionNames.size() > 0) ?
8190                     makeStridedDeviceAddressRegionKHR(
8191                         getBufferDeviceAddress(deviceInterface, deviceVk, callableShaderBindingTablePtr->get(),
8192                                                0 /* offset */),
8193                         callStride, /* stride */
8194                         callStride * static_cast<uint32_t>(callableShaderCollectionNames.size())) :
8195                     makeStridedDeviceAddressRegionKHR(DE_NULL, 0, /* stride */
8196                                                       0 /* size   */);
8197 
8198             if (m_testPtr->usesDynamicStackSize())
8199             {
8200                 deviceInterface.cmdSetRayTracingPipelineStackSizeKHR(
8201                     *cmdBufferPtr, m_testPtr->getDynamicStackSize(m_testPtr->getMaxRecursionDepthUsed()));
8202             }
8203 
8204             for (uint32_t nInvocation = 0; nInvocation < nTraceRaysInvocationsNeeded; ++nInvocation)
8205             {
8206                 m_testPtr->onBeforeCmdTraceRays(nInvocation, m_context, *cmdBufferPtr, *pipelineLayoutPtr);
8207 
8208                 cmdTraceRays(deviceInterface, *cmdBufferPtr, &raygenShaderBindingTableRegion,
8209                              &missShaderBindingTableRegion, &hitShaderBindingTableRegion,
8210                              &callableShaderBindingTableRegion, m_testPtr->getDispatchSize()[0],
8211                              m_testPtr->getDispatchSize()[1], m_testPtr->getDispatchSize()[2]);
8212             }
8213         }
8214 
8215         {
8216             const auto postTraceMemoryBarrier = (m_data.type == TestType::USE_MEMORY_ACCESS) ?
8217                                                     makeMemoryBarrier(VK_ACCESS_MEMORY_WRITE_BIT, /* srcAccessMask */
8218                                                                       VK_ACCESS_MEMORY_READ_BIT)  /* dstAccessMask */
8219                                                     :
8220                                                     makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, /* srcAccessMask */
8221                                                                       VK_ACCESS_HOST_READ_BIT);   /* dstAccessMask */
8222 
8223             cmdPipelineMemoryBarrier(deviceInterface, *cmdBufferPtr,
8224                                      VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, /* srcStageMask */
8225                                      VK_PIPELINE_STAGE_HOST_BIT,                   /* dstStageMask */
8226                                      &postTraceMemoryBarrier);
8227         }
8228     }
8229     endCommandBuffer(deviceInterface, *cmdBufferPtr);
8230 
8231     submitCommandsAndWait(deviceInterface, deviceVk, queueVk, cmdBufferPtr.get());
8232 
8233     invalidateMappedMemoryRange(deviceInterface, deviceVk, resultBufferPtr->getAllocation().getMemory(),
8234                                 resultBufferPtr->getAllocation().getOffset(), VK_WHOLE_SIZE);
8235 
8236     m_testPtr->resetTLAS();
8237 
8238     return resultBufferPtr;
8239 }
8240 
iterate(void)8241 tcu::TestStatus RayTracingMiscTestInstance::iterate(void)
8242 {
8243     checkSupport();
8244 
8245     const de::MovePtr<BufferWithMemory> bufferGPUPtr = runTest();
8246     const uint32_t *bufferGPUDataPtr                 = (uint32_t *)bufferGPUPtr->getAllocation().getHostPtr();
8247     const bool result                                = m_testPtr->verifyResultBuffer(bufferGPUDataPtr);
8248 
8249     if (result)
8250         return tcu::TestStatus::pass("Pass");
8251     else
8252         return tcu::TestStatus::fail("Fail");
8253 }
8254 
checkRTPipelineSupport(Context & context)8255 void checkRTPipelineSupport(Context &context)
8256 {
8257     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
8258     context.requireDeviceFunctionality("VK_KHR_buffer_device_address");
8259     context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
8260 }
8261 
checkReuseCreationBufferSupport(Context & context,bool)8262 void checkReuseCreationBufferSupport(Context &context, bool)
8263 {
8264     checkRTPipelineSupport(context);
8265 }
8266 
initBasicHitBufferPrograms(vk::SourceCollections & programCollection)8267 void initBasicHitBufferPrograms(vk::SourceCollections &programCollection)
8268 {
8269     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
8270 
8271     std::ostringstream rgen;
8272     std::ostringstream chit;
8273 
8274     rgen << "#version 460\n"
8275          << "#extension GL_EXT_ray_tracing : require\n"
8276          << "layout(location=0) rayPayloadEXT vec3 unused;\n"
8277          << "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
8278          << "layout(set=0, binding=1) buffer OutputBuffer { float val; } outBuffer;\n"
8279          << "\n"
8280          << "void main()\n"
8281          << "{\n"
8282          << "  uint  rayFlags = 0u;\n"
8283          << "  uint  cullMask = 0xFFu;\n"
8284          << "  float tmin     = 0.0;\n"
8285          << "  float tmax     = 9.0;\n"
8286          << "  vec3  origin   = vec3(0.0, 0.0, 0.0);\n"
8287          << "  vec3  direct   = vec3(0.0, 0.0, 1.0);\n"
8288          << "  traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
8289          << "}\n";
8290 
8291     chit << "#version 460\n"
8292          << "#extension GL_EXT_ray_tracing : require\n"
8293          << "layout(location=0) rayPayloadInEXT vec3 unused;\n"
8294          << "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
8295          << "layout(set=0, binding=1) buffer OutputBuffer { float val; } outBuffer;\n"
8296          << "\n"
8297          << "void main()\n"
8298          << "{\n"
8299          << "  outBuffer.val = 1.0;\n"
8300          << "}\n";
8301 
8302     programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
8303     programCollection.glslSources.add("chit")
8304         << glu::ClosestHitSource(updateRayTracingGLSL(chit.str())) << buildOptions;
8305 }
8306 
initReuseCreationBufferPrograms(vk::SourceCollections & programCollection,bool)8307 void initReuseCreationBufferPrograms(vk::SourceCollections &programCollection, bool)
8308 {
8309     initBasicHitBufferPrograms(programCollection);
8310 }
8311 
8312 // Creates an empty shader binding table with a zeroed-out shader group handle.
createEmptySBT(const DeviceInterface & vkd,VkDevice device,Allocator & alloc,uint32_t shaderGroupHandleSize)8313 de::MovePtr<BufferWithMemory> createEmptySBT(const DeviceInterface &vkd, VkDevice device, Allocator &alloc,
8314                                              uint32_t shaderGroupHandleSize)
8315 {
8316     const auto sbtSize  = static_cast<VkDeviceSize>(shaderGroupHandleSize);
8317     const auto sbtFlags = (VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
8318                            VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
8319     const auto sbtInfo  = makeBufferCreateInfo(sbtSize, sbtFlags);
8320     const auto sbtReqs  = (MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress);
8321 
8322     auto sbtBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, alloc, sbtInfo, sbtReqs));
8323     auto &sbtAlloc = sbtBuffer->getAllocation();
8324     void *sbtData  = sbtAlloc.getHostPtr();
8325 
8326     deMemset(sbtData, 0, static_cast<size_t>(sbtSize));
8327     flushAlloc(vkd, device, sbtAlloc);
8328 
8329     return sbtBuffer;
8330 }
8331 
nullMissInstance(Context & context)8332 tcu::TestStatus nullMissInstance(Context &context)
8333 {
8334     const auto &vki    = context.getInstanceInterface();
8335     const auto physDev = context.getPhysicalDevice();
8336     const auto &vkd    = context.getDeviceInterface();
8337     const auto device  = context.getDevice();
8338     auto &alloc        = context.getDefaultAllocator();
8339     const auto qIndex  = context.getUniversalQueueFamilyIndex();
8340     const auto queue   = context.getUniversalQueue();
8341     const auto stages  = (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
8342 
8343     // Command pool and buffer.
8344     const auto cmdPool      = makeCommandPool(vkd, device, qIndex);
8345     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
8346     const auto cmdBuffer    = cmdBufferPtr.get();
8347 
8348     beginCommandBuffer(vkd, cmdBuffer);
8349 
8350     // Build acceleration structures.
8351     auto topLevelAS    = makeTopLevelAccelerationStructure();
8352     auto bottomLevelAS = makeBottomLevelAccelerationStructure();
8353 
8354     std::vector<tcu::Vec3> triangle;
8355     triangle.reserve(3u);
8356     triangle.emplace_back(0.0f, 1.0f, 10.0f);
8357     triangle.emplace_back(-1.0f, -1.0f, 10.0f);
8358     triangle.emplace_back(1.0f, -1.0f, 10.0f);
8359     bottomLevelAS->addGeometry(triangle, true /*triangles*/);
8360     bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
8361 
8362     de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr(bottomLevelAS.release());
8363     topLevelAS->setInstanceCount(1);
8364     topLevelAS->addInstance(blasSharedPtr);
8365     topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
8366 
8367     // Create output buffer.
8368     const auto bufferSize       = static_cast<VkDeviceSize>(sizeof(float));
8369     const auto bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
8370     BufferWithMemory buffer(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
8371     auto &bufferAlloc = buffer.getAllocation();
8372 
8373     // Fill output buffer with an initial value.
8374     deMemset(bufferAlloc.getHostPtr(), 0, sizeof(float));
8375     flushAlloc(vkd, device, bufferAlloc);
8376 
8377     // Descriptor set layout and pipeline layout.
8378     DescriptorSetLayoutBuilder setLayoutBuilder;
8379     setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
8380     setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
8381 
8382     const auto setLayout      = setLayoutBuilder.build(vkd, device);
8383     const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
8384 
8385     // Descriptor pool and set.
8386     DescriptorPoolBuilder poolBuilder;
8387     poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
8388     poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
8389     const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
8390     const auto descriptorSet  = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
8391 
8392     // Update descriptor set.
8393     {
8394         const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo = {
8395             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
8396             nullptr,
8397             1u,
8398             topLevelAS.get()->getPtr(),
8399         };
8400 
8401         const auto bufferDescInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, VK_WHOLE_SIZE);
8402 
8403         DescriptorSetUpdateBuilder updateBuilder;
8404         updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
8405                                   VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
8406         updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u),
8407                                   VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescInfo);
8408         updateBuilder.update(vkd, device);
8409     }
8410 
8411     // Shader modules.
8412     auto rgenModule = createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0);
8413     auto chitModule = createShaderModule(vkd, device, context.getBinaryCollection().get("chit"), 0);
8414 
8415     // Get some ray tracing properties.
8416     uint32_t shaderGroupHandleSize    = 0u;
8417     uint32_t shaderGroupBaseAlignment = 1u;
8418     {
8419         const auto rayTracingPropertiesKHR = makeRayTracingProperties(vki, physDev);
8420         shaderGroupHandleSize              = rayTracingPropertiesKHR->getShaderGroupHandleSize();
8421         shaderGroupBaseAlignment           = rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
8422     }
8423 
8424     // Create raytracing pipeline and shader binding tables.
8425     Move<VkPipeline> pipeline;
8426 
8427     de::MovePtr<BufferWithMemory> raygenSBT;
8428     de::MovePtr<BufferWithMemory> missSBT;
8429     de::MovePtr<BufferWithMemory> hitSBT;
8430     de::MovePtr<BufferWithMemory> callableSBT;
8431 
8432     VkStridedDeviceAddressRegionKHR raygenSBTRegion   = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8433     VkStridedDeviceAddressRegionKHR missSBTRegion     = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8434     VkStridedDeviceAddressRegionKHR hitSBTRegion      = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8435     VkStridedDeviceAddressRegionKHR callableSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8436 
8437     {
8438         const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
8439 
8440         rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0u);
8441         rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, 1u);
8442 
8443         pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
8444 
8445         raygenSBT = rayTracingPipeline->createShaderBindingTable(
8446             vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0u, 1u);
8447         raygenSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0ull),
8448                                                             shaderGroupHandleSize, shaderGroupHandleSize);
8449 
8450         hitSBT = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize,
8451                                                               shaderGroupBaseAlignment, 1u, 1u);
8452         hitSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitSBT->get(), 0ull),
8453                                                          shaderGroupHandleSize, shaderGroupHandleSize);
8454 
8455         // Critical for the test: the miss shader binding table buffer is empty and contains a zero'ed out shader group handle.
8456         missSBT       = createEmptySBT(vkd, device, alloc, shaderGroupHandleSize);
8457         missSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missSBT->get(), 0ull),
8458                                                           shaderGroupHandleSize, shaderGroupHandleSize);
8459     }
8460 
8461     // Trace rays.
8462     vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
8463     vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u,
8464                               &descriptorSet.get(), 0u, nullptr);
8465     vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, 1u, 1u, 1u);
8466 
8467     // Barrier for the output buffer just in case (no writes should take place).
8468     const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
8469     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u,
8470                            &bufferBarrier, 0u, nullptr, 0u, nullptr);
8471 
8472     endCommandBuffer(vkd, cmdBuffer);
8473     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
8474 
8475     // Read value back from the buffer. No write should have taken place.
8476     float bufferValue = 0.0f;
8477     invalidateAlloc(vkd, device, bufferAlloc);
8478     deMemcpy(&bufferValue, bufferAlloc.getHostPtr(), sizeof(bufferValue));
8479 
8480     if (bufferValue != 0.0f)
8481         TCU_FAIL("Unexpected value found in buffer: " + de::toString(bufferValue));
8482 
8483     return tcu::TestStatus::pass("Pass");
8484 }
8485 
getInRangeTrianglePoints(float offset)8486 std::vector<tcu::Vec3> getInRangeTrianglePoints(float offset)
8487 {
8488     std::vector<tcu::Vec3> triangle;
8489     triangle.reserve(3u);
8490     triangle.emplace_back(0.0f + offset, 1.0f + offset, 5.0f + offset);
8491     triangle.emplace_back(-1.0f + offset, -1.0f + offset, 5.0f + offset);
8492     triangle.emplace_back(1.0f + offset, -1.0f + offset, 5.0f + offset);
8493 
8494     return triangle;
8495 }
8496 
reuseCreationBufferInstance(Context & context,const bool disturbTop)8497 tcu::TestStatus reuseCreationBufferInstance(Context &context, const bool disturbTop /* if false, bottom AS */)
8498 {
8499     const auto &vki          = context.getInstanceInterface();
8500     const auto physDev       = context.getPhysicalDevice();
8501     const auto &vkd          = context.getDeviceInterface();
8502     const auto device        = context.getDevice();
8503     auto &alloc              = context.getDefaultAllocator();
8504     const auto qIndex        = context.getUniversalQueueFamilyIndex();
8505     const auto queue         = context.getUniversalQueue();
8506     const auto stages        = (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
8507     const bool disturbBottom = (!disturbTop);
8508 
8509     // We don't know exactly how much space each implementation is going to require to build the top and bottom accel structures,
8510     // but in practice the number appears to be in the low-KBs range, so creating a 4MB buffer will give us enough room to almost
8511     // guarantee the buffer is going to be used.
8512     const VkDeviceSize creationBufferSize = 4u * 1024u * 1024u;
8513     const auto creationBufferUsage =
8514         (VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
8515     const auto creationBufferInfo = makeBufferCreateInfo(creationBufferSize, creationBufferUsage);
8516     const auto creationBufferMemReqs =
8517         (MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
8518     BufferWithMemory creationBuffer(vkd, device, alloc, creationBufferInfo, creationBufferMemReqs);
8519 
8520     // Command pool and buffer.
8521     const auto cmdPool          = makeCommandPool(vkd, device, qIndex);
8522     const auto mainCmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
8523     const auto bottomBuildCmd   = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
8524     const auto topBuildCmd      = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
8525 
8526     // Build acceleration structures.
8527     auto topLevelAS         = makeTopLevelAccelerationStructure();
8528     auto topLevelOtherAS    = makeTopLevelAccelerationStructure();
8529     auto bottomLevelAS      = makeBottomLevelAccelerationStructure();
8530     auto bottomLevelOtherAS = makeBottomLevelAccelerationStructure();
8531 
8532     const auto goodTriangle = getInRangeTrianglePoints(0.0f);
8533     const auto badTriangle  = getInRangeTrianglePoints(100.0f);
8534 
8535     bottomLevelAS->addGeometry(goodTriangle, true /*triangles*/);
8536     bottomLevelOtherAS->addGeometry(badTriangle, true /*triangles*/);
8537 
8538     // Critical for the test: we create an additional acceleration structure without building it, and reusing the same creation
8539     // buffer. The creation operation is supposed to avoid touching the buffer, so this should not alter its contents and using the
8540     // original acceleration structure after this step should still work.
8541 
8542     beginCommandBuffer(vkd, bottomBuildCmd.get());
8543 
8544     if (disturbBottom)
8545     {
8546         bottomLevelAS->create(vkd, device, alloc, 0u, 0u, nullptr, MemoryRequirement::Any, creationBuffer.get(),
8547                               creationBufferSize);
8548         bottomLevelAS->build(vkd, device, bottomBuildCmd.get());
8549     }
8550     else
8551         bottomLevelAS->createAndBuild(vkd, device, bottomBuildCmd.get(), alloc);
8552 
8553     // Submit command buffer so the bottom acceleration structure is actually built and stored in the creation buffer.
8554     endCommandBuffer(vkd, bottomBuildCmd.get());
8555     submitCommandsAndWait(vkd, device, queue, bottomBuildCmd.get());
8556 
8557     if (disturbBottom)
8558     {
8559         bottomLevelOtherAS->create(vkd, device, alloc, 0u, 0u, nullptr, MemoryRequirement::Any, creationBuffer.get(),
8560                                    creationBufferSize);
8561         // Note how we have created the second bottom level accel structure reusing the buffer but we haven't built it.
8562     }
8563 
8564     using SharedBottomPtr = de::SharedPtr<BottomLevelAccelerationStructure>;
8565 
8566     SharedBottomPtr blasSharedPtr(bottomLevelAS.release());
8567     SharedBottomPtr blasOtherSharedPtr(nullptr);
8568 
8569     topLevelAS->setInstanceCount(1);
8570     topLevelAS->addInstance(blasSharedPtr);
8571 
8572     beginCommandBuffer(vkd, topBuildCmd.get());
8573 
8574     if (disturbTop)
8575     {
8576         topLevelAS->create(vkd, device, alloc, 0u, 0u, nullptr, MemoryRequirement::Any, creationBuffer.get(),
8577                            creationBufferSize);
8578         topLevelAS->build(vkd, device, topBuildCmd.get());
8579 
8580         bottomLevelOtherAS->createAndBuild(vkd, device, topBuildCmd.get(), alloc);
8581     }
8582     else
8583         topLevelAS->createAndBuild(vkd, device, topBuildCmd.get(), alloc);
8584 
8585     // Submit command buffer so the top acceleration structure is actually built and stored in the creation buffer.
8586     endCommandBuffer(vkd, topBuildCmd.get());
8587     submitCommandsAndWait(vkd, device, queue, topBuildCmd.get());
8588 
8589     if (disturbTop)
8590     {
8591         SharedBottomPtr auxiliar(bottomLevelOtherAS.release());
8592         blasOtherSharedPtr.swap(auxiliar);
8593 
8594         topLevelOtherAS->setInstanceCount(1);
8595         topLevelOtherAS->addInstance(blasOtherSharedPtr);
8596         topLevelOtherAS->create(vkd, device, alloc, 0u, 0u, nullptr, MemoryRequirement::Any, creationBuffer.get(),
8597                                 creationBufferSize);
8598         // Note how we have created the second top level accel structure reusing the buffer but we haven't built it.
8599     }
8600 
8601     // Create output buffer.
8602     const auto bufferSize       = static_cast<VkDeviceSize>(sizeof(float));
8603     const auto bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
8604     BufferWithMemory buffer(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
8605     auto &bufferAlloc = buffer.getAllocation();
8606 
8607     // Fill output buffer with an initial value.
8608     deMemset(bufferAlloc.getHostPtr(), 0, sizeof(float));
8609     flushAlloc(vkd, device, bufferAlloc);
8610 
8611     // Descriptor set layout and pipeline layout.
8612     DescriptorSetLayoutBuilder setLayoutBuilder;
8613     setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
8614     setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
8615 
8616     const auto setLayout      = setLayoutBuilder.build(vkd, device);
8617     const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
8618 
8619     // Descriptor pool and set.
8620     DescriptorPoolBuilder poolBuilder;
8621     poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
8622     poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
8623     const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
8624     const auto descriptorSet  = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
8625 
8626     // Update descriptor set.
8627     {
8628         const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo = {
8629             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
8630             nullptr,
8631             1u,
8632             topLevelAS.get()->getPtr(),
8633         };
8634 
8635         const auto bufferDescInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, VK_WHOLE_SIZE);
8636 
8637         DescriptorSetUpdateBuilder updateBuilder;
8638         updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
8639                                   VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
8640         updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u),
8641                                   VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescInfo);
8642         updateBuilder.update(vkd, device);
8643     }
8644 
8645     // Shader modules.
8646     auto rgenModule = createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0);
8647     auto chitModule = createShaderModule(vkd, device, context.getBinaryCollection().get("chit"), 0);
8648 
8649     // Get some ray tracing properties.
8650     uint32_t shaderGroupHandleSize    = 0u;
8651     uint32_t shaderGroupBaseAlignment = 1u;
8652     {
8653         const auto rayTracingPropertiesKHR = makeRayTracingProperties(vki, physDev);
8654         shaderGroupHandleSize              = rayTracingPropertiesKHR->getShaderGroupHandleSize();
8655         shaderGroupBaseAlignment           = rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
8656     }
8657 
8658     // Create raytracing pipeline and shader binding tables.
8659     Move<VkPipeline> pipeline;
8660 
8661     de::MovePtr<BufferWithMemory> raygenSBT;
8662     de::MovePtr<BufferWithMemory> missSBT;
8663     de::MovePtr<BufferWithMemory> hitSBT;
8664     de::MovePtr<BufferWithMemory> callableSBT;
8665 
8666     VkStridedDeviceAddressRegionKHR raygenSBTRegion   = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8667     VkStridedDeviceAddressRegionKHR missSBTRegion     = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8668     VkStridedDeviceAddressRegionKHR hitSBTRegion      = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8669     VkStridedDeviceAddressRegionKHR callableSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
8670 
8671     {
8672         const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
8673 
8674         rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0u);
8675         rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, 1u);
8676 
8677         pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
8678 
8679         raygenSBT = rayTracingPipeline->createShaderBindingTable(
8680             vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0u, 1u);
8681         raygenSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0ull),
8682                                                             shaderGroupHandleSize, shaderGroupHandleSize);
8683 
8684         hitSBT = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize,
8685                                                               shaderGroupBaseAlignment, 1u, 1u);
8686         hitSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitSBT->get(), 0ull),
8687                                                          shaderGroupHandleSize, shaderGroupHandleSize);
8688     }
8689 
8690     const auto mainCmdBuffer = mainCmdBufferPtr.get();
8691     beginCommandBuffer(vkd, mainCmdBuffer);
8692 
8693     // Trace rays.
8694     vkd.cmdBindPipeline(mainCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
8695     vkd.cmdBindDescriptorSets(mainCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u,
8696                               &descriptorSet.get(), 0u, nullptr);
8697     vkd.cmdTraceRaysKHR(mainCmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, 1u, 1u, 1u);
8698 
8699     // Barrier for the output buffer.
8700     const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
8701     vkd.cmdPipelineBarrier(mainCmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_HOST_BIT, 0u,
8702                            1u, &bufferBarrier, 0u, nullptr, 0u, nullptr);
8703 
8704     endCommandBuffer(vkd, mainCmdBuffer);
8705     submitCommandsAndWait(vkd, device, queue, mainCmdBuffer);
8706 
8707     // Read value back from the buffer.
8708     float bufferValue = 0.0f;
8709     invalidateAlloc(vkd, device, bufferAlloc);
8710     deMemcpy(&bufferValue, bufferAlloc.getHostPtr(), sizeof(bufferValue));
8711 
8712     if (bufferValue != 1.0f)
8713         TCU_FAIL("Unexpected value found in buffer: " + de::toString(bufferValue));
8714 
8715     return tcu::TestStatus::pass("Pass");
8716 }
8717 
8718 } // namespace
8719 
8720 class RayTracingTestCase : public TestCase
8721 {
8722 public:
8723     RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
8724     ~RayTracingTestCase(void);
8725 
8726     virtual void checkSupport(Context &context) const final;
8727     virtual TestInstance *createInstance(Context &context) const final;
8728     void initPrograms(SourceCollections &programCollection) const final;
8729 
8730 private:
8731     CaseDef m_data;
8732     mutable std::unique_ptr<TestBase> m_testPtr;
8733 };
8734 
RayTracingTestCase(tcu::TestContext & context,const char * name,const CaseDef data)8735 RayTracingTestCase::RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
8736     : vkt::TestCase(context, name)
8737     , m_data(data)
8738 {
8739     /* Stub */
8740 }
8741 
~RayTracingTestCase(void)8742 RayTracingTestCase::~RayTracingTestCase(void)
8743 {
8744 }
8745 
checkSupport(Context & context) const8746 void RayTracingTestCase::checkSupport(Context &context) const
8747 {
8748     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
8749     context.requireDeviceFunctionality("VK_KHR_buffer_device_address");
8750     context.requireDeviceFunctionality("VK_KHR_deferred_host_operations");
8751     context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
8752 
8753     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
8754         context.getAccelerationStructureFeatures();
8755     const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
8756         context.getRayTracingPipelineFeatures();
8757     const auto &rayTracingPipelinePropertiesKHR = context.getRayTracingPipelineProperties();
8758 
8759     if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
8760     {
8761         TCU_THROW(NotSupportedError, "VkPhysicalDeviceRayTracingPipelineFeaturesKHR::rayTracingPipeline is false");
8762     }
8763 
8764     if (accelerationStructureFeaturesKHR.accelerationStructure == false)
8765     {
8766         TCU_THROW(NotSupportedError,
8767                   "VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure is false");
8768     }
8769 
8770     if (ShaderRecordBlockTest::isTest(m_data.type))
8771     {
8772         if (ShaderRecordBlockTest::isExplicitScalarOffsetTest(m_data.type) ||
8773             ShaderRecordBlockTest::isScalarLayoutTest(m_data.type))
8774         {
8775             context.requireDeviceFunctionality("VK_EXT_scalar_block_layout");
8776         }
8777 
8778         if (ShaderRecordBlockTest::usesF64(m_data.type))
8779         {
8780             context.requireDeviceCoreFeature(vkt::DeviceCoreFeature::DEVICE_CORE_FEATURE_SHADER_FLOAT64);
8781         }
8782 
8783         if (ShaderRecordBlockTest::usesI8(m_data.type) || ShaderRecordBlockTest::usesU8(m_data.type))
8784         {
8785             if (context.get8BitStorageFeatures().storageBuffer8BitAccess == VK_FALSE)
8786             {
8787                 TCU_THROW(NotSupportedError, "storageBuffer8BitAccess feature is unavailable");
8788             }
8789         }
8790 
8791         if (ShaderRecordBlockTest::usesI16(m_data.type) || ShaderRecordBlockTest::usesU16(m_data.type))
8792         {
8793             context.requireDeviceCoreFeature(vkt::DeviceCoreFeature::DEVICE_CORE_FEATURE_SHADER_INT16);
8794         }
8795 
8796         if (ShaderRecordBlockTest::usesI64(m_data.type) || ShaderRecordBlockTest::usesU64(m_data.type))
8797         {
8798             context.requireDeviceCoreFeature(vkt::DeviceCoreFeature::DEVICE_CORE_FEATURE_SHADER_INT64);
8799         }
8800     }
8801 
8802     if (static_cast<uint32_t>(m_data.type) >= static_cast<uint32_t>(TestType::RECURSIVE_TRACES_1) &&
8803         static_cast<uint32_t>(m_data.type) <= static_cast<uint32_t>(TestType::RECURSIVE_TRACES_29))
8804     {
8805         const auto nLevels =
8806             static_cast<uint32_t>(m_data.type) - static_cast<uint32_t>(TestType::RECURSIVE_TRACES_1) + 1;
8807 
8808         if (rayTracingPipelinePropertiesKHR.maxRayRecursionDepth < nLevels)
8809         {
8810             TCU_THROW(NotSupportedError, "Cannot use an unsupported ray recursion depth.");
8811         }
8812     }
8813 }
8814 
initPrograms(SourceCollections & programCollection) const8815 void RayTracingTestCase::initPrograms(SourceCollections &programCollection) const
8816 {
8817     switch (m_data.type)
8818     {
8819     case TestType::AABBS_AND_TRIS_IN_ONE_TL:
8820     {
8821         m_testPtr.reset(new AABBTriTLTest(m_data.geometryType, m_data.asLayout));
8822 
8823         m_testPtr->initPrograms(programCollection);
8824 
8825         break;
8826     }
8827 
8828     case TestType::AS_STRESS_TEST:
8829     {
8830         m_testPtr.reset(new ASStressTest(m_data.geometryType, m_data.asLayout));
8831 
8832         m_testPtr->initPrograms(programCollection);
8833 
8834         break;
8835     }
8836 
8837     case TestType::CALLABLE_SHADER_STRESS_DYNAMIC_TEST:
8838     case TestType::CALLABLE_SHADER_STRESS_TEST:
8839     {
8840         const bool useDynamicStackSize = (m_data.type == TestType::CALLABLE_SHADER_STRESS_DYNAMIC_TEST);
8841 
8842         m_testPtr.reset(new CallableShaderStressTest(m_data.geometryType, m_data.asLayout, useDynamicStackSize));
8843 
8844         m_testPtr->initPrograms(programCollection);
8845 
8846         break;
8847     }
8848 
8849     case TestType::CULL_MASK:
8850     case TestType::CULL_MASK_EXTRA_BITS:
8851     {
8852         m_testPtr.reset(
8853             new CullMaskTest(m_data.asLayout, m_data.geometryType, (m_data.type == TestType::CULL_MASK_EXTRA_BITS)));
8854 
8855         m_testPtr->initPrograms(programCollection);
8856 
8857         break;
8858     }
8859 
8860     case TestType::MAX_RAY_HIT_ATTRIBUTE_SIZE:
8861     {
8862         m_testPtr.reset(new MAXRayHitAttributeSizeTest(m_data.geometryType, m_data.asLayout));
8863 
8864         m_testPtr->initPrograms(programCollection);
8865 
8866         break;
8867     }
8868 
8869     case TestType::MAX_RT_INVOCATIONS_SUPPORTED:
8870     {
8871         m_testPtr.reset(new MAXRTInvocationsSupportedTest(m_data.geometryType, m_data.asLayout));
8872 
8873         m_testPtr->initPrograms(programCollection);
8874 
8875         break;
8876     }
8877 
8878     case TestType::NO_DUPLICATE_ANY_HIT:
8879     {
8880         m_testPtr.reset(new NoDuplicateAnyHitTest(m_data.asLayout, m_data.geometryType));
8881 
8882         m_testPtr->initPrograms(programCollection);
8883 
8884         break;
8885     }
8886 
8887     case TestType::RECURSIVE_TRACES_0:
8888     case TestType::RECURSIVE_TRACES_1:
8889     case TestType::RECURSIVE_TRACES_2:
8890     case TestType::RECURSIVE_TRACES_3:
8891     case TestType::RECURSIVE_TRACES_4:
8892     case TestType::RECURSIVE_TRACES_5:
8893     case TestType::RECURSIVE_TRACES_6:
8894     case TestType::RECURSIVE_TRACES_7:
8895     case TestType::RECURSIVE_TRACES_8:
8896     case TestType::RECURSIVE_TRACES_9:
8897     case TestType::RECURSIVE_TRACES_10:
8898     case TestType::RECURSIVE_TRACES_11:
8899     case TestType::RECURSIVE_TRACES_12:
8900     case TestType::RECURSIVE_TRACES_13:
8901     case TestType::RECURSIVE_TRACES_14:
8902     case TestType::RECURSIVE_TRACES_15:
8903     case TestType::RECURSIVE_TRACES_16:
8904     case TestType::RECURSIVE_TRACES_17:
8905     case TestType::RECURSIVE_TRACES_18:
8906     case TestType::RECURSIVE_TRACES_19:
8907     case TestType::RECURSIVE_TRACES_20:
8908     case TestType::RECURSIVE_TRACES_21:
8909     case TestType::RECURSIVE_TRACES_22:
8910     case TestType::RECURSIVE_TRACES_23:
8911     case TestType::RECURSIVE_TRACES_24:
8912     case TestType::RECURSIVE_TRACES_25:
8913     case TestType::RECURSIVE_TRACES_26:
8914     case TestType::RECURSIVE_TRACES_27:
8915     case TestType::RECURSIVE_TRACES_28:
8916     case TestType::RECURSIVE_TRACES_29:
8917     {
8918         const auto nLevels =
8919             ((m_data.type == TestType::RECURSIVE_TRACES_0) ?
8920                  0u :
8921                  (static_cast<uint32_t>(m_data.type) - static_cast<uint32_t>(TestType::RECURSIVE_TRACES_1) + 1));
8922 
8923         m_testPtr.reset(new RecursiveTracesTest(m_data.geometryType, m_data.asLayout, nLevels));
8924 
8925         m_testPtr->initPrograms(programCollection);
8926 
8927         break;
8928     }
8929 
8930     case TestType::REPORT_INTERSECTION_RESULT:
8931     case TestType::USE_MEMORY_ACCESS:
8932     {
8933         m_testPtr.reset(new ReportIntersectionResultTest(m_data.asLayout, m_data.geometryType));
8934 
8935         m_testPtr->initPrograms(programCollection);
8936 
8937         break;
8938     }
8939 
8940     case TestType::RAY_PAYLOAD_IN:
8941     {
8942         m_testPtr.reset(new RayPayloadInTest(m_data.geometryType, m_data.asLayout));
8943 
8944         m_testPtr->initPrograms(programCollection);
8945 
8946         break;
8947     }
8948 
8949     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1:
8950     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2:
8951     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3:
8952     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4:
8953     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5:
8954     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6:
8955     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1:
8956     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2:
8957     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3:
8958     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4:
8959     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5:
8960     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6:
8961     case TestType::SHADER_RECORD_BLOCK_SCALAR_1:
8962     case TestType::SHADER_RECORD_BLOCK_SCALAR_2:
8963     case TestType::SHADER_RECORD_BLOCK_SCALAR_3:
8964     case TestType::SHADER_RECORD_BLOCK_SCALAR_4:
8965     case TestType::SHADER_RECORD_BLOCK_SCALAR_5:
8966     case TestType::SHADER_RECORD_BLOCK_SCALAR_6:
8967     case TestType::SHADER_RECORD_BLOCK_STD430_1:
8968     case TestType::SHADER_RECORD_BLOCK_STD430_2:
8969     case TestType::SHADER_RECORD_BLOCK_STD430_3:
8970     case TestType::SHADER_RECORD_BLOCK_STD430_4:
8971     case TestType::SHADER_RECORD_BLOCK_STD430_5:
8972     case TestType::SHADER_RECORD_BLOCK_STD430_6:
8973     {
8974         m_testPtr.reset(new ShaderRecordBlockTest(m_data.type, ShaderRecordBlockTest::getVarsToTest(m_data.type)));
8975 
8976         m_testPtr->initPrograms(programCollection);
8977 
8978         break;
8979     }
8980 
8981     case TestType::IGNORE_ANY_HIT_DYNAMICALLY:
8982     case TestType::IGNORE_ANY_HIT_STATICALLY:
8983     case TestType::TERMINATE_ANY_HIT_DYNAMICALLY:
8984     case TestType::TERMINATE_ANY_HIT_STATICALLY:
8985     case TestType::TERMINATE_INTERSECTION_DYNAMICALLY:
8986     case TestType::TERMINATE_INTERSECTION_STATICALLY:
8987     {
8988         m_testPtr.reset(new TerminationTest(TerminationTest::getModeFromTestType(m_data.type)));
8989 
8990         m_testPtr->initPrograms(programCollection);
8991 
8992         break;
8993     }
8994 
8995     default:
8996     {
8997         deAssertFail("This location should never be reached", __FILE__, __LINE__);
8998     }
8999     }
9000 }
9001 
createInstance(Context & context) const9002 TestInstance *RayTracingTestCase::createInstance(Context &context) const
9003 {
9004     switch (m_data.type)
9005     {
9006     case TestType::AABBS_AND_TRIS_IN_ONE_TL:
9007     {
9008         if (m_testPtr == nullptr)
9009         {
9010             m_testPtr.reset(new AABBTriTLTest(m_data.geometryType, m_data.asLayout));
9011         }
9012 
9013         break;
9014     }
9015 
9016     case TestType::AS_STRESS_TEST:
9017     {
9018         if (m_testPtr == nullptr)
9019         {
9020             m_testPtr.reset(new ASStressTest(m_data.geometryType, m_data.asLayout));
9021         }
9022 
9023         break;
9024     }
9025 
9026     case TestType::CALLABLE_SHADER_STRESS_DYNAMIC_TEST:
9027     case TestType::CALLABLE_SHADER_STRESS_TEST:
9028     {
9029         if (m_testPtr == nullptr)
9030         {
9031             const bool useDynamicStackSize = (m_data.type == TestType::CALLABLE_SHADER_STRESS_DYNAMIC_TEST);
9032 
9033             m_testPtr.reset(new CallableShaderStressTest(m_data.geometryType, m_data.asLayout, useDynamicStackSize));
9034         }
9035 
9036         break;
9037     }
9038 
9039     case TestType::CULL_MASK:
9040     case TestType::CULL_MASK_EXTRA_BITS:
9041     {
9042         if (m_testPtr == nullptr)
9043         {
9044             m_testPtr.reset(new CullMaskTest(m_data.asLayout, m_data.geometryType,
9045                                              (m_data.type == TestType::CULL_MASK_EXTRA_BITS)));
9046         }
9047 
9048         break;
9049     }
9050 
9051     case TestType::MAX_RAY_HIT_ATTRIBUTE_SIZE:
9052     {
9053         if (m_testPtr == nullptr)
9054         {
9055             m_testPtr.reset(new MAXRayHitAttributeSizeTest(m_data.geometryType, m_data.asLayout));
9056         }
9057 
9058         break;
9059     }
9060 
9061     case TestType::MAX_RT_INVOCATIONS_SUPPORTED:
9062     {
9063         if (m_testPtr == nullptr)
9064         {
9065             m_testPtr.reset(new MAXRTInvocationsSupportedTest(m_data.geometryType, m_data.asLayout));
9066         }
9067 
9068         break;
9069     }
9070 
9071     case TestType::NO_DUPLICATE_ANY_HIT:
9072     {
9073         if (m_testPtr == nullptr)
9074         {
9075             m_testPtr.reset(new NoDuplicateAnyHitTest(m_data.asLayout, m_data.geometryType));
9076         }
9077 
9078         break;
9079     }
9080 
9081     case TestType::RECURSIVE_TRACES_0:
9082     case TestType::RECURSIVE_TRACES_1:
9083     case TestType::RECURSIVE_TRACES_2:
9084     case TestType::RECURSIVE_TRACES_3:
9085     case TestType::RECURSIVE_TRACES_4:
9086     case TestType::RECURSIVE_TRACES_5:
9087     case TestType::RECURSIVE_TRACES_6:
9088     case TestType::RECURSIVE_TRACES_7:
9089     case TestType::RECURSIVE_TRACES_8:
9090     case TestType::RECURSIVE_TRACES_9:
9091     case TestType::RECURSIVE_TRACES_10:
9092     case TestType::RECURSIVE_TRACES_11:
9093     case TestType::RECURSIVE_TRACES_12:
9094     case TestType::RECURSIVE_TRACES_13:
9095     case TestType::RECURSIVE_TRACES_14:
9096     case TestType::RECURSIVE_TRACES_15:
9097     case TestType::RECURSIVE_TRACES_16:
9098     case TestType::RECURSIVE_TRACES_17:
9099     case TestType::RECURSIVE_TRACES_18:
9100     case TestType::RECURSIVE_TRACES_19:
9101     case TestType::RECURSIVE_TRACES_20:
9102     case TestType::RECURSIVE_TRACES_21:
9103     case TestType::RECURSIVE_TRACES_22:
9104     case TestType::RECURSIVE_TRACES_23:
9105     case TestType::RECURSIVE_TRACES_24:
9106     case TestType::RECURSIVE_TRACES_25:
9107     case TestType::RECURSIVE_TRACES_26:
9108     case TestType::RECURSIVE_TRACES_27:
9109     case TestType::RECURSIVE_TRACES_28:
9110     case TestType::RECURSIVE_TRACES_29:
9111     {
9112         const auto nLevels =
9113             ((m_data.type == TestType::RECURSIVE_TRACES_0) ?
9114                  0u :
9115                  (static_cast<uint32_t>(m_data.type) - static_cast<uint32_t>(TestType::RECURSIVE_TRACES_1) + 1));
9116 
9117         if (m_testPtr == nullptr)
9118         {
9119             m_testPtr.reset(new RecursiveTracesTest(m_data.geometryType, m_data.asLayout, nLevels));
9120         }
9121 
9122         break;
9123     }
9124 
9125     case TestType::REPORT_INTERSECTION_RESULT:
9126     case TestType::USE_MEMORY_ACCESS:
9127     {
9128         if (m_testPtr == nullptr)
9129         {
9130             m_testPtr.reset(new ReportIntersectionResultTest(m_data.asLayout, m_data.geometryType));
9131         }
9132 
9133         break;
9134     }
9135 
9136     case TestType::RAY_PAYLOAD_IN:
9137     {
9138         if (m_testPtr == nullptr)
9139         {
9140             m_testPtr.reset(new RayPayloadInTest(m_data.geometryType, m_data.asLayout));
9141         }
9142 
9143         break;
9144     }
9145 
9146     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1:
9147     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2:
9148     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3:
9149     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4:
9150     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5:
9151     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6:
9152     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1:
9153     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2:
9154     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3:
9155     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4:
9156     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5:
9157     case TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6:
9158     case TestType::SHADER_RECORD_BLOCK_SCALAR_1:
9159     case TestType::SHADER_RECORD_BLOCK_SCALAR_2:
9160     case TestType::SHADER_RECORD_BLOCK_SCALAR_3:
9161     case TestType::SHADER_RECORD_BLOCK_SCALAR_4:
9162     case TestType::SHADER_RECORD_BLOCK_SCALAR_5:
9163     case TestType::SHADER_RECORD_BLOCK_SCALAR_6:
9164     case TestType::SHADER_RECORD_BLOCK_STD430_1:
9165     case TestType::SHADER_RECORD_BLOCK_STD430_2:
9166     case TestType::SHADER_RECORD_BLOCK_STD430_3:
9167     case TestType::SHADER_RECORD_BLOCK_STD430_4:
9168     case TestType::SHADER_RECORD_BLOCK_STD430_5:
9169     case TestType::SHADER_RECORD_BLOCK_STD430_6:
9170     {
9171         if (m_testPtr == nullptr)
9172         {
9173             m_testPtr.reset(new ShaderRecordBlockTest(m_data.type, ShaderRecordBlockTest::getVarsToTest(m_data.type)));
9174         }
9175 
9176         break;
9177     }
9178 
9179     case TestType::IGNORE_ANY_HIT_DYNAMICALLY:
9180     case TestType::IGNORE_ANY_HIT_STATICALLY:
9181     case TestType::TERMINATE_ANY_HIT_DYNAMICALLY:
9182     case TestType::TERMINATE_ANY_HIT_STATICALLY:
9183     case TestType::TERMINATE_INTERSECTION_DYNAMICALLY:
9184     case TestType::TERMINATE_INTERSECTION_STATICALLY:
9185     {
9186         if (m_testPtr == nullptr)
9187         {
9188             m_testPtr.reset(new TerminationTest(TerminationTest::getModeFromTestType(m_data.type)));
9189         }
9190 
9191         break;
9192     }
9193 
9194     default:
9195     {
9196         deAssertFail("This location should never be reached", __FILE__, __LINE__);
9197     }
9198     }
9199 
9200     auto newTestInstancePtr = new RayTracingMiscTestInstance(context, m_data, m_testPtr.get());
9201 
9202     return newTestInstancePtr;
9203 }
9204 
createMiscTests(tcu::TestContext & testCtx)9205 tcu::TestCaseGroup *createMiscTests(tcu::TestContext &testCtx)
9206 {
9207     de::MovePtr<tcu::TestCaseGroup> miscGroupPtr(
9208         // Miscellaneous ray-tracing tests
9209         new tcu::TestCaseGroup(testCtx, "misc"));
9210 
9211     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9212          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9213     {
9214         for (auto currentASLayout = AccelerationStructureLayout::FIRST;
9215              currentASLayout != AccelerationStructureLayout::COUNT;
9216              currentASLayout = static_cast<AccelerationStructureLayout>(static_cast<uint32_t>(currentASLayout) + 1))
9217         {
9218             for (uint32_t nIteration = 0; nIteration < 2; ++nIteration)
9219             {
9220                 const auto testType = (nIteration == 0) ? TestType::CALLABLE_SHADER_STRESS_DYNAMIC_TEST :
9221                                                           TestType::CALLABLE_SHADER_STRESS_TEST;
9222                 const std::string newTestCaseName =
9223                     "callableshaderstress_" + de::toString(getSuffixForASLayout(currentASLayout)) + "_" +
9224                     de::toString(getSuffixForGeometryType(currentGeometryType)) + "_" +
9225                     ((testType == TestType::CALLABLE_SHADER_STRESS_DYNAMIC_TEST) ? "dynamic" : "static");
9226 
9227                 // Verifies that the maximum ray hit attribute size property reported by the implementation is actually supported.
9228                 auto newTestCasePtr = new RayTracingTestCase(testCtx, newTestCaseName.data(),
9229                                                              CaseDef{testType, currentGeometryType, currentASLayout});
9230 
9231                 miscGroupPtr->addChild(newTestCasePtr);
9232             }
9233         }
9234     }
9235 
9236     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9237          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9238     {
9239         const std::string newTestCaseName =
9240             "AS_stresstest_" + de::toString(getSuffixForGeometryType(currentGeometryType));
9241 
9242         // Verifies raygen shader invocations can simultaneously access as many AS instances as reported
9243         auto newTestCasePtr =
9244             new RayTracingTestCase(testCtx, newTestCaseName.data(),
9245                                    CaseDef{TestType::AS_STRESS_TEST, currentGeometryType,
9246                                            AccelerationStructureLayout::ONE_TL_MANY_BLS_ONE_GEOMETRY});
9247 
9248         miscGroupPtr->addChild(newTestCasePtr);
9249     }
9250 
9251     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9252          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9253     {
9254         for (int nUseExtraCullMaskBits = 0; nUseExtraCullMaskBits < 2 /* false, true */; ++nUseExtraCullMaskBits)
9255         {
9256             const std::string newTestCaseName = "cullmask_" +
9257                                                 de::toString(getSuffixForGeometryType(currentGeometryType)) +
9258                                                 de::toString((nUseExtraCullMaskBits) ? "_extrabits" : "");
9259             const auto testType = (nUseExtraCullMaskBits == 0) ? TestType::CULL_MASK : TestType::CULL_MASK_EXTRA_BITS;
9260 
9261             // Verifies cull mask works as specified
9262             auto newTestCasePtr = new RayTracingTestCase(
9263                 testCtx, newTestCaseName.data(),
9264                 CaseDef{testType, currentGeometryType, AccelerationStructureLayout::ONE_TL_MANY_BLS_ONE_GEOMETRY});
9265 
9266             miscGroupPtr->addChild(newTestCasePtr);
9267         }
9268     }
9269 
9270     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9271          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9272     {
9273         const std::string newTestCaseName =
9274             "maxrtinvocations_" + de::toString(getSuffixForGeometryType(currentGeometryType));
9275 
9276         // Verifies top-level acceleration structures built of AABB and triangle bottom-level AS instances work as expected
9277         auto newTestCasePtr =
9278             new RayTracingTestCase(testCtx, newTestCaseName.data(),
9279                                    CaseDef{TestType::MAX_RT_INVOCATIONS_SUPPORTED, currentGeometryType,
9280                                            AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9281 
9282         miscGroupPtr->addChild(newTestCasePtr);
9283     }
9284 
9285     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9286          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9287     {
9288         for (auto currentASLayout = AccelerationStructureLayout::FIRST;
9289              currentASLayout != AccelerationStructureLayout::COUNT;
9290              currentASLayout = static_cast<AccelerationStructureLayout>(static_cast<uint32_t>(currentASLayout) + 1))
9291         {
9292             const std::string newTestCaseName = "NO_DUPLICATE_ANY_HIT_" +
9293                                                 de::toString(getSuffixForASLayout(currentASLayout)) + "_" +
9294                                                 de::toString(getSuffixForGeometryType(currentGeometryType));
9295 
9296             // Verifies the NO_DUPLICATE_ANY_HIT flag is adhered to when tracing rays
9297             auto newTestCasePtr =
9298                 new RayTracingTestCase(testCtx, newTestCaseName.data(),
9299                                        CaseDef{TestType::NO_DUPLICATE_ANY_HIT, currentGeometryType, currentASLayout});
9300 
9301             miscGroupPtr->addChild(newTestCasePtr);
9302         }
9303     }
9304 
9305     {
9306         // Verifies top-level acceleration structures built of AABB and triangle bottom-level AS instances work as expected
9307         auto newTestCasePtr = new RayTracingTestCase(
9308             testCtx, "mixedPrimTL",
9309             CaseDef{TestType::AABBS_AND_TRIS_IN_ONE_TL, GeometryType::AABB_AND_TRIANGLES,
9310                     AccelerationStructureLayout::ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES});
9311 
9312         miscGroupPtr->addChild(newTestCasePtr);
9313     }
9314 
9315     for (auto currentASLayout = AccelerationStructureLayout::FIRST;
9316          currentASLayout != AccelerationStructureLayout::COUNT;
9317          currentASLayout = static_cast<AccelerationStructureLayout>(static_cast<uint32_t>(currentASLayout) + 1))
9318     {
9319         const std::string newTestCaseName =
9320             "maxrayhitattributesize_" + de::toString(getSuffixForASLayout(currentASLayout));
9321 
9322         // Verifies that the maximum ray hit attribute size property reported by the implementation is actually supported.
9323         auto newTestCasePtr = new RayTracingTestCase(testCtx, newTestCaseName.data(),
9324                                                      CaseDef{TestType::MAX_RAY_HIT_ATTRIBUTE_SIZE, GeometryType::AABB,
9325                                                              AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9326 
9327         miscGroupPtr->addChild(newTestCasePtr);
9328     }
9329 
9330     {
9331         // Test the return value of reportIntersectionEXT
9332         auto newTestCase1Ptr = new RayTracingTestCase(testCtx, "report_intersection_result",
9333                                                       CaseDef{TestType::REPORT_INTERSECTION_RESULT, GeometryType::AABB,
9334                                                               AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9335         // Test replacing VK_ACCESS_*_WRITE/READ_BIT with VK_ACCESS_MEMORY_WRITE/READ_BIT.
9336         auto newTestCase2Ptr = new RayTracingTestCase(testCtx, "memory_access",
9337                                                       CaseDef{TestType::USE_MEMORY_ACCESS, GeometryType::AABB,
9338                                                               AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9339 
9340         miscGroupPtr->addChild(newTestCase1Ptr);
9341         miscGroupPtr->addChild(newTestCase2Ptr);
9342     }
9343 
9344     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9345          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9346     {
9347         const std::string newTestCaseName =
9348             "raypayloadin_" + de::toString(getSuffixForGeometryType(currentGeometryType));
9349 
9350         // Verifies that relevant shader stages can correctly read large ray payloads provided by raygen shader stage.
9351         auto newTestCasePtr = new RayTracingTestCase(testCtx, newTestCaseName.data(),
9352                                                      CaseDef{TestType::RAY_PAYLOAD_IN, currentGeometryType,
9353                                                              AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9354         miscGroupPtr->addChild(newTestCasePtr);
9355     }
9356 
9357     {
9358         // Tests usage of various variables inside a shader record block using std430 layout
9359         auto newTestCaseSTD430_1Ptr =
9360             new RayTracingTestCase(testCtx, "shaderRecordSTD430_1", CaseDef(TestType::SHADER_RECORD_BLOCK_STD430_1));
9361         auto newTestCaseSTD430_2Ptr =
9362             new RayTracingTestCase(testCtx, "shaderRecordSTD430_2", CaseDef(TestType::SHADER_RECORD_BLOCK_STD430_2));
9363         auto newTestCaseSTD430_3Ptr =
9364             new RayTracingTestCase(testCtx, "shaderRecordSTD430_3", CaseDef(TestType::SHADER_RECORD_BLOCK_STD430_3));
9365         auto newTestCaseSTD430_4Ptr =
9366             new RayTracingTestCase(testCtx, "shaderRecordSTD430_4", CaseDef(TestType::SHADER_RECORD_BLOCK_STD430_4));
9367         auto newTestCaseSTD430_5Ptr =
9368             new RayTracingTestCase(testCtx, "shaderRecordSTD430_5", CaseDef(TestType::SHADER_RECORD_BLOCK_STD430_5));
9369         auto newTestCaseSTD430_6Ptr =
9370             new RayTracingTestCase(testCtx, "shaderRecordSTD430_6", CaseDef(TestType::SHADER_RECORD_BLOCK_STD430_6));
9371 
9372         // Tests usage of various variables inside a shader record block using scalar layout
9373         auto newTestCaseScalar_1Ptr =
9374             new RayTracingTestCase(testCtx, "shaderRecordScalar_1", CaseDef(TestType::SHADER_RECORD_BLOCK_SCALAR_1));
9375         auto newTestCaseScalar_2Ptr =
9376             new RayTracingTestCase(testCtx, "shaderRecordScalar_2", CaseDef(TestType::SHADER_RECORD_BLOCK_SCALAR_2));
9377         auto newTestCaseScalar_3Ptr =
9378             new RayTracingTestCase(testCtx, "shaderRecordScalar_3", CaseDef(TestType::SHADER_RECORD_BLOCK_SCALAR_3));
9379         auto newTestCaseScalar_4Ptr =
9380             new RayTracingTestCase(testCtx, "shaderRecordScalar_4", CaseDef(TestType::SHADER_RECORD_BLOCK_SCALAR_4));
9381         auto newTestCaseScalar_5Ptr =
9382             new RayTracingTestCase(testCtx, "shaderRecordScalar_5", CaseDef(TestType::SHADER_RECORD_BLOCK_SCALAR_5));
9383         auto newTestCaseScalar_6Ptr =
9384             new RayTracingTestCase(testCtx, "shaderRecordScalar_6", CaseDef(TestType::SHADER_RECORD_BLOCK_SCALAR_6));
9385 
9386         // Tests usage of various variables inside a shader record block using scalar layout and explicit offset qualifiers
9387         auto newTestCaseExplicitScalarOffset_1Ptr =
9388             new RayTracingTestCase(testCtx, "shaderRecordExplicitScalarOffset_1",
9389                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1));
9390         auto newTestCaseExplicitScalarOffset_2Ptr =
9391             new RayTracingTestCase(testCtx, "shaderRecordExplicitScalarOffset_2",
9392                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2));
9393         auto newTestCaseExplicitScalarOffset_3Ptr =
9394             new RayTracingTestCase(testCtx, "shaderRecordExplicitScalarOffset_3",
9395                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3));
9396         auto newTestCaseExplicitScalarOffset_4Ptr =
9397             new RayTracingTestCase(testCtx, "shaderRecordExplicitScalarOffset_4",
9398                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4));
9399         auto newTestCaseExplicitScalarOffset_5Ptr =
9400             new RayTracingTestCase(testCtx, "shaderRecordExplicitScalarOffset_5",
9401                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5));
9402         auto newTestCaseExplicitScalarOffset_6Ptr =
9403             new RayTracingTestCase(testCtx, "shaderRecordExplicitScalarOffset_6",
9404                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6));
9405 
9406         // Tests usage of various variables inside a shader record block using std430 layout and explicit offset qualifiers
9407         auto newTestCaseExplicitSTD430Offset_1Ptr =
9408             new RayTracingTestCase(testCtx, "shaderRecordExplicitSTD430Offset_1",
9409                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1));
9410         auto newTestCaseExplicitSTD430Offset_2Ptr =
9411             new RayTracingTestCase(testCtx, "shaderRecordExplicitSTD430Offset_2",
9412                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2));
9413         auto newTestCaseExplicitSTD430Offset_3Ptr =
9414             new RayTracingTestCase(testCtx, "shaderRecordExplicitSTD430Offset_3",
9415                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3));
9416         auto newTestCaseExplicitSTD430Offset_4Ptr =
9417             new RayTracingTestCase(testCtx, "shaderRecordExplicitSTD430Offset_4",
9418                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4));
9419         auto newTestCaseExplicitSTD430Offset_5Ptr =
9420             new RayTracingTestCase(testCtx, "shaderRecordExplicitSTD430Offset_5",
9421                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5));
9422         auto newTestCaseExplicitSTD430Offset_6Ptr =
9423             new RayTracingTestCase(testCtx, "shaderRecordExplicitSTD430Offset_6",
9424                                    CaseDef(TestType::SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6));
9425         miscGroupPtr->addChild(newTestCaseSTD430_1Ptr);
9426         miscGroupPtr->addChild(newTestCaseSTD430_2Ptr);
9427         miscGroupPtr->addChild(newTestCaseSTD430_3Ptr);
9428         miscGroupPtr->addChild(newTestCaseSTD430_4Ptr);
9429         miscGroupPtr->addChild(newTestCaseSTD430_5Ptr);
9430         miscGroupPtr->addChild(newTestCaseSTD430_6Ptr);
9431 
9432         miscGroupPtr->addChild(newTestCaseScalar_1Ptr);
9433         miscGroupPtr->addChild(newTestCaseScalar_2Ptr);
9434         miscGroupPtr->addChild(newTestCaseScalar_3Ptr);
9435         miscGroupPtr->addChild(newTestCaseScalar_4Ptr);
9436         miscGroupPtr->addChild(newTestCaseScalar_5Ptr);
9437         miscGroupPtr->addChild(newTestCaseScalar_6Ptr);
9438 
9439         miscGroupPtr->addChild(newTestCaseExplicitScalarOffset_1Ptr);
9440         miscGroupPtr->addChild(newTestCaseExplicitScalarOffset_2Ptr);
9441         miscGroupPtr->addChild(newTestCaseExplicitScalarOffset_3Ptr);
9442         miscGroupPtr->addChild(newTestCaseExplicitScalarOffset_4Ptr);
9443         miscGroupPtr->addChild(newTestCaseExplicitScalarOffset_5Ptr);
9444         miscGroupPtr->addChild(newTestCaseExplicitScalarOffset_6Ptr);
9445 
9446         miscGroupPtr->addChild(newTestCaseExplicitSTD430Offset_1Ptr);
9447         miscGroupPtr->addChild(newTestCaseExplicitSTD430Offset_2Ptr);
9448         miscGroupPtr->addChild(newTestCaseExplicitSTD430Offset_3Ptr);
9449         miscGroupPtr->addChild(newTestCaseExplicitSTD430Offset_4Ptr);
9450         miscGroupPtr->addChild(newTestCaseExplicitSTD430Offset_5Ptr);
9451         miscGroupPtr->addChild(newTestCaseExplicitSTD430Offset_6Ptr);
9452     }
9453 
9454     for (auto currentGeometryType = GeometryType::FIRST; currentGeometryType != GeometryType::COUNT;
9455          currentGeometryType      = static_cast<GeometryType>(static_cast<uint32_t>(currentGeometryType) + 1))
9456     {
9457         const std::string newTestCaseName =
9458             "recursiveTraces_" + de::toString(getSuffixForGeometryType(currentGeometryType)) + "_";
9459 
9460         // 0 recursion levels.
9461         {
9462             // Verifies that relevant shader stages can correctly read large ray payloads provided by raygen shader stage.
9463             auto newTestCasePtr =
9464                 new RayTracingTestCase(testCtx, (newTestCaseName + "0").data(),
9465                                        CaseDef{TestType::RECURSIVE_TRACES_0, currentGeometryType,
9466                                                AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9467 
9468             miscGroupPtr->addChild(newTestCasePtr);
9469         }
9470 
9471         // TODO: for (uint32_t nLevels = 1; nLevels <= 29; ++nLevels)
9472         for (uint32_t nLevels = 1; nLevels <= 15; ++nLevels)
9473         {
9474             // Verifies that relevant shader stages can correctly read large ray payloads provided by raygen shader stage.
9475             auto newTestCasePtr = new RayTracingTestCase(
9476                 testCtx, (newTestCaseName + de::toString(nLevels)).data(),
9477                 CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::RECURSIVE_TRACES_1) + (nLevels - 1)),
9478                         currentGeometryType, AccelerationStructureLayout::ONE_TL_ONE_BL_ONE_GEOMETRY});
9479 
9480             miscGroupPtr->addChild(newTestCasePtr);
9481         }
9482     }
9483 
9484     {
9485         // Verifies that OpIgnoreIntersectionKHR works as per spec (static invocations).
9486         auto newTestCase1Ptr = new RayTracingTestCase(
9487             testCtx, "OpIgnoreIntersectionKHR_AnyHitStatically",
9488             CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::IGNORE_ANY_HIT_STATICALLY)),
9489                     GeometryType::TRIANGLES, AccelerationStructureLayout::COUNT});
9490         // Verifies that OpIgnoreIntersectionKHR works as per spec (dynamic invocations).
9491         auto newTestCase2Ptr = new RayTracingTestCase(
9492             testCtx, "OpIgnoreIntersectionKHR_AnyHitDynamically",
9493             CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::IGNORE_ANY_HIT_DYNAMICALLY)),
9494                     GeometryType::TRIANGLES, AccelerationStructureLayout::COUNT});
9495         // Verifies that OpTerminateRayKHR works as per spec (static invocations).
9496         auto newTestCase3Ptr = new RayTracingTestCase(
9497             testCtx, "OpTerminateRayKHR_AnyHitStatically",
9498             CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::TERMINATE_ANY_HIT_STATICALLY)),
9499                     GeometryType::TRIANGLES, AccelerationStructureLayout::COUNT});
9500         // Verifies that OpTerminateRayKHR works as per spec (dynamic invocations).
9501         auto newTestCase4Ptr = new RayTracingTestCase(
9502             testCtx, "OpTerminateRayKHR_AnyHitDynamically",
9503             CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::TERMINATE_ANY_HIT_DYNAMICALLY)),
9504                     GeometryType::TRIANGLES, AccelerationStructureLayout::COUNT});
9505         // Verifies that OpTerminateRayKHR works as per spec (static invocations).
9506         auto newTestCase5Ptr = new RayTracingTestCase(
9507             testCtx, "OpTerminateRayKHR_IntersectionStatically",
9508             CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::TERMINATE_INTERSECTION_STATICALLY)),
9509                     GeometryType::AABB, AccelerationStructureLayout::COUNT});
9510         // Verifies that OpTerminateRayKHR works as per spec (dynamic invocations).
9511         auto newTestCase6Ptr = new RayTracingTestCase(
9512             testCtx, "OpTerminateRayKHR_IntersectionDynamically",
9513             CaseDef{static_cast<TestType>(static_cast<uint32_t>(TestType::TERMINATE_INTERSECTION_DYNAMICALLY)),
9514                     GeometryType::AABB, AccelerationStructureLayout::COUNT});
9515 
9516         miscGroupPtr->addChild(newTestCase1Ptr);
9517         miscGroupPtr->addChild(newTestCase2Ptr);
9518         miscGroupPtr->addChild(newTestCase3Ptr);
9519         miscGroupPtr->addChild(newTestCase4Ptr);
9520         miscGroupPtr->addChild(newTestCase5Ptr);
9521         miscGroupPtr->addChild(newTestCase6Ptr);
9522     }
9523 
9524     {
9525         addFunctionCaseWithPrograms(miscGroupPtr.get(), "null_miss", checkRTPipelineSupport, initBasicHitBufferPrograms,
9526                                     nullMissInstance);
9527         addFunctionCaseWithPrograms(miscGroupPtr.get(), "reuse_creation_buffer_top", checkReuseCreationBufferSupport,
9528                                     initReuseCreationBufferPrograms, reuseCreationBufferInstance, true /*top*/);
9529         addFunctionCaseWithPrograms(miscGroupPtr.get(), "reuse_creation_buffer_bottom", checkReuseCreationBufferSupport,
9530                                     initReuseCreationBufferPrograms, reuseCreationBufferInstance, false /*top*/);
9531     }
9532 
9533     return miscGroupPtr.release();
9534 }
9535 
9536 } // namespace RayTracing
9537 } // namespace vkt
9538