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