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