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