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 Testing acceleration structures in ray query extension
22 *//*--------------------------------------------------------------------*/
23
24#include "vktRayQueryAccelerationStructuresTests.hpp"
25
26#include <array>
27#include <set>
28#include <limits>
29
30#include "vkDefs.hpp"
31#include "deClock.h"
32#include "vktTestCase.hpp"
33#include "vktTestGroupUtil.hpp"
34#include "vkCmdUtil.hpp"
35#include "vkObjUtil.hpp"
36#include "vkBuilderUtil.hpp"
37#include "vkBarrierUtil.hpp"
38#include "vkBufferWithMemory.hpp"
39#include "vkImageWithMemory.hpp"
40#include "vkTypeUtil.hpp"
41#include "vkImageUtil.hpp"
42#include "vkRayTracingUtil.hpp"
43#include "deRandom.hpp"
44#include "tcuTexture.hpp"
45#include "tcuTextureUtil.hpp"
46#include "tcuTestLog.hpp"
47#include "tcuImageCompare.hpp"
48#include "tcuFloat.hpp"
49#include "deModularCounter.hpp"
50
51namespace vkt
52{
53namespace RayQuery
54{
55namespace
56{
57using namespace vk;
58using namespace vkt;
59
60static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
61												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
62												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
63												| VK_SHADER_STAGE_MISS_BIT_KHR
64												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
65												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
66
67enum ShaderSourcePipeline
68{
69	SSP_GRAPHICS_PIPELINE,
70	SSP_COMPUTE_PIPELINE,
71	SSP_RAY_TRACING_PIPELINE
72};
73
74enum ShaderSourceType
75{
76	SST_VERTEX_SHADER,
77	SST_TESSELATION_CONTROL_SHADER,
78	SST_TESSELATION_EVALUATION_SHADER,
79	SST_GEOMETRY_SHADER,
80	SST_FRAGMENT_SHADER,
81	SST_COMPUTE_SHADER,
82	SST_RAY_GENERATION_SHADER,
83	SST_INTERSECTION_SHADER,
84	SST_ANY_HIT_SHADER,
85	SST_CLOSEST_HIT_SHADER,
86	SST_MISS_SHADER,
87	SST_CALLABLE_SHADER,
88};
89
90enum ShaderTestType
91{
92	STT_GENERATE_INTERSECTION		= 0,
93	STT_SKIP_INTERSECTION			= 1,
94};
95
96enum class BottomTestType
97{
98	TRIANGLES = 0,
99	AABBS = 1,
100};
101
102enum class TopTestType
103{
104	IDENTICAL_INSTANCES,
105	DIFFERENT_INSTANCES,
106	UPDATED_INSTANCES
107};
108
109enum OperationTarget
110{
111	OT_NONE,
112	OT_TOP_ACCELERATION,
113	OT_BOTTOM_ACCELERATION
114};
115
116enum OperationType
117{
118	OP_NONE,
119	OP_COPY,
120	OP_COMPACT,
121	OP_SERIALIZE,
122	OP_UPDATE,
123	OP_UPDATE_IN_PLACE
124};
125
126enum class InstanceCullFlags
127{
128	NONE,
129	CULL_DISABLE,
130	COUNTERCLOCKWISE,
131	ALL,
132};
133
134enum class EmptyAccelerationStructureCase
135{
136	NOT_EMPTY				= 0,
137	INACTIVE_TRIANGLES		= 1,
138	INACTIVE_INSTANCES		= 2,
139	NO_GEOMETRIES_BOTTOM	= 3,	// geometryCount zero when building.
140	NO_PRIMITIVES_BOTTOM	= 4,	// primitiveCount zero when building.
141	NO_PRIMITIVES_TOP		= 5,	// primitiveCount zero when building.
142};
143
144const deUint32			TEST_WIDTH			= 8;
145const deUint32			TEST_HEIGHT			= 8;
146
147struct TestParams;
148
149class TestConfiguration
150{
151public:
152	virtual					~TestConfiguration					();
153	virtual void			initConfiguration					(Context&						context,
154																 TestParams&					testParams) = 0;
155	virtual void			fillCommandBuffer					(Context&						context,
156																 TestParams&					testParams,
157																 VkCommandBuffer				commandBuffer,
158																 const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
159																 const VkDescriptorImageInfo&	resultImageInfo) = 0;
160	virtual bool			verifyImage							(BufferWithMemory*				resultBuffer,
161																 Context&						context,
162																 TestParams&					testParams) = 0;
163	virtual VkFormat		getResultImageFormat				() = 0;
164	virtual size_t			getResultImageFormatSize			() = 0;
165	virtual VkClearValue	getClearValue						() = 0;
166};
167
168TestConfiguration::~TestConfiguration()
169{
170}
171
172class SceneBuilder
173{
174public:
175	virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
176																												 TestParams&						testParams) = 0;
177	virtual de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
178																												 TestParams&						testParams,
179																												 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) = 0;
180};
181
182struct TestParams
183{
184	ShaderSourceType						shaderSourceType;
185	ShaderSourcePipeline					shaderSourcePipeline;
186	vk::VkAccelerationStructureBuildTypeKHR	buildType;		// are we making AS on CPU or GPU
187	VkFormat								vertexFormat;
188	bool									padVertices;
189	VkIndexType								indexType;
190	BottomTestType							bottomTestType; // what kind of geometry is stored in bottom AS
191	InstanceCullFlags						cullFlags;		// Flags for instances, if needed.
192	bool									bottomUsesAOP;	// does bottom AS use arrays, or arrays of pointers
193	bool									bottomGeneric;	// Bottom created as generic AS type.
194	bool									bottomUnboundedCreation; // Bottom created with unbounded buffer memory.
195	TopTestType								topTestType;	// If instances are identical then bottom geometries must have different vertices/aabbs
196	bool									topUsesAOP;		// does top AS use arrays, or arrays of pointers
197	bool									topGeneric;		// Top created as generic AS type.
198	bool									topUnboundedCreation; // Top created with unbounded buffer memory.
199	VkBuildAccelerationStructureFlagsKHR	buildFlags;
200	OperationTarget							operationTarget;
201	OperationType							operationType;
202	deUint32								width;
203	deUint32								height;
204	deUint32								workerThreadsCount;
205	EmptyAccelerationStructureCase			emptyASCase;
206};
207
208deUint32 getShaderGroupHandleSize (const InstanceInterface&	vki,
209								   const VkPhysicalDevice	physicalDevice)
210{
211	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
212
213	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
214	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
215}
216
217deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
218									  const VkPhysicalDevice	physicalDevice)
219{
220	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
221
222	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
223	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
224}
225
226VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
227{
228	const VkImageCreateInfo			imageCreateInfo			=
229	{
230		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
231		DE_NULL,																							// const void*				pNext;
232		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
233		VK_IMAGE_TYPE_3D,																					// VkImageType				imageType;
234		format,																								// VkFormat					format;
235		makeExtent3D(width, height, depth),																	// VkExtent3D				extent;
236		1u,																									// deUint32					mipLevels;
237		1u,																									// deUint32					arrayLayers;
238		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
239		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
240		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
241		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
242		0u,																									// deUint32					queueFamilyIndexCount;
243		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
244		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
245	};
246
247	return imageCreateInfo;
248}
249
250Move<VkQueryPool> makeQueryPool(const DeviceInterface&		vk,
251								const VkDevice				device,
252								const VkQueryType			queryType,
253								deUint32					queryCount)
254{
255	const VkQueryPoolCreateInfo				queryPoolCreateInfo =
256	{
257		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// sType
258		DE_NULL,										// pNext
259		(VkQueryPoolCreateFlags)0,						// flags
260		queryType,										// queryType
261		queryCount,										// queryCount
262		0u,												// pipelineStatistics
263	};
264	return createQueryPool(vk, device, &queryPoolCreateInfo);
265}
266
267
268bool registerShaderModule (const DeviceInterface&								vkd,
269						   const VkDevice										device,
270						   Context&												context,
271						   std::vector<de::SharedPtr<Move<VkShaderModule>>>&	shaderModules,
272						   std::vector<VkPipelineShaderStageCreateInfo>&		shaderCreateInfos,
273						   VkShaderStageFlagBits								stage,
274						   const std::string&									externalNamePart,
275						   const std::string&									internalNamePart)
276{
277	char fullShaderName[40];
278	snprintf(fullShaderName, 40, externalNamePart.c_str(), internalNamePart.c_str());
279	std::string fsn = fullShaderName;
280	if (fsn.empty())
281		return false;
282
283	shaderModules.push_back(makeVkSharedPtr(createShaderModule(vkd, device, context.getBinaryCollection().get(fsn), 0)));
284
285	shaderCreateInfos.push_back(
286		{
287			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
288			DE_NULL,
289			(VkPipelineShaderStageCreateFlags)0,
290			stage,														// stage
291			shaderModules.back()->get(),								// shader
292			"main",
293			DE_NULL,													// pSpecializationInfo
294		});
295
296	return true;
297}
298
299bool registerShaderModule (const DeviceInterface&	vkd,
300						   const VkDevice			device,
301						   Context&					context,
302						   RayTracingPipeline&		rayTracingPipeline,
303						   VkShaderStageFlagBits	shaderStage,
304						   const std::string&		externalNamePart,
305						   const std::string&		internalNamePart,
306						   deUint32					groupIndex)
307{
308	char fullShaderName[40];
309	snprintf(fullShaderName, 40, externalNamePart.c_str(), internalNamePart.c_str());
310	std::string fsn = fullShaderName;
311	if (fsn.empty())
312		return false;
313	Move<VkShaderModule> shaderModule = createShaderModule(vkd, device, context.getBinaryCollection().get(fsn), 0);
314	if (*shaderModule == DE_NULL)
315		return false;
316	rayTracingPipeline.addShader(shaderStage, shaderModule, groupIndex);
317	return true;
318}
319
320VkGeometryInstanceFlagsKHR getCullFlags (InstanceCullFlags flags)
321{
322	VkGeometryInstanceFlagsKHR cullFlags = 0u;
323
324	if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
325		cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
326
327	if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
328		cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
329
330	return cullFlags;
331}
332
333class GraphicsConfiguration : public TestConfiguration
334{
335public:
336	virtual							~GraphicsConfiguration		();
337	void							initConfiguration			(Context&						context,
338																 TestParams&					testParams) override;
339	void							fillCommandBuffer			(Context&						context,
340																 TestParams&					testParams,
341																 VkCommandBuffer				commandBuffer,
342																 const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
343																 const VkDescriptorImageInfo&	resultImageInfo) override;
344	bool							verifyImage					(BufferWithMemory*				resultBuffer,
345																 Context&						context,
346																 TestParams&					testParams) override;
347	VkFormat						getResultImageFormat		() override;
348	size_t							getResultImageFormatSize	() override;
349	VkClearValue					getClearValue				() override;
350protected:
351	Move<VkDescriptorSetLayout>		descriptorSetLayout;
352	Move<VkDescriptorPool>			descriptorPool;
353	Move<VkDescriptorSet>			descriptorSet;
354	Move<VkPipelineLayout>			pipelineLayout;
355	Move<VkRenderPass>				renderPass;
356	Move<VkFramebuffer>				framebuffer;
357	std::vector<de::SharedPtr<Move<VkShaderModule> > >	shaderModules;
358	Move<VkPipeline>				pipeline;
359	std::vector<tcu::Vec3>			vertices;
360	Move<VkBuffer>					vertexBuffer;
361	de::MovePtr<Allocation>			vertexAlloc;
362};
363
364GraphicsConfiguration::~GraphicsConfiguration()
365{
366	shaderModules.clear();
367}
368
369void GraphicsConfiguration::initConfiguration (Context&						context,
370											   TestParams&					testParams)
371{
372	const DeviceInterface&										vkd								= context.getDeviceInterface();
373	const VkDevice												device							= context.getDevice();
374	const deUint32												queueFamilyIndex				= context.getUniversalQueueFamilyIndex();
375	Allocator&													allocator						= context.getDefaultAllocator();
376
377	descriptorSetLayout																			= DescriptorSetLayoutBuilder()
378																										.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_ALL_GRAPHICS)
379																										.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL_GRAPHICS)
380																										.build(vkd, device);
381	descriptorPool																				= DescriptorPoolBuilder()
382																										.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
383																										.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
384																										.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
385	descriptorSet																				= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
386	pipelineLayout																				= makePipelineLayout(vkd, device, descriptorSetLayout.get());
387
388	std::vector<std::string> rayQueryTestName;
389	rayQueryTestName.push_back("as_triangle");
390	rayQueryTestName.push_back("as_aabb");
391
392	const std::map<ShaderSourceType,std::vector<std::string>>	shaderNames						=
393	{
394										//idx:		0				1				2				3				4
395										//shader:	vert,			tesc,			tese,			geom,			frag,
396		{	SST_VERTEX_SHADER,					{	"vert_%s",		"",				"",				"",				"",			}	},
397		{	SST_TESSELATION_CONTROL_SHADER,		{	"vert",			"tesc_%s",		"tese",			"",				"",			}	},
398		{	SST_TESSELATION_EVALUATION_SHADER,	{	"vert",			"tesc",			"tese_%s",		"",				"",			}	},
399		{	SST_GEOMETRY_SHADER,				{	"vert_vid",		"",				"",				"geom_%s",		"",			}	},
400		{	SST_FRAGMENT_SHADER,				{	"vert",			"",				"",				"",				"frag_%s",	}	},
401	};
402
403	auto														shaderNameIt					= shaderNames.find(testParams.shaderSourceType);
404	if(shaderNameIt == end(shaderNames))
405		TCU_THROW(InternalError, "Wrong shader source type");
406
407	std::vector<VkPipelineShaderStageCreateInfo>				shaderCreateInfos;
408	bool tescX, teseX, fragX;
409	const auto bottomTestTypeIdx = static_cast<int>(testParams.bottomTestType);
410			registerShaderModule(vkd,	device,	context,	shaderModules,	shaderCreateInfos,	VK_SHADER_STAGE_VERTEX_BIT,						shaderNameIt->second[0],	rayQueryTestName[bottomTestTypeIdx]);
411	tescX = registerShaderModule(vkd,	device, context,	shaderModules,	shaderCreateInfos,	VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		shaderNameIt->second[1],	rayQueryTestName[bottomTestTypeIdx]);
412	teseX = registerShaderModule(vkd,	device,	context,	shaderModules,	shaderCreateInfos,	VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	shaderNameIt->second[2],	rayQueryTestName[bottomTestTypeIdx]);
413			registerShaderModule(vkd,	device,	context,	shaderModules,	shaderCreateInfos,	VK_SHADER_STAGE_GEOMETRY_BIT,					shaderNameIt->second[3],	rayQueryTestName[bottomTestTypeIdx]);
414	fragX = registerShaderModule(vkd,	device,	context,	shaderModules,	shaderCreateInfos,	VK_SHADER_STAGE_FRAGMENT_BIT,					shaderNameIt->second[4],	rayQueryTestName[bottomTestTypeIdx]);
415
416	const vk::VkSubpassDescription		subpassDesc			=
417	{
418		(vk::VkSubpassDescriptionFlags)0,
419		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,							// pipelineBindPoint
420		0u,																// inputCount
421		DE_NULL,														// pInputAttachments
422		0u,																// colorCount
423		DE_NULL,														// pColorAttachments
424		DE_NULL,														// pResolveAttachments
425		DE_NULL,														// depthStencilAttachment
426		0u,																// preserveCount
427		DE_NULL,														// pPreserveAttachments
428	};
429	const vk::VkRenderPassCreateInfo	renderPassParams	=
430	{
431		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,					// sType
432		DE_NULL,														// pNext
433		(vk::VkRenderPassCreateFlags)0,
434		0u,																// attachmentCount
435		DE_NULL,														// pAttachments
436		1u,																// subpassCount
437		&subpassDesc,													// pSubpasses
438		0u,																// dependencyCount
439		DE_NULL,														// pDependencies
440	};
441
442	renderPass = createRenderPass(vkd, device, &renderPassParams);
443
444	const vk::VkFramebufferCreateInfo	framebufferParams	=
445	{
446		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,					// sType
447		DE_NULL,														// pNext
448		(vk::VkFramebufferCreateFlags)0,
449		*renderPass,													// renderPass
450		0u,																// attachmentCount
451		DE_NULL,														// pAttachments
452		testParams.width,												// width
453		testParams.height,												// height
454		1u,																// layers
455	};
456
457	framebuffer = createFramebuffer(vkd, device, &framebufferParams);
458
459	VkPrimitiveTopology					testTopology		= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
460	tcu::Vec3 v0(0.0f, 0.0f, 0.0f);
461	tcu::Vec3 v1(float(testParams.width) - 1.0f, 0.0f, 0.0f);
462	tcu::Vec3 v2(0.0f, float(testParams.height) - 1.0f, 0.0f);
463	tcu::Vec3 v3(float(testParams.width) - 1.0f, float(testParams.height) - 1.0f, 0.0f);
464
465	switch (testParams.shaderSourceType)
466	{
467		case SST_TESSELATION_CONTROL_SHADER:
468		case SST_TESSELATION_EVALUATION_SHADER:
469			testTopology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
470			vertices.push_back(v0);
471			vertices.push_back(v1);
472			vertices.push_back(v2);
473			vertices.push_back(v1);
474			vertices.push_back(v3);
475			vertices.push_back(v2);
476			break;
477		case SST_VERTEX_SHADER:
478		case SST_GEOMETRY_SHADER:
479			vertices.push_back(v0);
480			vertices.push_back(v1);
481			vertices.push_back(v2);
482			vertices.push_back(v3);
483			break;
484		case SST_FRAGMENT_SHADER:
485			vertices.push_back( tcu::Vec3(-1.0f,  1.0f, 0.0f) );
486			vertices.push_back( tcu::Vec3(-1.0f, -1.0f, 0.0f) );
487			vertices.push_back( tcu::Vec3( 1.0f,  1.0f, 0.0f) );
488			vertices.push_back( tcu::Vec3( 1.0f, -1.0f, 0.0f) );
489			break;
490		default:
491			TCU_THROW(InternalError, "Wrong shader source type");
492	}
493
494	const VkVertexInputBindingDescription vertexInputBindingDescription =
495	{
496		0u,																// uint32_t											binding;
497		sizeof(tcu::Vec3),												// uint32_t											stride;
498		VK_VERTEX_INPUT_RATE_VERTEX,									// VkVertexInputRate								inputRate;
499	};
500
501	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
502	{
503		0u,																// uint32_t											location;
504		0u,																// uint32_t											binding;
505		VK_FORMAT_R32G32B32_SFLOAT,										// VkFormat											format;
506		0u,																// uint32_t											offset;
507	};
508
509	const VkPipelineVertexInputStateCreateInfo					vertexInputStateCreateInfo		=
510	{
511		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType									sType;
512		DE_NULL,														// const void*										pNext;
513		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags			flags;
514		1u,																// deUint32											vertexBindingDescriptionCount;
515		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*			pVertexBindingDescriptions;
516		1u,																// deUint32											vertexAttributeDescriptionCount;
517		&vertexInputAttributeDescription								// const VkVertexInputAttributeDescription*			pVertexAttributeDescriptions;
518	};
519
520	const VkPipelineInputAssemblyStateCreateInfo				inputAssemblyStateCreateInfo	=
521	{
522		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType									sType;
523		DE_NULL,														// const void*										pNext;
524		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags			flags;
525		testTopology,													// VkPrimitiveTopology								topology;
526		VK_FALSE														// VkBool32											primitiveRestartEnable;
527	};
528
529	const VkPipelineTessellationStateCreateInfo					tessellationStateCreateInfo		=
530	{
531		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType									sType;
532		DE_NULL,														// const void*										pNext;
533		VkPipelineTessellationStateCreateFlags(0u),						// VkPipelineTessellationStateCreateFlags			flags;
534		3u																// deUint32											patchControlPoints;
535	};
536
537	VkViewport													viewport						= makeViewport(testParams.width, testParams.height);
538	VkRect2D													scissor							= makeRect2D(testParams.width, testParams.height);
539
540	const VkPipelineViewportStateCreateInfo						viewportStateCreateInfo			=
541	{
542		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType									sType
543		DE_NULL,														// const void*										pNext
544		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags				flags
545		1u,																// deUint32											viewportCount
546		&viewport,														// const VkViewport*								pViewports
547		1u,																// deUint32											scissorCount
548		&scissor														// const VkRect2D*									pScissors
549	};
550
551	const VkPipelineRasterizationStateCreateInfo				rasterizationStateCreateInfo =
552	{
553		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType									sType;
554		DE_NULL,														// const void*										pNext;
555		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags			flags;
556		VK_FALSE,														// VkBool32											depthClampEnable;
557		fragX ? VK_FALSE : VK_TRUE,										// VkBool32											rasterizerDiscardEnable;
558		VK_POLYGON_MODE_FILL,											// VkPolygonMode									polygonMode;
559		VK_CULL_MODE_NONE,												// VkCullModeFlags									cullMode;
560		VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace										frontFace;
561		VK_FALSE,														// VkBool32											depthBiasEnable;
562		0.0f,															// float											depthBiasConstantFactor;
563		0.0f,															// float											depthBiasClamp;
564		0.0f,															// float											depthBiasSlopeFactor;
565		1.0f															// float											lineWidth;
566	};
567
568	const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo =
569	{
570		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType									sType;
571		DE_NULL,														// const void*										pNext;
572		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags			flags;
573		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits							rasterizationSamples;
574		VK_FALSE,														// VkBool32											sampleShadingEnable;
575		0.0f,															// float											minSampleShading;
576		DE_NULL,														// const VkSampleMask*								pSampleMask;
577		VK_FALSE,														// VkBool32											alphaToCoverageEnable;
578		VK_FALSE														// VkBool32											alphaToOneEnable;
579	};
580
581	const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo =
582	{
583		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType									sType;
584		DE_NULL,														// const void*										pNext;
585		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags				flags;
586		DE_FALSE,														// VkBool32											logicOpEnable;
587		VK_LOGIC_OP_CLEAR,												// VkLogicOp										logicOp;
588		0,																// deUint32											attachmentCount;
589		DE_NULL,														// const VkPipelineColorBlendAttachmentState*		pAttachments;
590		{ 1.0f, 1.0f, 1.0f, 1.0f }										// float											blendConstants[4];
591	};
592
593	const VkGraphicsPipelineCreateInfo							graphicsPipelineCreateInfo		=
594	{
595		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,				// VkStructureType									sType;
596		DE_NULL,														// const void*										pNext;
597		(VkPipelineCreateFlags)0,										// VkPipelineCreateFlags							flags;
598		static_cast<deUint32>(shaderCreateInfos.size()),				// deUint32											stageCount;
599		shaderCreateInfos.data(),										// const VkPipelineShaderStageCreateInfo*			pStages;
600		&vertexInputStateCreateInfo,									// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
601		&inputAssemblyStateCreateInfo,									// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
602		(tescX||teseX) ? &tessellationStateCreateInfo : DE_NULL,		// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
603		fragX ? &viewportStateCreateInfo : DE_NULL,						// const VkPipelineViewportStateCreateInfo*			pViewportState;
604		&rasterizationStateCreateInfo,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
605		fragX ? &multisampleStateCreateInfo : DE_NULL,					// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
606		DE_NULL,														// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
607		fragX ? &colorBlendStateCreateInfo : DE_NULL,					// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
608		DE_NULL,														// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
609		pipelineLayout.get(),											// VkPipelineLayout									layout;
610		renderPass.get(),												// VkRenderPass										renderPass;
611		0u,																// deUint32											subpass;
612		DE_NULL,														// VkPipeline										basePipelineHandle;
613		0																// int												basePipelineIndex;
614	};
615
616	pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &graphicsPipelineCreateInfo);
617
618	const VkBufferCreateInfo									vertexBufferParams				=
619	{
620		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,							// VkStructureType									sType;
621		DE_NULL,														// const void*										pNext;
622		0u,																// VkBufferCreateFlags								flags;
623		VkDeviceSize(sizeof(tcu::Vec3) * vertices.size()),				// VkDeviceSize										size;
624		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
625			VK_BUFFER_USAGE_TRANSFER_DST_BIT,							// VkBufferUsageFlags								usage;
626		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode									sharingMode;
627		1u,																// deUint32											queueFamilyIndexCount;
628		&queueFamilyIndex												// const deUint32*									pQueueFamilyIndices;
629	};
630
631	vertexBuffer	= createBuffer(vkd, device, &vertexBufferParams);
632	vertexAlloc		= allocator.allocate(getBufferMemoryRequirements(vkd, device, *vertexBuffer), MemoryRequirement::HostVisible);
633	VK_CHECK(vkd.bindBufferMemory(device, *vertexBuffer, vertexAlloc->getMemory(), vertexAlloc->getOffset()));
634
635	// Upload vertex data
636	deMemcpy(vertexAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(tcu::Vec3));
637	flushAlloc(vkd, device, *vertexAlloc);
638}
639
640void GraphicsConfiguration::fillCommandBuffer (Context&						context,
641											   TestParams&					testParams,
642											   VkCommandBuffer				commandBuffer,
643											   const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
644											   const VkDescriptorImageInfo&	resultImageInfo)
645{
646	const DeviceInterface&				vkd									= context.getDeviceInterface();
647	const VkDevice						device								= context.getDevice();
648
649	DescriptorSetUpdateBuilder()
650		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
651		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
652		.update(vkd, device);
653
654	const VkRenderPassBeginInfo			renderPassBeginInfo					=
655	{
656		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// VkStructureType								sType;
657		DE_NULL,															// const void*									pNext;
658		*renderPass,														// VkRenderPass									renderPass;
659		*framebuffer,														// VkFramebuffer								framebuffer;
660		makeRect2D(testParams.width, testParams.height),					// VkRect2D										renderArea;
661		0u,																	// uint32_t										clearValueCount;
662		DE_NULL																// const VkClearValue*							pClearValues;
663	};
664	VkDeviceSize						vertexBufferOffset					= 0u;
665
666	vkd.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
667	vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
668	vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
669	vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
670	vkd.cmdDraw(commandBuffer, deUint32(vertices.size()), 1, 0, 0);
671	vkd.cmdEndRenderPass(commandBuffer);
672}
673
674bool GraphicsConfiguration::verifyImage (BufferWithMemory*					resultBuffer,
675										 Context&							context,
676										 TestParams&						testParams)
677{
678	// create result image
679	const bool					allMiss							= (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
680	tcu::TextureFormat			imageFormat						= vk::mapVkFormat(getResultImageFormat());
681	tcu::ConstPixelBufferAccess	resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
682
683	// create reference image
684	std::vector<deUint32>		reference(testParams.width * testParams.height * 2);
685	tcu::PixelBufferAccess		referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
686
687	std::vector<std::vector<deUint32>> primitives				=
688	{
689		{0, 1, 2},
690		{1, 3, 2}
691	};
692
693	tcu::UVec4					hitValue0						= tcu::UVec4(1, 0, 0, 0);
694	tcu::UVec4					hitValue1						= tcu::UVec4(1, 0, 0, 0);
695	tcu::UVec4					missValue						= tcu::UVec4(0, 0, 0, 0);
696	tcu::UVec4					clearValue						= tcu::UVec4(0xFF, 0, 0, 0);
697
698	switch (testParams.shaderSourceType)
699	{
700		case SST_VERTEX_SHADER:
701			tcu::clear(referenceAccess, clearValue);
702			for (deUint32 vertexNdx = 0; vertexNdx < 4; ++vertexNdx)
703			{
704				if (!allMiss && (vertexNdx == 1 || vertexNdx == 2))
705				{
706					referenceAccess.setPixel(hitValue0, vertexNdx, 0, 0);
707					referenceAccess.setPixel(hitValue1, vertexNdx, 0, 1);
708				}
709				else
710				{
711					referenceAccess.setPixel(missValue, vertexNdx, 0, 0);
712					referenceAccess.setPixel(missValue, vertexNdx, 0, 1);
713				}
714			}
715			break;
716		case SST_TESSELATION_EVALUATION_SHADER:
717		case SST_TESSELATION_CONTROL_SHADER:
718		case SST_GEOMETRY_SHADER:
719			tcu::clear(referenceAccess, clearValue);
720			for (deUint32 primitiveNdx = 0; primitiveNdx < primitives.size(); ++primitiveNdx)
721			for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
722			{
723				deUint32 vNdx = primitives[primitiveNdx][vertexNdx];
724				if (!allMiss && (vNdx==1 || vNdx==2))
725				{
726					referenceAccess.setPixel(hitValue0, primitiveNdx, vertexNdx, 0);
727					referenceAccess.setPixel(hitValue1, primitiveNdx, vertexNdx, 1);
728				}
729				else
730				{
731					referenceAccess.setPixel(missValue, primitiveNdx, vertexNdx, 0);
732					referenceAccess.setPixel(missValue, primitiveNdx, vertexNdx, 1);
733				}
734			}
735			break;
736		case SST_FRAGMENT_SHADER:
737			tcu::clear(referenceAccess, missValue);
738			for (deUint32 y = 0; y < testParams.height; ++y)
739			for (deUint32 x = 0; x < testParams.width; ++x)
740			{
741				if (allMiss || ((x + y) % 2) == 0)
742					continue;
743
744				referenceAccess.setPixel(hitValue0, x, y, 0);
745				referenceAccess.setPixel(hitValue1, x, y, 1);
746			}
747			break;
748		default:
749			TCU_THROW(InternalError, "Wrong shader source type");
750	}
751
752	// compare result and reference
753	return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
754}
755
756VkFormat GraphicsConfiguration::getResultImageFormat ()
757{
758	return VK_FORMAT_R32_UINT;
759}
760
761size_t GraphicsConfiguration::getResultImageFormatSize ()
762{
763	return sizeof(deUint32);
764}
765
766VkClearValue GraphicsConfiguration::getClearValue ()
767{
768	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
769}
770
771class ComputeConfiguration : public TestConfiguration
772{
773public:
774	virtual							~ComputeConfiguration		();
775	void							initConfiguration			(Context&						context,
776																 TestParams&					testParams) override;
777	void							fillCommandBuffer			(Context&						context,
778																 TestParams&					testParams,
779																 VkCommandBuffer				commandBuffer,
780																 const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
781																 const VkDescriptorImageInfo&	resultImageInfo) override;
782	bool							verifyImage					(BufferWithMemory*				resultBuffer,
783																 Context&						context,
784																 TestParams&					testParams) override;
785	VkFormat						getResultImageFormat		() override;
786	size_t							getResultImageFormatSize	() override;
787	VkClearValue					getClearValue				() override;
788protected:
789	Move<VkDescriptorSetLayout>		descriptorSetLayout;
790	Move<VkDescriptorPool>			descriptorPool;
791	Move<VkDescriptorSet>			descriptorSet;
792	Move<VkPipelineLayout>			pipelineLayout;
793	Move<VkShaderModule>			shaderModule;
794	Move<VkPipeline>				pipeline;
795};
796
797ComputeConfiguration::~ComputeConfiguration()
798{
799}
800
801void ComputeConfiguration::initConfiguration (Context&						context,
802											  TestParams&					testParams)
803{
804	const DeviceInterface&				vkd									= context.getDeviceInterface();
805	const VkDevice						device								= context.getDevice();
806
807	descriptorSetLayout														= DescriptorSetLayoutBuilder()
808																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
809																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_COMPUTE_BIT)
810																					.build(vkd, device);
811	descriptorPool															= DescriptorPoolBuilder()
812																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
813																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
814																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
815	descriptorSet															= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
816	pipelineLayout															= makePipelineLayout(vkd, device, descriptorSetLayout.get());
817
818	std::vector<std::string> rayQueryTestName;
819	rayQueryTestName.push_back("comp_as_triangle");
820	rayQueryTestName.push_back("comp_as_aabb");
821
822	const auto bottomTestTypeIdx = static_cast<int>(testParams.bottomTestType);
823	shaderModule															= createShaderModule(vkd, device, context.getBinaryCollection().get(rayQueryTestName[bottomTestTypeIdx]), 0u);
824	const VkPipelineShaderStageCreateInfo pipelineShaderStageParams			=
825	{
826		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
827		DE_NULL,												// const void*							pNext;
828		0u,														// VkPipelineShaderStageCreateFlags		flags;
829		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
830		*shaderModule,											// VkShaderModule						module;
831		"main",													// const char*							pName;
832		DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
833	};
834	const VkComputePipelineCreateInfo pipelineCreateInfo =
835	{
836		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
837		DE_NULL,											// const void*						pNext;
838		0u,													// VkPipelineCreateFlags			flags;
839		pipelineShaderStageParams,							// VkPipelineShaderStageCreateInfo	stage;
840		*pipelineLayout,									// VkPipelineLayout					layout;
841		DE_NULL,											// VkPipeline						basePipelineHandle;
842		0,													// deInt32							basePipelineIndex;
843	};
844
845	pipeline																= createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo);
846}
847
848void ComputeConfiguration::fillCommandBuffer (Context&						context,
849											  TestParams&					testParams,
850											  VkCommandBuffer				commandBuffer,
851											  const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
852											  const VkDescriptorImageInfo&	resultImageInfo)
853{
854	const DeviceInterface&				vkd									= context.getDeviceInterface();
855	const VkDevice						device								= context.getDevice();
856
857	DescriptorSetUpdateBuilder()
858		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
859		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
860		.update(vkd, device);
861
862	vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
863
864	vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
865
866	vkd.cmdDispatch(commandBuffer, testParams.width, testParams.height, 1);
867}
868
869bool ComputeConfiguration::verifyImage (BufferWithMemory*					resultBuffer,
870										Context&							context,
871										TestParams&							testParams)
872{
873	// create result image
874	const bool					allMiss							= (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
875	tcu::TextureFormat			imageFormat						= vk::mapVkFormat(getResultImageFormat());
876	tcu::ConstPixelBufferAccess	resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
877
878	// create reference image
879	std::vector<deUint32>		reference(testParams.width * testParams.height * 2);
880	tcu::PixelBufferAccess		referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
881
882	tcu::UVec4 hitValue0	= tcu::UVec4(1, 0, 0, 0);
883	tcu::UVec4 hitValue1	= tcu::UVec4(1, 0, 0, 0);
884	tcu::UVec4 missValue	= tcu::UVec4(0, 0, 0, 0);
885
886	tcu::clear(referenceAccess, missValue);
887
888	for (deUint32 y = 0; y < testParams.height; ++y)
889	for (deUint32 x = 0; x < testParams.width; ++x)
890	{
891		if (allMiss || ((x + y) % 2) == 0)
892			continue;
893
894		referenceAccess.setPixel(hitValue0, x, y, 0);
895		referenceAccess.setPixel(hitValue1, x, y, 1);
896	}
897
898	// compare result and reference
899	return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
900}
901
902VkFormat ComputeConfiguration::getResultImageFormat ()
903{
904	return VK_FORMAT_R32_UINT;
905}
906
907size_t ComputeConfiguration::getResultImageFormatSize ()
908{
909	return sizeof(deUint32);
910}
911
912VkClearValue ComputeConfiguration::getClearValue ()
913{
914	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
915}
916
917class RayTracingConfiguration : public TestConfiguration
918{
919public:
920	virtual							~RayTracingConfiguration	();
921	void							initConfiguration			(Context&						context,
922																 TestParams&					testParams) override;
923	void							fillCommandBuffer			(Context&						context,
924																 TestParams&					testParams,
925																 VkCommandBuffer				commandBuffer,
926																 const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
927																 const VkDescriptorImageInfo&	resultImageInfo) override;
928	bool							verifyImage					(BufferWithMemory*				resultBuffer,
929																 Context&						context,
930																 TestParams&					testParams) override;
931	VkFormat						getResultImageFormat		() override;
932	size_t							getResultImageFormatSize	() override;
933	VkClearValue					getClearValue				() override;
934protected:
935	Move<VkDescriptorSetLayout>		descriptorSetLayout;
936	Move<VkDescriptorPool>			descriptorPool;
937	Move<VkDescriptorSet>			descriptorSet;
938	Move<VkPipelineLayout>			pipelineLayout;
939
940	de::MovePtr<RayTracingPipeline>	rayTracingPipeline;
941	Move<VkPipeline>				rtPipeline;
942
943	de::MovePtr<BufferWithMemory>	raygenShaderBindingTable;
944	de::MovePtr<BufferWithMemory>	hitShaderBindingTable;
945	de::MovePtr<BufferWithMemory>	missShaderBindingTable;
946	de::MovePtr<BufferWithMemory>	callableShaderBindingTable;
947
948	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
949	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
950};
951
952RayTracingConfiguration::~RayTracingConfiguration()
953{
954}
955
956void RayTracingConfiguration::initConfiguration (Context&						context,
957												 TestParams&					testParams)
958{
959	const InstanceInterface&			vki									= context.getInstanceInterface();
960	const DeviceInterface&				vkd									= context.getDeviceInterface();
961	const VkDevice						device								= context.getDevice();
962	const VkPhysicalDevice				physicalDevice						= context.getPhysicalDevice();
963	Allocator&							allocator							= context.getDefaultAllocator();
964
965	descriptorSetLayout														= DescriptorSetLayoutBuilder()
966																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
967																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
968																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
969																					.build(vkd, device);
970	descriptorPool															= DescriptorPoolBuilder()
971																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
972																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
973																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
974																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
975	descriptorSet															= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
976	pipelineLayout															= makePipelineLayout(vkd, device, descriptorSetLayout.get());
977
978	rayTracingPipeline														= de::newMovePtr<RayTracingPipeline>();
979
980	const std::map<ShaderSourceType,std::vector<std::string>> shaderNames =
981	{
982								//idx:		0				1				2				3				4				5
983								//shader:	rgen,			isect,			ahit,			chit,			miss,			call
984								//group:	0				1				1				1				2				3
985		{	SST_RAY_GENERATION_SHADER,	{	"rgen_%s",		"",				"",				"",				"",				""			}	},
986		{	SST_INTERSECTION_SHADER,	{	"rgen",			"isect_%s",		"",				"chit_isect",	"miss",			""			}	},
987		{	SST_ANY_HIT_SHADER,			{	"rgen",			"isect",		"ahit_%s",		"",				"miss",			""			}	},
988		{	SST_CLOSEST_HIT_SHADER,		{	"rgen",			"isect",		"",				"chit_%s",		"miss",			""			}	},
989		{	SST_MISS_SHADER,			{	"rgen",			"isect",		"",				"chit",			"miss_%s",		""			}	},
990		{	SST_CALLABLE_SHADER,		{	"rgen_call",	"",				"",				"chit",			"miss",			"call_%s"	}	},
991	};
992
993	std::vector<std::string> rayQueryTestName;
994	rayQueryTestName.push_back("as_triangle");
995	rayQueryTestName.push_back("as_aabb");
996
997	auto shaderNameIt = shaderNames.find(testParams.shaderSourceType);
998	if(shaderNameIt == end(shaderNames))
999		TCU_THROW(InternalError, "Wrong shader source type");
1000
1001	bool rgenX, isectX, ahitX, chitX, missX, callX;
1002	const auto bottomTestTypeIdx = static_cast<int>(testParams.bottomTestType);
1003	rgenX = registerShaderModule(vkd,	device,	context,		*rayTracingPipeline,	VK_SHADER_STAGE_RAYGEN_BIT_KHR,			shaderNameIt->second[0],	rayQueryTestName[bottomTestTypeIdx],	0);
1004	if (testParams.shaderSourceType == SST_INTERSECTION_SHADER)
1005		isectX = registerShaderModule(vkd, device, context,		*rayTracingPipeline,	VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	shaderNameIt->second[1],	rayQueryTestName[bottomTestTypeIdx],	1);
1006	else
1007		isectX = false;
1008	ahitX = registerShaderModule(vkd,	device,	context,		*rayTracingPipeline,	VK_SHADER_STAGE_ANY_HIT_BIT_KHR,		shaderNameIt->second[2],	rayQueryTestName[bottomTestTypeIdx],	1);
1009	chitX = registerShaderModule(vkd,	device,	context,		*rayTracingPipeline,	VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	shaderNameIt->second[3],	rayQueryTestName[bottomTestTypeIdx],	1);
1010	missX = registerShaderModule(vkd,	device,	context,		*rayTracingPipeline,	VK_SHADER_STAGE_MISS_BIT_KHR,			shaderNameIt->second[4],	rayQueryTestName[bottomTestTypeIdx],	2);
1011	callX = registerShaderModule(vkd,	device,	context,		*rayTracingPipeline,	VK_SHADER_STAGE_CALLABLE_BIT_KHR,		shaderNameIt->second[5],	rayQueryTestName[bottomTestTypeIdx],	3);
1012	bool hitX = isectX || ahitX || chitX;
1013
1014	rtPipeline																= rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
1015
1016	deUint32							shaderGroupHandleSize				= getShaderGroupHandleSize(vki, physicalDevice);
1017	deUint32							shaderGroupBaseAlignment			= getShaderGroupBaseAlignment(vki, physicalDevice);
1018
1019	if (rgenX)	raygenShaderBindingTable									= rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
1020	if (hitX)	hitShaderBindingTable										= rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
1021	if (missX)	missShaderBindingTable										= rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
1022	if (callX)	callableShaderBindingTable									= rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1);
1023}
1024
1025void RayTracingConfiguration::fillCommandBuffer (Context&						context,
1026												 TestParams&					testParams,
1027												 VkCommandBuffer				commandBuffer,
1028												 const VkWriteDescriptorSetAccelerationStructureKHR&	rayQueryAccelerationStructureWriteDescriptorSet,
1029												 const VkDescriptorImageInfo&	resultImageInfo)
1030{
1031	const InstanceInterface&			vki									= context.getInstanceInterface();
1032	const DeviceInterface&				vkd									= context.getDeviceInterface();
1033	const VkDevice						device								= context.getDevice();
1034	const VkPhysicalDevice				physicalDevice						= context.getPhysicalDevice();
1035	Allocator&							allocator							= context.getDefaultAllocator();
1036
1037	{
1038		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
1039		bottomLevelAccelerationStructure->setGeometryCount(1);
1040
1041		de::SharedPtr<RaytracedGeometryBase> geometry;
1042		if (testParams.shaderSourceType != SST_INTERSECTION_SHADER)
1043		{
1044			tcu::Vec3 v0(0.0f, float(testParams.height), 0.0f);
1045			tcu::Vec3 v1(0.0f, 0.0f, 0.0f);
1046			tcu::Vec3 v2(float(testParams.width), float(testParams.height), 0.0f);
1047			tcu::Vec3 v3(float(testParams.width), 0.0f, 0.0f);
1048			tcu::Vec3 missOffset(0.0f, 0.0f, 0.0f);
1049			if (testParams.shaderSourceType == SST_MISS_SHADER)
1050				missOffset = tcu::Vec3(1.0f + float(testParams.width), 0.0f, 0.0f);
1051
1052			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
1053			geometry->addVertex(v0 + missOffset);
1054			geometry->addVertex(v1 + missOffset);
1055			geometry->addVertex(v2 + missOffset);
1056			geometry->addVertex(v2 + missOffset);
1057			geometry->addVertex(v1 + missOffset);
1058			geometry->addVertex(v3 + missOffset);
1059		}
1060		else // testParams.shaderSourceType == SST_INTERSECTION_SHADER
1061		{
1062			tcu::Vec3 v0(0.0f, 0.0f, -0.1f);
1063			tcu::Vec3 v1(float(testParams.width), float(testParams.height), 0.1f);
1064
1065			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
1066			geometry->addVertex(v0);
1067			geometry->addVertex(v1);
1068		}
1069		bottomLevelAccelerationStructure->addGeometry(geometry);
1070		bottomLevelAccelerationStructures.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1071
1072		for (auto& blas : bottomLevelAccelerationStructures)
1073			blas->createAndBuild(vkd, device, commandBuffer, allocator);
1074	}
1075
1076	topLevelAccelerationStructure = makeTopLevelAccelerationStructure();
1077	topLevelAccelerationStructure->setInstanceCount(1);
1078	topLevelAccelerationStructure->addInstance(bottomLevelAccelerationStructures[0]);
1079	topLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator);
1080
1081	const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
1082	VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
1083	{
1084		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1085		DE_NULL,															//  const void*							pNext;
1086		1u,																	//  deUint32							accelerationStructureCount;
1087		topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1088	};
1089
1090	DescriptorSetUpdateBuilder()
1091		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
1092		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1093		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
1094		.update(vkd, device);
1095
1096	vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1097
1098	vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *rtPipeline);
1099
1100	deUint32							shaderGroupHandleSize				= getShaderGroupHandleSize(vki, physicalDevice);
1101	VkStridedDeviceAddressRegionKHR		raygenShaderBindingTableRegion		= raygenShaderBindingTable.get() != DE_NULL		? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize)		: makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1102	VkStridedDeviceAddressRegionKHR		hitShaderBindingTableRegion			= hitShaderBindingTable.get() != DE_NULL		? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize)			: makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1103	VkStridedDeviceAddressRegionKHR		missShaderBindingTableRegion		= missShaderBindingTable.get() != DE_NULL		? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize)		: makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1104	VkStridedDeviceAddressRegionKHR		callableShaderBindingTableRegion	= callableShaderBindingTable.get() != DE_NULL	? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize)	: makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1105
1106	cmdTraceRays(vkd,
1107		commandBuffer,
1108		&raygenShaderBindingTableRegion,
1109		&missShaderBindingTableRegion,
1110		&hitShaderBindingTableRegion,
1111		&callableShaderBindingTableRegion,
1112		testParams.width, testParams.height, 1);
1113}
1114
1115bool RayTracingConfiguration::verifyImage (BufferWithMemory*					resultBuffer,
1116										   Context&								context,
1117										   TestParams&							testParams)
1118{
1119	// create result image
1120	const bool					allMiss							= (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
1121	tcu::TextureFormat			imageFormat						= vk::mapVkFormat(getResultImageFormat());
1122	tcu::ConstPixelBufferAccess	resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
1123
1124	// create reference image
1125	std::vector<deUint32>		reference(testParams.width * testParams.height * 2);
1126	tcu::PixelBufferAccess		referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
1127
1128	tcu::UVec4					missValue	(0, 0, 0, 0);
1129	tcu::UVec4					hitValue	(1, 0, 0, 0);
1130
1131	for (deUint32 y = 0; y < testParams.height; ++y)
1132	for (deUint32 x = 0; x < testParams.width; ++x)
1133	{
1134		if (allMiss || ((x + y) % 2) == 0)
1135		{
1136			referenceAccess.setPixel(missValue, x, y, 0);
1137			referenceAccess.setPixel(missValue, x, y, 1);
1138		}
1139		else
1140		{
1141			referenceAccess.setPixel(hitValue, x, y, 0);
1142			referenceAccess.setPixel(hitValue, x, y, 1);
1143		}
1144	}
1145
1146	// compare result and reference
1147	return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
1148}
1149
1150VkFormat RayTracingConfiguration::getResultImageFormat ()
1151{
1152	return VK_FORMAT_R32_UINT;
1153}
1154
1155size_t RayTracingConfiguration::getResultImageFormatSize ()
1156{
1157	return sizeof(deUint32);
1158}
1159
1160VkClearValue RayTracingConfiguration::getClearValue ()
1161{
1162	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
1163}
1164
1165de::SharedPtr<TestConfiguration> createTestConfiguration(const ShaderSourcePipeline& shaderSourcePipeline)
1166{
1167	switch (shaderSourcePipeline)
1168	{
1169	case SSP_GRAPHICS_PIPELINE:
1170		return de::SharedPtr<TestConfiguration>(new GraphicsConfiguration());
1171	case SSP_COMPUTE_PIPELINE:
1172		return de::SharedPtr<TestConfiguration>(new ComputeConfiguration());
1173	case SSP_RAY_TRACING_PIPELINE:
1174		return de::SharedPtr<TestConfiguration>(new RayTracingConfiguration());
1175	default:
1176		TCU_THROW(InternalError, "Wrong shader source pipeline");
1177	}
1178	return de::SharedPtr<TestConfiguration>();
1179}
1180
1181class CheckerboardSceneBuilder : public SceneBuilder
1182{
1183public:
1184	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures (Context&							context,
1185																									  TestParams&						testParams) override;
1186	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure	 (Context&							context,
1187																									  TestParams&						testParams,
1188																									  std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
1189};
1190
1191std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> CheckerboardSceneBuilder::initBottomAccelerationStructures (Context&			context,
1192																														  TestParams&		testParams)
1193{
1194	DE_UNREF(context);
1195
1196	// Cull flags can only be used with triangles.
1197	DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE || testParams.bottomTestType == BottomTestType::TRIANGLES);
1198
1199	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
1200
1201	const auto instanceFlags = getCullFlags(testParams.cullFlags);
1202
1203	tcu::Vec3 v0(0.0, 1.0, 0.0);
1204	tcu::Vec3 v1(0.0, 0.0, 0.0);
1205	tcu::Vec3 v2(1.0, 1.0, 0.0);
1206	tcu::Vec3 v3(1.0, 0.0, 0.0);
1207
1208	// Different vertex configurations of a triangle whose parameter x is set to NaN during inactive_triangles tests
1209	const bool nanConfig[4][4] =
1210	{
1211		{ true,		true,		true,		true	},
1212		{ false,	true,		true,		false	},
1213		{ false,	false,		true,		false	},
1214		{ false,	true,		false,		false	},
1215	};
1216
1217	unsigned int geometryCount = testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES ? 4U : 1U;
1218
1219	if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
1220	{
1221		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
1222		bottomLevelAccelerationStructure->setGeometryCount(1u);
1223		de::SharedPtr<RaytracedGeometryBase> geometry;
1224		if (testParams.bottomTestType == BottomTestType::TRIANGLES)
1225		{
1226			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
1227			if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
1228			{
1229				if (instanceFlags == 0u)
1230				{
1231					geometry->addVertex(v0);
1232					geometry->addVertex(v1);
1233					geometry->addVertex(v2);
1234					geometry->addVertex(v2);
1235					geometry->addVertex(v1);
1236					geometry->addVertex(v3);
1237				}
1238				else // Counterclockwise so the flags will be needed for the geometry to be visible.
1239				{
1240					geometry->addVertex(v2);
1241					geometry->addVertex(v1);
1242					geometry->addVertex(v0);
1243					geometry->addVertex(v3);
1244					geometry->addVertex(v1);
1245					geometry->addVertex(v2);
1246				}
1247			}
1248			else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
1249			{
1250				geometry->addVertex(v0);
1251				geometry->addVertex(v1);
1252				geometry->addVertex(v2);
1253				geometry->addVertex(v3);
1254
1255				if (instanceFlags == 0u)
1256				{
1257					geometry->addIndex(0);
1258					geometry->addIndex(1);
1259					geometry->addIndex(2);
1260					geometry->addIndex(2);
1261					geometry->addIndex(1);
1262					geometry->addIndex(3);
1263				}
1264				else // Counterclockwise so the flags will be needed for the geometry to be visible.
1265				{
1266					geometry->addIndex(2);
1267					geometry->addIndex(1);
1268					geometry->addIndex(0);
1269					geometry->addIndex(3);
1270					geometry->addIndex(1);
1271					geometry->addIndex(2);
1272				}
1273
1274			}
1275		}
1276		else // m_data.bottomTestType == BTT_AABBS
1277		{
1278			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
1279
1280			if (!testParams.padVertices)
1281			{
1282				// Single AABB.
1283				geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
1284				geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
1285			}
1286			else
1287			{
1288				// Multiple AABBs covering the same space.
1289				geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
1290				geometry->addVertex(tcu::Vec3(0.5f, 0.5f,  0.1f));
1291
1292				geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
1293				geometry->addVertex(tcu::Vec3(1.0f, 1.0f,  0.1f));
1294
1295				geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
1296				geometry->addVertex(tcu::Vec3(0.5f, 1.0f,  0.1f));
1297
1298				geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
1299				geometry->addVertex(tcu::Vec3(1.0f, 0.5f,  0.1f));
1300			}
1301		}
1302
1303		bottomLevelAccelerationStructure->addGeometry(geometry);
1304		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1305	}
1306	else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
1307	{
1308		tcu::TextureFormat	texFormat	= mapVkFormat(testParams.vertexFormat);
1309		tcu::Vec3			scale		( 1.0f, 1.0f, 1.0f );
1310		if (tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
1311			scale = tcu::Vec3(1.0f / float(testParams.width), 1.0f / float(testParams.height), 1.0f);
1312
1313		// triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
1314		for (deUint32 y = 0; y < testParams.height; ++y)
1315		for (deUint32 x = 0; x < testParams.width; ++x)
1316		{
1317			// let's build a chessboard of geometries
1318			if (((x + y) % 2) == 0)
1319				continue;
1320			tcu::Vec3 xyz((float)x, (float)y, 0.0f);
1321
1322			de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
1323			bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
1324
1325			if (testParams.bottomTestType == BottomTestType::TRIANGLES)
1326			{
1327				for (unsigned int i = 0; i < geometryCount; i++)
1328				{
1329					de::SharedPtr<RaytracedGeometryBase> geometry;
1330					geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
1331
1332					if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
1333					{
1334						const auto nanValue = tcu::Float32::nan().asFloat();
1335
1336						if (nanConfig[i][0])
1337							v0.x() = nanValue;
1338						if (nanConfig[i][1])
1339							v1.x() = nanValue;
1340						if (nanConfig[i][2])
1341							v2.x() = nanValue;
1342						if (nanConfig[i][3])
1343							v3.x() = nanValue;
1344					}
1345
1346					if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
1347					{
1348						if (instanceFlags == 0u)
1349						{
1350							geometry->addVertex(scale * (xyz + v0));
1351							geometry->addVertex(scale * (xyz + v1));
1352							geometry->addVertex(scale * (xyz + v2));
1353							geometry->addVertex(scale * (xyz + v2));
1354							geometry->addVertex(scale * (xyz + v1));
1355							geometry->addVertex(scale * (xyz + v3));
1356						}
1357						else // Counterclockwise so the flags will be needed for the geometry to be visible.
1358						{
1359							geometry->addVertex(scale * (xyz + v2));
1360							geometry->addVertex(scale * (xyz + v1));
1361							geometry->addVertex(scale * (xyz + v0));
1362							geometry->addVertex(scale * (xyz + v3));
1363							geometry->addVertex(scale * (xyz + v1));
1364							geometry->addVertex(scale * (xyz + v2));
1365						}
1366					}
1367
1368					else
1369					{
1370						geometry->addVertex(scale * (xyz + v0));
1371						geometry->addVertex(scale * (xyz + v1));
1372						geometry->addVertex(scale * (xyz + v2));
1373						geometry->addVertex(scale * (xyz + v3));
1374
1375						if (instanceFlags == 0u)
1376						{
1377							geometry->addIndex(0);
1378							geometry->addIndex(1);
1379							geometry->addIndex(2);
1380							geometry->addIndex(2);
1381							geometry->addIndex(1);
1382							geometry->addIndex(3);
1383						}
1384						else // Counterclockwise so the flags will be needed for the geometry to be visible.
1385						{
1386							geometry->addIndex(2);
1387							geometry->addIndex(1);
1388							geometry->addIndex(0);
1389							geometry->addIndex(3);
1390							geometry->addIndex(1);
1391							geometry->addIndex(2);
1392						}
1393					}
1394
1395					bottomLevelAccelerationStructure->addGeometry(geometry);
1396				}
1397			}
1398			else // testParams.bottomTestType == BTT_AABBS
1399			{
1400				de::SharedPtr<RaytracedGeometryBase> geometry;
1401				geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
1402
1403				if (!testParams.padVertices)
1404				{
1405					// Single AABB.
1406					geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)));
1407					geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 1.0f, 0.1f)));
1408				}
1409				else
1410				{
1411					// Multiple AABBs covering the same space.
1412					geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)));
1413					geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.5f,  0.1f)));
1414
1415					geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.5f, -0.1f)));
1416					geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 1.0f,  0.1f)));
1417
1418					geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.5f, -0.1f)));
1419					geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 1.0f,  0.1f)));
1420
1421					geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.0f, -0.1f)));
1422					geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 0.5f,  0.1f)));
1423				}
1424
1425				bottomLevelAccelerationStructure->addGeometry(geometry);
1426			}
1427
1428			result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1429		}
1430	}
1431
1432	return result;
1433}
1434
1435de::MovePtr<TopLevelAccelerationStructure> CheckerboardSceneBuilder::initTopAccelerationStructure (Context&			context,
1436																								   TestParams&		testParams,
1437																								   std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
1438{
1439	DE_UNREF(context);
1440
1441	const auto instanceCount = testParams.width * testParams.height / 2u;
1442	const auto instanceFlags = getCullFlags(testParams.cullFlags);
1443
1444	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
1445	result->setInstanceCount(instanceCount);
1446
1447	if (testParams.topTestType == TopTestType::DIFFERENT_INSTANCES)
1448	{
1449
1450		for (deUint32 y = 0; y < testParams.height; ++y)
1451		for (deUint32 x = 0; x < testParams.width; ++x)
1452		{
1453			if (((x + y) % 2) == 0)
1454				continue;
1455			const VkTransformMatrixKHR			transformMatrixKHR =
1456			{
1457				{								//  float	matrix[3][4];
1458					{ 1.0f, 0.0f, 0.0f, (float)x },
1459					{ 0.0f, 1.0f, 0.0f, (float)y },
1460					{ 0.0f, 0.0f, 1.0f, 0.0f },
1461				}
1462			};
1463			result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, 0u, 0xFFu, 0u, instanceFlags);
1464		}
1465	}
1466	else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
1467	{
1468		tcu::TextureFormat	texFormat	= mapVkFormat(testParams.vertexFormat);
1469		tcu::Vec3			scale		( 1.0f, 1.0f, 1.0f );
1470		if (tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
1471			scale = tcu::Vec3(float(testParams.width), float(testParams.height), 1.0f);
1472
1473		const VkTransformMatrixKHR			transformMatrixKHR =
1474		{
1475			{								//  float	matrix[3][4];
1476				{ scale.x(), 0.0f, 0.0f, 0.0f },
1477				{ 0.0f, scale.y(), 0.0f, 0.0f },
1478				{ 0.0f, 0.0f, scale.z(), 0.0f },
1479			}
1480		};
1481
1482		deUint32 currentInstanceIndex = 0;
1483
1484		for (deUint32 y = 0; y < testParams.height; ++y)
1485		for (deUint32 x = 0; x < testParams.width; ++x)
1486		{
1487			if (((x + y) % 2) == 0)
1488				continue;
1489			result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], transformMatrixKHR, 0u, 0xFFu, 0u, instanceFlags);
1490		}
1491	}
1492
1493	return result;
1494}
1495
1496void commonASTestsCheckSupport(Context& context)
1497{
1498	context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
1499	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1500	context.requireDeviceFunctionality("VK_KHR_ray_query");
1501
1502	const VkPhysicalDeviceRayQueryFeaturesKHR&	rayQueryFeaturesKHR = context.getRayQueryFeatures();
1503	if (rayQueryFeaturesKHR.rayQuery == DE_FALSE)
1504		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
1505
1506	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
1507	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
1508		TCU_THROW(TestError, "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
1509}
1510
1511class RayQueryASBasicTestCase : public TestCase
1512{
1513public:
1514							RayQueryASBasicTestCase		(tcu::TestContext& context, const char* name, const TestParams& data);
1515							~RayQueryASBasicTestCase	(void);
1516
1517	virtual void			checkSupport				(Context& context) const;
1518	virtual	void			initPrograms				(SourceCollections& programCollection) const;
1519	virtual TestInstance*	createInstance				(Context& context) const;
1520protected:
1521	TestParams				m_data;
1522};
1523
1524class RayQueryASFuncArgTestCase : public RayQueryASBasicTestCase
1525{
1526public:
1527							RayQueryASFuncArgTestCase		(tcu::TestContext& context, const char* name, const TestParams& data);
1528							~RayQueryASFuncArgTestCase		(void) {}
1529
1530	virtual	void			initPrograms					(SourceCollections& programCollection) const;
1531};
1532
1533class RayQueryASBasicTestInstance : public TestInstance
1534{
1535public:
1536									RayQueryASBasicTestInstance		(Context& context,
1537																	 const TestParams& data);
1538									~RayQueryASBasicTestInstance	(void);
1539	tcu::TestStatus					iterate							(void);
1540protected:
1541	bool							iterateNoWorkers				(void);
1542	bool							iterateWithWorkers				(void);
1543	de::MovePtr<BufferWithMemory>	runTest							(TestConfiguration* testConfiguration,
1544																	 SceneBuilder* sceneBuilder,
1545																	 const deUint32 workerThreadsCount);
1546
1547
1548private:
1549	TestParams														m_data;
1550};
1551
1552RayQueryASBasicTestCase::RayQueryASBasicTestCase (tcu::TestContext& context, const char* name, const TestParams& data)
1553	: vkt::TestCase	(context, name)
1554	, m_data		(data)
1555{
1556}
1557
1558RayQueryASBasicTestCase::~RayQueryASBasicTestCase (void)
1559{
1560}
1561
1562void RayQueryASBasicTestCase::checkSupport (Context& context) const
1563{
1564	commonASTestsCheckSupport(context);
1565
1566	const VkPhysicalDeviceFeatures2& features2 = context.getDeviceFeatures2();
1567
1568	if ((m_data.shaderSourceType == SST_TESSELATION_CONTROL_SHADER ||
1569		 m_data.shaderSourceType == SST_TESSELATION_EVALUATION_SHADER) &&
1570		features2.features.tessellationShader == DE_FALSE )
1571		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.tessellationShader");
1572
1573	if (m_data.shaderSourceType == SST_GEOMETRY_SHADER &&
1574		features2.features.geometryShader == DE_FALSE )
1575		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.geometryShader");
1576
1577	if (m_data.shaderSourceType == SST_RAY_GENERATION_SHADER ||
1578		m_data.shaderSourceType == SST_INTERSECTION_SHADER ||
1579		m_data.shaderSourceType == SST_ANY_HIT_SHADER ||
1580		m_data.shaderSourceType == SST_CLOSEST_HIT_SHADER ||
1581		m_data.shaderSourceType == SST_MISS_SHADER ||
1582		m_data.shaderSourceType == SST_CALLABLE_SHADER)
1583	{
1584		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1585
1586		const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
1587
1588		if(rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
1589			TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
1590	}
1591
1592	switch (m_data.shaderSourceType)
1593	{
1594	case SST_VERTEX_SHADER:
1595	case SST_TESSELATION_CONTROL_SHADER:
1596	case SST_TESSELATION_EVALUATION_SHADER:
1597	case SST_GEOMETRY_SHADER:
1598		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1599		break;
1600	default:
1601		break;
1602	}
1603
1604	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
1605	if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
1606		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
1607
1608	// Check supported vertex format.
1609	checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_data.vertexFormat);
1610}
1611
1612void RayQueryASBasicTestCase::initPrograms (SourceCollections& programCollection) const
1613{
1614	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1615
1616	// create parts of programs responsible for test execution
1617	std::vector<std::string> rayQueryTest;
1618	std::vector<std::string> rayQueryTestName;
1619	rayQueryTestName.push_back("as_triangle");
1620	rayQueryTestName.push_back("as_aabb");
1621
1622	{
1623		std::stringstream css;
1624		css <<
1625			"  float tmin     = 0.0;\n"
1626			"  float tmax     = 1.0;\n"
1627			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
1628			"  rayQueryEXT rq;\n"
1629			"  rayQueryInitializeEXT(rq, rqTopLevelAS, " << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0" : "gl_RayFlagsCullBackFacingTrianglesEXT") << ", 0xFF, origin, tmin, direct, tmax);\n"
1630			"  if(rayQueryProceedEXT(rq))\n"
1631			"  {\n"
1632			"    if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionTriangleEXT)\n"
1633			"    {\n"
1634			"      hitValue.y = 1;\n"
1635			"      hitValue.x = 1;\n"
1636			"    }\n"
1637			"  }\n";
1638		rayQueryTest.push_back(css.str());
1639	}
1640	{
1641		std::stringstream css;
1642		css <<
1643			"  float tmin     = 0.0;\n"
1644			"  float tmax     = 1.0;\n"
1645			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
1646			"  rayQueryEXT rq;\n"
1647			"  rayQueryInitializeEXT(rq, rqTopLevelAS, 0, 0xFF, origin, tmin, direct, tmax);\n"
1648			"  if(rayQueryProceedEXT(rq))\n"
1649			"  {\n"
1650			"    if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionAABBEXT)\n"
1651			"    {\n"
1652			"      hitValue.y = 1;\n"
1653			"      hitValue.x = 1;\n"
1654			"    }\n"
1655			"  }\n";
1656		rayQueryTest.push_back(css.str());
1657	}
1658
1659	const auto bottomTestTypeIdx = static_cast<int>(m_data.bottomTestType);
1660
1661	// create all programs
1662	if (m_data.shaderSourcePipeline == SSP_GRAPHICS_PIPELINE)
1663	{
1664		{
1665			std::stringstream css;
1666			css <<
1667				"#version 460 core\n"
1668				"layout (location = 0) in vec3 position;\n"
1669				"out gl_PerVertex\n"
1670				"{\n"
1671				"  vec4 gl_Position;\n"
1672				"};\n"
1673				"void main()\n"
1674				"{\n"
1675				"  gl_Position = vec4(position, 1.0);\n"
1676				"}\n";
1677			programCollection.glslSources.add("vert") << glu::VertexSource(css.str()) << buildOptions;
1678		}
1679
1680		{
1681			std::stringstream css;
1682			css <<
1683				"#version 460 core\n"
1684				"layout (location = 0) in vec3 position;\n"
1685				"out gl_PerVertex\n"
1686				"{\n"
1687				"  vec4 gl_Position;\n"
1688				"};\n"
1689				"layout(location = 0) out int vertexIndex;\n"
1690				"void main()\n"
1691				"{\n"
1692				"  gl_Position = vec4(position, 1.0);\n"
1693				"  vertexIndex = gl_VertexIndex;\n"
1694				"}\n";
1695			programCollection.glslSources.add("vert_vid") << glu::VertexSource(css.str()) << buildOptions;
1696		}
1697
1698		{
1699			std::stringstream css;
1700			css <<
1701				"#version 460 core\n"
1702				"#extension GL_EXT_ray_query : require\n"
1703				"layout (location = 0) in vec3 position;\n"
1704				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1705				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1706				"void main()\n"
1707				"{\n"
1708				"  vec3  origin   = vec3(float(position.x) + 0.5, float(position.y) + 0.5, 0.5);\n"
1709				"  uvec4 hitValue = uvec4(0,0,0,0);\n" <<
1710				rayQueryTest[bottomTestTypeIdx] <<
1711				"  imageStore(result, ivec3(gl_VertexIndex, 0, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1712				"  imageStore(result, ivec3(gl_VertexIndex, 0, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1713				"  gl_Position = vec4(position,1);\n"
1714				"}\n";
1715			std::stringstream cssName;
1716			cssName << "vert_" << rayQueryTestName[bottomTestTypeIdx];
1717
1718			programCollection.glslSources.add(cssName.str()) << glu::VertexSource(css.str()) << buildOptions;
1719		}
1720
1721		{
1722			std::stringstream css;
1723			css <<
1724				"#version 460 core\n"
1725				"#extension GL_EXT_tessellation_shader : require\n"
1726				"in gl_PerVertex {\n"
1727				"  vec4  gl_Position;\n"
1728				"} gl_in[];\n"
1729				"layout(vertices = 3) out;\n"
1730				"void main (void)\n"
1731				"{\n"
1732				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1733				"  gl_TessLevelInner[0] = 1;\n"
1734				"  gl_TessLevelOuter[0] = 1;\n"
1735				"  gl_TessLevelOuter[1] = 1;\n"
1736				"  gl_TessLevelOuter[2] = 1;\n"
1737				"}\n";
1738			programCollection.glslSources.add("tesc") << glu::TessellationControlSource(css.str()) << buildOptions;
1739		}
1740
1741		{
1742			std::stringstream css;
1743			css <<
1744				"#version 460 core\n"
1745				"#extension GL_EXT_tessellation_shader : require\n"
1746				"#extension GL_EXT_ray_query : require\n"
1747				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1748				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1749				"in gl_PerVertex {\n"
1750				"  vec4  gl_Position;\n"
1751				"} gl_in[];\n"
1752				"layout(vertices = 3) out;\n"
1753				"void main (void)\n"
1754				"{\n"
1755				"  vec3  origin   = vec3(gl_in[gl_InvocationID].gl_Position.x + 0.5, gl_in[gl_InvocationID].gl_Position.y + 0.5, 0.5);\n"
1756				"  uvec4 hitValue = uvec4(0,0,0,0);\n" <<
1757				rayQueryTest[bottomTestTypeIdx] <<
1758				"  imageStore(result, ivec3(gl_PrimitiveID, gl_InvocationID, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1759				"  imageStore(result, ivec3(gl_PrimitiveID, gl_InvocationID, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1760				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1761				"  gl_TessLevelInner[0] = 1;\n"
1762				"  gl_TessLevelOuter[0] = 1;\n"
1763				"  gl_TessLevelOuter[1] = 1;\n"
1764				"  gl_TessLevelOuter[2] = 1;\n"
1765				"}\n";
1766			std::stringstream cssName;
1767			cssName << "tesc_" << rayQueryTestName[bottomTestTypeIdx];
1768
1769			programCollection.glslSources.add(cssName.str()) << glu::TessellationControlSource(css.str()) << buildOptions;
1770		}
1771
1772		{
1773			std::stringstream css;
1774			css <<
1775				"#version 460 core\n"
1776				"#extension GL_EXT_tessellation_shader : require\n"
1777				"#extension GL_EXT_ray_query : require\n"
1778				"layout(triangles, equal_spacing, ccw) in;\n"
1779				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1780				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1781				"void main (void)\n"
1782				"{\n"
1783				"  for (int i = 0; i < 3; ++i)\n"
1784				"  {\n"
1785				"    vec3  origin   = vec3(gl_in[i].gl_Position.x + 0.5, gl_in[i].gl_Position.y + 0.5, 0.5);\n"
1786				"    uvec4 hitValue = uvec4(0,0,0,0);\n" <<
1787				rayQueryTest[bottomTestTypeIdx] <<
1788				"    imageStore(result, ivec3(gl_PrimitiveID, i, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1789				"    imageStore(result, ivec3(gl_PrimitiveID, i, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1790				"  }\n"
1791				"  gl_Position = gl_in[0].gl_Position;\n"
1792				"}\n";
1793			std::stringstream cssName;
1794			cssName << "tese_" << rayQueryTestName[bottomTestTypeIdx];
1795
1796			programCollection.glslSources.add(cssName.str()) << glu::TessellationEvaluationSource(css.str()) << buildOptions;
1797		}
1798
1799		{
1800			std::stringstream css;
1801			css <<
1802				"#version 460 core\n"
1803				"#extension GL_EXT_tessellation_shader : require\n"
1804				"layout(triangles, equal_spacing, ccw) in;\n"
1805				"void main (void)\n"
1806				"{\n"
1807				"  gl_Position = gl_in[0].gl_Position;\n"
1808				"}\n";
1809
1810			programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(css.str()) << buildOptions;
1811		}
1812
1813		{
1814			std::stringstream css;
1815			css <<
1816				"#version 460 core\n"
1817				"#extension GL_EXT_ray_query : require\n"
1818				"layout(triangles) in;\n"
1819				"layout (triangle_strip, max_vertices = 4) out;\n"
1820				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1821				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1822				"\n"
1823				"in gl_PerVertex {\n"
1824				"  vec4  gl_Position;\n"
1825				"} gl_in[];\n"
1826				"layout(location = 0) in int vertexIndex[];\n"
1827				"out gl_PerVertex {\n"
1828				"  vec4 gl_Position;\n"
1829				"};\n"
1830				"void main (void)\n"
1831				"{\n"
1832				"  // geometry shader may reorder the vertices, keeping only the winding of the triangles.\n"
1833				"  // To iterate from the 'first vertex' of the triangle we need to find it first by looking for\n"
1834				"  // smallest vertex index value.\n"
1835				"  int minVertexIndex = 10000;"
1836				"  int firstVertex;"
1837				"  for (int i = 0; i < gl_in.length(); ++i)\n"
1838				"  {\n"
1839				"    if (minVertexIndex > vertexIndex[i])\n"
1840				"    {\n"
1841				"      minVertexIndex = vertexIndex[i];\n"
1842				"      firstVertex    = i;\n"
1843				"    }\n"
1844				"  }\n"
1845				"  for (int j = 0; j < gl_in.length(); ++j)\n"
1846				"  {\n"
1847				"    // iterate starting at firstVertex, possibly wrapping around, so the triangle is\n"
1848				"    // always iterated starting from the smallest vertex index, as found above.\n"
1849				"    int i = (firstVertex + j) % gl_in.length();\n"
1850				"    vec3  origin   = vec3(gl_in[i].gl_Position.x + 0.5, gl_in[i].gl_Position.y + 0.5, 0.5);\n"
1851				"    uvec4 hitValue = uvec4(0,0,0,0);\n" <<
1852				rayQueryTest[bottomTestTypeIdx] <<
1853				"    imageStore(result, ivec3(gl_PrimitiveIDIn, j, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1854				"    imageStore(result, ivec3(gl_PrimitiveIDIn, j, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1855				"    gl_Position      = gl_in[i].gl_Position;\n"
1856				"    EmitVertex();\n"
1857				"  }\n"
1858				"  EndPrimitive();\n"
1859				"}\n";
1860			std::stringstream cssName;
1861			cssName << "geom_" << rayQueryTestName[bottomTestTypeIdx];
1862
1863			programCollection.glslSources.add(cssName.str()) << glu::GeometrySource(css.str()) << buildOptions;
1864		}
1865
1866		{
1867			std::stringstream css;
1868			css <<
1869				"#version 460 core\n"
1870				"#extension GL_EXT_ray_query : require\n"
1871				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1872				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1873				"void main()\n"
1874				"{\n"
1875				"  vec3  origin   = vec3(gl_FragCoord.x, gl_FragCoord.y, 0.5);\n"
1876				"  uvec4 hitValue = uvec4(0,0,0,0);\n" <<
1877				rayQueryTest[bottomTestTypeIdx] <<
1878				"  imageStore(result, ivec3(gl_FragCoord.xy-vec2(0.5,0.5), 0), uvec4(hitValue.x, 0, 0, 0));\n"
1879				"  imageStore(result, ivec3(gl_FragCoord.xy-vec2(0.5,0.5), 1), uvec4(hitValue.y, 0, 0, 0));\n"
1880				"}\n";
1881			std::stringstream cssName;
1882			cssName << "frag_" << rayQueryTestName[bottomTestTypeIdx];
1883
1884			programCollection.glslSources.add(cssName.str()) << glu::FragmentSource(css.str()) << buildOptions;
1885		}
1886	}
1887	else if (m_data.shaderSourcePipeline == SSP_COMPUTE_PIPELINE)
1888	{
1889		{
1890			std::stringstream css;
1891			css <<
1892				"#version 460 core\n"
1893				"#extension GL_EXT_ray_query : require\n"
1894				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1895				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
1896				"void main()\n"
1897				"{\n"
1898				"  vec3  origin   = vec3(float(gl_GlobalInvocationID.x) + 0.5, float(gl_GlobalInvocationID.y) + 0.5, 0.5);\n"
1899				"  uvec4 hitValue = uvec4(0,0,0,0);\n" <<
1900				rayQueryTest[bottomTestTypeIdx] <<
1901				"  imageStore(result, ivec3(gl_GlobalInvocationID.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1902				"  imageStore(result, ivec3(gl_GlobalInvocationID.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1903				"}\n";
1904			std::stringstream cssName;
1905			cssName << "comp_" << rayQueryTestName[bottomTestTypeIdx];
1906
1907			programCollection.glslSources.add(cssName.str()) << glu::ComputeSource(css.str()) << buildOptions;
1908		}
1909	}
1910	else if (m_data.shaderSourcePipeline == SSP_RAY_TRACING_PIPELINE)
1911	{
1912		{
1913			std::stringstream css;
1914			css <<
1915				"#version 460 core\n"
1916				"#extension GL_EXT_ray_tracing : require\n"
1917				"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
1918				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1919				"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1920				"void main()\n"
1921				"{\n"
1922				"  float tmin     = 0.0;\n"
1923				"  float tmax     = 1.0;\n"
1924				"  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
1925				"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
1926				"  hitValue       = uvec4(0,0,0,0);\n"
1927				"  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
1928				"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1929				"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1930				"}\n";
1931			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1932		}
1933
1934		{
1935			std::stringstream css;
1936			css <<
1937				"#version 460 core\n"
1938				"#extension GL_EXT_ray_tracing : require\n"
1939				"#extension GL_EXT_ray_query : require\n"
1940				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1941				"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1942				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
1943				"void main()\n"
1944				"{\n"
1945				"  vec3  origin    = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
1946				"  uvec4  hitValue = uvec4(0,0,0,0);\n" <<
1947				rayQueryTest[bottomTestTypeIdx] <<
1948				"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
1949				"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
1950				"}\n";
1951			std::stringstream cssName;
1952			cssName << "rgen_" << rayQueryTestName[bottomTestTypeIdx];
1953
1954			programCollection.glslSources.add(cssName.str()) << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1955		}
1956
1957		{
1958			std::stringstream css;
1959			css <<
1960				"#version 460 core\n"
1961				"#extension GL_EXT_ray_tracing : require\n"
1962				"struct CallValue\n{\n"
1963				"  vec3  origin;\n"
1964				"  uvec4 hitValue;\n"
1965				"};\n"
1966				"layout(location = 0) callableDataEXT CallValue param;\n"
1967				"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
1968				"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1969				"void main()\n"
1970				"{\n"
1971				"  param.origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
1972				"  param.hitValue = uvec4(0, 0, 0, 0);\n"
1973				"  executeCallableEXT(0, 0);\n"
1974				"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(param.hitValue.x, 0, 0, 0));\n"
1975				"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(param.hitValue.y, 0, 0, 0));\n"
1976				"}\n";
1977			programCollection.glslSources.add("rgen_call") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1978		}
1979
1980		{
1981			std::stringstream css;
1982			css <<
1983				"#version 460 core\n"
1984				"#extension GL_EXT_ray_tracing : require\n"
1985				"hitAttributeEXT uvec4 hitValue;\n"
1986				"void main()\n"
1987				"{\n"
1988				"  reportIntersectionEXT(0.5f, 0);\n"
1989				"}\n";
1990
1991			programCollection.glslSources.add("isect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1992		}
1993
1994		{
1995			std::stringstream css;
1996			css <<
1997				"#version 460 core\n"
1998				"#extension GL_EXT_ray_tracing : require\n"
1999				"#extension GL_EXT_ray_query : require\n"
2000				"hitAttributeEXT uvec4 hitValue;\n"
2001				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2002				"void main()\n"
2003				"{\n"
2004				"  vec3 origin = gl_WorldRayOriginEXT;\n"
2005				"  hitValue    = uvec4(0,0,0,0);\n" <<
2006				rayQueryTest[bottomTestTypeIdx] <<
2007				"  reportIntersectionEXT(0.5f, 0);\n"
2008				"}\n";
2009			std::stringstream cssName;
2010			cssName << "isect_" << rayQueryTestName[bottomTestTypeIdx];
2011
2012			programCollection.glslSources.add(cssName.str()) << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
2013		}
2014
2015		{
2016			std::stringstream css;
2017			css <<
2018				"#version 460 core\n"
2019				"#extension GL_EXT_ray_tracing : require\n"
2020				"#extension GL_EXT_ray_query : require\n"
2021				"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2022				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2023				"void main()\n"
2024				"{\n"
2025				"  vec3 origin = gl_WorldRayOriginEXT;\n" <<
2026				rayQueryTest[bottomTestTypeIdx] <<
2027				"}\n";
2028			std::stringstream cssName;
2029			cssName << "ahit_" << rayQueryTestName[bottomTestTypeIdx];
2030
2031			programCollection.glslSources.add(cssName.str()) << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2032		}
2033
2034		{
2035			std::stringstream css;
2036			css <<
2037				"#version 460 core\n"
2038				"#extension GL_EXT_ray_tracing : require\n"
2039				"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2040				"void main()\n"
2041				"{\n"
2042				"  hitValue.y = 3;\n"
2043				"}\n";
2044
2045			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2046		}
2047
2048		{
2049			std::stringstream css;
2050			css <<
2051				"#version 460 core\n"
2052				"#extension GL_EXT_ray_tracing : require\n"
2053				"#extension GL_EXT_ray_query : require\n"
2054				"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2055				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2056				"void main()\n"
2057				"{\n"
2058				"  vec3 origin = gl_WorldRayOriginEXT;\n" <<
2059				rayQueryTest[bottomTestTypeIdx] <<
2060				"}\n";
2061			std::stringstream cssName;
2062			cssName << "chit_" << rayQueryTestName[bottomTestTypeIdx];
2063
2064			programCollection.glslSources.add(cssName.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2065		}
2066
2067		{
2068			std::stringstream css;
2069			css <<
2070				"#version 460 core\n"
2071				"#extension GL_EXT_ray_tracing : require\n"
2072				"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2073				"hitAttributeEXT uvec4 hitAttrib;\n"
2074				"void main()\n"
2075				"{\n"
2076				"  hitValue = hitAttrib;\n"
2077				"}\n";
2078
2079			programCollection.glslSources.add("chit_isect") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
2080		}
2081
2082		{
2083			std::stringstream css;
2084			css <<
2085				"#version 460 core\n"
2086				"#extension GL_EXT_ray_tracing : require\n"
2087				"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2088				"void main()\n"
2089				"{\n"
2090				"  hitValue.x = 4;\n"
2091				"}\n";
2092
2093			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
2094		}
2095
2096		{
2097			std::stringstream css;
2098			css <<
2099				"#version 460 core\n"
2100				"#extension GL_EXT_ray_tracing : require\n"
2101				"#extension GL_EXT_ray_query : require\n"
2102				"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
2103				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2104				"void main()\n"
2105				"{\n"
2106				"  vec3 origin = gl_WorldRayOriginEXT;\n" <<
2107				rayQueryTest[bottomTestTypeIdx] <<
2108				"}\n";
2109			std::stringstream cssName;
2110			cssName << "miss_" << rayQueryTestName[bottomTestTypeIdx];
2111
2112			programCollection.glslSources.add(cssName.str()) << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
2113		}
2114
2115		{
2116			std::stringstream css;
2117			css <<
2118				"#version 460 core\n"
2119				"#extension GL_EXT_ray_tracing : require\n"
2120				"#extension GL_EXT_ray_query : require\n"
2121				"struct CallValue\n{\n"
2122				"  vec3  origin;\n"
2123				"  uvec4 hitValue;\n"
2124				"};\n"
2125				"layout(location = 0) callableDataInEXT CallValue result;\n"
2126				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
2127				"void main()\n"
2128				"{\n"
2129				"  vec3 origin    = result.origin;\n"
2130				"  uvec4 hitValue = uvec4(0,0,0,0);\n" <<
2131				rayQueryTest[bottomTestTypeIdx] <<
2132				"  result.hitValue = hitValue;\n"
2133				"}\n";
2134			std::stringstream cssName;
2135			cssName << "call_" << rayQueryTestName[bottomTestTypeIdx];
2136
2137			programCollection.glslSources.add(cssName.str()) << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
2138		}
2139	}
2140}
2141
2142TestInstance* RayQueryASBasicTestCase::createInstance (Context& context) const
2143{
2144	return new RayQueryASBasicTestInstance(context, m_data);
2145}
2146
2147RayQueryASFuncArgTestCase::RayQueryASFuncArgTestCase (tcu::TestContext& context, const char* name, const TestParams& data)
2148	: RayQueryASBasicTestCase (context, name, data)
2149{
2150}
2151
2152void RayQueryASFuncArgTestCase::initPrograms (SourceCollections& programCollection) const
2153{
2154	const vk::SpirVAsmBuildOptions	spvBuildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2155
2156	DE_ASSERT(m_data.shaderSourcePipeline == SSP_COMPUTE_PIPELINE);
2157	DE_ASSERT(m_data.bottomTestType == BottomTestType::TRIANGLES);
2158
2159	// The SPIR-V assembly shader below is based on the following GLSL code.
2160	// In it, rayQueryInitializeBottomWrapper has been modified to take a
2161	// bare AS as the second argument, instead of a pointer.
2162	//
2163	//	#version 460 core
2164	//	#extension GL_EXT_ray_query : require
2165	//	layout(r32ui, set = 0, binding = 0) uniform uimage3D result;
2166	//	layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;
2167	//
2168	//	void rayQueryInitializeBottomWrapper(rayQueryEXT rayQuery,
2169	//	       accelerationStructureEXT topLevel,
2170	//	       uint rayFlags, uint cullMask, vec3 origin,
2171	//	       float tMin, vec3 direction, float tMax)
2172	//	{
2173	//	  rayQueryInitializeEXT(rayQuery, topLevel, rayFlags, cullMask, origin, tMin, direction, tMax);
2174	//	}
2175	//
2176	//	void rayQueryInitializeTopWrapper(rayQueryEXT rayQuery,
2177	//	       accelerationStructureEXT topLevel,
2178	//	       uint rayFlags, uint cullMask, vec3 origin,
2179	//	       float tMin, vec3 direction, float tMax)
2180	//	{
2181	//	  rayQueryInitializeBottomWrapper(rayQuery, topLevel, rayFlags, cullMask, origin, tMin, direction, tMax);
2182	//	}
2183	//
2184	//	void main()
2185	//	{
2186	//	  vec3  origin   = vec3(float(gl_GlobalInvocationID.x) + 0.5, float(gl_GlobalInvocationID.y) + 0.5, 0.5);
2187	//	  uvec4 hitValue = uvec4(0,0,0,0);
2188	//	  float tmin     = 0.0;
2189	//	  float tmax     = 1.0;
2190	//	  vec3  direct   = vec3(0.0, 0.0, -1.0);
2191	//	  rayQueryEXT rq;
2192	//	  rayQueryInitializeTopWrapper(rq, rqTopLevelAS, 0, 0xFF, origin, tmin, direct, tmax);
2193	//	  if(rayQueryProceedEXT(rq))
2194	//	  {
2195	//	    if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionTriangleEXT)
2196	//	    {
2197	//	      hitValue.y = 1;
2198	//	      hitValue.x = 1;
2199	//	    }
2200	//	  }
2201	//	  imageStore(result, ivec3(gl_GlobalInvocationID.xy, 0), uvec4(hitValue.x, 0, 0, 0));
2202	//	  imageStore(result, ivec3(gl_GlobalInvocationID.xy, 1), uvec4(hitValue.y, 0, 0, 0));
2203	//	}
2204
2205	std::stringstream css;
2206	css
2207		<< "; SPIR-V\n"
2208		<< "; Version: 1.4\n"
2209		<< "; Generator: Khronos Glslang Reference Front End; 10\n"
2210		<< "; Bound: 139\n"
2211		<< "; Schema: 0\n"
2212		<< "OpCapability Shader\n"
2213		<< "OpCapability RayQueryKHR\n"
2214		<< "OpExtension \"SPV_KHR_ray_query\"\n"
2215		<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2216		<< "OpMemoryModel Logical GLSL450\n"
2217		<< "OpEntryPoint GLCompute %4 \"main\" %60 %86 %114\n"
2218		<< "OpExecutionMode %4 LocalSize 1 1 1\n"
2219		<< "OpDecorate %60 BuiltIn GlobalInvocationId\n"
2220		<< "OpDecorate %86 DescriptorSet 0\n"
2221		<< "OpDecorate %86 Binding 1\n"
2222		<< "OpDecorate %114 DescriptorSet 0\n"
2223		<< "OpDecorate %114 Binding 0\n"
2224		<< "%2 = OpTypeVoid\n"
2225		<< "%3 = OpTypeFunction %2\n"
2226
2227		// Bare query type
2228		<< "%6 = OpTypeRayQueryKHR\n"
2229
2230		// Pointer to query.
2231		<< "%7 = OpTypePointer Function %6\n"
2232
2233		// Bare AS type.
2234		<< "%8 = OpTypeAccelerationStructureKHR\n"
2235
2236		// Pointer to AS.
2237		<< "%9 = OpTypePointer UniformConstant %8\n"
2238
2239		<< "%10 = OpTypeInt 32 0\n"
2240		<< "%11 = OpTypePointer Function %10\n"
2241		<< "%12 = OpTypeFloat 32\n"
2242		<< "%13 = OpTypeVector %12 3\n"
2243		<< "%14 = OpTypePointer Function %13\n"
2244		<< "%15 = OpTypePointer Function %12\n"
2245
2246		// This is the function type for rayQueryInitializeTopWrapper and the old rayQueryInitializeBottomWrapper.
2247		<< "%16 = OpTypeFunction %2 %7 %9 %11 %11 %14 %15 %14 %15\n"
2248
2249		// This is the new function type for the modified rayQueryInitializeBottomWrapper that uses a bare AS.
2250		//<< "%16b = OpTypeFunction %2 %6 %8 %11 %11 %14 %15 %14 %15\n"
2251		<< "%16b = OpTypeFunction %2 %7 %8 %11 %11 %14 %15 %14 %15\n"
2252
2253		<< "%58 = OpTypeVector %10 3\n"
2254		<< "%59 = OpTypePointer Input %58\n"
2255		<< "%60 = OpVariable %59 Input\n"
2256		<< "%61 = OpConstant %10 0\n"
2257		<< "%62 = OpTypePointer Input %10\n"
2258		<< "%66 = OpConstant %12 0.5\n"
2259		<< "%68 = OpConstant %10 1\n"
2260		<< "%74 = OpTypeVector %10 4\n"
2261		<< "%75 = OpTypePointer Function %74\n"
2262		<< "%77 = OpConstantComposite %74 %61 %61 %61 %61\n"
2263		<< "%79 = OpConstant %12 0\n"
2264		<< "%81 = OpConstant %12 1\n"
2265		<< "%83 = OpConstant %12 -1\n"
2266		<< "%84 = OpConstantComposite %13 %79 %79 %83\n"
2267		<< "%86 = OpVariable %9 UniformConstant\n"
2268		<< "%87 = OpConstant %10 255\n"
2269		<< "%99 = OpTypeBool\n"
2270		<< "%103 = OpConstantFalse %99\n"
2271		<< "%104 = OpTypeInt 32 1\n"
2272		<< "%105 = OpConstant %104 0\n"
2273		<< "%112 = OpTypeImage %10 3D 0 0 0 2 R32ui\n"
2274		<< "%113 = OpTypePointer UniformConstant %112\n"
2275		<< "%114 = OpVariable %113 UniformConstant\n"
2276		<< "%116 = OpTypeVector %10 2\n"
2277		<< "%119 = OpTypeVector %104 2\n"
2278		<< "%121 = OpTypeVector %104 3\n"
2279		<< "%132 = OpConstant %104 1\n"
2280
2281		// This is main().
2282		<< "%4 = OpFunction %2 None %3\n"
2283		<< "%5 = OpLabel\n"
2284		<< "%57 = OpVariable %14 Function\n"
2285		<< "%76 = OpVariable %75 Function\n"
2286		<< "%78 = OpVariable %15 Function\n"
2287		<< "%80 = OpVariable %15 Function\n"
2288		<< "%82 = OpVariable %14 Function\n"
2289		<< "%85 = OpVariable %7 Function\n"
2290		<< "%88 = OpVariable %11 Function\n"
2291		<< "%89 = OpVariable %11 Function\n"
2292		<< "%90 = OpVariable %14 Function\n"
2293		<< "%92 = OpVariable %15 Function\n"
2294		<< "%94 = OpVariable %14 Function\n"
2295		<< "%96 = OpVariable %15 Function\n"
2296		<< "%63 = OpAccessChain %62 %60 %61\n"
2297		<< "%64 = OpLoad %10 %63\n"
2298		<< "%65 = OpConvertUToF %12 %64\n"
2299		<< "%67 = OpFAdd %12 %65 %66\n"
2300		<< "%69 = OpAccessChain %62 %60 %68\n"
2301		<< "%70 = OpLoad %10 %69\n"
2302		<< "%71 = OpConvertUToF %12 %70\n"
2303		<< "%72 = OpFAdd %12 %71 %66\n"
2304		<< "%73 = OpCompositeConstruct %13 %67 %72 %66\n"
2305		<< "OpStore %57 %73\n"
2306		<< "OpStore %76 %77\n"
2307		<< "OpStore %78 %79\n"
2308		<< "OpStore %80 %81\n"
2309		<< "OpStore %82 %84\n"
2310		<< "OpStore %88 %61\n"
2311		<< "OpStore %89 %87\n"
2312		<< "%91 = OpLoad %13 %57\n"
2313		<< "OpStore %90 %91\n"
2314		<< "%93 = OpLoad %12 %78\n"
2315		<< "OpStore %92 %93\n"
2316		<< "%95 = OpLoad %13 %82\n"
2317		<< "OpStore %94 %95\n"
2318		<< "%97 = OpLoad %12 %80\n"
2319		<< "OpStore %96 %97\n"
2320		<< "%98 = OpFunctionCall %2 %35 %85 %86 %88 %89 %90 %92 %94 %96\n"
2321		<< "%100 = OpRayQueryProceedKHR %99 %85\n"
2322		<< "OpSelectionMerge %102 None\n"
2323		<< "OpBranchConditional %100 %101 %102\n"
2324		<< "%101 = OpLabel\n"
2325		<< "%106 = OpRayQueryGetIntersectionTypeKHR %10 %85 %105\n"
2326		<< "%107 = OpIEqual %99 %106 %61\n"
2327		<< "OpSelectionMerge %109 None\n"
2328		<< "OpBranchConditional %107 %108 %109\n"
2329		<< "%108 = OpLabel\n"
2330		<< "%110 = OpAccessChain %11 %76 %68\n"
2331		<< "OpStore %110 %68\n"
2332		<< "%111 = OpAccessChain %11 %76 %61\n"
2333		<< "OpStore %111 %68\n"
2334		<< "OpBranch %109\n"
2335		<< "%109 = OpLabel\n"
2336		<< "OpBranch %102\n"
2337		<< "%102 = OpLabel\n"
2338		<< "%115 = OpLoad %112 %114\n"
2339		<< "%117 = OpLoad %58 %60\n"
2340		<< "%118 = OpVectorShuffle %116 %117 %117 0 1\n"
2341		<< "%120 = OpBitcast %119 %118\n"
2342		<< "%122 = OpCompositeExtract %104 %120 0\n"
2343		<< "%123 = OpCompositeExtract %104 %120 1\n"
2344		<< "%124 = OpCompositeConstruct %121 %122 %123 %105\n"
2345		<< "%125 = OpAccessChain %11 %76 %61\n"
2346		<< "%126 = OpLoad %10 %125\n"
2347		<< "%127 = OpCompositeConstruct %74 %126 %61 %61 %61\n"
2348		<< "OpImageWrite %115 %124 %127 ZeroExtend\n"
2349		<< "%128 = OpLoad %112 %114\n"
2350		<< "%129 = OpLoad %58 %60\n"
2351		<< "%130 = OpVectorShuffle %116 %129 %129 0 1\n"
2352		<< "%131 = OpBitcast %119 %130\n"
2353		<< "%133 = OpCompositeExtract %104 %131 0\n"
2354		<< "%134 = OpCompositeExtract %104 %131 1\n"
2355		<< "%135 = OpCompositeConstruct %121 %133 %134 %132\n"
2356		<< "%136 = OpAccessChain %11 %76 %68\n"
2357		<< "%137 = OpLoad %10 %136\n"
2358		<< "%138 = OpCompositeConstruct %74 %137 %61 %61 %61\n"
2359		<< "OpImageWrite %128 %135 %138 ZeroExtend\n"
2360		<< "OpReturn\n"
2361		<< "OpFunctionEnd\n"
2362
2363		// This is rayQueryInitializeBottomWrapper, calling OpRayQueryInitializeKHR.
2364		// We have modified the function type so it takes bare arguments.
2365		//%25 = OpFunction %2 None %16
2366		<< "%25 = OpFunction %2 None %16b\n"
2367
2368		// These is the modified parameter.
2369		<< "%17 = OpFunctionParameter %7\n"
2370		//<< "%17 = OpFunctionParameter %6\n"
2371		//%18 = OpFunctionParameter %9
2372		<< "%18 = OpFunctionParameter %8\n"
2373
2374		<< "%19 = OpFunctionParameter %11\n"
2375		<< "%20 = OpFunctionParameter %11\n"
2376		<< "%21 = OpFunctionParameter %14\n"
2377		<< "%22 = OpFunctionParameter %15\n"
2378		<< "%23 = OpFunctionParameter %14\n"
2379		<< "%24 = OpFunctionParameter %15\n"
2380		<< "%26 = OpLabel\n"
2381
2382		// We no longer need to load this parameter.
2383		//%37 = OpLoad %8 %18
2384
2385		<< "%38 = OpLoad %10 %19\n"
2386		<< "%39 = OpLoad %10 %20\n"
2387		<< "%40 = OpLoad %13 %21\n"
2388		<< "%41 = OpLoad %12 %22\n"
2389		<< "%42 = OpLoad %13 %23\n"
2390		<< "%43 = OpLoad %12 %24\n"
2391
2392		// We call OpRayQueryInitializeKHR with bare arguments.
2393		// Note: some experimental lines to pass a bare rayQuery as the first argument have been commented out.
2394		//OpRayQueryInitializeKHR %17 %37 %38 %39 %40 %41 %42 %43
2395		<< "OpRayQueryInitializeKHR %17 %18 %38 %39 %40 %41 %42 %43\n"
2396
2397		<< "OpReturn\n"
2398		<< "OpFunctionEnd\n"
2399
2400		// This is rayQueryInitializeTopWrapper, calling rayQueryInitializeBottomWrapper.
2401		<< "%35 = OpFunction %2 None %16\n"
2402		<< "%27 = OpFunctionParameter %7\n"
2403		<< "%28 = OpFunctionParameter %9\n"
2404		<< "%29 = OpFunctionParameter %11\n"
2405		<< "%30 = OpFunctionParameter %11\n"
2406		<< "%31 = OpFunctionParameter %14\n"
2407		<< "%32 = OpFunctionParameter %15\n"
2408		<< "%33 = OpFunctionParameter %14\n"
2409		<< "%34 = OpFunctionParameter %15\n"
2410		<< "%36 = OpLabel\n"
2411		<< "%44 = OpVariable %11 Function\n"
2412		<< "%46 = OpVariable %11 Function\n"
2413		<< "%48 = OpVariable %14 Function\n"
2414		<< "%50 = OpVariable %15 Function\n"
2415		<< "%52 = OpVariable %14 Function\n"
2416		<< "%54 = OpVariable %15 Function\n"
2417
2418		// We need to load the second argument.
2419		//<< "%27b = OpLoad %6 %27\n"
2420		<< "%28b = OpLoad %8 %28\n"
2421
2422		<< "%45 = OpLoad %10 %29\n"
2423		<< "OpStore %44 %45\n"
2424		<< "%47 = OpLoad %10 %30\n"
2425		<< "OpStore %46 %47\n"
2426		<< "%49 = OpLoad %13 %31\n"
2427		<< "OpStore %48 %49\n"
2428		<< "%51 = OpLoad %12 %32\n"
2429		<< "OpStore %50 %51\n"
2430		<< "%53 = OpLoad %13 %33\n"
2431		<< "OpStore %52 %53\n"
2432		<< "%55 = OpLoad %12 %34\n"
2433		<< "OpStore %54 %55\n"
2434
2435		// We call rayQueryInitializeBottomWrapper with the loaded argument.
2436		//%56 = OpFunctionCall %2 %25 %27 %28 %44 %46 %48 %50 %52 %54
2437		//<< "%56 = OpFunctionCall %2 %25 %27b %28b %44 %46 %48 %50 %52 %54\n"
2438		<< "%56 = OpFunctionCall %2 %25 %27 %28b %44 %46 %48 %50 %52 %54\n"
2439
2440		<< "OpReturn\n"
2441		<< "OpFunctionEnd\n"
2442		;
2443
2444	programCollection.spirvAsmSources.add("comp_as_triangle") << spvBuildOptions << css.str();
2445}
2446
2447RayQueryASBasicTestInstance::RayQueryASBasicTestInstance (Context& context, const TestParams& data)
2448	: vkt::TestInstance		(context)
2449	, m_data				(data)
2450{
2451}
2452
2453RayQueryASBasicTestInstance::~RayQueryASBasicTestInstance (void)
2454{
2455}
2456
2457de::MovePtr<BufferWithMemory> RayQueryASBasicTestInstance::runTest (TestConfiguration* testConfiguration,
2458																	SceneBuilder* sceneBuilder,
2459																	const deUint32 workerThreadsCount)
2460{
2461	testConfiguration->initConfiguration(m_context, m_data);
2462
2463	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
2464	const VkDevice						device								= m_context.getDevice();
2465	const VkQueue						queue								= m_context.getUniversalQueue();
2466	Allocator&							allocator							= m_context.getDefaultAllocator();
2467	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
2468
2469	const bool							htCopy								= (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
2470	const bool							htSerialize							= (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
2471
2472
2473	const VkFormat						imageFormat							= testConfiguration->getResultImageFormat();
2474	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, 2, imageFormat);
2475	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2476	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
2477	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
2478
2479	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(m_data.width * m_data.height * 2 * testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2480	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2481	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 2), resultBufferImageSubresourceLayers);
2482	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2483
2484	const VkDescriptorImageInfo			resultImageInfo						= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
2485
2486	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
2487	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2488
2489	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	bottomLevelAccelerationStructures;
2490	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
2491	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	bottomLevelAccelerationStructureCopies;
2492	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructureCopy;
2493	std::vector<de::SharedPtr<SerialStorage>>						bottomSerialized;
2494	std::vector<de::SharedPtr<SerialStorage>>						topSerialized;
2495	std::vector<VkDeviceSize>			accelerationCompactedSizes;
2496	std::vector<VkDeviceSize>			accelerationSerialSizes;
2497	Move<VkQueryPool>					m_queryPoolCompact;
2498	Move<VkQueryPool>					m_queryPoolSerial;
2499
2500	beginCommandBuffer(vkd, *cmdBuffer, 0u);
2501	{
2502		const VkImageMemoryBarrier			preImageBarrier					= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2503																					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2504																					**image, imageSubresourceRange);
2505		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
2506
2507		const VkClearValue					clearValue						= testConfiguration->getClearValue();
2508		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
2509
2510		const VkImageMemoryBarrier			postImageBarrier				= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
2511																				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2512																				**image, imageSubresourceRange);
2513		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
2514
2515		// build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
2516		bool									bottomCompact		= m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
2517		bool									bottomSerial		= m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
2518		const bool								buildWithoutGeom	= (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
2519		const bool								bottomNoPrimitives	= (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
2520		const bool								topNoPrimitives		= (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
2521		const bool								inactiveInstances	= (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
2522		bottomLevelAccelerationStructures							= sceneBuilder->initBottomAccelerationStructures(m_context, m_data);
2523		VkBuildAccelerationStructureFlagsKHR	allowCompactionFlag	= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
2524		VkBuildAccelerationStructureFlagsKHR	emptyCompactionFlag	= VkBuildAccelerationStructureFlagsKHR(0);
2525		VkBuildAccelerationStructureFlagsKHR	bottomCompactFlags	= (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
2526		VkBuildAccelerationStructureFlagsKHR	bottomBuildFlags	= m_data.buildFlags | bottomCompactFlags;
2527		std::vector<VkAccelerationStructureKHR>	accelerationStructureHandles;
2528		std::vector<VkDeviceSize>				bottomBlasCompactSize;
2529		std::vector<VkDeviceSize>				bottomBlasSerialSize;
2530
2531		for (auto& blas : bottomLevelAccelerationStructures)
2532		{
2533			blas->setBuildType						(m_data.buildType);
2534			blas->setBuildFlags						(bottomBuildFlags);
2535			blas->setUseArrayOfPointers				(m_data.bottomUsesAOP);
2536			blas->setCreateGeneric					(m_data.bottomGeneric);
2537			blas->setCreationBufferUnbounded		(m_data.bottomUnboundedCreation);
2538			blas->setBuildWithoutGeometries			(buildWithoutGeom);
2539			blas->setBuildWithoutPrimitives			(bottomNoPrimitives);
2540			blas->createAndBuild					(vkd, device, *cmdBuffer, allocator);
2541			accelerationStructureHandles.push_back	(*(blas->getPtr()));
2542		}
2543
2544		if (m_data.operationType == OP_COMPACT)
2545		{
2546			deUint32 queryCount	= (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
2547			if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2548				m_queryPoolCompact = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
2549			if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
2550				queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
2551		}
2552		if (m_data.operationType == OP_SERIALIZE)
2553		{
2554			deUint32 queryCount	= (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
2555			if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2556				m_queryPoolSerial = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
2557			if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
2558				queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
2559		}
2560
2561		// 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
2562		if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
2563		{
2564			endCommandBuffer(vkd, *cmdBuffer);
2565
2566			submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2567
2568			if (bottomCompact)
2569				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));
2570			if (bottomSerial)
2571				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));
2572
2573			vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2574			beginCommandBuffer(vkd, *cmdBuffer, 0u);
2575		}
2576
2577		auto bottomLevelAccelerationStructuresPtr								= &bottomLevelAccelerationStructures;
2578		if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
2579		{
2580			switch (m_data.operationType)
2581			{
2582			case OP_COPY:
2583			{
2584				for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2585				{
2586					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2587					asCopy->setDeferredOperation(htCopy, workerThreadsCount);
2588					asCopy->setBuildType(m_data.buildType);
2589					asCopy->setBuildFlags(m_data.buildFlags);
2590					asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2591					asCopy->setCreateGeneric(m_data.bottomGeneric);
2592					asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2593					asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2594					asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2595					asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), 0u, 0u);
2596					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2597				}
2598				break;
2599			}
2600			case OP_COMPACT:
2601			{
2602				for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2603				{
2604					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2605					asCopy->setBuildType(m_data.buildType);
2606					asCopy->setBuildFlags(m_data.buildFlags);
2607					asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2608					asCopy->setCreateGeneric(m_data.bottomGeneric);
2609					asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2610					asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2611					asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2612					asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
2613					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2614				}
2615				break;
2616			}
2617			case OP_SERIALIZE:
2618			{
2619				for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
2620				{
2621					de::SharedPtr<SerialStorage> storage(new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
2622
2623					bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
2624					bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
2625					bottomSerialized.push_back(storage);
2626
2627					if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2628					{
2629						endCommandBuffer(vkd, *cmdBuffer);
2630
2631						submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2632
2633						vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2634						beginCommandBuffer(vkd, *cmdBuffer, 0u);
2635					}
2636
2637					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
2638					asCopy->setBuildType(m_data.buildType);
2639					asCopy->setBuildFlags(m_data.buildFlags);
2640					asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
2641					asCopy->setCreateGeneric(m_data.bottomGeneric);
2642					asCopy->setCreationBufferUnbounded(m_data.bottomUnboundedCreation);
2643					asCopy->setBuildWithoutGeometries(buildWithoutGeom);
2644					asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
2645					asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2646					asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
2647					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
2648				}
2649				break;
2650			}
2651			default:
2652				DE_ASSERT(DE_FALSE);
2653			}
2654			bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
2655		}
2656
2657		// build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
2658		bool									topCompact			= m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
2659		bool									topSerial			= m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
2660		VkBuildAccelerationStructureFlagsKHR	topCompactFlags		= (topCompact ? allowCompactionFlag : emptyCompactionFlag);
2661		VkBuildAccelerationStructureFlagsKHR	topBuildFlags		= m_data.buildFlags | topCompactFlags;
2662		std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
2663		std::vector<VkDeviceSize>				topBlasCompactSize;
2664		std::vector<VkDeviceSize>				topBlasSerialSize;
2665
2666		topLevelAccelerationStructure								= sceneBuilder->initTopAccelerationStructure(m_context, m_data, *bottomLevelAccelerationStructuresPtr);
2667		topLevelAccelerationStructure->setBuildType					(m_data.buildType);
2668		topLevelAccelerationStructure->setBuildFlags				(topBuildFlags);
2669		topLevelAccelerationStructure->setBuildWithoutPrimitives	(topNoPrimitives);
2670		topLevelAccelerationStructure->setUseArrayOfPointers		(m_data.topUsesAOP);
2671		topLevelAccelerationStructure->setCreateGeneric				(m_data.topGeneric);
2672		topLevelAccelerationStructure->setCreationBufferUnbounded	(m_data.topUnboundedCreation);
2673		topLevelAccelerationStructure->setInactiveInstances			(inactiveInstances);
2674		topLevelAccelerationStructure->createAndBuild				(vkd, device, *cmdBuffer, allocator);
2675		topLevelStructureHandles.push_back							(*(topLevelAccelerationStructure->getPtr()));
2676
2677		if (topCompact)
2678			queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
2679		if (topSerial)
2680			queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
2681
2682		// 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
2683		if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
2684		{
2685			endCommandBuffer(vkd, *cmdBuffer);
2686
2687			submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2688
2689			if (topCompact)
2690				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));
2691			if (topSerial)
2692				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));
2693
2694			vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2695			beginCommandBuffer(vkd, *cmdBuffer, 0u);
2696		}
2697
2698		const TopLevelAccelerationStructure*			topLevelRayTracedPtr	= topLevelAccelerationStructure.get();
2699		if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
2700		{
2701			switch (m_data.operationType)
2702			{
2703				case OP_COPY:
2704				{
2705					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2706					topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2707					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2708					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2709					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2710					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2711					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2712					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2713					topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2714					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), 0u, 0u);
2715					break;
2716				}
2717				case OP_COMPACT:
2718				{
2719					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2720					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2721					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2722					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2723					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2724					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2725					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2726					topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2727					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
2728					break;
2729				}
2730				case OP_SERIALIZE:
2731				{
2732					de::SharedPtr<SerialStorage> storage(new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
2733
2734					topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
2735					topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
2736					topSerialized.push_back(storage);
2737
2738					if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2739					{
2740						endCommandBuffer(vkd, *cmdBuffer);
2741
2742						submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2743
2744						vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2745						beginCommandBuffer(vkd, *cmdBuffer, 0u);
2746					}
2747
2748					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2749					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2750					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2751					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2752					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2753					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2754					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2755					topLevelAccelerationStructureCopy->setCreationBufferUnbounded(m_data.topUnboundedCreation);
2756					topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
2757					topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
2758					break;
2759				}
2760				case OP_UPDATE:
2761				{
2762					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2763					topLevelAccelerationStructureCopy->create(vkd, device, allocator, 0u, 0u);
2764					// Update AS based on topLevelAccelerationStructure
2765					topLevelAccelerationStructureCopy->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2766					break;
2767				}
2768				case OP_UPDATE_IN_PLACE:
2769				{
2770					// Update in place
2771					topLevelAccelerationStructure->build(vkd, device, *cmdBuffer, topLevelAccelerationStructure.get());
2772					// Make a coppy
2773					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
2774					topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
2775					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
2776					topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
2777					topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
2778					topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
2779					topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
2780					topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
2781					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), 0u, 0u);
2782					break;
2783				}
2784				default:
2785					DE_ASSERT(DE_FALSE);
2786
2787			}
2788			topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
2789		}
2790
2791		const VkMemoryBarrier				preTraceMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
2792		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &preTraceMemoryBarrier);
2793
2794		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
2795		{
2796			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
2797			DE_NULL,															//  const void*							pNext;
2798			1u,																	//  deUint32							accelerationStructureCount;
2799			topLevelRayTracedPtr->getPtr(),										//  const VkAccelerationStructureKHR*	pAccelerationStructures;
2800		};
2801
2802		testConfiguration->fillCommandBuffer(m_context, m_data, *cmdBuffer, accelerationStructureWriteDescriptorSet, resultImageInfo);
2803
2804		const VkMemoryBarrier							postTestMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2805		const VkMemoryBarrier							postCopyMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2806		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTestMemoryBarrier);
2807
2808		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
2809
2810		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
2811	}
2812	endCommandBuffer(vkd, *cmdBuffer);
2813
2814	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2815
2816	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
2817
2818	return resultBuffer;
2819}
2820
2821bool RayQueryASBasicTestInstance::iterateNoWorkers (void)
2822{
2823	de::SharedPtr<TestConfiguration> testConfiguration	= createTestConfiguration(m_data.shaderSourcePipeline);
2824	de::SharedPtr<SceneBuilder> sceneBuilder			= de::SharedPtr<SceneBuilder>(new CheckerboardSceneBuilder());
2825
2826	const de::MovePtr<BufferWithMemory>	buffer		= runTest(testConfiguration.get(), sceneBuilder.get(), 0);
2827
2828	return testConfiguration->verifyImage(buffer.get(), m_context, m_data);
2829}
2830
2831bool RayQueryASBasicTestInstance::iterateWithWorkers (void)
2832{
2833	de::SharedPtr<SceneBuilder> sceneBuilder = de::SharedPtr<SceneBuilder>(new CheckerboardSceneBuilder());
2834
2835	de::SharedPtr<TestConfiguration> testConfigurationS		= createTestConfiguration(m_data.shaderSourcePipeline);
2836	de::MovePtr<BufferWithMemory>	singleThreadBufferCPU	= runTest(testConfigurationS.get(), sceneBuilder.get(), 0);
2837	const bool						singleThreadValidation	= testConfigurationS->verifyImage(singleThreadBufferCPU.get(), m_context, m_data);
2838	testConfigurationS.clear();
2839
2840	de::SharedPtr<TestConfiguration> testConfigurationM		= createTestConfiguration(m_data.shaderSourcePipeline);
2841	de::MovePtr<BufferWithMemory>	multiThreadBufferCPU	= runTest(testConfigurationM.get(), sceneBuilder.get(), m_data.workerThreadsCount);
2842	const bool						multiThreadValidation	= testConfigurationM->verifyImage(multiThreadBufferCPU.get(), m_context, m_data);
2843	testConfigurationM.clear();
2844
2845	const deUint32					result					= singleThreadValidation && multiThreadValidation;
2846
2847	return result;
2848}
2849
2850tcu::TestStatus RayQueryASBasicTestInstance::iterate(void)
2851{
2852	bool result;
2853	if (m_data.workerThreadsCount != 0)
2854		result = iterateWithWorkers();
2855	else
2856		result = iterateNoWorkers();
2857
2858	if (result)
2859		return tcu::TestStatus::pass("Pass");
2860	else
2861		return tcu::TestStatus::fail("Fail");
2862}
2863
2864// Tests dynamic indexing of acceleration structures
2865class RayQueryASDynamicIndexingTestCase : public TestCase
2866{
2867public:
2868						RayQueryASDynamicIndexingTestCase		(tcu::TestContext& context, const char* name);
2869						~RayQueryASDynamicIndexingTestCase		(void) = default;
2870
2871	void				checkSupport							(Context& context) const override;
2872	void				initPrograms							(SourceCollections& programCollection) const override;
2873	TestInstance*		createInstance							(Context& context) const override;
2874};
2875
2876class RayQueryASDynamicIndexingTestInstance : public TestInstance
2877{
2878public:
2879						RayQueryASDynamicIndexingTestInstance	(Context& context);
2880						~RayQueryASDynamicIndexingTestInstance	(void) = default;
2881	tcu::TestStatus		iterate									(void) override;
2882};
2883
2884RayQueryASDynamicIndexingTestCase::RayQueryASDynamicIndexingTestCase(tcu::TestContext& context, const char* name)
2885	: TestCase(context, name)
2886{
2887}
2888
2889void RayQueryASDynamicIndexingTestCase::checkSupport(Context& context) const
2890{
2891	commonASTestsCheckSupport(context);
2892	context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
2893}
2894
2895void RayQueryASDynamicIndexingTestCase::initPrograms(SourceCollections& programCollection) const
2896{
2897	const vk::SpirVAsmBuildOptions spvBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2898
2899	// compute shader is defined in spir-v as it requires possing pointer to TLAS that was read from ssbo;
2900	// original spir-v code was generated using following glsl code but resulting spir-v code was modiifed
2901
2902	// #version 460 core
2903	// #extension GL_EXT_ray_query : require
2904	// #extension GL_EXT_nonuniform_qualifier : enable
2905
2906	// #define ARRAY_SIZE 500
2907	// layout(set = 0, binding = 0) uniform accelerationStructureEXT tlasArray[ARRAY_SIZE];
2908	// layout(set = 0, binding = 1) readonly buffer topLevelASPointers {
2909	//     uvec2 ptr[];
2910	// } tlasPointers;
2911	// layout(set = 0, binding = 2) readonly buffer topLevelASIndices {
2912	//     uint idx[];
2913	// } tlasIndices;
2914	// layout(set = 0, binding = 3, std430) writeonly buffer Result {
2915	//     uint value[];
2916	// } result;
2917
2918	// void main()
2919	// {
2920	//   float tmin      = 0.0;
2921	//   float tmax      = 2.0;
2922	//   vec3  origin    = vec3(0.25f, 0.5f, 1.0);
2923	//   vec3  direction = vec3(0.0,0.0,-1.0);
2924	//   uint  tlasIndex = tlasIndices.idx[nonuniformEXT(gl_GlobalInvocationID.x)];
2925
2926	//   rayQueryEXT rq;
2927	//   rayQueryInitializeEXT(rq, tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, direction, tmax);
2928	//   atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x)], 2);
2929
2930	//   if (rayQueryProceedEXT(rq))
2931	//   {
2932	//     if (rayQueryGetIntersectionTypeEXT(rq, false) == gl_RayQueryCandidateIntersectionTriangleEXT)
2933	//       atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x + gl_NumWorkGroups.x)], 3);
2934	//   }
2935
2936	//   //rayQueryInitializeEXT(rq, tlasArray[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, direction, tmax);
2937	//   rayQueryInitializeEXT(rq, *tlasPointers.ptr[nonuniformEXT(tlasIndex)], gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, direction, tmax);
2938	//   atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x + gl_NumWorkGroups.x * 2)], 5);
2939
2940	//   if (rayQueryProceedEXT(rq))
2941	//   {
2942	//     if (rayQueryGetIntersectionTypeEXT(rq, false) == gl_RayQueryCandidateIntersectionTriangleEXT)
2943	//       atomicAdd(result.value[nonuniformEXT(gl_GlobalInvocationID.x + gl_NumWorkGroups.x * 3)], 7);
2944	//   }
2945	// }
2946
2947	const std::string compSource =
2948		"OpCapability Shader\n"
2949		"OpCapability RayQueryKHR\n"
2950		"OpCapability ShaderNonUniform\n"
2951		"OpExtension \"SPV_EXT_descriptor_indexing\"\n"
2952		"OpExtension \"SPV_KHR_ray_query\"\n"
2953		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2954		"OpMemoryModel Logical GLSL450\n"
2955		"OpEntryPoint GLCompute %4 \"main\" %var_index_ssbo %33 %var_as_arr_uni_ptr %64 %83 %var_as_pointers_ssbo\n"
2956		"OpExecutionMode %4 LocalSize 1 1 1\n"
2957		"OpDecorate %25 ArrayStride 4\n"
2958		"OpMemberDecorate %26 0 NonWritable\n"
2959		"OpMemberDecorate %26 0 Offset 0\n"
2960		"OpDecorate %26 Block\n"
2961		"OpDecorate %var_index_ssbo DescriptorSet 0\n"
2962		"OpDecorate %var_index_ssbo Binding 2\n"
2963		"OpDecorate %33 BuiltIn GlobalInvocationId\n"
2964		"OpDecorate %38 NonUniform\n"
2965		"OpDecorate %40 NonUniform\n"
2966		"OpDecorate %41 NonUniform\n"
2967		"OpDecorate %var_as_arr_uni_ptr DescriptorSet 0\n"
2968		"OpDecorate %var_as_arr_uni_ptr Binding 0\n"
2969		"OpDecorate %51 NonUniform\n"
2970		"OpDecorate %53 NonUniform\n"
2971		"OpDecorate %54 NonUniform\n"
2972		"OpDecorate %61 ArrayStride 4\n"
2973		"OpMemberDecorate %62 0 NonReadable\n"
2974		"OpMemberDecorate %62 0 Offset 0\n"
2975		"OpDecorate %62 Block\n"
2976		"OpDecorate %64 DescriptorSet 0\n"
2977		"OpDecorate %64 Binding 3\n"
2978		"OpDecorate %67 NonUniform\n"
2979		"OpDecorate %83 BuiltIn NumWorkgroups\n"
2980		"OpDecorate %87 NonUniform\n"
2981		"OpDecorate %as_index NonUniform\n"
2982		"OpDecorate %as_device_addres NonUniform\n"
2983		"OpDecorate %105 NonUniform\n"
2984		"OpDecorate %122 NonUniform\n"
2985		"OpDecorate %127 ArrayStride 8\n"
2986		"OpMemberDecorate %128 0 NonWritable\n"
2987		"OpMemberDecorate %128 0 Offset 0\n"
2988		"OpDecorate %128 Block\n"
2989		"OpDecorate %var_as_pointers_ssbo DescriptorSet 0\n"
2990		"OpDecorate %var_as_pointers_ssbo Binding 1\n"
2991		"%2							= OpTypeVoid\n"
2992		"%3							= OpTypeFunction %2\n"
2993		"%6							= OpTypeFloat 32\n"
2994		"%7							= OpTypePointer Function %6\n"
2995		"%9							= OpConstant %6 0\n"
2996		"%11						= OpConstant %6 2\n"
2997		"%12						= OpTypeVector %6 3\n"
2998		"%13						= OpTypePointer Function %12\n"
2999		"%15						= OpConstant %6 0.25\n"
3000		"%16						= OpConstant %6 0.5\n"
3001		"%17						= OpConstant %6 1\n"
3002		"%18						= OpConstantComposite %12 %15 %16 %17\n"
3003		"%20						= OpConstant %6 -1\n"
3004		"%21						= OpConstantComposite %12 %9 %9 %20\n"
3005		"%type_uint32				= OpTypeInt 32 0\n"
3006		"%23						= OpTypePointer Function %type_uint32\n"
3007		"%25						= OpTypeRuntimeArray %type_uint32\n"
3008		"%26						= OpTypeStruct %25\n"
3009		"%27						= OpTypePointer StorageBuffer %26\n"
3010		"%var_index_ssbo			= OpVariable %27 StorageBuffer\n"
3011		"%29						= OpTypeInt 32 1\n"
3012		"%c_int32_0					= OpConstant %29 0\n"
3013		"%31						= OpTypeVector %type_uint32 3\n"
3014		"%32						= OpTypePointer Input %31\n"
3015		"%33						= OpVariable %32 Input\n"
3016		"%34						= OpConstant %type_uint32 0\n"
3017		"%35						= OpTypePointer Input %type_uint32\n"
3018		"%type_uint32_ssbo_ptr		= OpTypePointer StorageBuffer %type_uint32\n"
3019		"%42						= OpTypeRayQueryKHR\n"
3020		"%43						= OpTypePointer Function %42\n"
3021		"%type_as					= OpTypeAccelerationStructureKHR\n"
3022		"%46						= OpConstant %type_uint32 500\n"
3023		"%type_as_arr				= OpTypeArray %type_as %46\n"
3024		"%type_as_arr_uni_ptr		= OpTypePointer UniformConstant %type_as_arr\n"
3025		"%var_as_arr_uni_ptr		= OpVariable %type_as_arr_uni_ptr UniformConstant\n"
3026		"%type_as_uni_ptr			= OpTypePointer UniformConstant %type_as\n"
3027		"%55						= OpConstant %type_uint32 16\n"
3028		"%56						= OpConstant %type_uint32 255\n"
3029		"%61						= OpTypeRuntimeArray %type_uint32\n"
3030		"%62						= OpTypeStruct %61\n"
3031		"%63						= OpTypePointer StorageBuffer %62\n"
3032		"%64						= OpVariable %63 StorageBuffer\n"
3033		"%69						= OpConstant %type_uint32 2\n"
3034		"%70						= OpConstant %type_uint32 1\n"
3035		"%72						= OpTypeBool\n"
3036		"%76						= OpConstantFalse %72\n"
3037		"%83						= OpVariable %32 Input\n"
3038		"%89						= OpConstant %type_uint32 3\n"
3039		"%107						= OpConstant %type_uint32 5\n"
3040		"%124						= OpConstant %type_uint32 7\n"
3041
3042		// <changed_section>
3043		"%v2uint					= OpTypeVector %type_uint32 2\n"
3044		"%127						= OpTypeRuntimeArray %v2uint\n"
3045		"%128						= OpTypeStruct %127\n"
3046		"%129						= OpTypePointer StorageBuffer %128\n"
3047		"%var_as_pointers_ssbo		= OpVariable %129 StorageBuffer\n"
3048		"%type_uint64_ssbo_ptr		= OpTypePointer StorageBuffer %v2uint\n"
3049		// </changed_section>
3050
3051		// void main()
3052		"%4							= OpFunction %2 None %3\n"
3053		"%5							= OpLabel\n"
3054		"%8							= OpVariable %7 Function\n"
3055		"%10						= OpVariable %7 Function\n"
3056		"%14						= OpVariable %13 Function\n"
3057		"%19						= OpVariable %13 Function\n"
3058		"%24						= OpVariable %23 Function\n"
3059		"%var_ray_query				= OpVariable %43 Function\n"
3060		"OpStore %8 %9\n"
3061		"OpStore %10 %11\n"
3062		"OpStore %14 %18\n"
3063		"OpStore %19 %21\n"
3064		"%36						= OpAccessChain %35 %33 %34\n"
3065		"%37						= OpLoad %type_uint32 %36\n"
3066		"%38						= OpCopyObject %type_uint32 %37\n"
3067		"%40						= OpAccessChain %type_uint32_ssbo_ptr %var_index_ssbo %c_int32_0 %38\n"
3068		"%41						= OpLoad %type_uint32 %40\n"
3069		"OpStore %24 %41\n"
3070
3071		// rayQueryInitializeEXT using AS that was read from array
3072		"%50						= OpLoad %type_uint32 %24\n"
3073		"%51						= OpCopyObject %type_uint32 %50\n"
3074		"%53						= OpAccessChain %type_as_uni_ptr %var_as_arr_uni_ptr %51\n"
3075		"%54						= OpLoad %type_as %53\n"
3076		"%57						= OpLoad %12 %14\n"
3077		"%58						= OpLoad %6 %8\n"
3078		"%59						= OpLoad %12 %19\n"
3079		"%60						= OpLoad %6 %10\n"
3080		"OpRayQueryInitializeKHR %var_ray_query %54 %55 %56 %57 %58 %59 %60\n"
3081
3082		"%65						= OpAccessChain %35 %33 %34\n"
3083		"%66						= OpLoad %type_uint32 %65\n"
3084		"%67						= OpCopyObject %type_uint32 %66\n"
3085		"%68						= OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %67\n"
3086		"%71						= OpAtomicIAdd %type_uint32 %68 %70 %34 %69\n"
3087
3088		"%73						= OpRayQueryProceedKHR %72 %var_ray_query\n"
3089		"OpSelectionMerge %75 None\n"
3090		"OpBranchConditional %73 %74 %75\n"
3091		"%74						= OpLabel\n"
3092
3093		"%77						= OpRayQueryGetIntersectionTypeKHR %type_uint32 %var_ray_query %c_int32_0\n"
3094		"%78						= OpIEqual %72 %77 %34\n"
3095		"OpSelectionMerge %80 None\n"
3096		"OpBranchConditional %78 %79 %80\n"
3097		"%79						= OpLabel\n"
3098		"%81						= OpAccessChain %35 %33 %34\n"
3099		"%82						= OpLoad %type_uint32 %81\n"
3100		"%84						= OpAccessChain %35 %83 %34\n"
3101		"%85						= OpLoad %type_uint32 %84\n"
3102		"%86						= OpIAdd %type_uint32 %82 %85\n"
3103		"%87						= OpCopyObject %type_uint32 %86\n"
3104		"%88						= OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %87\n"
3105		"%90						= OpAtomicIAdd %type_uint32 %88 %70 %34 %89\n"
3106		"OpBranch %80\n"
3107		"%80						= OpLabel\n"
3108		"OpBranch %75\n"
3109		"%75						= OpLabel\n"
3110
3111		// rayQueryInitializeEXT using pointer to AS
3112		"%91						= OpLoad %type_uint32 %24\n"
3113		"%as_index					= OpCopyObject %type_uint32 %91\n"
3114
3115		// <changed_section>
3116		"%as_device_addres_ptr		= OpAccessChain %type_uint64_ssbo_ptr %var_as_pointers_ssbo %c_int32_0 %as_index\n"
3117		"%as_device_addres			= OpLoad %v2uint %as_device_addres_ptr\n"
3118		"%as_to_use					= OpConvertUToAccelerationStructureKHR %type_as %as_device_addres\n"
3119		// </changed_section>
3120
3121		"%95						= OpLoad %12 %14\n"
3122		"%96						= OpLoad %6 %8\n"
3123		"%97						= OpLoad %12 %19\n"
3124		"%98						= OpLoad %6 %10\n"
3125		"OpRayQueryInitializeKHR %var_ray_query %as_to_use %55 %56 %95 %96 %97 %98\n"
3126
3127		"%99						= OpAccessChain %35 %33 %34\n"
3128		"%100						= OpLoad %type_uint32 %99\n"
3129		"%101						= OpAccessChain %35 %83 %34\n"
3130		"%102						= OpLoad %type_uint32 %101\n"
3131		"%103						= OpIMul %type_uint32 %102 %69\n"
3132		"%104						= OpIAdd %type_uint32 %100 %103\n"
3133		"%105						= OpCopyObject %type_uint32 %104\n"
3134		"%106						= OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %105\n"
3135		"%108						= OpAtomicIAdd %type_uint32 %106 %70 %34 %107\n"
3136
3137		"%109						= OpRayQueryProceedKHR %72 %var_ray_query\n"
3138		"OpSelectionMerge %111 None\n"
3139		"OpBranchConditional %109 %110 %111\n"
3140		"%110						= OpLabel\n"
3141
3142		"%112						= OpRayQueryGetIntersectionTypeKHR %type_uint32 %var_ray_query %c_int32_0\n"
3143		"%113						= OpIEqual %72 %112 %34\n"
3144		"OpSelectionMerge %115 None\n"
3145		"OpBranchConditional %113 %114 %115\n"
3146		"%114						= OpLabel\n"
3147		"%116						= OpAccessChain %35 %33 %34\n"
3148		"%117						= OpLoad %type_uint32 %116\n"
3149		"%118						= OpAccessChain %35 %83 %34\n"
3150		"%119						= OpLoad %type_uint32 %118\n"
3151		"%120						= OpIMul %type_uint32 %119 %89\n"
3152		"%121						= OpIAdd %type_uint32 %117 %120\n"
3153		"%122						= OpCopyObject %type_uint32 %121\n"
3154		"%123						= OpAccessChain %type_uint32_ssbo_ptr %64 %c_int32_0 %122\n"
3155		"%125						= OpAtomicIAdd %type_uint32 %123 %70 %34 %124\n"
3156		"OpBranch %115\n"
3157		"%115						= OpLabel\n"
3158		"OpBranch %111\n"
3159		"%111						= OpLabel\n"
3160		"OpReturn\n"
3161		"OpFunctionEnd\n";
3162
3163	programCollection.spirvAsmSources.add("comp") << compSource << spvBuildOptions;
3164}
3165
3166TestInstance* RayQueryASDynamicIndexingTestCase::createInstance(Context& context) const
3167{
3168	return new RayQueryASDynamicIndexingTestInstance(context);
3169}
3170
3171
3172RayQueryASDynamicIndexingTestInstance::RayQueryASDynamicIndexingTestInstance(Context& context)
3173	: vkt::TestInstance(context)
3174{
3175}
3176
3177tcu::TestStatus RayQueryASDynamicIndexingTestInstance::iterate(void)
3178{
3179	const DeviceInterface&		vkd							= m_context.getDeviceInterface();
3180	const VkDevice				device						= m_context.getDevice();
3181	const deUint32				queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
3182	const VkQueue				queue						= m_context.getUniversalQueue();
3183	Allocator&					allocator					= m_context.getDefaultAllocator();
3184	const deUint32				tlasCount					= 500;	// changing this will require also changing shaders
3185	const deUint32				activeTlasCount				= 32;	// number of tlas out of <tlasCount> that will be active
3186
3187	const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
3188		.addArrayBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, VK_SHADER_STAGE_COMPUTE_BIT)
3189		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)			// pointers to all acceleration structures
3190		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)			// ssbo with indices of all acceleration structures
3191		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)			// ssbo with result values
3192		.build(vkd, device);
3193
3194	const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
3195		.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount)
3196		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3197		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3198		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3199		.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
3200	const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
3201
3202	const Move<VkPipelineLayout>		pipelineLayout		= makePipelineLayout(vkd, device, descriptorSetLayout.get());
3203	Move<VkShaderModule>				shaderModule		= createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
3204	const VkComputePipelineCreateInfo	pipelineCreateInfo
3205	{
3206		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType						sType
3207		DE_NULL,												// const void*							pNext
3208		0u,														// VkPipelineCreateFlags				flags
3209		{														// VkPipelineShaderStageCreateInfo		stage
3210			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
3211			DE_NULL,
3212			(VkPipelineShaderStageCreateFlags)0,
3213			VK_SHADER_STAGE_COMPUTE_BIT,
3214			*shaderModule,
3215			"main",
3216			DE_NULL
3217		},
3218		*pipelineLayout,										// VkPipelineLayout						layout
3219		DE_NULL,												// VkPipeline							basePipelineHandle
3220		0,														// deInt32								basePipelineIndex
3221	};
3222
3223	Move<VkPipeline>				pipeline				= createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo);
3224
3225	const VkDeviceSize				pointerBufferSize		= tlasCount * sizeof(VkDeviceAddress);
3226	const VkBufferCreateInfo		pointerBufferCreateInfo = makeBufferCreateInfo(pointerBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3227	de::MovePtr<BufferWithMemory>	pointerBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, pointerBufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
3228
3229	const VkDeviceSize				indicesBufferSize		= activeTlasCount * sizeof(deUint32);
3230	const VkBufferCreateInfo		indicesBufferCreateInfo = makeBufferCreateInfo(indicesBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3231	de::MovePtr<BufferWithMemory>	indicesBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, indicesBufferCreateInfo, MemoryRequirement::HostVisible));
3232
3233	const VkDeviceSize				resultBufferSize		= activeTlasCount * sizeof(deUint32) * 4;
3234	const VkBufferCreateInfo		resultBufferCreateInfo	= makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
3235	de::MovePtr<BufferWithMemory>	resultBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3236
3237	const Move<VkCommandPool>		cmdPool					= createCommandPool(vkd, device, 0, queueFamilyIndex);
3238	const Move<VkCommandBuffer>		cmdBuffer				= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3239
3240	de::SharedPtr<BottomLevelAccelerationStructure>				blas = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3241	std::vector<de::MovePtr<TopLevelAccelerationStructure>>		tlasVect(tlasCount);
3242	std::vector<VkDeviceAddress>								tlasPtrVect(tlasCount);
3243	std::vector<VkAccelerationStructureKHR>						tlasVkVect;
3244
3245	// randomly scatter AS indices across the range (number of them should be equal to the max subgroup size)
3246	deRandom rnd;
3247	deRandom_init(&rnd, 123);
3248	std::set<deUint32> asIndicesSet;
3249	while (asIndicesSet.size() < activeTlasCount)
3250		asIndicesSet.insert(deRandom_getUint32(&rnd) % tlasCount);
3251
3252	// fill indices buffer
3253	deUint32 helperIndex = 0;
3254	auto& indicesBufferAlloc = indicesBuffer->getAllocation();
3255	deUint32* indicesBufferPtr = reinterpret_cast<deUint32*>(indicesBufferAlloc.getHostPtr());
3256	std::for_each(asIndicesSet.begin(), asIndicesSet.end(),
3257		[&helperIndex, indicesBufferPtr](const deUint32& index)
3258		{
3259			indicesBufferPtr[helperIndex++] = index;
3260		});
3261	vk::flushAlloc(vkd, device, indicesBufferAlloc);
3262
3263	// clear result buffer
3264	auto& resultBufferAlloc = resultBuffer->getAllocation();
3265	void* resultBufferPtr = resultBufferAlloc.getHostPtr();
3266	deMemset(resultBufferPtr, 0, static_cast<size_t>(resultBufferSize));
3267	vk::flushAlloc(vkd, device, resultBufferAlloc);
3268
3269	beginCommandBuffer(vkd, *cmdBuffer, 0u);
3270	{
3271		// build bottom level acceleration structure
3272		blas->setGeometryData(
3273			{
3274				{ 0.0, 0.0, 0.0 },
3275				{ 1.0, 0.0, 0.0 },
3276				{ 0.0, 1.0, 0.0 },
3277			},
3278			true,
3279			0u
3280			);
3281
3282		blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3283
3284		// build top level acceleration structures
3285		for (deUint32 tlasIndex = 0; tlasIndex < tlasCount; ++tlasIndex)
3286		{
3287			auto& tlas = tlasVect[tlasIndex];
3288			tlas = makeTopLevelAccelerationStructure();
3289			tlas->setInstanceCount(1);
3290			tlas->addInstance(blas);
3291			if (!asIndicesSet.count(tlasIndex))
3292			{
3293				// tlas that are not in asIndicesSet should be empty but it is hard to do
3294				// that with current cts utils so we are marking them as inactive instead
3295				tlas->setInactiveInstances(true);
3296			}
3297			tlas->createAndBuild(vkd, device, *cmdBuffer, allocator);
3298
3299			// get acceleration structure device address
3300			const VkAccelerationStructureDeviceAddressInfoKHR addressInfo =
3301			{
3302				VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType				sType
3303				DE_NULL,															// const void*					pNext
3304				*tlas->getPtr()														// VkAccelerationStructureKHR	accelerationStructure
3305			};
3306			VkDeviceAddress vkda = vkd.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
3307			tlasPtrVect[tlasIndex] = vkda;
3308		}
3309
3310		// fill pointer buffer
3311		vkd.cmdUpdateBuffer(*cmdBuffer, **pointerBuffer, 0, pointerBufferSize, tlasPtrVect.data());
3312
3313		// wait for data transfers
3314		const VkMemoryBarrier uploadBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
3315		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, &uploadBarrier, 1u);
3316
3317		// wait for as build
3318		const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
3319		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, &asBuildBarrier, 1u);
3320
3321		tlasVkVect.reserve(tlasCount);
3322		for (auto& tlas : tlasVect)
3323			tlasVkVect.push_back(*tlas->getPtr());
3324
3325		VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
3326		{
3327			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	// VkStructureType						sType;
3328			DE_NULL,															// const void*							pNext;
3329			tlasCount,															// deUint32								accelerationStructureCount;
3330			tlasVkVect.data(),													// const VkAccelerationStructureKHR*	pAccelerationStructures;
3331		};
3332
3333		const vk::VkDescriptorBufferInfo pointerBufferInfo	= makeDescriptorBufferInfo(**pointerBuffer, 0u, VK_WHOLE_SIZE);
3334		const vk::VkDescriptorBufferInfo indicesBufferInfo	= makeDescriptorBufferInfo(**indicesBuffer, 0u, VK_WHOLE_SIZE);
3335		const vk::VkDescriptorBufferInfo resultInfo			= makeDescriptorBufferInfo(**resultBuffer,  0u, VK_WHOLE_SIZE);
3336
3337		DescriptorSetUpdateBuilder()
3338			.writeArray (*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, tlasCount, &accelerationStructureWriteDescriptorSet)
3339			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &pointerBufferInfo)
3340			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indicesBufferInfo)
3341			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo)
3342			.update(vkd, device);
3343
3344		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
3345
3346		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
3347
3348		vkd.cmdDispatch(*cmdBuffer, activeTlasCount, 1, 1);
3349
3350		const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
3351		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
3352	}
3353	endCommandBuffer(vkd, *cmdBuffer);
3354
3355	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
3356
3357	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), resultBufferSize);
3358
3359	// verify result buffer
3360	deUint32		failures = 0;
3361	const deUint32*	resultPtr = reinterpret_cast<deUint32*>(resultBuffer->getAllocation().getHostPtr());
3362	for (deUint32 index = 0; index < activeTlasCount; ++index)
3363	{
3364		failures += (resultPtr[0 * activeTlasCount + index] != 2) +
3365					(resultPtr[1 * activeTlasCount + index] != 3) +
3366					(resultPtr[2 * activeTlasCount + index] != 5) +
3367					(resultPtr[3 * activeTlasCount + index] != 7);
3368	}
3369
3370	if (failures)
3371		return tcu::TestStatus::fail(de::toString(failures) + " failures, " + de::toString(4 * activeTlasCount - failures) + " are ok");
3372	return tcu::TestStatus::pass("Pass");
3373}
3374
3375}	// anonymous
3376
3377/********************/
3378
3379void addBasicBuildingTests(tcu::TestCaseGroup* group)
3380{
3381	struct ShaderSourceTypeData
3382	{
3383		ShaderSourceType						shaderSourceType;
3384		ShaderSourcePipeline					shaderSourcePipeline;
3385		const char*								name;
3386	} shaderSourceTypes[] =
3387	{
3388		{ SST_FRAGMENT_SHADER,					SSP_GRAPHICS_PIPELINE,		"fragment_shader",			},
3389		{ SST_COMPUTE_SHADER,					SSP_COMPUTE_PIPELINE,		"compute_shader",			},
3390		{ SST_CLOSEST_HIT_SHADER,				SSP_RAY_TRACING_PIPELINE,	"chit_shader",				},
3391	};
3392
3393	struct
3394	{
3395		vk::VkAccelerationStructureBuildTypeKHR	buildType;
3396		const char*								name;
3397	} buildTypes[] =
3398	{
3399		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,				"cpu_built"	},
3400		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,				"gpu_built"	},
3401	};
3402
3403	struct
3404	{
3405		BottomTestType							testType;
3406		bool									usesAOP;
3407		const char*								name;
3408	} bottomTestTypes[] =
3409	{
3410		{ BottomTestType::TRIANGLES,	false,							"triangles" },
3411		{ BottomTestType::TRIANGLES,	true,							"triangles_aop" },
3412		{ BottomTestType::AABBS,		false,							"aabbs" },
3413		{ BottomTestType::AABBS,		true,							"aabbs_aop" },
3414	};
3415
3416	struct
3417	{
3418		TopTestType								testType;
3419		bool									usesAOP;
3420		const char*								name;
3421	} topTestTypes[] =
3422	{
3423		{ TopTestType::IDENTICAL_INSTANCES,	false,						"identical_instances" },
3424		{ TopTestType::IDENTICAL_INSTANCES,	true,						"identical_instances_aop" },
3425		{ TopTestType::DIFFERENT_INSTANCES,	false,						"different_instances" },
3426		{ TopTestType::DIFFERENT_INSTANCES,	true,						"different_instances_aop" },
3427	};
3428
3429	struct BuildFlagsData
3430	{
3431		VkBuildAccelerationStructureFlagsKHR	flags;
3432		const char*								name;
3433	};
3434
3435	BuildFlagsData optimizationTypes[] =
3436	{
3437		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
3438		{ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,	"fasttrace" },
3439		{ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR,	"fastbuild" },
3440	};
3441
3442	BuildFlagsData updateTypes[] =
3443	{
3444		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
3445		{ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,			"update" },
3446	};
3447
3448	BuildFlagsData compactionTypes[] =
3449	{
3450		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
3451		{ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR,		"compaction" },
3452	};
3453
3454	BuildFlagsData lowMemoryTypes[] =
3455	{
3456		{ VkBuildAccelerationStructureFlagsKHR(0u),						"0" },
3457		{ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR,			"lowmemory" },
3458	};
3459
3460	struct
3461	{
3462		bool		padVertices;
3463		const char*	name;
3464	} paddingType[] =
3465	{
3466		{ false,	"nopadding"	},
3467		{ true,		"padded"	},
3468	};
3469
3470	struct
3471	{
3472		bool		topGeneric;
3473		bool		bottomGeneric;
3474		const char*	suffix;
3475	} createGenericParams[] =
3476	{
3477		{	false,	false,	""					},
3478		{	false,	true,	"_bottomgeneric"	},
3479		{	true,	false,	"_topgeneric"		},
3480		{	true,	true,	"_bothgeneric"		},
3481	};
3482
3483	// In order not to create thousands of new test variants for unbound buffer memory on acceleration structure creation, we will
3484	// set these options on some of the tests.
3485	de::ModCounter32 unboundedCreationBottomCounter	(3u);
3486	de::ModCounter32 unboundedCreationTopCounter	(7u);
3487
3488	for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
3489	{
3490		de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name));
3491
3492		for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3493		{
3494			de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
3495
3496			for (size_t bottomNdx = 0; bottomNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++bottomNdx)
3497			{
3498				de::MovePtr<tcu::TestCaseGroup> bottomGroup(new tcu::TestCaseGroup(group->getTestContext(), bottomTestTypes[bottomNdx].name));
3499
3500				for (size_t topNdx = 0; topNdx < DE_LENGTH_OF_ARRAY(topTestTypes); ++topNdx)
3501				{
3502					de::MovePtr<tcu::TestCaseGroup> topGroup(new tcu::TestCaseGroup(group->getTestContext(), topTestTypes[topNdx].name));
3503
3504					for (int paddingTypeIdx = 0; paddingTypeIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingTypeIdx)
3505					{
3506						de::MovePtr<tcu::TestCaseGroup> paddingTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingTypeIdx].name));
3507
3508						for (size_t optimizationNdx = 0; optimizationNdx < DE_LENGTH_OF_ARRAY(optimizationTypes); ++optimizationNdx)
3509						{
3510							for (size_t updateNdx = 0; updateNdx < DE_LENGTH_OF_ARRAY(updateTypes); ++updateNdx)
3511							{
3512								for (size_t compactionNdx = 0; compactionNdx < DE_LENGTH_OF_ARRAY(compactionTypes); ++compactionNdx)
3513								{
3514									for (size_t lowMemoryNdx = 0; lowMemoryNdx < DE_LENGTH_OF_ARRAY(lowMemoryTypes); ++lowMemoryNdx)
3515									{
3516										for (int createGenericIdx = 0; createGenericIdx < DE_LENGTH_OF_ARRAY(createGenericParams); ++createGenericIdx)
3517										{
3518											std::string testName =
3519												std::string(optimizationTypes[optimizationNdx].name) + "_" +
3520												std::string(updateTypes[updateNdx].name) + "_" +
3521												std::string(compactionTypes[compactionNdx].name) + "_" +
3522												std::string(lowMemoryTypes[lowMemoryNdx].name) +
3523												std::string(createGenericParams[createGenericIdx].suffix);
3524
3525											const bool unboundedCreationBottom	= (static_cast<uint32_t>(unboundedCreationBottomCounter++) == 0u);
3526											const bool unboundedCreationTop		= (static_cast<uint32_t>(unboundedCreationTopCounter++) == 0u);
3527
3528											TestParams testParams
3529											{
3530												shaderSourceTypes[shaderSourceNdx].shaderSourceType,
3531												shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
3532												buildTypes[buildTypeNdx].buildType,
3533												VK_FORMAT_R32G32B32_SFLOAT,
3534												paddingType[paddingTypeIdx].padVertices,
3535												VK_INDEX_TYPE_NONE_KHR,
3536												bottomTestTypes[bottomNdx].testType,
3537												InstanceCullFlags::NONE,
3538												bottomTestTypes[bottomNdx].usesAOP,
3539												createGenericParams[createGenericIdx].bottomGeneric,
3540												unboundedCreationBottom,
3541												topTestTypes[topNdx].testType,
3542												topTestTypes[topNdx].usesAOP,
3543												createGenericParams[createGenericIdx].topGeneric,
3544												unboundedCreationTop,
3545												optimizationTypes[optimizationNdx].flags | updateTypes[updateNdx].flags | compactionTypes[compactionNdx].flags | lowMemoryTypes[lowMemoryNdx].flags,
3546												OT_NONE,
3547												OP_NONE,
3548												TEST_WIDTH,
3549												TEST_HEIGHT,
3550												0u,
3551												EmptyAccelerationStructureCase::NOT_EMPTY,
3552											};
3553											paddingTypeGroup->addChild(new RayQueryASBasicTestCase(group->getTestContext(), testName.c_str(), testParams));
3554										}
3555									}
3556								}
3557							}
3558						}
3559						topGroup->addChild(paddingTypeGroup.release());
3560					}
3561					bottomGroup->addChild(topGroup.release());
3562				}
3563				buildGroup->addChild(bottomGroup.release());
3564			}
3565			sourceTypeGroup->addChild(buildGroup.release());
3566		}
3567		group->addChild(sourceTypeGroup.release());
3568	}
3569}
3570
3571void addVertexIndexFormatsTests(tcu::TestCaseGroup* group)
3572{
3573	struct ShaderSourceTypeData
3574	{
3575		ShaderSourceType						shaderSourceType;
3576		ShaderSourcePipeline					shaderSourcePipeline;
3577		const char*								name;
3578	} shaderSourceTypes[] =
3579	{
3580		{ SST_VERTEX_SHADER,					SSP_GRAPHICS_PIPELINE,		"vertex_shader"				},
3581		{ SST_TESSELATION_CONTROL_SHADER,		SSP_GRAPHICS_PIPELINE,		"tess_control_shader"		},
3582		{ SST_TESSELATION_EVALUATION_SHADER,	SSP_GRAPHICS_PIPELINE,		"tess_evaluation_shader"	},
3583		{ SST_GEOMETRY_SHADER,					SSP_GRAPHICS_PIPELINE,		"geometry_shader",			},
3584		{ SST_FRAGMENT_SHADER,					SSP_GRAPHICS_PIPELINE,		"fragment_shader",			},
3585		{ SST_COMPUTE_SHADER,					SSP_COMPUTE_PIPELINE,		"compute_shader",			},
3586		{ SST_RAY_GENERATION_SHADER,			SSP_RAY_TRACING_PIPELINE,	"rgen_shader",				},
3587		{ SST_INTERSECTION_SHADER,				SSP_RAY_TRACING_PIPELINE,	"isect_shader",				},
3588		{ SST_ANY_HIT_SHADER,					SSP_RAY_TRACING_PIPELINE,	"ahit_shader",				},
3589		{ SST_CLOSEST_HIT_SHADER,				SSP_RAY_TRACING_PIPELINE,	"chit_shader",				},
3590		{ SST_MISS_SHADER,						SSP_RAY_TRACING_PIPELINE,	"miss_shader",				},
3591		{ SST_CALLABLE_SHADER,					SSP_RAY_TRACING_PIPELINE,	"call_shader",				},
3592	};
3593
3594	struct
3595	{
3596		vk::VkAccelerationStructureBuildTypeKHR				buildType;
3597		const char*											name;
3598	} buildTypes[] =
3599	{
3600		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
3601		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
3602	};
3603
3604	const VkFormat vertexFormats[] =
3605	{
3606		// Mandatory formats.
3607		VK_FORMAT_R32G32_SFLOAT,
3608		VK_FORMAT_R32G32B32_SFLOAT,
3609		VK_FORMAT_R16G16_SFLOAT,
3610		VK_FORMAT_R16G16B16A16_SFLOAT,
3611		VK_FORMAT_R16G16_SNORM,
3612		VK_FORMAT_R16G16B16A16_SNORM,
3613
3614		// Additional formats.
3615		VK_FORMAT_R8G8_SNORM,
3616		VK_FORMAT_R8G8B8_SNORM,
3617		VK_FORMAT_R8G8B8A8_SNORM,
3618		VK_FORMAT_R16G16B16_SNORM,
3619		VK_FORMAT_R16G16B16_SFLOAT,
3620		VK_FORMAT_R32G32B32A32_SFLOAT,
3621		VK_FORMAT_R64G64_SFLOAT,
3622		VK_FORMAT_R64G64B64_SFLOAT,
3623		VK_FORMAT_R64G64B64A64_SFLOAT,
3624	};
3625
3626	struct
3627	{
3628		VkIndexType								indexType;
3629		const char*								name;
3630	} indexFormats[] =
3631	{
3632		{ VK_INDEX_TYPE_NONE_KHR ,				"index_none"	},
3633		{ VK_INDEX_TYPE_UINT16 ,				"index_uint16"	},
3634		{ VK_INDEX_TYPE_UINT32 ,				"index_uint32"	},
3635	};
3636
3637	struct
3638	{
3639		bool		padVertices;
3640		const char*	name;
3641	} paddingType[] =
3642	{
3643		{ false,	"nopadding"	},
3644		{ true,		"padded"	},
3645	};
3646
3647	for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
3648	{
3649		de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name));
3650
3651		for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3652		{
3653			de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
3654
3655			for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
3656			{
3657				const auto format		= vertexFormats[vertexFormatNdx];
3658				const auto formatName	= getFormatSimpleName(format);
3659
3660				de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str()));
3661
3662				for (int paddingIdx = 0; paddingIdx < DE_LENGTH_OF_ARRAY(paddingType); ++paddingIdx)
3663				{
3664					de::MovePtr<tcu::TestCaseGroup> paddingGroup(new tcu::TestCaseGroup(group->getTestContext(), paddingType[paddingIdx].name));
3665
3666					for (size_t indexFormatNdx = 0; indexFormatNdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatNdx)
3667					{
3668						TestParams testParams
3669						{
3670							shaderSourceTypes[shaderSourceNdx].shaderSourceType,
3671							shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
3672							buildTypes[buildTypeNdx].buildType,
3673							format,
3674							paddingType[paddingIdx].padVertices,
3675							indexFormats[indexFormatNdx].indexType,
3676							BottomTestType::TRIANGLES,
3677							InstanceCullFlags::NONE,
3678							false,
3679							false,
3680							false,
3681							TopTestType::IDENTICAL_INSTANCES,
3682							false,
3683							false,
3684							false,
3685							VkBuildAccelerationStructureFlagsKHR(0u),
3686							OT_NONE,
3687							OP_NONE,
3688							TEST_WIDTH,
3689							TEST_HEIGHT,
3690							0u,
3691							EmptyAccelerationStructureCase::NOT_EMPTY,
3692						};
3693						paddingGroup->addChild(new RayQueryASBasicTestCase(group->getTestContext(), indexFormats[indexFormatNdx].name, testParams));
3694					}
3695					vertexFormatGroup->addChild(paddingGroup.release());
3696				}
3697				buildGroup->addChild(vertexFormatGroup.release());
3698			}
3699			sourceTypeGroup->addChild(buildGroup.release());
3700		}
3701		group->addChild(sourceTypeGroup.release());
3702	}
3703}
3704
3705void addOperationTestsImpl (tcu::TestCaseGroup* group, const deUint32 workerThreads)
3706{
3707	struct ShaderSourceTypeData
3708	{
3709		ShaderSourceType						shaderSourceType;
3710		ShaderSourcePipeline					shaderSourcePipeline;
3711		const char*								name;
3712	} shaderSourceTypes[] =
3713	{
3714		{ SST_VERTEX_SHADER,					SSP_GRAPHICS_PIPELINE,		"vertex_shader"				},
3715		{ SST_TESSELATION_CONTROL_SHADER,		SSP_GRAPHICS_PIPELINE,		"tess_control_shader"		},
3716		{ SST_TESSELATION_EVALUATION_SHADER,	SSP_GRAPHICS_PIPELINE,		"tess_evaluation_shader"	},
3717		{ SST_GEOMETRY_SHADER,					SSP_GRAPHICS_PIPELINE,		"geometry_shader",			},
3718		{ SST_FRAGMENT_SHADER,					SSP_GRAPHICS_PIPELINE,		"fragment_shader",			},
3719		{ SST_COMPUTE_SHADER,					SSP_COMPUTE_PIPELINE,		"compute_shader",			},
3720		{ SST_RAY_GENERATION_SHADER,			SSP_RAY_TRACING_PIPELINE,	"rgen_shader",				},
3721		{ SST_INTERSECTION_SHADER,				SSP_RAY_TRACING_PIPELINE,	"isect_shader",				},
3722		{ SST_ANY_HIT_SHADER,					SSP_RAY_TRACING_PIPELINE,	"ahit_shader",				},
3723		{ SST_CLOSEST_HIT_SHADER,				SSP_RAY_TRACING_PIPELINE,	"chit_shader",				},
3724		{ SST_MISS_SHADER,						SSP_RAY_TRACING_PIPELINE,	"miss_shader",				},
3725		{ SST_CALLABLE_SHADER,					SSP_RAY_TRACING_PIPELINE,	"call_shader",				},
3726	};
3727
3728	struct
3729	{
3730		OperationType										operationType;
3731		const char*											name;
3732	} operationTypes[] =
3733	{
3734		{ OP_COPY,											"copy"			},
3735		{ OP_COMPACT,										"compaction"	},
3736		{ OP_SERIALIZE,										"serialization"	},
3737	};
3738
3739	struct
3740	{
3741		vk::VkAccelerationStructureBuildTypeKHR				buildType;
3742		const char*											name;
3743	} buildTypes[] =
3744	{
3745		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
3746		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
3747	};
3748
3749	struct
3750	{
3751		OperationTarget										operationTarget;
3752		const char*											name;
3753	} operationTargets[] =
3754	{
3755		{ OT_TOP_ACCELERATION,								"top_acceleration_structure"		},
3756		{ OT_BOTTOM_ACCELERATION,							"bottom_acceleration_structure"	},
3757	};
3758
3759	struct
3760	{
3761		BottomTestType										testType;
3762		const char*											name;
3763	} bottomTestTypes[] =
3764	{
3765		{ BottomTestType::TRIANGLES,						"triangles" },
3766		{ BottomTestType::AABBS,							"aabbs" },
3767	};
3768
3769	for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
3770	{
3771		de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name));
3772
3773		for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
3774		{
3775			if (workerThreads > 0)
3776				if (operationTypes[operationTypeNdx].operationType != OP_COPY && operationTypes[operationTypeNdx].operationType != OP_SERIALIZE)
3777					continue;
3778
3779			de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name));
3780
3781			for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3782			{
3783				if (workerThreads > 0 && buildTypes[buildTypeNdx].buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
3784					continue;
3785
3786				de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
3787
3788				for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets); ++operationTargetNdx)
3789				{
3790					de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name));
3791
3792					for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
3793					{
3794						TopTestType topTest = (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ? TopTestType::DIFFERENT_INSTANCES : TopTestType::IDENTICAL_INSTANCES;
3795
3796						TestParams testParams
3797						{
3798							shaderSourceTypes[shaderSourceNdx].shaderSourceType,
3799							shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
3800							buildTypes[buildTypeNdx].buildType,
3801							VK_FORMAT_R32G32B32_SFLOAT,
3802							false,
3803							VK_INDEX_TYPE_NONE_KHR,
3804							bottomTestTypes[testTypeNdx].testType,
3805							InstanceCullFlags::NONE,
3806							false,
3807							false,
3808							false,
3809							topTest,
3810							false,
3811							false,
3812							false,
3813							VkBuildAccelerationStructureFlagsKHR(0u),
3814							operationTargets[operationTargetNdx].operationTarget,
3815							operationTypes[operationTypeNdx].operationType,
3816							TEST_WIDTH,
3817							TEST_HEIGHT,
3818							workerThreads,
3819							EmptyAccelerationStructureCase::NOT_EMPTY,
3820						};
3821						operationTargetGroup->addChild(new RayQueryASBasicTestCase(group->getTestContext(), bottomTestTypes[testTypeNdx].name, testParams));
3822					}
3823					buildGroup->addChild(operationTargetGroup.release());
3824				}
3825				operationTypeGroup->addChild(buildGroup.release());
3826			}
3827			sourceTypeGroup->addChild(operationTypeGroup.release());
3828		}
3829		group->addChild(sourceTypeGroup.release());
3830	}
3831}
3832
3833void addOperationTests (tcu::TestCaseGroup* group)
3834{
3835	addOperationTestsImpl(group, 0);
3836}
3837
3838void addHostThreadingOperationTests (tcu::TestCaseGroup* group)
3839{
3840	const deUint32	threads[]	= { 1, 2, 3, 4, 8, std::numeric_limits<deUint32>::max() };
3841
3842	for (size_t threadsNdx = 0; threadsNdx < DE_LENGTH_OF_ARRAY(threads); ++threadsNdx)
3843	{
3844		const std::string groupName = threads[threadsNdx] != std::numeric_limits<deUint32>::max()
3845									? de::toString(threads[threadsNdx])
3846									: "max";
3847
3848		de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), groupName.c_str()));
3849
3850		addOperationTestsImpl(threadGroup.get(), threads[threadsNdx]);
3851
3852		group->addChild(threadGroup.release());
3853	}
3854}
3855
3856void addFuncArgTests (tcu::TestCaseGroup* group)
3857{
3858	const struct
3859	{
3860		vk::VkAccelerationStructureBuildTypeKHR				buildType;
3861		const char*											name;
3862	} buildTypes[] =
3863	{
3864		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
3865		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
3866	};
3867
3868	auto& ctx = group->getTestContext();
3869
3870	for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
3871	{
3872		TestParams testParams
3873		{
3874			SST_COMPUTE_SHADER,
3875			SSP_COMPUTE_PIPELINE,
3876			buildTypes[buildTypeNdx].buildType,
3877			VK_FORMAT_R32G32B32_SFLOAT,
3878			false,
3879			VK_INDEX_TYPE_NONE_KHR,
3880			BottomTestType::TRIANGLES,
3881			InstanceCullFlags::NONE,
3882			false,
3883			false,
3884			false,
3885			TopTestType::IDENTICAL_INSTANCES,
3886			false,
3887			false,
3888			false,
3889			VkBuildAccelerationStructureFlagsKHR(0u),
3890			OT_NONE,
3891			OP_NONE,
3892			TEST_WIDTH,
3893			TEST_HEIGHT,
3894			0u,
3895			EmptyAccelerationStructureCase::NOT_EMPTY,
3896		};
3897
3898		group->addChild(new RayQueryASFuncArgTestCase(ctx, buildTypes[buildTypeNdx].name, testParams));
3899	}
3900}
3901
3902void addInstanceTriangleCullingTests (tcu::TestCaseGroup* group)
3903{
3904	const struct
3905	{
3906		ShaderSourceType						shaderSourceType;
3907		ShaderSourcePipeline					shaderSourcePipeline;
3908		std::string								name;
3909	} shaderSourceTypes[] =
3910	{
3911		{ SST_VERTEX_SHADER,					SSP_GRAPHICS_PIPELINE,		"vertex_shader"				},
3912		{ SST_TESSELATION_CONTROL_SHADER,		SSP_GRAPHICS_PIPELINE,		"tess_control_shader"		},
3913		{ SST_TESSELATION_EVALUATION_SHADER,	SSP_GRAPHICS_PIPELINE,		"tess_evaluation_shader"	},
3914		{ SST_GEOMETRY_SHADER,					SSP_GRAPHICS_PIPELINE,		"geometry_shader",			},
3915		{ SST_FRAGMENT_SHADER,					SSP_GRAPHICS_PIPELINE,		"fragment_shader",			},
3916		{ SST_COMPUTE_SHADER,					SSP_COMPUTE_PIPELINE,		"compute_shader",			},
3917		{ SST_RAY_GENERATION_SHADER,			SSP_RAY_TRACING_PIPELINE,	"rgen_shader",				},
3918		{ SST_INTERSECTION_SHADER,				SSP_RAY_TRACING_PIPELINE,	"isect_shader",				},
3919		{ SST_ANY_HIT_SHADER,					SSP_RAY_TRACING_PIPELINE,	"ahit_shader",				},
3920		{ SST_CLOSEST_HIT_SHADER,				SSP_RAY_TRACING_PIPELINE,	"chit_shader",				},
3921		{ SST_MISS_SHADER,						SSP_RAY_TRACING_PIPELINE,	"miss_shader",				},
3922		{ SST_CALLABLE_SHADER,					SSP_RAY_TRACING_PIPELINE,	"call_shader",				},
3923	};
3924
3925	const struct
3926	{
3927		InstanceCullFlags	cullFlags;
3928		std::string			name;
3929	} cullFlags[] =
3930	{
3931		{ InstanceCullFlags::NONE,				"noflags"		},
3932		{ InstanceCullFlags::COUNTERCLOCKWISE,	"ccw"			},
3933		{ InstanceCullFlags::CULL_DISABLE,		"nocull"		},
3934		{ InstanceCullFlags::ALL,				"ccw_nocull"	},
3935	};
3936
3937	const struct
3938	{
3939		TopTestType	topType;
3940		std::string	name;
3941	} topType[] =
3942	{
3943		{ TopTestType::DIFFERENT_INSTANCES, "transformed"	},	// Each instance has its own transformation matrix.
3944		{ TopTestType::IDENTICAL_INSTANCES, "notransform"	},	// "Identical" instances, different geometries.
3945	};
3946
3947	const struct
3948	{
3949		vk::VkAccelerationStructureBuildTypeKHR	buildType;
3950		std::string								name;
3951	} buildTypes[] =
3952	{
3953		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
3954		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
3955	};
3956
3957	const struct
3958	{
3959		VkIndexType	indexType;
3960		std::string	name;
3961	} indexFormats[] =
3962	{
3963		{ VK_INDEX_TYPE_NONE_KHR ,	"index_none"	},
3964		{ VK_INDEX_TYPE_UINT16 ,	"index_uint16"	},
3965		{ VK_INDEX_TYPE_UINT32 ,	"index_uint32"	},
3966	};
3967
3968	auto& ctx = group->getTestContext();
3969
3970	for (int shaderSourceIdx = 0; shaderSourceIdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceIdx)
3971	{
3972		de::MovePtr<tcu::TestCaseGroup> shaderSourceGroup(new tcu::TestCaseGroup(ctx, shaderSourceTypes[shaderSourceIdx].name.c_str()));
3973
3974		for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
3975		{
3976			de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
3977
3978			for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
3979			{
3980				de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
3981
3982				for (int topTypeIdx = 0; topTypeIdx < DE_LENGTH_OF_ARRAY(topType); ++topTypeIdx)
3983				{
3984					for (int cullFlagsIdx = 0; cullFlagsIdx < DE_LENGTH_OF_ARRAY(cullFlags); ++cullFlagsIdx)
3985					{
3986						const std::string testName = topType[topTypeIdx].name + "_" + cullFlags[cullFlagsIdx].name;
3987
3988						TestParams testParams
3989						{
3990							shaderSourceTypes[shaderSourceIdx].shaderSourceType,
3991							shaderSourceTypes[shaderSourceIdx].shaderSourcePipeline,
3992							buildTypes[buildTypeIdx].buildType,
3993							VK_FORMAT_R32G32B32_SFLOAT,
3994							false,
3995							indexFormats[indexFormatIdx].indexType,
3996							BottomTestType::TRIANGLES,
3997							cullFlags[cullFlagsIdx].cullFlags,
3998							false,
3999							false,
4000							false,
4001							topType[topTypeIdx].topType,
4002							false,
4003							false,
4004							false,
4005							VkBuildAccelerationStructureFlagsKHR(0u),
4006							OT_NONE,
4007							OP_NONE,
4008							TEST_WIDTH,
4009							TEST_HEIGHT,
4010							0u,
4011							EmptyAccelerationStructureCase::NOT_EMPTY,
4012						};
4013						indexTypeGroup->addChild(new RayQueryASBasicTestCase(ctx, testName.c_str(), testParams));
4014					}
4015				}
4016				buildTypeGroup->addChild(indexTypeGroup.release());
4017			}
4018			shaderSourceGroup->addChild(buildTypeGroup.release());
4019		}
4020		group->addChild(shaderSourceGroup.release());
4021	}
4022}
4023
4024void addInstanceUpdateTests (tcu::TestCaseGroup* group)
4025{
4026	const struct
4027	{
4028		vk::VkAccelerationStructureBuildTypeKHR	buildType;
4029		std::string								name;
4030	} buildTypes[] =
4031	{
4032		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
4033		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
4034	};
4035
4036	struct
4037	{
4038		OperationType										operationType;
4039		const char*											name;
4040	} operationTypes[] =
4041	{
4042		{ OP_UPDATE,											"update"			},
4043		{ OP_UPDATE_IN_PLACE,									"update_in_place"	},
4044	};
4045
4046	auto& ctx = group->getTestContext();
4047
4048	for (int buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
4049	{
4050		de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeNdx].name.c_str()));
4051
4052		for (int operationTypesIdx = 0; operationTypesIdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypesIdx)
4053		{
4054			TestParams testParams
4055			{
4056				SST_COMPUTE_SHADER,
4057				SSP_COMPUTE_PIPELINE,
4058				buildTypes[buildTypeNdx].buildType,
4059				VK_FORMAT_R32G32B32_SFLOAT,
4060				false,
4061				VK_INDEX_TYPE_NONE_KHR,
4062				BottomTestType::TRIANGLES,
4063				InstanceCullFlags::NONE,
4064				false,
4065				false,
4066				false,
4067				TopTestType::IDENTICAL_INSTANCES,
4068				false,
4069				false,
4070				false,
4071				VkBuildAccelerationStructureFlagsKHR(0u),
4072				OT_NONE,
4073				OP_NONE,
4074				TEST_WIDTH,
4075				TEST_HEIGHT,
4076				0u,
4077				EmptyAccelerationStructureCase::NOT_EMPTY,
4078			};
4079
4080			buildTypeGroup->addChild(new RayQueryASFuncArgTestCase(ctx, operationTypes[operationTypesIdx].name, testParams));
4081		}
4082		group->addChild(buildTypeGroup.release());
4083	}
4084}
4085
4086void addDynamicIndexingTests(tcu::TestCaseGroup* group)
4087{
4088	auto& ctx = group->getTestContext();
4089	group->addChild(new RayQueryASDynamicIndexingTestCase(ctx, "dynamic_indexing"));
4090}
4091
4092void addEmptyAccelerationStructureTests (tcu::TestCaseGroup* group)
4093{
4094	const struct
4095	{
4096		ShaderSourceType						shaderSourceType;
4097		ShaderSourcePipeline					shaderSourcePipeline;
4098		std::string								name;
4099	} shaderSourceTypes[] =
4100	{
4101		{ SST_VERTEX_SHADER,					SSP_GRAPHICS_PIPELINE,		"vertex_shader"				},
4102		{ SST_TESSELATION_CONTROL_SHADER,		SSP_GRAPHICS_PIPELINE,		"tess_control_shader"		},
4103		{ SST_TESSELATION_EVALUATION_SHADER,	SSP_GRAPHICS_PIPELINE,		"tess_evaluation_shader"	},
4104		{ SST_GEOMETRY_SHADER,					SSP_GRAPHICS_PIPELINE,		"geometry_shader",			},
4105		{ SST_FRAGMENT_SHADER,					SSP_GRAPHICS_PIPELINE,		"fragment_shader",			},
4106		{ SST_COMPUTE_SHADER,					SSP_COMPUTE_PIPELINE,		"compute_shader",			},
4107		{ SST_RAY_GENERATION_SHADER,			SSP_RAY_TRACING_PIPELINE,	"rgen_shader",				},
4108		{ SST_INTERSECTION_SHADER,				SSP_RAY_TRACING_PIPELINE,	"isect_shader",				},
4109		{ SST_ANY_HIT_SHADER,					SSP_RAY_TRACING_PIPELINE,	"ahit_shader",				},
4110		{ SST_CLOSEST_HIT_SHADER,				SSP_RAY_TRACING_PIPELINE,	"chit_shader",				},
4111		{ SST_MISS_SHADER,						SSP_RAY_TRACING_PIPELINE,	"miss_shader",				},
4112		{ SST_CALLABLE_SHADER,					SSP_RAY_TRACING_PIPELINE,	"call_shader",				},
4113	};
4114
4115	const struct
4116	{
4117		vk::VkAccelerationStructureBuildTypeKHR				buildType;
4118		std::string											name;
4119	} buildTypes[] =
4120	{
4121		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
4122		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
4123	};
4124
4125	const struct
4126	{
4127		VkIndexType								indexType;
4128		std::string								name;
4129	} indexFormats[] =
4130	{
4131		{ VK_INDEX_TYPE_NONE_KHR ,				"index_none"		},
4132		{ VK_INDEX_TYPE_UINT16 ,				"index_uint16"	},
4133		{ VK_INDEX_TYPE_UINT32 ,				"index_uint32"	},
4134	};
4135
4136	const struct
4137	{
4138		EmptyAccelerationStructureCase	emptyASCase;
4139		std::string						name;
4140	} emptyCases[] =
4141	{
4142		{ EmptyAccelerationStructureCase::INACTIVE_TRIANGLES,	"inactive_triangles"	},
4143		{ EmptyAccelerationStructureCase::INACTIVE_INSTANCES,	"inactive_instances"	},
4144		{ EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM,	"no_geometries_bottom"	},
4145		{ EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP,	"no_primitives_top"		},
4146		{ EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM,	"no_primitives_bottom"	},
4147	};
4148
4149	auto& ctx = group->getTestContext();
4150
4151	for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
4152	{
4153		de::MovePtr<tcu::TestCaseGroup> sourceTypeGroup(new tcu::TestCaseGroup(ctx, shaderSourceTypes[shaderSourceNdx].name.c_str()));
4154
4155		for (int buildTypeIdx = 0; buildTypeIdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeIdx)
4156		{
4157			de::MovePtr<tcu::TestCaseGroup> buildTypeGroup(new tcu::TestCaseGroup(ctx, buildTypes[buildTypeIdx].name.c_str()));
4158
4159			for (int indexFormatIdx = 0; indexFormatIdx < DE_LENGTH_OF_ARRAY(indexFormats); ++indexFormatIdx)
4160			{
4161				de::MovePtr<tcu::TestCaseGroup> indexTypeGroup(new tcu::TestCaseGroup(ctx, indexFormats[indexFormatIdx].name.c_str()));
4162
4163				for (int emptyCaseIdx = 0; emptyCaseIdx < DE_LENGTH_OF_ARRAY(emptyCases); ++emptyCaseIdx)
4164				{
4165							TestParams testParams
4166							{
4167								shaderSourceTypes[shaderSourceNdx].shaderSourceType,
4168								shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline,
4169								buildTypes[buildTypeIdx].buildType,
4170								VK_FORMAT_R32G32B32_SFLOAT,
4171								false,
4172								indexFormats[indexFormatIdx].indexType,
4173								BottomTestType::TRIANGLES,
4174								InstanceCullFlags::NONE,
4175								false,
4176								false,
4177								false,
4178								TopTestType::IDENTICAL_INSTANCES,
4179								false,
4180								false,
4181								false,
4182								VkBuildAccelerationStructureFlagsKHR(0u),
4183								OT_NONE,
4184								OP_NONE,
4185								TEST_WIDTH,
4186								TEST_HEIGHT,
4187								0u,
4188								emptyCases[emptyCaseIdx].emptyASCase,
4189							};
4190					indexTypeGroup->addChild(new RayQueryASBasicTestCase(ctx, emptyCases[emptyCaseIdx].name.c_str(), testParams));
4191				}
4192				buildTypeGroup->addChild(indexTypeGroup.release());
4193			}
4194			sourceTypeGroup->addChild(buildTypeGroup.release());
4195		}
4196		group->addChild(sourceTypeGroup.release());
4197	}
4198}
4199
4200tcu::TestCaseGroup*	createAccelerationStructuresTests(tcu::TestContext& testCtx)
4201{
4202	// Acceleration structure tests using rayQuery feature
4203	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "acceleration_structures"));
4204
4205	// Test building AS with different build types, build flags and geometries/instances using arrays or arrays of pointers
4206	addTestGroup(group.get(), "flags", addBasicBuildingTests);
4207	// Test building AS with different vertex and index formats
4208	addTestGroup(group.get(), "format", addVertexIndexFormatsTests);
4209	// Test copying, compaction and serialization of AS
4210	addTestGroup(group.get(), "operations", addOperationTests);
4211	// Test host threading operations
4212	addTestGroup(group.get(), "host_threading", addHostThreadingOperationTests);
4213	// Test using AS as function argument using both pointers and bare values
4214	addTestGroup(group.get(), "function_argument", addFuncArgTests);
4215	// Test building AS with counterclockwise triangles and/or disabling face culling
4216	addTestGroup(group.get(), "instance_triangle_culling", addInstanceTriangleCullingTests);
4217	// Test updating instance index using both in-place and separate src/dst acceleration structures
4218	addTestGroup(group.get(), "instance_update", addInstanceUpdateTests);
4219	// Exercise dynamic indexing of acceleration structures
4220	addTestGroup(group.get(), "dynamic_indexing", addDynamicIndexingTests);
4221	// Test building empty acceleration structures using different methods
4222	addTestGroup(group.get(), "empty", addEmptyAccelerationStructureTests);
4223
4224	return group.release();
4225}
4226
4227}	// RayQuery
4228
4229}	// vkt
4230