• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *	  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Ray Tracing Misc tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingMiscTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 
27 #include "vkDefs.hpp"
28 
29 #include "vktTestCase.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 
38 #include "vkRayTracingUtil.hpp"
39 
40 #include "deRandom.hpp"
41 #include <algorithm>
42 #include <memory>
43 #include <sstream>
44 
45 namespace vkt
46 {
47 namespace RayTracing
48 {
49 namespace
50 {
51 using namespace vk;
52 using namespace std;
53 
54 enum class BaseType
55 {
56 	F32,
57 	F64,
58 	I8,
59 	I16,
60 	I32,
61 	I64,
62 	U8,
63 	U16,
64 	U32,
65 	U64,
66 
67 	UNKNOWN
68 };
69 
70 enum class GeometryType
71 {
72 	FIRST = 0,
73 
74 	AABB		= FIRST,
75 	TRIANGLES,
76 
77 	COUNT,
78 
79 	AABB_AND_TRIANGLES, //< Only compatible with ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES AS layout.
80 };
81 
82 enum class MatrixMajorOrder
83 {
84 	COLUMN_MAJOR,
85 	ROW_MAJOR,
86 
87 	UNKNOWN
88 };
89 
90 enum class ShaderGroups
91 {
92 	FIRST_GROUP		= 0,
93 	RAYGEN_GROUP	= FIRST_GROUP,
94 	MISS_GROUP,
95 	HIT_GROUP,
96 
97 	FIRST_CALLABLE_GROUP,
98 };
99 
100 enum class TestType
101 {
102 	AABBS_AND_TRIS_IN_ONE_TL,
103 	AS_STRESS_TEST,
104 	CALLABLE_SHADER_STRESS_DYNAMIC_TEST,
105 	CALLABLE_SHADER_STRESS_TEST,
106 	CULL_MASK,
107 	MAX_RAY_HIT_ATTRIBUTE_SIZE,
108 	MAX_RT_INVOCATIONS_SUPPORTED,
109 	CULL_MASK_EXTRA_BITS,
110 	NO_DUPLICATE_ANY_HIT,
111 	REPORT_INTERSECTION_RESULT,
112 	RAY_PAYLOAD_IN,
113 	RECURSIVE_TRACES_0,
114 	RECURSIVE_TRACES_1,
115 	RECURSIVE_TRACES_2,
116 	RECURSIVE_TRACES_3,
117 	RECURSIVE_TRACES_4,
118 	RECURSIVE_TRACES_5,
119 	RECURSIVE_TRACES_6,
120 	RECURSIVE_TRACES_7,
121 	RECURSIVE_TRACES_8,
122 	RECURSIVE_TRACES_9,
123 	RECURSIVE_TRACES_10,
124 	RECURSIVE_TRACES_11,
125 	RECURSIVE_TRACES_12,
126 	RECURSIVE_TRACES_13,
127 	RECURSIVE_TRACES_14,
128 	RECURSIVE_TRACES_15,
129 	RECURSIVE_TRACES_16,
130 	RECURSIVE_TRACES_17,
131 	RECURSIVE_TRACES_18,
132 	RECURSIVE_TRACES_19,
133 	RECURSIVE_TRACES_20,
134 	RECURSIVE_TRACES_21,
135 	RECURSIVE_TRACES_22,
136 	RECURSIVE_TRACES_23,
137 	RECURSIVE_TRACES_24,
138 	RECURSIVE_TRACES_25,
139 	RECURSIVE_TRACES_26,
140 	RECURSIVE_TRACES_27,
141 	RECURSIVE_TRACES_28,
142 	RECURSIVE_TRACES_29,
143 	SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_1,
144 	SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_2,
145 	SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_3,
146 	SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_4,
147 	SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_5,
148 	SHADER_RECORD_BLOCK_EXPLICIT_SCALAR_OFFSET_6,
149 	SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_1,
150 	SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_2,
151 	SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_3,
152 	SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_4,
153 	SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_5,
154 	SHADER_RECORD_BLOCK_EXPLICIT_STD430_OFFSET_6,
155 	SHADER_RECORD_BLOCK_SCALAR_1,
156 	SHADER_RECORD_BLOCK_SCALAR_2,
157 	SHADER_RECORD_BLOCK_SCALAR_3,
158 	SHADER_RECORD_BLOCK_SCALAR_4,
159 	SHADER_RECORD_BLOCK_SCALAR_5,
160 	SHADER_RECORD_BLOCK_SCALAR_6,
161 	SHADER_RECORD_BLOCK_STD430_1,
162 	SHADER_RECORD_BLOCK_STD430_2,
163 	SHADER_RECORD_BLOCK_STD430_3,
164 	SHADER_RECORD_BLOCK_STD430_4,
165 	SHADER_RECORD_BLOCK_STD430_5,
166 	SHADER_RECORD_BLOCK_STD430_6,
167 	IGNORE_ANY_HIT_STATICALLY,
168 	IGNORE_ANY_HIT_DYNAMICALLY,
169 	TERMINATE_ANY_HIT_STATICALLY,
170 	TERMINATE_ANY_HIT_DYNAMICALLY,
171 	TERMINATE_INTERSECTION_STATICALLY,
172 	TERMINATE_INTERSECTION_DYNAMICALLY,
173 	USE_MEMORY_ACCESS,
174 
175 	COUNT
176 };
177 
178 enum class VariableType
179 {
180 	FIRST,
181 
182 	FLOAT = FIRST,
183 	VEC2,
184 	VEC3,
185 	VEC4,
186 
187 	MAT2,
188 	MAT2X2,
189 	MAT2X3,
190 	MAT2X4,
191 	MAT3,
192 	MAT3X2,
193 	MAT3X3,
194 	MAT3X4,
195 	MAT4,
196 	MAT4X2,
197 	MAT4X3,
198 	MAT4X4,
199 
200 	INT,
201 	IVEC2,
202 	IVEC3,
203 	IVEC4,
204 
205 	INT8,
206 	I8VEC2,
207 	I8VEC3,
208 	I8VEC4,
209 
210 	INT16,
211 	I16VEC2,
212 	I16VEC3,
213 	I16VEC4,
214 
215 	INT64,
216 	I64VEC2,
217 	I64VEC3,
218 	I64VEC4,
219 
220 	UINT,
221 	UVEC2,
222 	UVEC3,
223 	UVEC4,
224 
225 	UINT16,
226 	U16VEC2,
227 	U16VEC3,
228 	U16VEC4,
229 
230 	UINT64,
231 	U64VEC2,
232 	U64VEC3,
233 	U64VEC4,
234 
235 	UINT8,
236 	U8VEC2,
237 	U8VEC3,
238 	U8VEC4,
239 
240 	DOUBLE,
241 	DVEC2,
242 	DVEC3,
243 	DVEC4,
244 
245 	DMAT2,
246 	DMAT2X2,
247 	DMAT2X3,
248 	DMAT2X4,
249 	DMAT3,
250 	DMAT3X2,
251 	DMAT3X3,
252 	DMAT3X4,
253 	DMAT4,
254 	DMAT4X2,
255 	DMAT4X3,
256 	DMAT4X4,
257 
258 	UNKNOWN,
259 	COUNT = UNKNOWN,
260 };
261 
262 enum class AccelerationStructureLayout
263 {
264 	FIRST = 0,
265 
266 	ONE_TL_ONE_BL_ONE_GEOMETRY    = FIRST,
267 	ONE_TL_ONE_BL_MANY_GEOMETRIES,
268 	ONE_TL_MANY_BLS_ONE_GEOMETRY,
269 	ONE_TL_MANY_BLS_MANY_GEOMETRIES,
270 
271 	COUNT,
272 
273 	ONE_TL_MANY_BLS_MANY_GEOMETRIES_WITH_VARYING_PRIM_TYPES
274 };
275 
276 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
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