• 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 Acceleration Structures tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingAccelerationStructuresTests.hpp"
25 
26 #include "vkDefs.hpp"
27 #include "deClock.h"
28 #include "deRandom.h"
29 
30 #include "vktTestCase.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBufferWithMemory.hpp"
37 #include "vkImageWithMemory.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkRayTracingUtil.hpp"
41 #include "tcuVectorUtil.hpp"
42 #include "tcuTexture.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuFloat.hpp"
46 
47 #include <set>
48 
49 namespace vkt
50 {
51 namespace RayTracing
52 {
53 namespace
54 {
55 using namespace vk;
56 using namespace vkt;
57 
58 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
59 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
60 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
61 												| VK_SHADER_STAGE_MISS_BIT_KHR
62 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
63 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
64 
65 
66 enum BottomTestType
67 {
68 	BTT_TRIANGLES,
69 	BTT_AABBS
70 };
71 
72 enum TopTestType
73 {
74 	TTT_IDENTICAL_INSTANCES,
75 	TTT_DIFFERENT_INSTANCES
76 };
77 
78 enum OperationTarget
79 {
80 	OT_NONE,
81 	OT_TOP_ACCELERATION,
82 	OT_BOTTOM_ACCELERATION
83 };
84 
85 enum OperationType
86 {
87 	OP_NONE,
88 	OP_COPY,
89 	OP_COMPACT,
90 	OP_SERIALIZE
91 };
92 
93 enum class InstanceCullFlags
94 {
95 	NONE,
96 	CULL_DISABLE,
97 	COUNTERCLOCKWISE,
98 	ALL,
99 };
100 
101 enum class EmptyAccelerationStructureCase
102 {
103 	NOT_EMPTY				= 0,
104 	INACTIVE_TRIANGLES		= 1,
105 	INACTIVE_INSTANCES		= 2,
106 	NO_GEOMETRIES_BOTTOM	= 3,	// geometryCount zero when building.
107 	NO_PRIMITIVES_BOTTOM	= 4,	// primitiveCount zero when building.
108 	NO_PRIMITIVES_TOP		= 5,	// primitiveCount zero when building.
109 };
110 
111 enum class InstanceCustomIndexCase
112 {
113 	NONE			= 0,
114 	CLOSEST_HIT		= 1,
115 	ANY_HIT			= 2,
116 	INTERSECTION	= 3,
117 };
118 
119 static const deUint32 RTAS_DEFAULT_SIZE = 8u;
120 
121 // Chosen to have the most significant bit set to 1 when represented using 24 bits.
122 // This will make sure the instance custom index will not be sign-extended by mistake.
123 constexpr deUint32 INSTANCE_CUSTOM_INDEX_BASE = 0x807f00u;
124 
125 struct TestParams;
126 
127 class TestConfiguration
128 {
129 public:
130 	virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
131 																												 TestParams&						testParams) = 0;
132 	virtual de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
133 																												 TestParams&						testParams,
134 																												 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) = 0;
135 	virtual void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
136 																												 Context&							context,
137 																												TestParams&							testParams) = 0;
138 	virtual void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
139 																												 Context&							context,
140 																												 TestParams&						testParams,
141 																												 VkPipeline							pipeline,
142 																												 deUint32							shaderGroupHandleSize,
143 																												 deUint32							shaderGroupBaseAlignment,
144 																												 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
145 																												 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
146 																												 de::MovePtr<BufferWithMemory>&		missShaderBindingTable) = 0;
147 	virtual bool															verifyImage							(BufferWithMemory*					resultBuffer,
148 																												 Context&							context,
149 																												 TestParams&						testParams) = 0;
150 	virtual VkFormat														getResultImageFormat				() = 0;
151 	virtual size_t															getResultImageFormatSize			() = 0;
152 	virtual VkClearValue													getClearValue						() = 0;
153 };
154 
155 struct TestParams
156 {
157 	vk::VkAccelerationStructureBuildTypeKHR	buildType;		// are we making AS on CPU or GPU
158 	VkFormat								vertexFormat;
159 	bool									padVertices;
160 	VkIndexType								indexType;
161 	BottomTestType							bottomTestType; // what kind of geometry is stored in bottom AS
162 	InstanceCullFlags						cullFlags;		// Flags for instances, if needed.
163 	bool									bottomUsesAOP;	// does bottom AS use arrays, or arrays of pointers
164 	bool									bottomGeneric;	// Bottom created as generic AS type.
165 	TopTestType								topTestType;	// If instances are identical then bottom geometries must have different vertices/aabbs
166 	bool									topUsesAOP;		// does top AS use arrays, or arrays of pointers
167 	bool									topGeneric;		// Top created as generic AS type.
168 	VkBuildAccelerationStructureFlagsKHR	buildFlags;
169 	OperationTarget							operationTarget;
170 	OperationType							operationType;
171 	deUint32								width;
172 	deUint32								height;
173 	de::SharedPtr<TestConfiguration>		testConfiguration;
174 	deUint32								workerThreadsCount;
175 	EmptyAccelerationStructureCase			emptyASCase;
176 	InstanceCustomIndexCase					instanceCustomIndexCase;
177 };
178 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)179 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
180 							 const VkPhysicalDevice		physicalDevice)
181 {
182 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
183 
184 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
185 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
186 }
187 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)188 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
189 									  const VkPhysicalDevice	physicalDevice)
190 {
191 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
192 
193 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
194 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
195 }
196 
makeImageCreateInfo(deUint32 width,deUint32 height,VkFormat format)197 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, VkFormat format)
198 {
199 	const VkImageCreateInfo			imageCreateInfo			=
200 	{
201 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
202 		DE_NULL,																							// const void*				pNext;
203 		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
204 		VK_IMAGE_TYPE_2D,																					// VkImageType				imageType;
205 		format,																								// VkFormat					format;
206 		makeExtent3D(width, height, 1u),																	// VkExtent3D				extent;
207 		1u,																									// deUint32					mipLevels;
208 		1u,																									// deUint32					arrayLayers;
209 		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
210 		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
211 		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
212 		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
213 		0u,																									// deUint32					queueFamilyIndexCount;
214 		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
215 		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
216 	};
217 
218 	return imageCreateInfo;
219 }
220 
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,deUint32 queryCount)221 Move<VkQueryPool> makeQueryPool(const DeviceInterface&		vk,
222 								const VkDevice				device,
223 								const VkQueryType			queryType,
224 								deUint32					queryCount)
225 {
226 	const VkQueryPoolCreateInfo				queryPoolCreateInfo =
227 	{
228 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// sType
229 		DE_NULL,										// pNext
230 		(VkQueryPoolCreateFlags)0,						// flags
231 		queryType,										// queryType
232 		queryCount,										// queryCount
233 		0u,												// pipelineStatistics
234 	};
235 	return createQueryPool(vk, device, &queryPoolCreateInfo);
236 }
237 
getCullFlags(InstanceCullFlags flags)238 VkGeometryInstanceFlagsKHR getCullFlags (InstanceCullFlags flags)
239 {
240 	VkGeometryInstanceFlagsKHR cullFlags = 0u;
241 
242 	if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
243 		cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
244 
245 	if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
246 		cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
247 
248 	return cullFlags;
249 }
250 
251 class CheckerboardConfiguration : public TestConfiguration
252 {
253 public:
254 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
255 																										 TestParams&						testParams) override;
256 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
257 																										 TestParams&						testParams,
258 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
259 	void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
260 																										 Context&							context,
261 																										 TestParams&						testParams) override;
262 	void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
263 																										 Context&							context,
264 																										 TestParams&						testParams,
265 																										 VkPipeline							pipeline,
266 																										 deUint32							shaderGroupHandleSize,
267 																										 deUint32							shaderGroupBaseAlignment,
268 																										 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
269 																										 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
270 																										 de::MovePtr<BufferWithMemory>&		missShaderBindingTable) override;
271 	bool															verifyImage							(BufferWithMemory*					resultBuffer,
272 																										 Context&							context,
273 																										 TestParams&						testParams) override;
274 	VkFormat														getResultImageFormat				() override;
275 	size_t															getResultImageFormatSize			() override;
276 	VkClearValue													getClearValue						() override;
277 };
278 
initBottomAccelerationStructures(Context & context,TestParams & testParams)279 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > CheckerboardConfiguration::initBottomAccelerationStructures (Context&			context,
280 																														   TestParams&		testParams)
281 {
282 	DE_UNREF(context);
283 
284 	// Cull flags can only be used with triangles.
285 	DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE || testParams.bottomTestType == BTT_TRIANGLES);
286 
287 	// Checkerboard configuration does not support empty geometry tests.
288 	DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
289 
290 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
291 
292 	const auto instanceFlags = getCullFlags(testParams.cullFlags);
293 
294 	tcu::Vec3 v0(0.0, 1.0, 0.0);
295 	tcu::Vec3 v1(0.0, 0.0, 0.0);
296 	tcu::Vec3 v2(1.0, 1.0, 0.0);
297 	tcu::Vec3 v3(1.0, 0.0, 0.0);
298 
299 	if (testParams.topTestType == TTT_DIFFERENT_INSTANCES)
300 	{
301 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
302 		bottomLevelAccelerationStructure->setGeometryCount(1u);
303 		de::SharedPtr<RaytracedGeometryBase> geometry;
304 		if (testParams.bottomTestType == BTT_TRIANGLES)
305 		{
306 			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
307 			if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
308 			{
309 				if (instanceFlags == 0u)
310 				{
311 					geometry->addVertex(v0);
312 					geometry->addVertex(v1);
313 					geometry->addVertex(v2);
314 					geometry->addVertex(v2);
315 					geometry->addVertex(v1);
316 					geometry->addVertex(v3);
317 				}
318 				else // Counterclockwise so the flags will be needed for the geometry to be visible.
319 				{
320 					geometry->addVertex(v2);
321 					geometry->addVertex(v1);
322 					geometry->addVertex(v0);
323 					geometry->addVertex(v3);
324 					geometry->addVertex(v1);
325 					geometry->addVertex(v2);
326 				}
327 			}
328 			else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
329 			{
330 				geometry->addVertex(v0);
331 				geometry->addVertex(v1);
332 				geometry->addVertex(v2);
333 				geometry->addVertex(v3);
334 
335 				if (instanceFlags == 0u)
336 				{
337 					geometry->addIndex(0);
338 					geometry->addIndex(1);
339 					geometry->addIndex(2);
340 					geometry->addIndex(2);
341 					geometry->addIndex(1);
342 					geometry->addIndex(3);
343 				}
344 				else // Counterclockwise so the flags will be needed for the geometry to be visible.
345 				{
346 					geometry->addIndex(2);
347 					geometry->addIndex(1);
348 					geometry->addIndex(0);
349 					geometry->addIndex(3);
350 					geometry->addIndex(1);
351 					geometry->addIndex(2);
352 				}
353 			}
354 		}
355 		else // m_data.bottomTestType == BTT_AABBS
356 		{
357 			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
358 
359 			if (!testParams.padVertices)
360 			{
361 				// Single AABB.
362 				geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
363 				geometry->addVertex(tcu::Vec3(1.0f, 1.0f,  0.1f));
364 			}
365 			else
366 			{
367 				// Multiple AABBs covering the same space.
368 				geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
369 				geometry->addVertex(tcu::Vec3(0.5f, 0.5f,  0.1f));
370 
371 				geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
372 				geometry->addVertex(tcu::Vec3(1.0f, 1.0f,  0.1f));
373 
374 				geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
375 				geometry->addVertex(tcu::Vec3(0.5f, 1.0f,  0.1f));
376 
377 				geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
378 				geometry->addVertex(tcu::Vec3(1.0f, 0.5f,  0.1f));
379 			}
380 		}
381 
382 		bottomLevelAccelerationStructure->addGeometry(geometry);
383 
384 		if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
385 			geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
386 
387 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
388 	}
389 	else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
390 	{
391 		// triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
392 		for (deUint32 y = 0; y < testParams.height; ++y)
393 		for (deUint32 x = 0; x < testParams.width; ++x)
394 		{
395 			// let's build a chessboard of geometries
396 			if (((x + y) % 2) == 0)
397 				continue;
398 			tcu::Vec3 xyz((float)x, (float)y, 0.0f);
399 
400 			de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
401 			bottomLevelAccelerationStructure->setGeometryCount(1u);
402 
403 			de::SharedPtr<RaytracedGeometryBase> geometry;
404 			if (testParams.bottomTestType == BTT_TRIANGLES)
405 			{
406 				geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
407 				if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
408 				{
409 					if (instanceFlags == 0u)
410 					{
411 						geometry->addVertex(xyz + v0);
412 						geometry->addVertex(xyz + v1);
413 						geometry->addVertex(xyz + v2);
414 						geometry->addVertex(xyz + v2);
415 						geometry->addVertex(xyz + v1);
416 						geometry->addVertex(xyz + v3);
417 					}
418 					else // Counterclockwise so the flags will be needed for the geometry to be visible.
419 					{
420 						geometry->addVertex(xyz + v2);
421 						geometry->addVertex(xyz + v1);
422 						geometry->addVertex(xyz + v0);
423 						geometry->addVertex(xyz + v3);
424 						geometry->addVertex(xyz + v1);
425 						geometry->addVertex(xyz + v2);
426 					}
427 				}
428 				else
429 				{
430 					geometry->addVertex(xyz + v0);
431 					geometry->addVertex(xyz + v1);
432 					geometry->addVertex(xyz + v2);
433 					geometry->addVertex(xyz + v3);
434 
435 					if (instanceFlags == 0u)
436 					{
437 						geometry->addIndex(0);
438 						geometry->addIndex(1);
439 						geometry->addIndex(2);
440 						geometry->addIndex(2);
441 						geometry->addIndex(1);
442 						geometry->addIndex(3);
443 					}
444 					else // Counterclockwise so the flags will be needed for the geometry to be visible.
445 					{
446 						geometry->addIndex(2);
447 						geometry->addIndex(1);
448 						geometry->addIndex(0);
449 						geometry->addIndex(3);
450 						geometry->addIndex(1);
451 						geometry->addIndex(2);
452 					}
453 				}
454 			}
455 			else // testParams.bottomTestType == BTT_AABBS
456 			{
457 				geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
458 
459 				if (!testParams.padVertices)
460 				{
461 					// Single AABB.
462 					geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
463 					geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f,  0.1f));
464 				}
465 				else
466 				{
467 					// Multiple AABBs covering the same space.
468 					geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
469 					geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f,  0.1f));
470 
471 					geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.5f, -0.1f));
472 					geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f,  0.1f));
473 
474 					geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.5f, -0.1f));
475 					geometry->addVertex(xyz + tcu::Vec3(0.5f, 1.0f,  0.1f));
476 
477 					geometry->addVertex(xyz + tcu::Vec3(0.5f, 0.0f, -0.1f));
478 					geometry->addVertex(xyz + tcu::Vec3(1.0f, 0.5f,  0.1f));
479 				}
480 			}
481 
482 			bottomLevelAccelerationStructure->addGeometry(geometry);
483 
484 			if (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT)
485 				geometry->setGeometryFlags(VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
486 
487 			result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
488 		}
489 	}
490 
491 	return result;
492 }
493 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)494 de::MovePtr<TopLevelAccelerationStructure> CheckerboardConfiguration::initTopAccelerationStructure (Context&		context,
495 																									TestParams&		testParams,
496 																									std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
497 {
498 	// Checkerboard configuration does not support empty geometry tests.
499 	DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
500 
501 	DE_UNREF(context);
502 
503 	const auto instanceCount = testParams.width * testParams.height / 2u;
504 	const auto instanceFlags = getCullFlags(testParams.cullFlags);
505 
506 	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
507 	result->setInstanceCount(instanceCount);
508 
509 	if (testParams.topTestType == TTT_DIFFERENT_INSTANCES)
510 	{
511 
512 		for (deUint32 y = 0; y < testParams.height; ++y)
513 		for (deUint32 x = 0; x < testParams.width; ++x)
514 		{
515 			if (((x + y) % 2) == 0)
516 				continue;
517 			const VkTransformMatrixKHR			transformMatrixKHR =
518 			{
519 				{								//  float	matrix[3][4];
520 					{ 1.0f, 0.0f, 0.0f, (float)x },
521 					{ 0.0f, 1.0f, 0.0f, (float)y },
522 					{ 0.0f, 0.0f, 1.0f, 0.0f },
523 				}
524 			};
525 			const deUint32 instanceCustomIndex = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ? (INSTANCE_CUSTOM_INDEX_BASE + x + y) : 0u);
526 			result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, instanceCustomIndex, 0xFFu, 0u, instanceFlags);
527 		}
528 	}
529 	else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
530 	{
531 		deUint32 currentInstanceIndex = 0;
532 
533 		for (deUint32 y = 0; y < testParams.height; ++y)
534 		for (deUint32 x = 0; x < testParams.width; ++x)
535 		{
536 			if (((x + y) % 2) == 0)
537 				continue;
538 			const deUint32 instanceCustomIndex = ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ? (INSTANCE_CUSTOM_INDEX_BASE + x + y) : 0u);
539 			result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix3x4, instanceCustomIndex, 0xFFu, 0u, instanceFlags);
540 		}
541 	}
542 
543 	return result;
544 }
545 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)546 void CheckerboardConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
547 													  Context&								context,
548 													  TestParams&							testParams)
549 {
550 	DE_UNREF(testParams);
551 	const DeviceInterface&						vkd						= context.getDeviceInterface();
552 	const VkDevice								device					= context.getDevice();
553 
554 	const bool useAnyHit		= (testParams.instanceCustomIndexCase == InstanceCustomIndexCase::ANY_HIT);
555 	const auto hitShaderStage	= (useAnyHit ? VK_SHADER_STAGE_ANY_HIT_BIT_KHR : VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
556 	const auto hitShaderName	= (useAnyHit ? "ahit" : "chit");
557 
558 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"),  0), 0);
559 	rayTracingPipeline->addShader(hitShaderStage,						createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName),  0), 1);
560 	rayTracingPipeline->addShader(hitShaderStage,						createShaderModule(vkd, device, context.getBinaryCollection().get(hitShaderName),  0), 2);
561 	if (testParams.bottomTestType == BTT_AABBS)
562 		rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0), 2);
563 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, context.getBinaryCollection().get("miss"),  0), 3);
564 }
565 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)566 void CheckerboardConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
567 														Context&							context,
568 														TestParams&							testParams,
569 														VkPipeline							pipeline,
570 														deUint32							shaderGroupHandleSize,
571 														deUint32							shaderGroupBaseAlignment,
572 														de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
573 														de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
574 														de::MovePtr<BufferWithMemory>&		missShaderBindingTable)
575 {
576 	const DeviceInterface&						vkd						= context.getDeviceInterface();
577 	const VkDevice								device					= context.getDevice();
578 	Allocator&									allocator				= context.getDefaultAllocator();
579 
580 	raygenShaderBindingTable											= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
581 	if(testParams.bottomTestType == BTT_AABBS)
582 		hitShaderBindingTable											= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
583 	else // testParams.bottomTestType == BTT_TRIANGLES
584 		hitShaderBindingTable											= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
585 	missShaderBindingTable												= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1 );
586 }
587 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)588 bool CheckerboardConfiguration::verifyImage(BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
589 {
590 	// Checkerboard configuration does not support empty geometry tests.
591 	DE_ASSERT(testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY);
592 
593 	DE_UNREF(context);
594 	const auto*						bufferPtr	= (deInt32*)resultBuffer->getAllocation().getHostPtr();
595 	deUint32						pos			= 0;
596 	deUint32						failures	= 0;
597 
598 	// verify results - each test case should generate checkerboard pattern
599 	for (deUint32 y = 0; y < testParams.height; ++y)
600 	for (deUint32 x = 0; x < testParams.width; ++x)
601 	{
602 		// The hit value should match the shader code.
603 		const deInt32 hitValue			= ((testParams.instanceCustomIndexCase != InstanceCustomIndexCase::NONE) ? static_cast<deInt32>(INSTANCE_CUSTOM_INDEX_BASE + x + y) : 2);
604 		const deInt32 expectedResult	= ((x + y) % 2) ? hitValue : 1;
605 
606 		if (bufferPtr[pos] != expectedResult)
607 			failures++;
608 
609 		++pos;
610 	}
611 	return failures == 0;
612 }
613 
getResultImageFormat()614 VkFormat CheckerboardConfiguration::getResultImageFormat()
615 {
616 	return VK_FORMAT_R32_SINT;
617 }
618 
getResultImageFormatSize()619 size_t CheckerboardConfiguration::getResultImageFormatSize()
620 {
621 	return sizeof(deUint32);
622 }
623 
getClearValue()624 VkClearValue CheckerboardConfiguration::getClearValue()
625 {
626 	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
627 }
628 
629 class SingleTriangleConfiguration : public TestConfiguration
630 {
631 public:
632 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
633 																										 TestParams&						testParams) override;
634 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
635 																										 TestParams&						testParams,
636 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
637 	void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
638 																										 Context&							context,
639 																										 TestParams&						testParams) override;
640 	void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
641 																										 Context&							context,
642 																										 TestParams&						testParams,
643 																										 VkPipeline							pipeline,
644 																										 deUint32							shaderGroupHandleSize,
645 																										 deUint32							shaderGroupBaseAlignment,
646 																										 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
647 																										 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
648 																										 de::MovePtr<BufferWithMemory>&		missShaderBindingTable) override;
649 	bool															verifyImage							(BufferWithMemory*					resultBuffer,
650 																										 Context&							context,
651 																										 TestParams&						testParams) override;
652 	VkFormat														getResultImageFormat				() override;
653 	size_t															getResultImageFormatSize			() override;
654 	VkClearValue													getClearValue						() override;
655 
656 	// well, actually we have 2 triangles, but we ignore the first one ( see raygen shader for this configuration )
657 	const std::vector<tcu::Vec3> vertices =
658 	{
659 		tcu::Vec3(0.0f, 0.0f, -0.1f),
660 		tcu::Vec3(-0.1f, 0.0f, 0.0f),
661 		tcu::Vec3(0.0f, -0.1f, 0.0f),
662 		tcu::Vec3(0.0f, 0.0f, 0.0f),
663 		tcu::Vec3(0.5f, 0.0f, -0.5f),
664 		tcu::Vec3(0.0f, 0.5f, -0.5f),
665 	};
666 
667 	const std::vector<deUint32> indices =
668 	{
669 		3,
670 		4,
671 		5
672 	};
673 };
674 
initBottomAccelerationStructures(Context & context,TestParams & testParams)675 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > SingleTriangleConfiguration::initBottomAccelerationStructures (Context&			context,
676 																															 TestParams&		testParams)
677 {
678 	DE_UNREF(context);
679 
680 	// No other cases supported for the single triangle configuration.
681 	DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
682 
683 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
684 
685 	de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
686 	bottomLevelAccelerationStructure->setGeometryCount(1u);
687 
688 	de::SharedPtr<RaytracedGeometryBase> geometry;
689 	geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType);
690 
691 	auto customVertices(vertices);
692 
693 	if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
694 	{
695 		const auto nanValue = tcu::Float32::nan().asFloat();
696 		for (auto& vtx : customVertices)
697 			vtx.x() = nanValue;
698 	}
699 
700 	for (auto it = begin(customVertices), eit = end(customVertices); it != eit; ++it)
701 		geometry->addVertex(*it);
702 
703 	if (testParams.indexType != VK_INDEX_TYPE_NONE_KHR)
704 	{
705 		for (auto it = begin(indices), eit = end(indices); it != eit; ++it)
706 			geometry->addIndex(*it);
707 	}
708 	bottomLevelAccelerationStructure->addGeometry(geometry);
709 	result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
710 
711 	return result;
712 }
713 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)714 de::MovePtr<TopLevelAccelerationStructure> SingleTriangleConfiguration::initTopAccelerationStructure (Context&			context,
715 																									  TestParams&		testParams,
716 																									  std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
717 {
718 	DE_UNREF(context);
719 	DE_UNREF(testParams);
720 
721 	// Unsupported in this configuration.
722 	DE_ASSERT(testParams.instanceCustomIndexCase == InstanceCustomIndexCase::NONE);
723 
724 	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
725 	result->setInstanceCount(1u);
726 
727 	result->addInstance(bottomLevelAccelerationStructures[0]);
728 
729 	return result;
730 }
731 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)732 void SingleTriangleConfiguration::initRayTracingShaders(de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
733 														Context&								context,
734 														TestParams&								testParams)
735 {
736 	DE_UNREF(testParams);
737 	const DeviceInterface&						vkd						= context.getDeviceInterface();
738 	const VkDevice								device					= context.getDevice();
739 
740 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get("rgen_depth"),  0), 0);
741 	rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get("chit_depth"),  0), 1);
742 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, context.getBinaryCollection().get("miss_depth"),  0), 2);
743 }
744 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable)745 void SingleTriangleConfiguration::initShaderBindingTables(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
746 														  Context&							context,
747 														  TestParams&						testParams,
748 														  VkPipeline						pipeline,
749 														  deUint32							shaderGroupHandleSize,
750 														  deUint32							shaderGroupBaseAlignment,
751 														  de::MovePtr<BufferWithMemory>&	raygenShaderBindingTable,
752 														  de::MovePtr<BufferWithMemory>&	hitShaderBindingTable,
753 														  de::MovePtr<BufferWithMemory>&	missShaderBindingTable)
754 {
755 	DE_UNREF(testParams);
756 	const DeviceInterface&						vkd						= context.getDeviceInterface();
757 	const VkDevice								device					= context.getDevice();
758 	Allocator&									allocator				= context.getDefaultAllocator();
759 
760 	raygenShaderBindingTable											= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
761 	hitShaderBindingTable												= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
762 	missShaderBindingTable												= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
763 }
764 
pointInTriangle2D(const tcu::Vec3 & p,const tcu::Vec3 & p0,const tcu::Vec3 & p1,const tcu::Vec3 & p2)765 bool pointInTriangle2D(const tcu::Vec3& p, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::Vec3& p2)
766 {
767 	float s = p0.y() * p2.x() - p0.x() * p2.y() + (p2.y() - p0.y()) * p.x() + (p0.x() - p2.x()) * p.y();
768 	float t = p0.x() * p1.y() - p0.y() * p1.x() + (p0.y() - p1.y()) * p.x() + (p1.x() - p0.x()) * p.y();
769 
770 	if ((s < 0) != (t < 0))
771 		return false;
772 
773 	float a = -p1.y() * p2.x() + p0.y() * (p2.x() - p1.x()) + p0.x() * (p1.y() - p2.y()) + p1.x() * p2.y();
774 
775 	return a < 0 ?
776 		(s <= 0 && s + t >= a) :
777 		(s >= 0 && s + t <= a);
778 }
779 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)780 bool SingleTriangleConfiguration::verifyImage(BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
781 {
782 	tcu::TextureFormat			imageFormat		= vk::mapVkFormat(getResultImageFormat());
783 	tcu::TextureFormat			vertexFormat	= vk::mapVkFormat(testParams.vertexFormat);
784 	tcu::ConstPixelBufferAccess	resultAccess	(imageFormat, testParams.width, testParams.height, 1, resultBuffer->getAllocation().getHostPtr());
785 
786 	std::vector<float>			reference		(testParams.width * testParams.height);
787 	tcu::PixelBufferAccess		referenceAccess	(imageFormat, testParams.width, testParams.height, 1, reference.data());
788 
789 	// verify results
790 	tcu::Vec3					v0				= vertices[3];
791 	tcu::Vec3					v1				= vertices[4];
792 	tcu::Vec3					v2				= vertices[5];
793 	const int					numChannels		= tcu::getNumUsedChannels(vertexFormat.order);
794 	if (numChannels < 3)
795 	{
796 		v0.z() = 0.0f;
797 		v1.z() = 0.0f;
798 		v2.z() = 0.0f;
799 	}
800 	tcu::Vec3					abc				= tcu::cross((v2 - v0), (v1 - v0));
801 
802 	for (deUint32 j = 0; j < testParams.height; ++j)
803 	{
804 		float y = 0.1f + 0.2f * float(j) / float(testParams.height - 1);
805 		for (deUint32 i = 0; i < testParams.width; ++i)
806 		{
807 			float	x			= 0.1f + 0.2f * float(i) / float(testParams.width - 1);
808 			float	z			= (abc.x()*x + abc.y()*y) / abc.z();
809 			bool	inTriangle	= pointInTriangle2D(tcu::Vec3(x, y, z), v0, v1, v2);
810 			float	refValue	= ((inTriangle && testParams.emptyASCase == EmptyAccelerationStructureCase::NOT_EMPTY) ? 1.0f+z : 0.0f);
811 			referenceAccess.setPixel(tcu::Vec4(refValue, 0.0f, 0.0f, 1.0f), i, j);
812 		}
813 	}
814 	return tcu::floatThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
815 }
816 
getResultImageFormat()817 VkFormat SingleTriangleConfiguration::getResultImageFormat()
818 {
819 	return VK_FORMAT_R32_SFLOAT;
820 }
821 
getResultImageFormatSize()822 size_t SingleTriangleConfiguration::getResultImageFormatSize()
823 {
824 	return sizeof(float);
825 }
826 
getClearValue()827 VkClearValue SingleTriangleConfiguration::getClearValue()
828 {
829 	return makeClearValueColorF32(32.0f, 0.0f, 0.0f, 0.0f);
830 }
831 
commonASTestsCheckSupport(Context & context)832 void commonASTestsCheckSupport(Context& context)
833 {
834 	context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
835 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
836 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
837 
838 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
839 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE)
840 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
841 
842 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
843 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
844 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
845 }
846 
847 class RayTracingASBasicTestCase : public TestCase
848 {
849 public:
850 																	RayTracingASBasicTestCase			(tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
851 																	~RayTracingASBasicTestCase			(void);
852 
853 	void															checkSupport						(Context& context) const override;
854 	void															initPrograms						(SourceCollections& programCollection) const override;
855 	TestInstance*													createInstance						(Context& context) const override;
856 protected:
857 	TestParams														m_data;
858 };
859 
860 // Same as RayTracingASBasicTestCase but it will only initialize programs for SingleTriangleConfiguration and use hand-tuned SPIR-V
861 // assembly.
862 class RayTracingASFuncArgTestCase : public RayTracingASBasicTestCase
863 {
864 public:
865 																	RayTracingASFuncArgTestCase			(tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
~RayTracingASFuncArgTestCase(void)866 																	~RayTracingASFuncArgTestCase		(void) {}
867 
868 	void															initPrograms						(SourceCollections& programCollection) const override;
869 };
870 
871 class RayTracingASBasicTestInstance : public TestInstance
872 {
873 public:
874 																	RayTracingASBasicTestInstance		(Context& context, const TestParams& data);
875 																	~RayTracingASBasicTestInstance		(void) = default;
876 	tcu::TestStatus													iterate								(void) override;
877 
878 protected:
879 	bool															iterateNoWorkers					(void);
880 	bool															iterateWithWorkers					(void);
881 	de::MovePtr<BufferWithMemory>									runTest								(const deUint32 workerThreadsCount);
882 private:
883 	TestParams														m_data;
884 };
885 
RayTracingASBasicTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams & data)886 RayTracingASBasicTestCase::RayTracingASBasicTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
887 	: vkt::TestCase	(context, name, desc)
888 	, m_data		(data)
889 {
890 }
891 
~RayTracingASBasicTestCase(void)892 RayTracingASBasicTestCase::~RayTracingASBasicTestCase	(void)
893 {
894 }
895 
checkSupport(Context & context) const896 void RayTracingASBasicTestCase::checkSupport(Context& context) const
897 {
898 	commonASTestsCheckSupport(context);
899 
900 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
901 	if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
902 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
903 
904 	// Check supported vertex format.
905 	checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_data.vertexFormat);
906 }
907 
initPrograms(SourceCollections & programCollection) const908 void RayTracingASBasicTestCase::initPrograms (SourceCollections& programCollection) const
909 {
910 	bool storeInRGen = false;
911 	bool storeInAHit = false;
912 	bool storeInCHit = false;
913 	bool storeInISec = false;
914 
915 	switch (m_data.instanceCustomIndexCase)
916 	{
917 	case InstanceCustomIndexCase::NONE:			storeInRGen = true;	break;
918 	case InstanceCustomIndexCase::CLOSEST_HIT:	storeInCHit = true; break;
919 	case InstanceCustomIndexCase::ANY_HIT:		storeInAHit = true;	break;
920 	case InstanceCustomIndexCase::INTERSECTION:	storeInISec = true; break;
921 	default: DE_ASSERT(false); break;
922 	}
923 
924 	const std::string				imageDeclaration	= "layout(r32i, set = 0, binding = 0) uniform iimage2D result;\n";
925 	const std::string				storeCustomIndex	= "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), ivec4(gl_InstanceCustomIndexEXT, 0, 0, 1));\n";
926 	const vk::ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
927 
928 	{
929 		std::stringstream css;
930 		css
931 			<< "#version 460 core\n"
932 			<< "#extension GL_EXT_ray_tracing : require\n"
933 			<< "layout(location = 0) rayPayloadEXT ivec4 hitValue;\n";
934 
935 		if (storeInRGen)
936 			css << imageDeclaration;
937 
938 		css
939 			<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
940 			<< "\n"
941 			<< "void main()\n"
942 			<< "{\n"
943 			<< "  float tmin      = 0.0;\n"
944 			<< "  float tmax      = 1.0;\n"
945 			<< "  vec3  origin    = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n"
946 			<< "  vec3  direction = vec3(0.0,0.0,-1.0);\n"
947 			<< "  hitValue        = ivec4(0,0,0,0);\n"
948 			<< "  traceRayEXT(topLevelAS, " << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0" : "gl_RayFlagsCullBackFacingTrianglesEXT") << ", 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n";
949 
950 		if (storeInRGen)
951 			css << "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
952 
953 		css << "}\n";
954 
955 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
956 	}
957 
958 	{
959 		std::stringstream css;
960 		css
961 			<< "#version 460 core\n"
962 			<< "#extension GL_EXT_ray_tracing : require\n"
963 			<< "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
964 
965 		if (storeInCHit)
966 			css << imageDeclaration;
967 
968 		css
969 			<< "void main()\n"
970 			<< "{\n"
971 			<< "  hitValue = ivec4(2,0,0,1);\n";
972 
973 		if (storeInCHit)
974 			css << storeCustomIndex;
975 
976 		css << "}\n";
977 
978 		programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
979 	}
980 
981 	if (storeInAHit)
982 	{
983 		std::stringstream css;
984 		css
985 			<< "#version 460 core\n"
986 			<< "#extension GL_EXT_ray_tracing : require\n"
987 			<< imageDeclaration
988 			<< "void main()\n"
989 			<< "{\n"
990 			<< storeCustomIndex
991 			<< "}\n";
992 
993 		programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
994 	}
995 
996 	{
997 		std::stringstream css;
998 		css
999 			<< "#version 460 core\n"
1000 			<< "#extension GL_EXT_ray_tracing : require\n"
1001 			<< "hitAttributeEXT ivec4 hitAttribute;\n";
1002 
1003 		if (storeInISec)
1004 			css << imageDeclaration;
1005 
1006 		css
1007 			<< "void main()\n"
1008 			<< "{\n"
1009 			<< "  hitAttribute = ivec4(0,0,0,0);\n"
1010 			<< "  reportIntersectionEXT(0.5f, 0);\n";
1011 
1012 		if (storeInISec)
1013 			css << storeCustomIndex;
1014 
1015 		css << "}\n";
1016 
1017 		programCollection.glslSources.add("isect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1018 	}
1019 
1020 	{
1021 		std::stringstream css;
1022 		css
1023 			<< "#version 460 core\n"
1024 			<< "#extension GL_EXT_ray_tracing : require\n"
1025 			<< "layout(location = 0) rayPayloadInEXT ivec4 hitValue;\n";
1026 
1027 		if (!storeInRGen)
1028 			css << imageDeclaration;
1029 
1030 		css
1031 			<< "void main()\n"
1032 			<< "{\n"
1033 			<< "  hitValue = ivec4(1,0,0,1);\n";
1034 
1035 		if (!storeInRGen)
1036 			css << "  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n";
1037 
1038 		css << "}\n";
1039 
1040 		programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1041 	}
1042 
1043 	{
1044 		std::stringstream css;
1045 		css <<
1046 			"#version 460 core\n"
1047 			"#extension GL_EXT_ray_tracing : require\n"
1048 			"layout(location = 0) rayPayloadEXT vec4 hitValue;\n"
1049 			"layout(r32f, set = 0, binding = 0) uniform image2D result;\n"
1050 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1051 			"\n"
1052 			"vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)\n"
1053 			"{\n"
1054 			"  return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + (float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;\n"
1055 			"}\n"
1056 			"\n"
1057 			"void main()\n"
1058 			"{\n"
1059 			"  float tmin      = 0.0;\n"
1060 			"  float tmax      = 2.0;\n"
1061 			"  vec3  origin    = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );\n"
1062 			"  vec3  direction = vec3(0.0,0.0,-1.0);\n"
1063 			"  hitValue        = vec4(0.0,0.0,0.0,0.0);\n"
1064 			"  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
1065 			"  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
1066 			"}\n";
1067 		programCollection.glslSources.add("rgen_depth") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1068 	}
1069 
1070 	{
1071 		std::stringstream css;
1072 		css <<
1073 			"#version 460 core\n"
1074 			"#extension GL_EXT_ray_tracing : require\n"
1075 			"layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1076 			"void main()\n"
1077 			"{\n"
1078 			"  hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1079 			"}\n";
1080 
1081 		programCollection.glslSources.add("chit_depth") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1082 	}
1083 
1084 	{
1085 		std::stringstream css;
1086 		css <<
1087 			"#version 460 core\n"
1088 			"#extension GL_EXT_ray_tracing : require\n"
1089 			"layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1090 			"void main()\n"
1091 			"{\n"
1092 			"  hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1093 			"}\n";
1094 
1095 		programCollection.glslSources.add("miss_depth") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1096 	}
1097 }
1098 
createInstance(Context & context) const1099 TestInstance* RayTracingASBasicTestCase::createInstance (Context& context) const
1100 {
1101 	return new RayTracingASBasicTestInstance(context, m_data);
1102 }
1103 
RayTracingASFuncArgTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams & data)1104 RayTracingASFuncArgTestCase::RayTracingASFuncArgTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
1105 	: RayTracingASBasicTestCase (context, name, desc, data)
1106 {
1107 }
1108 
initPrograms(SourceCollections & programCollection) const1109 void RayTracingASFuncArgTestCase::initPrograms (SourceCollections& programCollection) const
1110 {
1111 	const vk::ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1112 	const vk::SpirVAsmBuildOptions	spvBuildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1113 
1114 	{
1115 		// The SPIR-V assembly below is based on the following GLSL code. Some
1116 		// modifications have been made to make traceRaysBottomWrapper take a bare
1117 		// acceleration structure as its argument instead of a pointer to it, so we can
1118 		// test passing a pointer and a bare value in the same test.
1119 		//
1120 		//	#version 460 core
1121 		//	#extension GL_EXT_ray_tracing : require
1122 		//	layout(location = 0) rayPayloadEXT vec4 hitValue;
1123 		//	layout(r32f, set = 0, binding = 0) uniform image2D result;
1124 		//	layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;
1125 		//
1126 		//	void traceRaysBottomWrapper(
1127 		//	  accelerationStructureEXT topLevel,
1128 		//	  uint rayFlags,
1129 		//	  uint cullMask,
1130 		//	  uint sbtRecordOffset,
1131 		//	  uint sbtRecordStride,
1132 		//	  uint missIndex,
1133 		//	  vec3 origin,
1134 		//	  float Tmin,
1135 		//	  vec3 direction,
1136 		//	  float Tmax)
1137 		//	{
1138 		//	  traceRayEXT(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax, 0);
1139 		//	}
1140 		//
1141 		//	void traceRaysTopWrapper(
1142 		//	  accelerationStructureEXT topLevel,
1143 		//	  uint rayFlags,
1144 		//	  uint cullMask,
1145 		//	  uint sbtRecordOffset,
1146 		//	  uint sbtRecordStride,
1147 		//	  uint missIndex,
1148 		//	  vec3 origin,
1149 		//	  float Tmin,
1150 		//	  vec3 direction,
1151 		//	  float Tmax)
1152 		//	{
1153 		//	  traceRaysBottomWrapper(topLevel, rayFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, origin, Tmin, direction, Tmax);
1154 		//	}
1155 		//
1156 		//	vec3 calculateOrigin(vec3 zeroOrigin, vec3 xAxis, vec3 yAxis)
1157 		//	{
1158 		//	  return zeroOrigin + (float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x-1)) * xAxis + (float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y-1)) * yAxis;
1159 		//	}
1160 		//
1161 		//	void main()
1162 		//	{
1163 		//	  float tmin      = 0.0;
1164 		//	  float tmax      = 2.0;
1165 		//	  vec3  origin    = calculateOrigin( vec3(0.1,0.1,1.0), vec3(0.2,0.0,0.0), vec3(0.0,0.2,0.0) );
1166 		//	  vec3  direction = vec3(0.0,0.0,-1.0);
1167 		//	  hitValue        = vec4(0.0,0.0,0.0,0.0);
1168 		//	  traceRaysTopWrapper(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direction, tmax);
1169 		//	  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);
1170 		//	}
1171 
1172 		std::ostringstream rgen;
1173 		rgen
1174 			<< "; SPIR-V\n"
1175 			<< "; Version: 1.4\n"
1176 			<< "; Generator: Khronos Glslang Reference Front End; 10\n"
1177 			<< "; Bound: 156\n"
1178 			<< "; Schema: 0\n"
1179 			<< "OpCapability RayTracingKHR\n"
1180 			<< "OpExtension \"SPV_KHR_ray_tracing\"\n"
1181 			<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1182 			<< "OpMemoryModel Logical GLSL450\n"
1183 			<< "OpEntryPoint RayGenerationKHR %4 \"main\" %59 %82 %88 %130 %148\n"
1184 			<< "OpDecorate %59 Location 0\n"
1185 			<< "OpDecorate %82 BuiltIn LaunchIdKHR\n"
1186 			<< "OpDecorate %88 BuiltIn LaunchSizeKHR\n"
1187 			<< "OpDecorate %130 DescriptorSet 0\n"
1188 			<< "OpDecorate %130 Binding 1\n"
1189 			<< "OpDecorate %148 DescriptorSet 0\n"
1190 			<< "OpDecorate %148 Binding 0\n"
1191 			<< "%2 = OpTypeVoid\n"
1192 			<< "%3 = OpTypeFunction %2\n"
1193 
1194 			// This is the bare type.
1195 			<< "%6 = OpTypeAccelerationStructureKHR\n"
1196 
1197 			// This is the pointer type.
1198 			<< "%7 = OpTypePointer UniformConstant %6\n"
1199 
1200 			<< "%8 = OpTypeInt 32 0\n"
1201 			<< "%9 = OpTypePointer Function %8\n"
1202 			<< "%10 = OpTypeFloat 32\n"
1203 			<< "%11 = OpTypeVector %10 3\n"
1204 			<< "%12 = OpTypePointer Function %11\n"
1205 			<< "%13 = OpTypePointer Function %10\n"
1206 
1207 			// This is the type for traceRaysTopWrapper and also the original traceRaysBottomWrapper.
1208 			<< "%14 = OpTypeFunction %2 %7 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1209 
1210 			// This is the modified type to take a bare AS as the first argument, for the modified version of traceRaysBottomWrapper.
1211 			<< "%14b = OpTypeFunction %2 %6 %9 %9 %9 %9 %9 %12 %13 %12 %13\n"
1212 
1213 			<< "%39 = OpTypeFunction %11 %12 %12 %12\n"
1214 			<< "%55 = OpTypeInt 32 1\n"
1215 			<< "%56 = OpConstant %55 0\n"
1216 			<< "%57 = OpTypeVector %10 4\n"
1217 			<< "%58 = OpTypePointer RayPayloadKHR %57\n"
1218 			<< "%59 = OpVariable %58 RayPayloadKHR\n"
1219 			<< "%80 = OpTypeVector %8 3\n"
1220 			<< "%81 = OpTypePointer Input %80\n"
1221 			<< "%82 = OpVariable %81 Input\n"
1222 			<< "%83 = OpConstant %8 0\n"
1223 			<< "%84 = OpTypePointer Input %8\n"
1224 			<< "%88 = OpVariable %81 Input\n"
1225 			<< "%91 = OpConstant %8 1\n"
1226 			<< "%112 = OpConstant %10 0\n"
1227 			<< "%114 = OpConstant %10 2\n"
1228 			<< "%116 = OpConstant %10 0.100000001\n"
1229 			<< "%117 = OpConstant %10 1\n"
1230 			<< "%118 = OpConstantComposite %11 %116 %116 %117\n"
1231 			<< "%119 = OpConstant %10 0.200000003\n"
1232 			<< "%120 = OpConstantComposite %11 %119 %112 %112\n"
1233 			<< "%121 = OpConstantComposite %11 %112 %119 %112\n"
1234 			<< "%127 = OpConstant %10 -1\n"
1235 			<< "%128 = OpConstantComposite %11 %112 %112 %127\n"
1236 			<< "%129 = OpConstantComposite %57 %112 %112 %112 %112\n"
1237 			<< "%130 = OpVariable %7 UniformConstant\n"
1238 			<< "%131 = OpConstant %8 255\n"
1239 			<< "%146 = OpTypeImage %10 2D 0 0 0 2 R32f\n"
1240 			<< "%147 = OpTypePointer UniformConstant %146\n"
1241 			<< "%148 = OpVariable %147 UniformConstant\n"
1242 			<< "%150 = OpTypeVector %8 2\n"
1243 			<< "%153 = OpTypeVector %55 2\n"
1244 
1245 			// This is main().
1246 			<< "%4 = OpFunction %2 None %3\n"
1247 			<< "%5 = OpLabel\n"
1248 			<< "%111 = OpVariable %13 Function\n"
1249 			<< "%113 = OpVariable %13 Function\n"
1250 			<< "%115 = OpVariable %12 Function\n"
1251 			<< "%122 = OpVariable %12 Function\n"
1252 			<< "%123 = OpVariable %12 Function\n"
1253 			<< "%124 = OpVariable %12 Function\n"
1254 			<< "%126 = OpVariable %12 Function\n"
1255 			<< "%132 = OpVariable %9 Function\n"
1256 			<< "%133 = OpVariable %9 Function\n"
1257 			<< "%134 = OpVariable %9 Function\n"
1258 			<< "%135 = OpVariable %9 Function\n"
1259 			<< "%136 = OpVariable %9 Function\n"
1260 			<< "%137 = OpVariable %12 Function\n"
1261 			<< "%139 = OpVariable %13 Function\n"
1262 			<< "%141 = OpVariable %12 Function\n"
1263 			<< "%143 = OpVariable %13 Function\n"
1264 			<< "OpStore %111 %112\n"
1265 			<< "OpStore %113 %114\n"
1266 			<< "OpStore %122 %118\n"
1267 			<< "OpStore %123 %120\n"
1268 			<< "OpStore %124 %121\n"
1269 			<< "%125 = OpFunctionCall %11 %43 %122 %123 %124\n"
1270 			<< "OpStore %115 %125\n"
1271 			<< "OpStore %126 %128\n"
1272 			<< "OpStore %59 %129\n"
1273 			<< "OpStore %132 %83\n"
1274 			<< "OpStore %133 %131\n"
1275 			<< "OpStore %134 %83\n"
1276 			<< "OpStore %135 %83\n"
1277 			<< "OpStore %136 %83\n"
1278 			<< "%138 = OpLoad %11 %115\n"
1279 			<< "OpStore %137 %138\n"
1280 			<< "%140 = OpLoad %10 %111\n"
1281 			<< "OpStore %139 %140\n"
1282 			<< "%142 = OpLoad %11 %126\n"
1283 			<< "OpStore %141 %142\n"
1284 			<< "%144 = OpLoad %10 %113\n"
1285 			<< "OpStore %143 %144\n"
1286 			<< "%145 = OpFunctionCall %2 %37 %130 %132 %133 %134 %135 %136 %137 %139 %141 %143\n"
1287 			<< "%149 = OpLoad %146 %148\n"
1288 			<< "%151 = OpLoad %80 %82\n"
1289 			<< "%152 = OpVectorShuffle %150 %151 %151 0 1\n"
1290 			<< "%154 = OpBitcast %153 %152\n"
1291 			<< "%155 = OpLoad %57 %59\n"
1292 			<< "OpImageWrite %149 %154 %155\n"
1293 			<< "OpReturn\n"
1294 			<< "OpFunctionEnd\n"
1295 
1296 			// This is traceRaysBottomWrapper, doing the OpTraceRayKHR call.
1297 			// We have modified the type so it takes a bare AS as the first argument.
1298 			// %25 = OpFunction %2 None %14
1299 			<< "%25 = OpFunction %2 None %14b\n"
1300 
1301 			// Also the type of the first argument here.
1302 			// %15 = OpFunctionParameter %7
1303 			<< "%15 = OpFunctionParameter %6\n"
1304 
1305 			<< "%16 = OpFunctionParameter %9\n"
1306 			<< "%17 = OpFunctionParameter %9\n"
1307 			<< "%18 = OpFunctionParameter %9\n"
1308 			<< "%19 = OpFunctionParameter %9\n"
1309 			<< "%20 = OpFunctionParameter %9\n"
1310 			<< "%21 = OpFunctionParameter %12\n"
1311 			<< "%22 = OpFunctionParameter %13\n"
1312 			<< "%23 = OpFunctionParameter %12\n"
1313 			<< "%24 = OpFunctionParameter %13\n"
1314 			<< "%26 = OpLabel\n"
1315 
1316 			// We no longer need to dereference the pointer here.
1317 			// %45 = OpLoad %6 %15
1318 
1319 			<< "%46 = OpLoad %8 %16\n"
1320 			<< "%47 = OpLoad %8 %17\n"
1321 			<< "%48 = OpLoad %8 %18\n"
1322 			<< "%49 = OpLoad %8 %19\n"
1323 			<< "%50 = OpLoad %8 %20\n"
1324 			<< "%51 = OpLoad %11 %21\n"
1325 			<< "%52 = OpLoad %10 %22\n"
1326 			<< "%53 = OpLoad %11 %23\n"
1327 			<< "%54 = OpLoad %10 %24\n"
1328 
1329 			// And we can use the first argument here directly.
1330 			// OpTraceRayKHR %45 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59
1331 			<< "OpTraceRayKHR %15 %46 %47 %48 %49 %50 %51 %52 %53 %54 %59\n"
1332 
1333 			<< "OpReturn\n"
1334 			<< "OpFunctionEnd\n"
1335 
1336 			// This is traceRaysTopWrapper, which calls traceRaysBottomWrapper.
1337 			<< "%37 = OpFunction %2 None %14\n"
1338 
1339 			// First argument, pointer to AS.
1340 			<< "%27 = OpFunctionParameter %7\n"
1341 
1342 			<< "%28 = OpFunctionParameter %9\n"
1343 			<< "%29 = OpFunctionParameter %9\n"
1344 			<< "%30 = OpFunctionParameter %9\n"
1345 			<< "%31 = OpFunctionParameter %9\n"
1346 			<< "%32 = OpFunctionParameter %9\n"
1347 			<< "%33 = OpFunctionParameter %12\n"
1348 			<< "%34 = OpFunctionParameter %13\n"
1349 			<< "%35 = OpFunctionParameter %12\n"
1350 			<< "%36 = OpFunctionParameter %13\n"
1351 			<< "%38 = OpLabel\n"
1352 			<< "%60 = OpVariable %9 Function\n"
1353 			<< "%62 = OpVariable %9 Function\n"
1354 			<< "%64 = OpVariable %9 Function\n"
1355 			<< "%66 = OpVariable %9 Function\n"
1356 			<< "%68 = OpVariable %9 Function\n"
1357 			<< "%70 = OpVariable %12 Function\n"
1358 			<< "%72 = OpVariable %13 Function\n"
1359 			<< "%74 = OpVariable %12 Function\n"
1360 			<< "%76 = OpVariable %13 Function\n"
1361 
1362 			// Dereference the pointer to pass the AS as the first argument.
1363 			<< "%27b = OpLoad %6 %27\n"
1364 
1365 			<< "%61 = OpLoad %8 %28\n"
1366 			<< "OpStore %60 %61\n"
1367 			<< "%63 = OpLoad %8 %29\n"
1368 			<< "OpStore %62 %63\n"
1369 			<< "%65 = OpLoad %8 %30\n"
1370 			<< "OpStore %64 %65\n"
1371 			<< "%67 = OpLoad %8 %31\n"
1372 			<< "OpStore %66 %67\n"
1373 			<< "%69 = OpLoad %8 %32\n"
1374 			<< "OpStore %68 %69\n"
1375 			<< "%71 = OpLoad %11 %33\n"
1376 			<< "OpStore %70 %71\n"
1377 			<< "%73 = OpLoad %10 %34\n"
1378 			<< "OpStore %72 %73\n"
1379 			<< "%75 = OpLoad %11 %35\n"
1380 			<< "OpStore %74 %75\n"
1381 			<< "%77 = OpLoad %10 %36\n"
1382 			<< "OpStore %76 %77\n"
1383 
1384 			// %2 is void, %25 is traceRaysBottomWrapper and %27 was the first argument.
1385 			// We need to pass the loaded AS instead.
1386 			// %78 = OpFunctionCall %2 %25 %27 %60 %62 %64 %66 %68 %70 %72 %74 %76
1387 			<< "%78 = OpFunctionCall %2 %25 %27b %60 %62 %64 %66 %68 %70 %72 %74 %76\n"
1388 
1389 			<< "OpReturn\n"
1390 			<< "OpFunctionEnd\n"
1391 
1392 			// This is calculateOrigin().
1393 			<< "%43 = OpFunction %11 None %39\n"
1394 			<< "%40 = OpFunctionParameter %12\n"
1395 			<< "%41 = OpFunctionParameter %12\n"
1396 			<< "%42 = OpFunctionParameter %12\n"
1397 			<< "%44 = OpLabel\n"
1398 			<< "%79 = OpLoad %11 %40\n"
1399 			<< "%85 = OpAccessChain %84 %82 %83\n"
1400 			<< "%86 = OpLoad %8 %85\n"
1401 			<< "%87 = OpConvertUToF %10 %86\n"
1402 			<< "%89 = OpAccessChain %84 %88 %83\n"
1403 			<< "%90 = OpLoad %8 %89\n"
1404 			<< "%92 = OpISub %8 %90 %91\n"
1405 			<< "%93 = OpConvertUToF %10 %92\n"
1406 			<< "%94 = OpFDiv %10 %87 %93\n"
1407 			<< "%95 = OpLoad %11 %41\n"
1408 			<< "%96 = OpVectorTimesScalar %11 %95 %94\n"
1409 			<< "%97 = OpFAdd %11 %79 %96\n"
1410 			<< "%98 = OpAccessChain %84 %82 %91\n"
1411 			<< "%99 = OpLoad %8 %98\n"
1412 			<< "%100 = OpConvertUToF %10 %99\n"
1413 			<< "%101 = OpAccessChain %84 %88 %91\n"
1414 			<< "%102 = OpLoad %8 %101\n"
1415 			<< "%103 = OpISub %8 %102 %91\n"
1416 			<< "%104 = OpConvertUToF %10 %103\n"
1417 			<< "%105 = OpFDiv %10 %100 %104\n"
1418 			<< "%106 = OpLoad %11 %42\n"
1419 			<< "%107 = OpVectorTimesScalar %11 %106 %105\n"
1420 			<< "%108 = OpFAdd %11 %97 %107\n"
1421 			<< "OpReturnValue %108\n"
1422 			<< "OpFunctionEnd\n"
1423 			;
1424 
1425 		programCollection.spirvAsmSources.add("rgen_depth") << spvBuildOptions << rgen.str();
1426 	}
1427 
1428 	// chit_depth and miss_depth below have been left untouched.
1429 
1430 	{
1431 		std::stringstream css;
1432 		css <<
1433 			"#version 460 core\n"
1434 			"#extension GL_EXT_ray_tracing : require\n"
1435 			"layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1436 			"void main()\n"
1437 			"{\n"
1438 			"  hitValue = vec4(gl_RayTmaxEXT,0.0,0.0,1.0);\n"
1439 			"}\n";
1440 
1441 		programCollection.glslSources.add("chit_depth") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1442 	}
1443 
1444 	{
1445 		std::stringstream css;
1446 		css <<
1447 			"#version 460 core\n"
1448 			"#extension GL_EXT_ray_tracing : require\n"
1449 			"layout(location = 0) rayPayloadInEXT vec4 hitValue;\n"
1450 			"void main()\n"
1451 			"{\n"
1452 			"  hitValue = vec4(0.0,0.0,0.0,1.0);\n"
1453 			"}\n";
1454 
1455 		programCollection.glslSources.add("miss_depth") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1456 	}
1457 }
1458 
RayTracingASBasicTestInstance(Context & context,const TestParams & data)1459 RayTracingASBasicTestInstance::RayTracingASBasicTestInstance (Context& context, const TestParams& data)
1460 	: vkt::TestInstance		(context)
1461 	, m_data				(data)
1462 {
1463 }
1464 
runTest(const deUint32 workerThreadsCount)1465 de::MovePtr<BufferWithMemory> RayTracingASBasicTestInstance::runTest(const deUint32 workerThreadsCount)
1466 {
1467 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
1468 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
1469 	const VkDevice						device								= m_context.getDevice();
1470 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
1471 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
1472 	const VkQueue						queue								= m_context.getUniversalQueue();
1473 	Allocator&							allocator							= m_context.getDefaultAllocator();
1474 	const deUint32						pixelCount							= m_data.width * m_data.height;
1475 	const deUint32						shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
1476 	const deUint32						shaderGroupBaseAlignment			= getShaderGroupBaseAlignment(vki, physicalDevice);
1477 	const bool							htCopy								= (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
1478 	const bool							htSerialize							= (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
1479 
1480 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
1481 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1482 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1483 																					.build(vkd, device);
1484 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
1485 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1486 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1487 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1488 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1489 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
1490 
1491 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
1492 	m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
1493 	Move<VkPipeline>					pipeline							= rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1494 
1495 	de::MovePtr<BufferWithMemory>		raygenShaderBindingTable;
1496 	de::MovePtr<BufferWithMemory>		hitShaderBindingTable;
1497 	de::MovePtr<BufferWithMemory>		missShaderBindingTable;
1498 	m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, m_data, *pipeline, shaderGroupHandleSize, shaderGroupBaseAlignment, raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable);
1499 
1500 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(),	0),	shaderGroupHandleSize,	shaderGroupHandleSize);
1501 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(),		0),	shaderGroupHandleSize,	shaderGroupHandleSize);
1502 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(),		0),	shaderGroupHandleSize,	shaderGroupHandleSize);
1503 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL,																	0,						0);
1504 
1505 	const VkFormat						imageFormat							= m_data.testConfiguration->getResultImageFormat();
1506 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
1507 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1508 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1509 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
1510 
1511 	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(pixelCount*m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1512 	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1513 	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), resultBufferImageSubresourceLayers);
1514 	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1515 
1516 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1517 
1518 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
1519 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1520 
1521 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	bottomLevelAccelerationStructures;
1522 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
1523 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	bottomLevelAccelerationStructureCopies;
1524 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructureCopy;
1525 	std::vector<de::SharedPtr<SerialStorage>>						bottomSerialized;
1526 	std::vector<de::SharedPtr<SerialStorage>>						topSerialized;
1527 	std::vector<VkDeviceSize>			accelerationCompactedSizes;
1528 	std::vector<VkDeviceSize>			accelerationSerialSizes;
1529 	Move<VkQueryPool>					m_queryPoolCompact;
1530 	Move<VkQueryPool>					m_queryPoolSerial;
1531 
1532 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
1533 	{
1534 		const VkImageMemoryBarrier				preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1535 			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1536 			**image, imageSubresourceRange);
1537 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1538 		const VkClearValue						clearValue = m_data.testConfiguration->getClearValue();
1539 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
1540 		const VkImageMemoryBarrier				postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1541 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1542 			**image, imageSubresourceRange);
1543 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1544 
1545 		// build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
1546 		bool									bottomCompact		= m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1547 		bool									bottomSerial		= m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1548 		const bool								buildWithoutGeom	= (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
1549 		const bool								bottomNoPrimitives	= (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
1550 		const bool								topNoPrimitives		= (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
1551 		const bool								inactiveInstances	= (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
1552 		bottomLevelAccelerationStructures							= m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1553 		VkBuildAccelerationStructureFlagsKHR	allowCompactionFlag	= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
1554 		VkBuildAccelerationStructureFlagsKHR	emptyCompactionFlag	= VkBuildAccelerationStructureFlagsKHR(0);
1555 		VkBuildAccelerationStructureFlagsKHR	bottomCompactFlags	= (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
1556 		VkBuildAccelerationStructureFlagsKHR	bottomBuildFlags	= m_data.buildFlags | bottomCompactFlags;
1557 		std::vector<VkAccelerationStructureKHR>	accelerationStructureHandles;
1558 		std::vector<VkDeviceSize>				bottomBlasCompactSize;
1559 		std::vector<VkDeviceSize>				bottomBlasSerialSize;
1560 
1561 		for (auto& blas : bottomLevelAccelerationStructures)
1562 		{
1563 			blas->setBuildType						(m_data.buildType);
1564 			blas->setBuildFlags						(bottomBuildFlags);
1565 			blas->setUseArrayOfPointers				(m_data.bottomUsesAOP);
1566 			blas->setCreateGeneric					(m_data.bottomGeneric);
1567 			blas->setBuildWithoutGeometries			(buildWithoutGeom);
1568 			blas->setBuildWithoutPrimitives			(bottomNoPrimitives);
1569 			blas->createAndBuild					(vkd, device, *cmdBuffer, allocator);
1570 			accelerationStructureHandles.push_back	(*(blas->getPtr()));
1571 		}
1572 
1573 		if (m_data.operationType == OP_COMPACT)
1574 		{
1575 			deUint32 queryCount	= (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
1576 			if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1577 				m_queryPoolCompact = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
1578 			if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1579 				queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
1580 		}
1581 		if (m_data.operationType == OP_SERIALIZE)
1582 		{
1583 			deUint32 queryCount	= (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
1584 			if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1585 				m_queryPoolSerial = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
1586 			if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1587 				queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
1588 		}
1589 
1590 		// if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1591 		if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
1592 		{
1593 			endCommandBuffer(vkd, *cmdBuffer);
1594 
1595 			submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1596 
1597 			if (bottomCompact)
1598 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(bottomBlasCompactSize.size()), sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1599 			if (bottomSerial)
1600 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(bottomBlasSerialSize.size()), sizeof(VkDeviceSize) * bottomBlasSerialSize.size(), bottomBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1601 
1602 			vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1603 			beginCommandBuffer(vkd, *cmdBuffer, 0u);
1604 		}
1605 
1606 		auto bottomLevelAccelerationStructuresPtr								= &bottomLevelAccelerationStructures;
1607 		if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1608 		{
1609 			switch (m_data.operationType)
1610 			{
1611 			case OP_COPY:
1612 			{
1613 				for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1614 				{
1615 					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1616 					asCopy->setDeferredOperation(htCopy, workerThreadsCount);
1617 					asCopy->setBuildType(m_data.buildType);
1618 					asCopy->setBuildFlags(m_data.buildFlags);
1619 					asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1620 					asCopy->setCreateGeneric(m_data.bottomGeneric);
1621 					asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1622 					asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1623 					asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), 0u, 0u);
1624 					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1625 				}
1626 				break;
1627 			}
1628 			case OP_COMPACT:
1629 			{
1630 				for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1631 				{
1632 					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1633 					asCopy->setBuildType(m_data.buildType);
1634 					asCopy->setBuildFlags(m_data.buildFlags);
1635 					asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1636 					asCopy->setCreateGeneric(m_data.bottomGeneric);
1637 					asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1638 					asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1639 					asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
1640 					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1641 				}
1642 				break;
1643 			}
1644 			case OP_SERIALIZE:
1645 			{
1646 				//bottomLevelAccelerationStructureCopies = m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1647 				for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
1648 				{
1649 					de::SharedPtr<SerialStorage> storage ( new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
1650 
1651 					bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
1652 					bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
1653 					bottomSerialized.push_back(storage);
1654 
1655 					if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1656 					{
1657 						endCommandBuffer(vkd, *cmdBuffer);
1658 
1659 						submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1660 
1661 						vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1662 						beginCommandBuffer(vkd, *cmdBuffer, 0u);
1663 					}
1664 
1665 					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1666 					asCopy->setBuildType(m_data.buildType);
1667 					asCopy->setBuildFlags(m_data.buildFlags);
1668 					asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
1669 					asCopy->setCreateGeneric(m_data.bottomGeneric);
1670 					asCopy->setBuildWithoutGeometries(buildWithoutGeom);
1671 					asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
1672 					asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
1673 					asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
1674 					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1675 				}
1676 				break;
1677 			}
1678 			default:
1679 				DE_ASSERT(DE_FALSE);
1680 			}
1681 			bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
1682 		}
1683 
1684 		// build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
1685 		bool									topCompact			= m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
1686 		bool									topSerial			= m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
1687 		VkBuildAccelerationStructureFlagsKHR	topCompactFlags		= (topCompact ? allowCompactionFlag : emptyCompactionFlag);
1688 		VkBuildAccelerationStructureFlagsKHR	topBuildFlags		= m_data.buildFlags | topCompactFlags;
1689 		std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
1690 		std::vector<VkDeviceSize>				topBlasCompactSize;
1691 		std::vector<VkDeviceSize>				topBlasSerialSize;
1692 
1693 		topLevelAccelerationStructure								= m_data.testConfiguration->initTopAccelerationStructure(m_context, m_data, *bottomLevelAccelerationStructuresPtr);
1694 		topLevelAccelerationStructure->setBuildType					(m_data.buildType);
1695 		topLevelAccelerationStructure->setBuildFlags				(topBuildFlags);
1696 		topLevelAccelerationStructure->setBuildWithoutPrimitives	(topNoPrimitives);
1697 		topLevelAccelerationStructure->setUseArrayOfPointers		(m_data.topUsesAOP);
1698 		topLevelAccelerationStructure->setCreateGeneric				(m_data.topGeneric);
1699 		topLevelAccelerationStructure->setInactiveInstances			(inactiveInstances);
1700 		topLevelAccelerationStructure->createAndBuild				(vkd, device, *cmdBuffer, allocator);
1701 		topLevelStructureHandles.push_back							(*(topLevelAccelerationStructure->getPtr()));
1702 
1703 		if (topCompact)
1704 			queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
1705 		if (topSerial)
1706 			queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
1707 
1708 		// if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1709 		if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
1710 		{
1711 			endCommandBuffer(vkd, *cmdBuffer);
1712 
1713 			submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1714 
1715 			if (topCompact)
1716 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(topBlasCompactSize.size()), sizeof(VkDeviceSize) * topBlasCompactSize.size(), topBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1717 			if (topSerial)
1718 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(topBlasSerialSize.size()), sizeof(VkDeviceSize) * topBlasSerialSize.size(), topBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1719 
1720 			vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1721 			beginCommandBuffer(vkd, *cmdBuffer, 0u);
1722 		}
1723 
1724 		const TopLevelAccelerationStructure*			topLevelRayTracedPtr	= topLevelAccelerationStructure.get();
1725 		if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
1726 		{
1727 			switch (m_data.operationType)
1728 			{
1729 				case OP_COPY:
1730 				{
1731 					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1732 					topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
1733 					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1734 					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
1735 					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
1736 					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
1737 					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
1738 					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
1739 					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), 0u, 0u);
1740 					break;
1741 				}
1742 				case OP_COMPACT:
1743 				{
1744 					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1745 					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1746 					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
1747 					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
1748 					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
1749 					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
1750 					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
1751 					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
1752 					break;
1753 				}
1754 				case OP_SERIALIZE:
1755 				{
1756 					de::SharedPtr<SerialStorage> storage = de::SharedPtr<SerialStorage>(new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
1757 
1758 					topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
1759 					topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
1760 					topSerialized.push_back(storage);
1761 
1762 					if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1763 					{
1764 						endCommandBuffer(vkd, *cmdBuffer);
1765 
1766 						submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1767 
1768 						vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1769 						beginCommandBuffer(vkd, *cmdBuffer, 0u);
1770 					}
1771 
1772 					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1773 					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1774 					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
1775 					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
1776 					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
1777 					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
1778 					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
1779 					topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
1780 					topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
1781 					break;
1782 				}
1783 				default:
1784 					DE_ASSERT(DE_FALSE);
1785 			}
1786 			topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
1787 		}
1788 
1789 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
1790 		{
1791 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1792 			DE_NULL,															//  const void*							pNext;
1793 			1u,																	//  deUint32							accelerationStructureCount;
1794 			topLevelRayTracedPtr->getPtr(),										//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1795 		};
1796 
1797 		DescriptorSetUpdateBuilder()
1798 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1799 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1800 			.update(vkd, device);
1801 
1802 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1803 
1804 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1805 
1806 		cmdTraceRays(vkd,
1807 			*cmdBuffer,
1808 			&raygenShaderBindingTableRegion,
1809 			&missShaderBindingTableRegion,
1810 			&hitShaderBindingTableRegion,
1811 			&callableShaderBindingTableRegion,
1812 			m_data.width, m_data.height, 1);
1813 
1814 		const VkMemoryBarrier				postTraceMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1815 		const VkMemoryBarrier				postCopyMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1816 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1817 
1818 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
1819 
1820 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
1821 	}
1822 	endCommandBuffer(vkd, *cmdBuffer);
1823 
1824 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1825 
1826 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(deUint32));
1827 
1828 	return resultBuffer;
1829 }
1830 
iterateNoWorkers(void)1831 bool RayTracingASBasicTestInstance::iterateNoWorkers (void)
1832 {
1833 	// run test using arrays of pointers
1834 	const de::MovePtr<BufferWithMemory>	buffer		= runTest(0);
1835 
1836 	return m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data);
1837 }
1838 
iterateWithWorkers(void)1839 bool RayTracingASBasicTestInstance::iterateWithWorkers (void)
1840 {
1841 	const deUint64					singleThreadTimeStart	= deGetMicroseconds();
1842 	de::MovePtr<BufferWithMemory>	singleThreadBufferCPU	= runTest(0);
1843 	const bool						singleThreadValidation	= m_data.testConfiguration->verifyImage(singleThreadBufferCPU.get(), m_context, m_data);
1844 	const deUint64					singleThreadTime		= deGetMicroseconds() - singleThreadTimeStart;
1845 
1846 	deUint64						multiThreadTimeStart	= deGetMicroseconds();
1847 	de::MovePtr<BufferWithMemory>	multiThreadBufferCPU	= runTest(m_data.workerThreadsCount);
1848 	const bool						multiThreadValidation	= m_data.testConfiguration->verifyImage(multiThreadBufferCPU.get(), m_context, m_data);
1849 	deUint64						multiThreadTime			= deGetMicroseconds() - multiThreadTimeStart;
1850 	const deUint64					multiThreadTimeOut		= 10 * singleThreadTime;
1851 
1852 	const deUint32					result					= singleThreadValidation && multiThreadValidation;
1853 
1854 	if (multiThreadTime > multiThreadTimeOut)
1855 	{
1856 		std::string failMsg	= "Time of multithreaded test execution " + de::toString(multiThreadTime) +
1857 							  " that is longer than expected execution time " + de::toString(multiThreadTimeOut);
1858 
1859 		TCU_FAIL(failMsg);
1860 	}
1861 
1862 	return result;
1863 }
1864 
iterate(void)1865 tcu::TestStatus RayTracingASBasicTestInstance::iterate (void)
1866 {
1867 	bool result;
1868 
1869 	if (m_data.workerThreadsCount != 0)
1870 		result = iterateWithWorkers();
1871 	else
1872 		result = iterateNoWorkers();
1873 
1874 	if (result)
1875 		return tcu::TestStatus::pass("Pass");
1876 	else
1877 		return tcu::TestStatus::fail("Fail");
1878 }
1879 
1880 // Tests dynamic indexing of acceleration structures
1881 class RayTracingASDynamicIndexingTestCase : public TestCase
1882 {
1883 public:
1884 						RayTracingASDynamicIndexingTestCase			(tcu::TestContext& context, const char* name);
1885 						~RayTracingASDynamicIndexingTestCase		(void) = default;
1886 
1887 	void				checkSupport								(Context& context) const override;
1888 	void				initPrograms								(SourceCollections& programCollection) const override;
1889 	TestInstance*		createInstance								(Context& context) const override;
1890 };
1891 
1892 class RayTracingASDynamicIndexingTestInstance : public TestInstance
1893 {
1894 public:
1895 						RayTracingASDynamicIndexingTestInstance		(Context& context);
1896 						~RayTracingASDynamicIndexingTestInstance	(void) = default;
1897 	tcu::TestStatus		iterate										(void) override;
1898 };
1899 
RayTracingASDynamicIndexingTestCase(tcu::TestContext & context,const char * name)1900 RayTracingASDynamicIndexingTestCase::RayTracingASDynamicIndexingTestCase(tcu::TestContext& context, const char* name)
1901 	: TestCase(context, name, "")
1902 {
1903 }
1904 
checkSupport(Context & context) const1905 void RayTracingASDynamicIndexingTestCase::checkSupport(Context& context) const
1906 {
1907 	commonASTestsCheckSupport(context);
1908 	context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
1909 }
1910 
initPrograms(SourceCollections & programCollection) const1911 void RayTracingASDynamicIndexingTestCase::initPrograms(SourceCollections& programCollection) const
1912 {
1913 	const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
1914 	const vk::ShaderBuildOptions glslBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1915 
1916 	// raygen shader is defined in spir-v as it requires possing pointer to TLAS that was read from ssbo;
1917 	// original spir-v code was generated using following glsl code but resulting spir-v code was modiifed
1918 	//
1919 	// #version 460 core
1920 	// #extension GL_EXT_ray_tracing : require
1921 	// #extension GL_EXT_nonuniform_qualifier : enable
1922 	// #extension GL_ARB_gpu_shader_int64 : enable			// needed only to generate spir-v
1923 	// #define ARRAY_SIZE 500
1924 	// layout(location = 0) rayPayloadEXT uvec2 payload;	// offset and flag indicating if we are using descriptors or pointers
1925 
1926 	// layout(set = 0, binding = 0) uniform accelerationStructureEXT tlasArray[ARRAY_SIZE];
1927 	// layout(set = 0, binding = 1) readonly buffer topLevelASPointers {
1928 	//     uint64_t ptr[];
1929 	// } tlasPointers;
1930 	// layout(set = 0, binding = 2) readonly buffer topLevelASIndices {
1931 	//     uint idx[];
1932 	// } tlasIndices;
1933 	// layout(set = 0, binding = 3, std430) writeonly buffer Result {
1934 	//     uint value[];
1935 	// } result;
1936 
1937 	// void main()
1938 	// {
1939 	//   float tmin            = 0.0;\n"
1940 	//   float tmax            = 2.0;\n"
1941 	//   vec3  origin          = vec3(0.25f, 0.5f, 1.0);\n"
1942 	//   vec3  direction       = vec3(0.0,0.0,-1.0);\n"
1943 	//   uint  activeTlasIndex = gl_LaunchIDEXT.x;\n"
1944 	//   uint  activeTlasCount = gl_LaunchSizeEXT.x;\n"
1945 	//   uint  tlasIndex       = tlasIndices.idx[nonuniformEXT(activeTlasIndex)];\n"
1946 
1947 	//   atomicAdd(result.value[nonuniformEXT(activeTlasIndex)], 2);\n"
1948 	//   payload = uvec2(activeTlasIndex + activeTlasCount.x, 0);\n"
1949 	//   traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
1950 
1951 	//   atomicAdd(result.value[nonuniformEXT(activeTlasIndex + activeTlasCount * 2)], 5);\n"
1952 	//   payload = uvec2(activeTlasIndex + activeTlasCount * 3, 1);\n"
1953 	//   traceRayEXT(tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);				// used to generate initial spirv
1954 	//   //traceRayEXT(*tlasPointers.ptr[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);	// not available in glsl but should be done in spirv
1955 	// };
1956 
1957 	const std::string rgenSource =
1958 		"OpCapability Int64\n"
1959 		"OpCapability RayTracingKHR\n"
1960 		"OpCapability ShaderNonUniform\n"
1961 		"OpExtension \"SPV_EXT_descriptor_indexing\"\n"
1962 		"OpExtension \"SPV_KHR_ray_tracing\"\n"
1963 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1964 		"OpMemoryModel Logical GLSL450\n"
1965 		"OpEntryPoint RayGenerationKHR %4 \"main\" %27 %33 %var_tlas_indices %var_result %60 %var_as_arr_ptr %var_as_pointers_ssbo\n"
1966 		"OpDecorate %27 BuiltIn LaunchIdNV\n"
1967 		"OpDecorate %33 BuiltIn LaunchSizeNV\n"
1968 		"OpDecorate %37 ArrayStride 4\n"
1969 		"OpMemberDecorate %38 0 NonWritable\n"
1970 		"OpMemberDecorate %38 0 Offset 0\n"
1971 		"OpDecorate %38 Block\n"
1972 		"OpDecorate %var_tlas_indices DescriptorSet 0\n"
1973 		"OpDecorate %var_tlas_indices Binding 2\n"
1974 		"OpDecorate %44 NonUniform\n"
1975 		"OpDecorate %46 NonUniform\n"
1976 		"OpDecorate %47 NonUniform\n"
1977 		"OpDecorate %48 ArrayStride 4\n"
1978 		"OpMemberDecorate %49 0 NonReadable\n"
1979 		"OpMemberDecorate %49 0 Offset 0\n"
1980 		"OpDecorate %49 Block\n"
1981 		"OpDecorate %var_result DescriptorSet 0\n"
1982 		"OpDecorate %var_result Binding 3\n"
1983 		"OpDecorate %53 NonUniform\n"
1984 		"OpDecorate %60 Location 0\n"
1985 		"OpDecorate %var_as_arr_ptr DescriptorSet 0\n"
1986 		"OpDecorate %var_as_arr_ptr Binding 0\n"
1987 		"OpDecorate %71 NonUniform\n"
1988 		"OpDecorate %73 NonUniform\n"
1989 		"OpDecorate %74 NonUniform\n"
1990 		"OpDecorate %85 NonUniform\n"
1991 		"OpDecorate %as_index NonUniform\n"
1992 		"OpDecorate %as_device_addres NonUniform\n"
1993 		"OpDecorate %104 ArrayStride 8\n"
1994 		"OpMemberDecorate %105 0 NonWritable\n"
1995 		"OpMemberDecorate %105 0 Offset 0\n"
1996 		"OpDecorate %105 Block\n"
1997 		"OpDecorate %var_as_pointers_ssbo DescriptorSet 0\n"
1998 		"OpDecorate %var_as_pointers_ssbo Binding 1\n"
1999 		// types, constants and variables
2000 		"%2								= OpTypeVoid\n"
2001 		"%3								= OpTypeFunction %2\n"
2002 		"%6								= OpTypeFloat 32\n"
2003 		"%7								= OpTypePointer Function %6\n"
2004 		"%9								= OpConstant %6 0\n"
2005 		"%11							= OpConstant %6 2\n"
2006 		"%12							= OpTypeVector %6 3\n"
2007 		"%13							= OpTypePointer Function %12\n"
2008 		"%15							= OpConstant %6 0.25\n"
2009 		"%16							= OpConstant %6 0.5\n"
2010 		"%17							= OpConstant %6 1\n"
2011 		"%18							= OpConstantComposite %12 %15 %16 %17\n"
2012 		"%20							= OpConstant %6 -1\n"
2013 		"%21							= OpConstantComposite %12 %9 %9 %20\n"
2014 		"%type_uint32					= OpTypeInt 32 0\n"
2015 		"%23							= OpTypePointer Function %type_uint32\n"
2016 		"%25							= OpTypeVector %type_uint32 3\n"
2017 		"%26							= OpTypePointer Input %25\n"
2018 		"%27							= OpVariable %26 Input\n"
2019 		"%28							= OpConstant %type_uint32 0\n"
2020 		"%29							= OpTypePointer Input %type_uint32\n"
2021 		"%33							= OpVariable %26 Input\n"
2022 		"%37							= OpTypeRuntimeArray %type_uint32\n"
2023 		"%38							= OpTypeStruct %37\n"
2024 		"%39							= OpTypePointer StorageBuffer %38\n"
2025 		"%var_tlas_indices				= OpVariable %39 StorageBuffer\n"
2026 		"%type_int32					= OpTypeInt 32 1\n"
2027 		"%c_int32_0						= OpConstant %type_int32 0\n"
2028 		"%45							= OpTypePointer StorageBuffer %type_uint32\n"
2029 		"%48							= OpTypeRuntimeArray %type_uint32\n"
2030 		"%49							= OpTypeStruct %48\n"
2031 		"%50							= OpTypePointer StorageBuffer %49\n"
2032 		"%var_result					= OpVariable %50 StorageBuffer\n"
2033 		"%55							= OpConstant %type_uint32 2\n"
2034 		"%56							= OpConstant %type_uint32 1\n"
2035 		"%58							= OpTypeVector %type_uint32 2\n"
2036 		"%59							= OpTypePointer RayPayloadNV %58\n"
2037 		"%60							= OpVariable %59 RayPayloadNV\n"
2038 		"%type_as						= OpTypeAccelerationStructureKHR\n"
2039 		"%66							= OpConstant %type_uint32 500\n"
2040 		"%67							= OpTypeArray %type_as %66\n"
2041 		"%68							= OpTypePointer UniformConstant %67\n"
2042 		"%var_as_arr_ptr				= OpVariable %68 UniformConstant\n"
2043 		"%72							= OpTypePointer UniformConstant %type_as\n"
2044 		"%75							= OpConstant %type_uint32 16\n"
2045 		"%76							= OpConstant %type_uint32 255\n"
2046 		"%87							= OpConstant %type_uint32 5\n"
2047 		"%91							= OpConstant %type_uint32 3\n"
2048 
2049 		// <changed_section>
2050 		"%type_uint64					= OpTypeInt 64 0\n"
2051 		"%104							= OpTypeRuntimeArray %type_uint64\n"
2052 		"%105							= OpTypeStruct %104\n"
2053 		"%106							= OpTypePointer StorageBuffer %105\n"
2054 		"%var_as_pointers_ssbo			= OpVariable %106 StorageBuffer\n"
2055 		"%type_uint64_ssbo_ptr			= OpTypePointer StorageBuffer %type_uint64\n"
2056 		// </changed_section>
2057 
2058 		// void main()
2059 		"%4								= OpFunction %2 None %3\n"
2060 		"%5								= OpLabel\n"
2061 		"%8								= OpVariable %7 Function\n"
2062 		"%10							= OpVariable %7 Function\n"
2063 		"%14							= OpVariable %13 Function\n"
2064 		"%19							= OpVariable %13 Function\n"
2065 		"%24							= OpVariable %23 Function\n"
2066 		"%32							= OpVariable %23 Function\n"
2067 		"%36							= OpVariable %23 Function\n"
2068 		"OpStore %8 %9\n"
2069 		"OpStore %10 %11\n"
2070 		"OpStore %14 %18\n"
2071 		"OpStore %19 %21\n"
2072 		"%30							= OpAccessChain %29 %27 %28\n"
2073 		"%31							= OpLoad %type_uint32 %30\n"
2074 		"OpStore %24 %31\n"
2075 		"%34							= OpAccessChain %29 %33 %28\n"
2076 		"%35							= OpLoad %type_uint32 %34\n"
2077 		"OpStore %32 %35\n"
2078 		"%43							= OpLoad %type_uint32 %24\n"
2079 		"%44							= OpCopyObject %type_uint32 %43\n"
2080 		"%46							= OpAccessChain %45 %var_tlas_indices %c_int32_0 %44\n"
2081 		"%47							= OpLoad %type_uint32 %46\n"
2082 		"OpStore %36 %47\n"
2083 		// atomicAdd
2084 		"%52							= OpLoad %type_uint32 %24\n"
2085 		"%53							= OpCopyObject %type_uint32 %52\n"
2086 		"%54							= OpAccessChain %45 %var_result %c_int32_0 %53\n"
2087 		"%57							= OpAtomicIAdd %type_uint32 %54 %56 %28 %55\n"
2088 		// setup payload
2089 		"%61							= OpLoad %type_uint32 %24\n"
2090 		"%62							= OpLoad %type_uint32 %32\n"
2091 		"%63							= OpIAdd %type_uint32 %61 %62\n"
2092 		"%64							= OpCompositeConstruct %58 %63 %28\n"
2093 		"OpStore %60 %64\n"
2094 		// trace rays using tlas from array
2095 		"%70							= OpLoad %type_uint32 %36\n"
2096 		"%71							= OpCopyObject %type_uint32 %70\n"
2097 		"%73							= OpAccessChain %72 %var_as_arr_ptr %71\n"
2098 		"%74							= OpLoad %type_as %73\n"
2099 		"%77							= OpLoad %12 %14\n"
2100 		"%78							= OpLoad %6 %8\n"
2101 		"%79							= OpLoad %12 %19\n"
2102 		"%80							= OpLoad %6 %10\n"
2103 		"OpTraceRayKHR %74 %75 %76 %28 %28 %28 %77 %78 %79 %80 %60\n"
2104 		// atomicAdd
2105 		"%81							= OpLoad %type_uint32 %24\n"
2106 		"%82							= OpLoad %type_uint32 %32\n"
2107 		"%83							= OpIMul %type_uint32 %82 %55\n"
2108 		"%84							= OpIAdd %type_uint32 %81 %83\n"
2109 		"%85							= OpCopyObject %type_uint32 %84\n"
2110 		"%86							= OpAccessChain %45 %var_result %c_int32_0 %85\n"
2111 		"%88							= OpAtomicIAdd %type_uint32 %86 %56 %28 %87\n"
2112 		// setup payload
2113 		"%89							= OpLoad %type_uint32 %24\n"
2114 		"%90							= OpLoad %type_uint32 %32\n"
2115 		"%92							= OpIMul %type_uint32 %90 %91\n"
2116 		"%93							= OpIAdd %type_uint32 %89 %92\n"
2117 		"%94							= OpCompositeConstruct %58 %93 %56\n"
2118 		"OpStore %60 %94\n"
2119 		// trace rays using pointers to tlas
2120 		"%95							= OpLoad %type_uint32 %36\n"
2121 		"%as_index						= OpCopyObject %type_uint32 %95\n"
2122 
2123 		// <changed_section> OLD
2124 		"%as_device_addres_ptr			= OpAccessChain %type_uint64_ssbo_ptr %var_as_pointers_ssbo %c_int32_0 %as_index\n"
2125 		"%as_device_addres				= OpLoad %type_uint64 %as_device_addres_ptr Aligned 8\n"
2126 		"%as_to_use						= OpConvertUToAccelerationStructureKHR %type_as %as_device_addres\n"
2127 		// </changed_section>
2128 
2129 		"%99							= OpLoad %12 %14\n"
2130 		"%100							= OpLoad %6 %8\n"
2131 		"%101							= OpLoad %12 %19\n"
2132 		"%102							= OpLoad %6 %10\n"
2133 		"OpTraceRayKHR %as_to_use %75 %76 %28 %28 %28 %99 %100 %101 %102 %60\n"
2134 		"OpReturn\n"
2135 		"OpFunctionEnd\n";
2136 	programCollection.spirvAsmSources.add("rgen") << rgenSource << spvBuildOptions;
2137 
2138 	std::string chitSource =
2139 		"#version 460 core\n"
2140 		"#extension GL_EXT_ray_tracing : require\n"
2141 		"#extension GL_EXT_nonuniform_qualifier : enable\n"
2142 		"layout(location = 0) rayPayloadInEXT uvec2 payload;\n"
2143 		"\n"
2144 		"layout(set = 0, binding = 3) writeonly buffer Result {\n"
2145 		"    uint value[];\n"
2146 		"} result;\n"
2147 		"void main()\n"
2148 		"{\n"
2149 		     // payload.y is 0 or 1 so we will add 3 or 7 (just two prime numbers)
2150 		"    atomicAdd(result.value[nonuniformEXT(payload.x)], 3 + payload.y * 4);\n"
2151 		"}\n";
2152 	programCollection.glslSources.add("chit") << glu::ClosestHitSource(chitSource) << glslBuildOptions;
2153 }
2154 
createInstance(Context & context) const2155 TestInstance* RayTracingASDynamicIndexingTestCase::createInstance(Context& context) const
2156 {
2157 	return new RayTracingASDynamicIndexingTestInstance(context);
2158 }
2159 
RayTracingASDynamicIndexingTestInstance(Context & context)2160 RayTracingASDynamicIndexingTestInstance::RayTracingASDynamicIndexingTestInstance(Context& context)
2161 	: vkt::TestInstance(context)
2162 {
2163 }
2164 
iterate(void)2165 tcu::TestStatus RayTracingASDynamicIndexingTestInstance::iterate(void)
2166 {
2167 	const InstanceInterface&	vki							= m_context.getInstanceInterface();
2168 	const DeviceInterface&		vkd							= m_context.getDeviceInterface();
2169 	const VkDevice				device						= m_context.getDevice();
2170 	const VkPhysicalDevice		physicalDevice				= m_context.getPhysicalDevice();
2171 	const deUint32				queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
2172 	const VkQueue				queue						= m_context.getUniversalQueue();
2173 	Allocator&					allocator					= m_context.getDefaultAllocator();
2174 	const deUint32				shaderGroupHandleSize		= getShaderGroupSize(vki, physicalDevice);
2175 	const deUint32				shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
2176 	const deUint32				tlasCount					= 500;	// changing this will require also changing shaders
2177 	const deUint32				activeTlasCount				= 32;	// number of tlas out of <tlasCount> that will be active
2178 
2179 	const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
2180 		.addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, ALL_RAY_TRACING_STAGES)
2181 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES)				// pointers to all acceleration structures
2182 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES)				// ssbo with indices of all acceleration structures
2183 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES)				// ssbo with result values
2184 		.build(vkd, device);
2185 
2186 	const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
2187 		.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount)
2188 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2189 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2190 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2191 		.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2192 	const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
2193 
2194 	de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
2195 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,      createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
2196 	rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
2197 
2198 	const Move<VkPipelineLayout>			pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
2199 	Move<VkPipeline>						pipeline							= rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
2200 	de::MovePtr<BufferWithMemory>			raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
2201 	de::MovePtr<BufferWithMemory>			hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
2202 
2203 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2204 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2205 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
2206 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2207 
2208 	const VkDeviceSize						pointerBufferSize		= tlasCount * sizeof(VkDeviceAddress);
2209 	const VkBufferCreateInfo				pointerBufferCreateInfo	= makeBufferCreateInfo(pointerBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2210 	de::MovePtr<BufferWithMemory>			pointerBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, pointerBufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
2211 
2212 	const VkDeviceSize						indicesBufferSize		= activeTlasCount * sizeof(deUint32);
2213 	const VkBufferCreateInfo				indicesBufferCreateInfo	= makeBufferCreateInfo(indicesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2214 	de::MovePtr<BufferWithMemory>			indicesBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, indicesBufferCreateInfo, MemoryRequirement::HostVisible));
2215 
2216 	const VkDeviceSize						resultBufferSize		= activeTlasCount * sizeof(deUint32) * 4;
2217 	const VkBufferCreateInfo				resultBufferCreateInfo	= makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2218 	de::MovePtr<BufferWithMemory>			resultBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2219 
2220 	const Move<VkCommandPool>				cmdPool					= createCommandPool(vkd, device, 0, queueFamilyIndex);
2221 	const Move<VkCommandBuffer>				cmdBuffer				= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2222 
2223 	de::SharedPtr<BottomLevelAccelerationStructure>				blas = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
2224 	std::vector<de::MovePtr<TopLevelAccelerationStructure>>		tlasVect(tlasCount);
2225 	std::vector<VkDeviceAddress>								tlasPtrVect(tlasCount);
2226 	std::vector<VkAccelerationStructureKHR>						tlasVkVect;
2227 
2228 	// randomly scatter active AS across the range
2229 	deRandom rnd;
2230 	deRandom_init(&rnd, 123);
2231 	std::set<deUint32> asIndicesSet;
2232 	while (asIndicesSet.size() < activeTlasCount)
2233 		asIndicesSet.insert(deRandom_getUint32(&rnd) % tlasCount);
2234 
2235 	// fill indices buffer
2236 	deUint32 helperIndex = 0;
2237 	auto& indicesBufferAlloc	= indicesBuffer->getAllocation();
2238 	deUint32* indicesBufferPtr	= reinterpret_cast<deUint32*>(indicesBufferAlloc.getHostPtr());
2239 	std::for_each(asIndicesSet.begin(), asIndicesSet.end(),
2240 		[&helperIndex, indicesBufferPtr](const deUint32& index)
2241 		{
2242 			indicesBufferPtr[helperIndex++] = index;
2243 		});
2244 	vk::flushAlloc(vkd, device, indicesBufferAlloc);
2245 
2246 	// clear result buffer
2247 	auto& resultBufferAlloc		= resultBuffer->getAllocation();
2248 	void* resultBufferPtr		= resultBufferAlloc.getHostPtr();
2249 	deMemset(resultBufferPtr, 0, static_cast<size_t>(resultBufferSize));
2250 	vk::flushAlloc(vkd, device, resultBufferAlloc);
2251 
2252 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
2253 	{
2254 		// build bottom level acceleration structure
2255 		blas->setGeometryData(
2256 			{
2257 				{ 0.0, 0.0, 0.0 },
2258 				{ 1.0, 0.0, 0.0 },
2259 				{ 0.0, 1.0, 0.0 },
2260 			},
2261 			true,
2262 			VK_GEOMETRY_OPAQUE_BIT_KHR
2263 		);
2264 
2265 		blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2266 
2267 		// build top level acceleration structures
2268 		for (deUint32 tlasIndex = 0; tlasIndex < tlasCount; ++tlasIndex)
2269 		{
2270 			auto& tlas = tlasVect[tlasIndex];
2271 			tlas = makeTopLevelAccelerationStructure();
2272 			tlas->setInstanceCount(1);
2273 			tlas->addInstance(blas);
2274 			if (!asIndicesSet.count(tlasIndex))
2275 			{
2276 				// tlas that are not in asIndicesSet should be empty but it is hard to do
2277 				// that with current cts utils so we are marking them as inactive instead
2278 				tlas->setInactiveInstances(true);
2279 			}
2280 			tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
2281 
2282 			// get acceleration structure device address
2283 			const VkAccelerationStructureDeviceAddressInfoKHR addressInfo =
2284 			{
2285 				VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType				sType
2286 				DE_NULL,															// const void*					pNext
2287 				*tlas->getPtr()														// VkAccelerationStructureKHR	accelerationStructure
2288 			};
2289 			VkDeviceAddress vkda = vkd.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
2290 			tlasPtrVect[tlasIndex] = vkda;
2291 		}
2292 
2293 		// fill pointer buffer
2294 		vkd.cmdUpdateBuffer(*cmdBuffer, **pointerBuffer, 0, pointerBufferSize, tlasPtrVect.data());
2295 
2296 		// wait for data transfers
2297 		const VkMemoryBarrier bufferUploadBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
2298 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &bufferUploadBarrier, 1u);
2299 
2300 		// wait for as build
2301 		const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
2302 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &asBuildBarrier, 1u);
2303 
2304 		tlasVkVect.reserve(tlasCount);
2305 		for (auto& tlas : tlasVect)
2306 			tlasVkVect.push_back(*tlas->getPtr());
2307 
2308 		VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
2309 		{
2310 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	// VkStructureType						sType;
2311 			DE_NULL,															// const void*							pNext;
2312 			tlasCount,															// deUint32								accelerationStructureCount;
2313 			tlasVkVect.data(),													// const VkAccelerationStructureKHR*	pAccelerationStructures;
2314 		};
2315 
2316 		const vk::VkDescriptorBufferInfo pointerBufferInfo	= makeDescriptorBufferInfo(**pointerBuffer, 0u, VK_WHOLE_SIZE);
2317 		const vk::VkDescriptorBufferInfo indicesBufferInfo	= makeDescriptorBufferInfo(**indicesBuffer, 0u, VK_WHOLE_SIZE);
2318 		const vk::VkDescriptorBufferInfo resultInfo			= makeDescriptorBufferInfo(**resultBuffer,  0u, VK_WHOLE_SIZE);
2319 
2320 		DescriptorSetUpdateBuilder()
2321 			.writeArray (*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, &accelerationStructureWriteDescriptorSet)
2322 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &pointerBufferInfo)
2323 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indicesBufferInfo)
2324 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo)
2325 			.update(vkd, device);
2326 
2327 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
2328 
2329 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
2330 
2331 		cmdTraceRays(vkd,
2332 			*cmdBuffer,
2333 			&raygenShaderBindingTableRegion,
2334 			&missShaderBindingTableRegion,
2335 			&hitShaderBindingTableRegion,
2336 			&callableShaderBindingTableRegion,
2337 			activeTlasCount, 1, 1);
2338 
2339 		const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2340 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
2341 	}
2342 	endCommandBuffer(vkd, *cmdBuffer);
2343 
2344 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2345 
2346 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), resultBufferSize);
2347 
2348 	// verify result buffer
2349 	deUint32		failures	= 0;
2350 	const deUint32*	resultPtr	= reinterpret_cast<deUint32*>(resultBuffer->getAllocation().getHostPtr());
2351 	for (deUint32 index = 0; index < activeTlasCount; ++index)
2352 	{
2353 		failures += (resultPtr[0 * activeTlasCount + index] != 2) +
2354 					(resultPtr[1 * activeTlasCount + index] != 3) +
2355 					(resultPtr[2 * activeTlasCount + index] != 5) +
2356 					(resultPtr[3 * activeTlasCount + index] != 7);
2357 	}
2358 
2359 	if (failures)
2360 		return tcu::TestStatus::fail(de::toString(failures) + " failures, " + de::toString(4 * activeTlasCount - failures) + " are ok");
2361 	return tcu::TestStatus::pass("Pass");
2362 }
2363 
2364 }	// anonymous
2365 
addBasicBuildingTests(tcu::TestCaseGroup * group)2366 void addBasicBuildingTests(tcu::TestCaseGroup* group)
2367 {
2368 	struct
2369 	{
2370 		vk::VkAccelerationStructureBuildTypeKHR	buildType;
2371 		const char*								name;
2372 	} buildTypes[] =
2373 	{
2374 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,				"cpu_built"	},
2375 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,				"gpu_built"	},
2376 	};
2377 
2378 	struct
2379 	{
2380 		BottomTestType							testType;
2381 		bool									usesAOP;
2382 		const char*								name;
2383 	} bottomTestTypes[] =
2384 	{
2385 		{ BTT_TRIANGLES,	false,										"triangles" },
2386 		{ BTT_TRIANGLES,	true,										"triangles_aop" },
2387 		{ BTT_AABBS,		false,										"aabbs" },
2388 		{ BTT_AABBS,		true,										"aabbs_aop" },
2389 	};
2390 
2391 	struct
2392 	{
2393 		TopTestType								testType;
2394 		bool									usesAOP;
2395 		const char*								name;
2396 	} topTestTypes[] =
2397 	{
2398 		{ TTT_IDENTICAL_INSTANCES,	false,								"identical_instances" },
2399 		{ TTT_IDENTICAL_INSTANCES,	true,								"identical_instances_aop" },
2400 		{ TTT_DIFFERENT_INSTANCES,	false,								"different_instances" },
2401 		{ TTT_DIFFERENT_INSTANCES,	true,								"different_instances_aop" },
2402 	};
2403 
2404 	struct BuildFlagsData
2405 	{
2406 		VkBuildAccelerationStructureFlagsKHR	flags;
2407 		const char*								name;
2408 	};
2409 
2410 	BuildFlagsData optimizationTypes[] =
2411 	{
2412 		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
2413 		{ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,	"fasttrace" },
2414 		{ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR,	"fastbuild" },
2415 	};
2416 
2417 	BuildFlagsData updateTypes[] =
2418 	{
2419 		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
2420 		{ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,			"update" },
2421 	};
2422 
2423 	BuildFlagsData compactionTypes[] =
2424 	{
2425 		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
2426 		{ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR,		"compaction" },
2427 	};
2428 
2429 	BuildFlagsData lowMemoryTypes[] =
2430 	{
2431 		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
2432 		{ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR,			"lowmemory" },
2433 	};
2434 
2435 	struct
2436 	{
2437 		bool		padVertices;
2438 		const char*	name;
2439 	} paddingType[] =
2440 	{
2441 		{ false,	"nopadding"	},
2442 		{ true,		"padded"	},
2443 	};
2444 
2445 	struct
2446 	{
2447 		bool		topGeneric;
2448 		bool		bottomGeneric;
2449 		const char*	suffix;
2450 	} createGenericParams[] =
2451 	{
2452 		{	false,	false,	""					},
2453 		{	false,	true,	"_bottomgeneric"	},
2454 		{	true,	false,	"_topgeneric"		},
2455 		{	true,	true,	"_bothgeneric"		},
2456 	};
2457 
2458 	for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2459 	{
2460 		de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
2461 
2462 		for (size_t bottomNdx = 0; bottomNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++bottomNdx)
2463 		{
2464 			de::MovePtr<tcu::TestCaseGroup> bottomGroup(new tcu::TestCaseGroup(group->getTestContext(), bottomTestTypes[bottomNdx].name, ""));
2465 
2466 			for (size_t topNdx = 0; topNdx < DE_LENGTH_OF_ARRAY(topTestTypes); ++topNdx)
2467 			{
2468 				de::MovePtr<tcu::TestCaseGroup> topGroup(new tcu::TestCaseGroup(group->getTestContext(), topTestTypes[topNdx].name, ""));
2469 
2470 				for (int paddingTypeIdx = 0; paddingTypeIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingTypeIdx)
2471 				{
2472 					de::MovePtr<tcu::TestCaseGroup> paddingGroup(new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingTypeIdx].name, ""));
2473 
2474 					for (size_t optimizationNdx = 0; optimizationNdx < DE_LENGTH_OF_ARRAY(optimizationTypes); ++optimizationNdx)
2475 					{
2476 						for (size_t updateNdx = 0; updateNdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateNdx)
2477 						{
2478 							for (size_t compactionNdx = 0; compactionNdx < DE_LENGTH_OF_ARRAY(compactionTypes); ++compactionNdx)
2479 							{
2480 								for (size_t lowMemoryNdx = 0; lowMemoryNdx < DE_LENGTH_OF_ARRAY(lowMemoryTypes); ++lowMemoryNdx)
2481 								{
2482 									for (int createGenericIdx = 0; createGenericIdx < DE_LENGTH_OF_ARRAY(createGenericParams); ++createGenericIdx)
2483 									{
2484 										std::string testName =
2485 											std::string(optimizationTypes[optimizationNdx].name) + "_" +
2486 											std::string(updateTypes[updateNdx].name) + "_" +
2487 											std::string(compactionTypes[compactionNdx].name) + "_" +
2488 											std::string(lowMemoryTypes[lowMemoryNdx].name) +
2489 											std::string(createGenericParams[createGenericIdx].suffix);
2490 
2491 										TestParams testParams
2492 										{
2493 											buildTypes[buildTypeNdx].buildType,
2494 											VK_FORMAT_R32G32B32_SFLOAT,
2495 											paddingType[paddingTypeIdx].padVertices,
2496 											VK_INDEX_TYPE_NONE_KHR,
2497 											bottomTestTypes[bottomNdx].testType,
2498 											InstanceCullFlags::NONE,
2499 											bottomTestTypes[bottomNdx].usesAOP,
2500 											createGenericParams[createGenericIdx].bottomGeneric,
2501 											topTestTypes[topNdx].testType,
2502 											topTestTypes[topNdx].usesAOP,
2503 											createGenericParams[createGenericIdx].topGeneric,
2504 											optimizationTypes[optimizationNdx].flags | updateTypes[updateNdx].flags | compactionTypes[compactionNdx].flags | lowMemoryTypes[lowMemoryNdx].flags,
2505 											OT_NONE,
2506 											OP_NONE,
2507 											RTAS_DEFAULT_SIZE,
2508 											RTAS_DEFAULT_SIZE,
2509 											de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
2510 											0u,
2511 											EmptyAccelerationStructureCase::NOT_EMPTY,
2512 											InstanceCustomIndexCase::NONE,
2513 										};
2514 										paddingGroup->addChild(new RayTracingASBasicTestCase(group->getTestContext(), testName.c_str(), "", testParams));
2515 									}
2516 								}
2517 							}
2518 						}
2519 					}
2520 					topGroup->addChild(paddingGroup.release());
2521 				}
2522 				bottomGroup->addChild(topGroup.release());
2523 			}
2524 			buildGroup->addChild(bottomGroup.release());
2525 		}
2526 		group->addChild(buildGroup.release());
2527 	}
2528 }
2529 
addVertexIndexFormatsTests(tcu::TestCaseGroup * group)2530 void addVertexIndexFormatsTests(tcu::TestCaseGroup* group)
2531 {
2532 	struct
2533 	{
2534 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
2535 		const char*											name;
2536 	} buildTypes[] =
2537 	{
2538 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
2539 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
2540 	};
2541 
2542 	const VkFormat vertexFormats[] =
2543 	{
2544 		// Mandatory formats.
2545 		VK_FORMAT_R32G32_SFLOAT,
2546 		VK_FORMAT_R32G32B32_SFLOAT,
2547 		VK_FORMAT_R16G16_SFLOAT,
2548 		VK_FORMAT_R16G16B16A16_SFLOAT,
2549 		VK_FORMAT_R16G16_SNORM,
2550 		VK_FORMAT_R16G16B16A16_SNORM,
2551 
2552 		// Additional formats.
2553 		VK_FORMAT_R8G8_SNORM,
2554 		VK_FORMAT_R8G8B8_SNORM,
2555 		VK_FORMAT_R8G8B8A8_SNORM,
2556 		VK_FORMAT_R16G16B16_SNORM,
2557 		VK_FORMAT_R16G16B16_SFLOAT,
2558 		VK_FORMAT_R32G32B32A32_SFLOAT,
2559 		VK_FORMAT_R64G64_SFLOAT,
2560 		VK_FORMAT_R64G64B64_SFLOAT,
2561 		VK_FORMAT_R64G64B64A64_SFLOAT,
2562 	};
2563 
2564 	struct
2565 	{
2566 		VkIndexType								indexType;
2567 		const char*								name;
2568 	} indexFormats[] =
2569 	{
2570 		{ VK_INDEX_TYPE_NONE_KHR ,				"index_none"		},
2571 		{ VK_INDEX_TYPE_UINT16 ,				"index_uint16"	},
2572 		{ VK_INDEX_TYPE_UINT32 ,				"index_uint32"	},
2573 	};
2574 
2575 	struct
2576 	{
2577 		bool		padVertices;
2578 		const char*	name;
2579 	} paddingType[] =
2580 	{
2581 		{ false,	"nopadding"	},
2582 		{ true,		"padded"	},
2583 	};
2584 
2585 	for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2586 	{
2587 		de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
2588 
2589 		for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
2590 		{
2591 			const auto format		= vertexFormats[vertexFormatNdx];
2592 			const auto formatName	= getFormatSimpleName(format);
2593 
2594 			de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str(), ""));
2595 
2596 			for (int paddingIdx = 0; paddingIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingIdx)
2597 			{
2598 				de::MovePtr<tcu::TestCaseGroup> paddingGroup(new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingIdx].name, ""));
2599 
2600 				for (size_t indexFormatNdx = 0; indexFormatNdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatNdx)
2601 				{
2602 					TestParams testParams
2603 					{
2604 						buildTypes[buildTypeNdx].buildType,
2605 						format,
2606 						paddingType[paddingIdx].padVertices,
2607 						indexFormats[indexFormatNdx].indexType,
2608 						BTT_TRIANGLES,
2609 						InstanceCullFlags::NONE,
2610 						false,
2611 						false,
2612 						TTT_IDENTICAL_INSTANCES,
2613 						false,
2614 						false,
2615 						VkBuildAccelerationStructureFlagsKHR(0u),
2616 						OT_NONE,
2617 						OP_NONE,
2618 						RTAS_DEFAULT_SIZE,
2619 						RTAS_DEFAULT_SIZE,
2620 						de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
2621 						0u,
2622 						EmptyAccelerationStructureCase::NOT_EMPTY,
2623 						InstanceCustomIndexCase::NONE,
2624 					};
2625 					paddingGroup->addChild(new RayTracingASBasicTestCase(group->getTestContext(), indexFormats[indexFormatNdx].name, "", testParams));
2626 				}
2627 				vertexFormatGroup->addChild(paddingGroup.release());
2628 			}
2629 			buildGroup->addChild(vertexFormatGroup.release());
2630 		}
2631 		group->addChild(buildGroup.release());
2632 	}
2633 }
2634 
addOperationTestsImpl(tcu::TestCaseGroup * group,const deUint32 workerThreads)2635 void addOperationTestsImpl (tcu::TestCaseGroup* group, const deUint32 workerThreads)
2636 {
2637 	struct
2638 	{
2639 		OperationType										operationType;
2640 		const char*											name;
2641 	} operationTypes[] =
2642 	{
2643 		{ OP_COPY,											"copy"			},
2644 		{ OP_COMPACT,										"compaction"	},
2645 		{ OP_SERIALIZE,										"serialization"	},
2646 	};
2647 
2648 	struct
2649 	{
2650 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
2651 		const char*											name;
2652 	} buildTypes[] =
2653 	{
2654 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
2655 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
2656 	};
2657 
2658 	struct
2659 	{
2660 		OperationTarget										operationTarget;
2661 		const char*											name;
2662 	} operationTargets[] =
2663 	{
2664 		{ OT_TOP_ACCELERATION,								"top_acceleration_structure"		},
2665 		{ OT_BOTTOM_ACCELERATION,							"bottom_acceleration_structure"	},
2666 	};
2667 
2668 	struct
2669 	{
2670 		BottomTestType										testType;
2671 		const char*											name;
2672 	} bottomTestTypes[] =
2673 	{
2674 		{ BTT_TRIANGLES,									"triangles" },
2675 		{ BTT_AABBS,										"aabbs" },
2676 	};
2677 
2678 	for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
2679 	{
2680 		if (workerThreads > 0)
2681 			if (operationTypes[operationTypeNdx].operationType != OP_COPY && operationTypes[operationTypeNdx].operationType != OP_SERIALIZE)
2682 				continue;
2683 
2684 		de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name, ""));
2685 
2686 		for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2687 		{
2688 			if (workerThreads > 0 && buildTypes[buildTypeNdx].buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
2689 				continue;
2690 
2691 			de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
2692 
2693 			for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets); ++operationTargetNdx)
2694 			{
2695 				de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name, ""));
2696 
2697 				for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
2698 				{
2699 					TopTestType topTest = (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ? TTT_DIFFERENT_INSTANCES : TTT_IDENTICAL_INSTANCES;
2700 
2701 					TestParams testParams
2702 					{
2703 						buildTypes[buildTypeNdx].buildType,
2704 						VK_FORMAT_R32G32B32_SFLOAT,
2705 						false,
2706 						VK_INDEX_TYPE_NONE_KHR,
2707 						bottomTestTypes[testTypeNdx].testType,
2708 						InstanceCullFlags::NONE,
2709 						false,
2710 						false,
2711 						topTest,
2712 						false,
2713 						false,
2714 						VkBuildAccelerationStructureFlagsKHR(0u),
2715 						operationTargets[operationTargetNdx].operationTarget,
2716 						operationTypes[operationTypeNdx].operationType,
2717 						RTAS_DEFAULT_SIZE,
2718 						RTAS_DEFAULT_SIZE,
2719 						de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
2720 						workerThreads,
2721 						EmptyAccelerationStructureCase::NOT_EMPTY,
2722 						InstanceCustomIndexCase::NONE,
2723 					};
2724 					operationTargetGroup->addChild(new RayTracingASBasicTestCase(group->getTestContext(), bottomTestTypes[testTypeNdx].name, "", testParams));
2725 				}
2726 				buildGroup->addChild(operationTargetGroup.release());
2727 			}
2728 			operationTypeGroup->addChild(buildGroup.release());
2729 		}
2730 		group->addChild(operationTypeGroup.release());
2731 	}
2732 }
2733 
addOperationTests(tcu::TestCaseGroup * group)2734 void addOperationTests (tcu::TestCaseGroup* group)
2735 {
2736 	addOperationTestsImpl(group, 0);
2737 }
2738 
addHostThreadingOperationTests(tcu::TestCaseGroup * group)2739 void addHostThreadingOperationTests (tcu::TestCaseGroup* group)
2740 {
2741 	const deUint32	threads[]	= { 1, 2, 3, 4, 8, std::numeric_limits<deUint32>::max() };
2742 
2743 	for (size_t threadsNdx = 0; threadsNdx < DE_LENGTH_OF_ARRAY(threads); ++threadsNdx)
2744 	{
2745 		const std::string groupName = threads[threadsNdx] != std::numeric_limits<deUint32>::max()
2746 									? de::toString(threads[threadsNdx])
2747 									: "max";
2748 
2749 		de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), groupName.c_str(), ""));
2750 
2751 		addOperationTestsImpl(threadGroup.get(), threads[threadsNdx]);
2752 
2753 		group->addChild(threadGroup.release());
2754 	}
2755 }
2756 
addFuncArgTests(tcu::TestCaseGroup * group)2757 void addFuncArgTests (tcu::TestCaseGroup* group)
2758 {
2759 	const struct
2760 	{
2761 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
2762 		const char*											name;
2763 	} buildTypes[] =
2764 	{
2765 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
2766 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
2767 	};
2768 
2769 	auto& ctx = group->getTestContext();
2770 
2771 	for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
2772 	{
2773 		TestParams testParams
2774 		{
2775 			buildTypes[buildTypeNdx].buildType,
2776 			VK_FORMAT_R32G32B32_SFLOAT,
2777 			false,
2778 			VK_INDEX_TYPE_NONE_KHR,
2779 			BTT_TRIANGLES,
2780 			InstanceCullFlags::NONE,
2781 			false,
2782 			false,
2783 			TTT_IDENTICAL_INSTANCES,
2784 			false,
2785 			false,
2786 			VkBuildAccelerationStructureFlagsKHR(0u),
2787 			OT_NONE,
2788 			OP_NONE,
2789 			RTAS_DEFAULT_SIZE,
2790 			RTAS_DEFAULT_SIZE,
2791 			de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
2792 			0u,
2793 			EmptyAccelerationStructureCase::NOT_EMPTY,
2794 			InstanceCustomIndexCase::NONE,
2795 		};
2796 
2797 		group->addChild(new RayTracingASFuncArgTestCase(ctx, buildTypes[buildTypeNdx].name, "", testParams));
2798 	}
2799 }
2800 
addInstanceTriangleCullingTests(tcu::TestCaseGroup * group)2801 void addInstanceTriangleCullingTests (tcu::TestCaseGroup* group)
2802 {
2803 	const struct
2804 	{
2805 		InstanceCullFlags	cullFlags;
2806 		std::string			name;
2807 	} cullFlags[] =
2808 	{
2809 		{ InstanceCullFlags::NONE,				"noflags"		},
2810 		{ InstanceCullFlags::COUNTERCLOCKWISE,	"ccw"			},
2811 		{ InstanceCullFlags::CULL_DISABLE,		"nocull"		},
2812 		{ InstanceCullFlags::ALL,				"ccw_nocull"	},
2813 	};
2814 
2815 	const struct
2816 	{
2817 		TopTestType	topType;
2818 		std::string	name;
2819 	} topType[] =
2820 	{
2821 		{ TTT_DIFFERENT_INSTANCES, "transformed"	},	// Each instance has its own transformation matrix.
2822 		{ TTT_IDENTICAL_INSTANCES, "notransform"	},	// "Identical" instances, different geometries.
2823 	};
2824 
2825 	const struct
2826 	{
2827 		vk::VkAccelerationStructureBuildTypeKHR	buildType;
2828 		std::string								name;
2829 	} buildTypes[] =
2830 	{
2831 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
2832 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
2833 	};
2834 
2835 	const struct
2836 	{
2837 		VkIndexType	indexType;
2838 		std::string	name;
2839 	} indexFormats[] =
2840 	{
2841 		{ VK_INDEX_TYPE_NONE_KHR ,	"index_none"	},
2842 		{ VK_INDEX_TYPE_UINT16 ,	"index_uint16"	},
2843 		{ VK_INDEX_TYPE_UINT32 ,	"index_uint32"	},
2844 	};
2845 
2846 	auto& ctx = group->getTestContext();
2847 
2848 	for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
2849 	{
2850 		de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str(), ""));
2851 
2852 		for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
2853 		{
2854 			de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str(), ""));
2855 
2856 			for (int topTypeIdx = 0; topTypeIdx < DE_LENGTH_OF_ARRAY(topType); ++topTypeIdx)
2857 			{
2858 				for (int cullFlagsIdx = 0; cullFlagsIdx < DE_LENGTH_OF_ARRAY(cullFlags); ++cullFlagsIdx)
2859 				{
2860 					const std::string testName = topType[topTypeIdx].name + "_" + cullFlags[cullFlagsIdx].name;
2861 
2862 					TestParams testParams
2863 					{
2864 						buildTypes[buildTypeIdx].buildType,
2865 						VK_FORMAT_R32G32B32_SFLOAT,
2866 						false,
2867 						indexFormats[indexFormatIdx].indexType,
2868 						BTT_TRIANGLES,
2869 						cullFlags[cullFlagsIdx].cullFlags,
2870 						false,
2871 						false,
2872 						topType[topTypeIdx].topType,
2873 						false,
2874 						false,
2875 						VkBuildAccelerationStructureFlagsKHR(0u),
2876 						OT_NONE,
2877 						OP_NONE,
2878 						RTAS_DEFAULT_SIZE,
2879 						RTAS_DEFAULT_SIZE,
2880 						de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
2881 						0u,
2882 						EmptyAccelerationStructureCase::NOT_EMPTY,
2883 						InstanceCustomIndexCase::NONE,
2884 					};
2885 					indexTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, testName.c_str(), "", testParams));
2886 				}
2887 			}
2888 			buildTypeGroup->addChild(indexTypeGroup.release());
2889 		}
2890 		group->addChild(buildTypeGroup.release());
2891 	}
2892 }
2893 
addDynamicIndexingTests(tcu::TestCaseGroup * group)2894 void addDynamicIndexingTests (tcu::TestCaseGroup* group)
2895 {
2896 	auto& ctx = group->getTestContext();
2897 	group->addChild(new RayTracingASDynamicIndexingTestCase(ctx, "dynamic_indexing"));
2898 }
2899 
addEmptyAccelerationStructureTests(tcu::TestCaseGroup * group)2900 void addEmptyAccelerationStructureTests (tcu::TestCaseGroup* group)
2901 {
2902 	const struct
2903 	{
2904 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
2905 		std::string											name;
2906 	} buildTypes[] =
2907 	{
2908 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
2909 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
2910 	};
2911 
2912 	const struct
2913 	{
2914 		VkIndexType								indexType;
2915 		std::string								name;
2916 	} indexFormats[] =
2917 	{
2918 		{ VK_INDEX_TYPE_NONE_KHR,				"index_none"	},
2919 		{ VK_INDEX_TYPE_UINT16,					"index_uint16"	},
2920 		{ VK_INDEX_TYPE_UINT32,					"index_uint32"	},
2921 	};
2922 
2923 	const struct
2924 	{
2925 		EmptyAccelerationStructureCase	emptyASCase;
2926 		std::string						name;
2927 	} emptyCases[] =
2928 	{
2929 		{ EmptyAccelerationStructureCase::INACTIVE_TRIANGLES,	"inactive_triangles"	},
2930 		{ EmptyAccelerationStructureCase::INACTIVE_INSTANCES,	"inactive_instances"	},
2931 		{ EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM,	"no_geometries_bottom"	},
2932 		{ EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP,	"no_primitives_top"		},
2933 		{ EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM,	"no_primitives_bottom"	},
2934 	};
2935 
2936 	auto& ctx = group->getTestContext();
2937 
2938 	for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
2939 	{
2940 		de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str(), ""));
2941 
2942 		for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
2943 		{
2944 			de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str(), ""));
2945 
2946 			for (int emptyCaseIdx = 0; emptyCaseIdx < DE_LENGTH_OF_ARRAY(emptyCases); ++emptyCaseIdx)
2947 			{
2948 				TestParams testParams
2949 				{
2950 					buildTypes[buildTypeIdx].buildType,
2951 					VK_FORMAT_R32G32B32_SFLOAT,
2952 					false,
2953 					indexFormats[indexFormatIdx].indexType,
2954 					BTT_TRIANGLES,
2955 					InstanceCullFlags::NONE,
2956 					false,
2957 					false,
2958 					TTT_IDENTICAL_INSTANCES,
2959 					false,
2960 					false,
2961 					VkBuildAccelerationStructureFlagsKHR(0u),
2962 					OT_NONE,
2963 					OP_NONE,
2964 					RTAS_DEFAULT_SIZE,
2965 					RTAS_DEFAULT_SIZE,
2966 					de::SharedPtr<TestConfiguration>(new SingleTriangleConfiguration()),
2967 					0u,
2968 					emptyCases[emptyCaseIdx].emptyASCase,
2969 					InstanceCustomIndexCase::NONE,
2970 				};
2971 				indexTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, emptyCases[emptyCaseIdx].name.c_str(), "", testParams));
2972 			}
2973 			buildTypeGroup->addChild(indexTypeGroup.release());
2974 		}
2975 		group->addChild(buildTypeGroup.release());
2976 	}
2977 }
2978 
addInstanceIndexTests(tcu::TestCaseGroup * group)2979 void addInstanceIndexTests (tcu::TestCaseGroup* group)
2980 {
2981 	const struct
2982 	{
2983 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
2984 		std::string											name;
2985 	} buildTypes[] =
2986 	{
2987 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
2988 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
2989 	};
2990 
2991 	const struct
2992 	{
2993 		InstanceCustomIndexCase						customIndexCase;
2994 		std::string									name;
2995 	} customIndexCases[] =
2996 	{
2997 		{ InstanceCustomIndexCase::NONE,			"no_instance_index"	},
2998 		{ InstanceCustomIndexCase::ANY_HIT,			"ahit"				},
2999 		{ InstanceCustomIndexCase::CLOSEST_HIT,		"chit"				},
3000 		{ InstanceCustomIndexCase::INTERSECTION,	"isec"				},
3001 	};
3002 
3003 	auto& ctx = group->getTestContext();
3004 
3005 	for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
3006 	{
3007 		de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str(), ""));
3008 
3009 		for (int customIndexCaseIdx = 0; customIndexCaseIdx < DE_LENGTH_OF_ARRAY(customIndexCases); ++customIndexCaseIdx)
3010 		{
3011 			const auto&	idxCase				= customIndexCases[customIndexCaseIdx].customIndexCase;
3012 			const auto	bottomGeometryType	= ((idxCase == InstanceCustomIndexCase::INTERSECTION) ? BTT_AABBS : BTT_TRIANGLES);
3013 
3014 			TestParams testParams
3015 			{
3016 				buildTypes[buildTypeIdx].buildType,
3017 				VK_FORMAT_R32G32B32_SFLOAT,
3018 				false,
3019 				VK_INDEX_TYPE_NONE_KHR,
3020 				bottomGeometryType,
3021 				InstanceCullFlags::NONE,
3022 				false,
3023 				false,
3024 				TTT_IDENTICAL_INSTANCES,
3025 				false,
3026 				false,
3027 				VkBuildAccelerationStructureFlagsKHR(0u),
3028 				OT_NONE,
3029 				OP_NONE,
3030 				RTAS_DEFAULT_SIZE,
3031 				RTAS_DEFAULT_SIZE,
3032 				de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration()),
3033 				0u,
3034 				EmptyAccelerationStructureCase::NOT_EMPTY,
3035 				customIndexCases[customIndexCaseIdx].customIndexCase,
3036 			};
3037 			buildTypeGroup->addChild(new RayTracingASBasicTestCase(ctx, customIndexCases[customIndexCaseIdx].name.c_str(), "", testParams));
3038 		}
3039 		group->addChild(buildTypeGroup.release());
3040 	}
3041 }
3042 
createAccelerationStructuresTests(tcu::TestContext & testCtx)3043 tcu::TestCaseGroup*	createAccelerationStructuresTests(tcu::TestContext& testCtx)
3044 {
3045 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "acceleration_structures", "Acceleration structure tests"));
3046 
3047 	addTestGroup(group.get(), "flags", "Test building AS with different build types, build flags and geometries/instances using arrays or arrays of pointers", addBasicBuildingTests);
3048 	addTestGroup(group.get(), "format", "Test building AS with different vertex and index formats", addVertexIndexFormatsTests);
3049 	addTestGroup(group.get(), "operations", "Test copying, compaction and serialization of AS", addOperationTests);
3050 	addTestGroup(group.get(), "host_threading", "Test host threading operations", addHostThreadingOperationTests);
3051 	addTestGroup(group.get(), "function_argument", "Test using AS as function argument using both pointers and bare values", addFuncArgTests);
3052 	addTestGroup(group.get(), "instance_triangle_culling", "Test building AS with counterclockwise triangles and/or disabling face culling", addInstanceTriangleCullingTests);
3053 	addTestGroup(group.get(), "dynamic_indexing", "Exercise dynamic indexing of acceleration structures", addDynamicIndexingTests);
3054 	addTestGroup(group.get(), "empty", "Test building empty acceleration structures using different methods", addEmptyAccelerationStructureTests);
3055 	addTestGroup(group.get(), "instance_index", "Test using different values for the instance index and checking them in shaders", addInstanceIndexTests);
3056 
3057 	return group.release();
3058 }
3059 
3060 }	// RayTracing
3061 
3062 }	// vkt
3063