1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *	  http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Ray Query Builtin tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktRayQueryWatertightnessTests.hpp"
25
26#include "vkDefs.hpp"
27
28#include "vktTestCase.hpp"
29#include "vktTestGroupUtil.hpp"
30#include "vkCmdUtil.hpp"
31#include "vkObjUtil.hpp"
32#include "vkBuilderUtil.hpp"
33#include "vkBarrierUtil.hpp"
34#include "vkBufferWithMemory.hpp"
35#include "vkImageWithMemory.hpp"
36#include "vkTypeUtil.hpp"
37#include "vkImageUtil.hpp"
38#include "deRandom.hpp"
39#include "tcuTexture.hpp"
40#include "tcuTextureUtil.hpp"
41#include "tcuTestLog.hpp"
42#include "tcuImageCompare.hpp"
43#include "tcuCommandLine.hpp"
44
45#include "vkRayTracingUtil.hpp"
46
47namespace vkt
48{
49namespace RayQuery
50{
51namespace
52{
53using namespace vk;
54using namespace vkt;
55
56static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
57												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
58												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
59												| VK_SHADER_STAGE_MISS_BIT_KHR
60												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
61												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
62
63enum TestType
64{
65	TEST_TYPE_NO_MISS		= 0,
66	TEST_TYPE_SINGLE_HIT,
67};
68
69enum GeomType
70{
71	GEOM_TYPE_TRIANGLES,
72	GEOM_TYPE_AABBS,
73	GEOM_TYPE_LAST,
74};
75
76const deUint32	TEST_WIDTH					= 256u;
77const deUint32	TEST_HEIGHT					= 256u;
78const float		MIN_AABB_SIDE_LENGTH		= 1e-6f;
79const float		MIN_TRIANGLE_EDGE_LENGTH	= 1.0f / float(10 * TEST_WIDTH * TEST_HEIGHT);
80const float		MIN_TRIANGLE_AREA_SIZE		= 1.0f / float(10 * TEST_WIDTH * TEST_HEIGHT);
81
82struct TestParams;
83
84typedef void (*CheckSupportFunc)(Context& context, const TestParams& testParams);
85typedef void (*InitProgramsFunc)(SourceCollections& programCollection, const TestParams& testParams);
86typedef const std::string (*ShaderBodyTextFunc)(const TestParams& testParams);
87
88class PipelineConfiguration
89{
90public:
91					PipelineConfiguration	()	{}
92	virtual			~PipelineConfiguration	()	{}
93
94	virtual void	initConfiguration	(Context&							context,
95										 TestParams&						testParams) = 0;
96	virtual void	fillCommandBuffer	(Context&							context,
97										 TestParams&						testParams,
98										 VkCommandBuffer					commandBuffer,
99										 const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
100										 const VkDescriptorImageInfo&		resultImageInfo) = 0;
101};
102
103class TestConfiguration
104{
105public:
106																	TestConfiguration				()
107																		: m_bottomAccelerationStructures	()
108																		, m_topAccelerationStructure		()
109																		, m_expected						()
110																	{
111																	}
112	virtual															~TestConfiguration				()
113																	{
114																	}
115
116	virtual const VkAccelerationStructureKHR*						initAccelerationStructures		(Context&							context,
117																									 TestParams&						testParams,
118																									 VkCommandBuffer					cmdBuffer) = 0;
119	virtual bool													verify							(BufferWithMemory*					resultBuffer,
120																									 Context&							context,
121																									 TestParams&						testParams) = 0;
122
123protected:
124	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	m_bottomAccelerationStructures;
125	de::SharedPtr<TopLevelAccelerationStructure>					m_topAccelerationStructure;
126	std::vector<deInt32>											m_expected;
127};
128
129struct TestParams
130{
131	deUint32				width;
132	deUint32				height;
133	deUint32				depth;
134	deUint32				randomSeed;
135	TestType				testType;
136	VkShaderStageFlagBits	stage;
137	GeomType				geomType;
138	deUint32				squaresGroupCount;
139	deUint32				geometriesGroupCount;
140	deUint32				instancesGroupCount;
141	VkFormat				format;
142	CheckSupportFunc		pipelineCheckSupport;
143	InitProgramsFunc		pipelineInitPrograms;
144	ShaderBodyTextFunc		testConfigShaderBodyText;
145};
146
147deUint32 getShaderGroupHandleSize (const InstanceInterface&	vki,
148								   const VkPhysicalDevice	physicalDevice)
149{
150	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
151
152	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
153
154	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
155}
156
157deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
158									  const VkPhysicalDevice	physicalDevice)
159{
160	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
161
162	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
163
164	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
165}
166
167VkBuffer getVkBuffer (const de::MovePtr<BufferWithMemory>& buffer)
168{
169	VkBuffer result = (buffer.get() == DE_NULL) ? DE_NULL : buffer->get();
170
171	return result;
172}
173
174VkStridedDeviceAddressRegionKHR makeStridedDeviceAddressRegion (const DeviceInterface& vkd, const VkDevice device, VkBuffer buffer, VkDeviceSize size)
175{
176	const VkDeviceSize sizeFixed = ((buffer == DE_NULL) ? 0ull : size);
177
178	return makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, buffer, 0), sizeFixed, sizeFixed);
179}
180
181VkImageCreateInfo makeImageCreateInfo (VkFormat				format,
182									   deUint32				width,
183									   deUint32				height,
184									   deUint32				depth,
185									   VkImageType			imageType	= VK_IMAGE_TYPE_3D,
186									   VkImageUsageFlags	usageFlags	= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
187{
188	const VkImageCreateInfo	imageCreateInfo	=
189	{
190		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
191		DE_NULL,								// const void*				pNext;
192		(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
193		imageType,								// VkImageType				imageType;
194		format,									// VkFormat					format;
195		makeExtent3D(width, height, depth),		// VkExtent3D				extent;
196		1u,										// deUint32					mipLevels;
197		1u,										// deUint32					arrayLayers;
198		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
199		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
200		usageFlags,								// VkImageUsageFlags		usage;
201		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
202		0u,										// deUint32					queueFamilyIndexCount;
203		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
204		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
205	};
206
207	return imageCreateInfo;
208}
209
210static const std::string getMissPassthrough (void)
211{
212	const std::string missPassthrough =
213		"#version 460 core\n"
214		"#extension GL_EXT_ray_tracing : require\n"
215		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
216		"\n"
217		"void main()\n"
218		"{\n"
219		"}\n";
220
221	return missPassthrough;
222}
223
224static const std::string getHitPassthrough (void)
225{
226	const std::string hitPassthrough =
227		"#version 460 core\n"
228		"#extension GL_EXT_ray_tracing : require\n"
229		"hitAttributeEXT vec3 attribs;\n"
230		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
231		"\n"
232		"void main()\n"
233		"{\n"
234		"}\n";
235
236	return hitPassthrough;
237}
238
239static const std::string getGraphicsPassthrough (void)
240{
241	std::ostringstream src;
242
243	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
244		<< "\n"
245		<< "void main(void)\n"
246		<< "{\n"
247		<< "}\n";
248
249	return src.str();
250}
251
252static const std::string getVertexPassthrough (void)
253{
254	std::ostringstream src;
255
256	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
257		<< "\n"
258		<< "layout(location = 0) in vec4 in_position;\n"
259		<< "\n"
260		<< "void main(void)\n"
261		<< "{\n"
262		<< "  gl_Position = in_position;\n"
263		<< "}\n";
264
265	return src.str();
266}
267
268static inline tcu::Vec2 mixVec2 (const tcu::Vec2& a, const tcu::Vec2& b, const float alpha)
269{
270	const tcu::Vec2 result = a * alpha + b * (1.0f - alpha);
271
272	return result;
273}
274
275static inline tcu::Vec2 mixCoordsVec2 (const tcu::Vec2& a, const tcu::Vec2& b, const float alpha, const float beta)
276{
277	const tcu::Vec2	result	= tcu::Vec2(deFloatMix(a.x(), b.x(), alpha), deFloatMix(a.y(), b.y(), beta));
278
279	return result;
280}
281
282inline float triangleEdgeLength (const tcu::Vec2& vertexA, const tcu::Vec2& vertexB)
283{
284	const float	abx	= vertexA.x() - vertexB.x();
285	const float	aby	= vertexA.y() - vertexB.y();
286	const float abq	= abx * abx + aby * aby;
287	const float	ab	= deFloatSqrt(abq);
288
289	return ab;
290}
291
292inline float triangleArea (const float edgeALen, const float edgeBLen, const float edgeCLen)
293{
294	const float	s	= (edgeALen + edgeBLen + edgeCLen) / 2.0f;
295	const float	q	= s * (s - edgeALen) * (s - edgeBLen) * (s - edgeCLen);
296
297	if (q <= 0.0f)
298		return 0.0f;
299
300	return deFloatSqrt(q);
301}
302
303static const std::string getGeomName (bool writePointSize)
304{
305	std::ostringstream str;
306	str << "geom" << (writePointSize ? "_point_size" : "");
307	return str.str();
308}
309
310class GraphicsConfiguration : public PipelineConfiguration
311{
312public:
313	static void						checkSupport			(Context&							context,
314															 const TestParams&					testParams);
315	static void						initPrograms			(SourceCollections&					programCollection,
316															 const TestParams&					testParams);
317
318									GraphicsConfiguration	();
319	virtual							~GraphicsConfiguration	() {}
320
321	void							initVertexBuffer		(Context&							context,
322															 TestParams&						testParams);
323	Move<VkPipeline>				makeGraphicsPipeline	(Context&							context,
324															 TestParams&						testParams);
325	virtual void					initConfiguration		(Context&							context,
326															 TestParams&						testParams) override;
327	virtual void					fillCommandBuffer		(Context&							context,
328															 TestParams&						testParams,
329															 VkCommandBuffer					commandBuffer,
330															 const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
331															 const VkDescriptorImageInfo&		resultImageInfo) override;
332
333private:
334	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
335	Move<VkDescriptorPool>			m_descriptorPool;
336	Move<VkDescriptorSet>			m_descriptorSet;
337
338	VkFormat						m_framebufferFormat;
339	Move<VkImage>					m_framebufferImage;
340	de::MovePtr<Allocation>			m_framebufferImageAlloc;
341	Move<VkImageView>				m_framebufferAttachment;
342
343	Move<VkShaderModule>			m_vertShaderModule;
344	Move<VkShaderModule>			m_geomShaderModule;
345	Move<VkShaderModule>			m_tescShaderModule;
346	Move<VkShaderModule>			m_teseShaderModule;
347	Move<VkShaderModule>			m_fragShaderModule;
348
349	Move<VkRenderPass>				m_renderPass;
350	Move<VkFramebuffer>				m_framebuffer;
351	Move<VkPipelineLayout>			m_pipelineLayout;
352	Move<VkPipeline>				m_pipeline;
353
354	deUint32						m_vertexCount;
355	Move<VkBuffer>					m_vertexBuffer;
356	de::MovePtr<Allocation>			m_vertexBufferAlloc;
357};
358
359GraphicsConfiguration::GraphicsConfiguration()
360	: PipelineConfiguration		()
361	, m_descriptorSetLayout		()
362	, m_descriptorPool			()
363	, m_descriptorSet			()
364	, m_framebufferFormat		(VK_FORMAT_R8G8B8A8_UNORM)
365	, m_framebufferImage		()
366	, m_framebufferImageAlloc	()
367	, m_framebufferAttachment	()
368	, m_vertShaderModule		()
369	, m_geomShaderModule		()
370	, m_tescShaderModule		()
371	, m_teseShaderModule		()
372	, m_fragShaderModule		()
373	, m_renderPass				()
374	, m_framebuffer				()
375	, m_pipelineLayout			()
376	, m_pipeline				()
377	, m_vertexCount				(0)
378	, m_vertexBuffer			()
379	, m_vertexBufferAlloc		()
380{
381}
382
383void GraphicsConfiguration::checkSupport (Context&			context,
384										  const TestParams&	testParams)
385{
386	switch (testParams.stage)
387	{
388	case VK_SHADER_STAGE_VERTEX_BIT:
389	case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
390	case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
391	case VK_SHADER_STAGE_GEOMETRY_BIT:
392		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
393		break;
394	default:
395		break;
396	}
397
398	switch (testParams.stage)
399	{
400	case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
401	case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
402		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
403		break;
404	case VK_SHADER_STAGE_GEOMETRY_BIT:
405		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
406		break;
407	default:
408		break;
409	}
410}
411
412void GraphicsConfiguration::initPrograms (SourceCollections&	programCollection,
413										  const TestParams&		testParams)
414{
415	const vk::ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
416	const std::string				testShaderBody	= testParams.testConfigShaderBodyText(testParams);
417
418	switch (testParams.stage)
419	{
420		case VK_SHADER_STAGE_VERTEX_BIT:
421		{
422			{
423				std::ostringstream src;
424				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
425					<< "#extension GL_EXT_ray_query : require\n"
426					<< "#extension GL_EXT_ray_tracing : require\n"
427					<< "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
428					<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
429					<< "\n"
430					<< "void testFunc(ivec3 pos, ivec3 size)\n"
431					<< "{\n"
432					<< testShaderBody
433					<< "}\n"
434					<< "\n"
435					<< "void main(void)\n"
436					<< "{\n"
437					<< "  const int   posId    = int(gl_VertexIndex / 3);\n"
438					<< "  const int   vertId   = int(gl_VertexIndex % 3);\n"
439					<< "  const ivec3 size     = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n"
440					<< "  const ivec3 pos      = ivec3(posId % size.x, posId / size.x, 0);\n"
441					<< "\n"
442					<< "  if (vertId == 0)\n"
443					<< "  {\n"
444					<< "    testFunc(pos, size);\n"
445					<< "  }\n"
446					<< "}\n";
447
448				programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << buildOptions;
449			}
450
451			programCollection.glslSources.add("frag") << glu::FragmentSource(getGraphicsPassthrough()) << buildOptions;
452
453			break;
454		}
455
456		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
457		{
458			{
459				std::ostringstream src;
460				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
461					<< "\n"
462					<< "layout(location = 0) in vec4 in_position;\n"
463					<< "out gl_PerVertex\n"
464					<< "{\n"
465					<< "  vec4 gl_Position;\n"
466					<< "};\n"
467					<< "\n"
468					<< "void main(void)\n"
469					<< "{\n"
470					<< "  gl_Position = in_position;\n"
471					<< "}\n";
472
473				programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << buildOptions;
474			}
475
476			{
477				std::ostringstream src;
478				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
479					<< "#extension GL_EXT_tessellation_shader : require\n"
480					<< "#extension GL_EXT_ray_query : require\n"
481					<< "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
482					<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
483					<< "in gl_PerVertex\n"
484					<< "{\n"
485					<< "  vec4 gl_Position;\n"
486					<< "} gl_in[];\n"
487					<< "layout(vertices = 3) out;\n"
488					<< "out gl_PerVertex\n"
489					<< "{\n"
490					<< "  vec4 gl_Position;\n"
491					<< "} gl_out[];\n"
492					<< "\n"
493					<< "void testFunc(ivec3 pos, ivec3 size)\n"
494					<< "{\n"
495					<< testShaderBody
496					<< "}\n"
497					<< "\n"
498					<< "void main(void)\n"
499					<< "{\n"
500					<< "\n"
501					<< "  if (gl_InvocationID == 0)\n"
502					<< "  {\n"
503					<< "    const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n"
504					<< "    int index = int(gl_in[gl_InvocationID].gl_Position.z);\n"
505					<< "    int x = index % size.x;\n"
506					<< "    int y = index / size.y;\n"
507					<< "    const ivec3 pos = ivec3(x, y, 0);\n"
508					<< "    testFunc(pos, size);\n"
509					<< "  }\n"
510					<< "\n"
511					<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
512					<< "  gl_TessLevelInner[0] = 1;\n"
513					<< "  gl_TessLevelInner[1] = 1;\n"
514					<< "  gl_TessLevelOuter[gl_InvocationID] = 1;\n"
515					<< "}\n";
516
517				programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()) << buildOptions;
518			}
519
520			{
521				std::ostringstream src;
522				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
523					<< "#extension GL_EXT_tessellation_shader : require\n"
524					<< "layout(triangles, equal_spacing, ccw) in;\n"
525					<< "in gl_PerVertex\n"
526					<< "{\n"
527					<< "  vec4 gl_Position;\n"
528					<< "} gl_in[];\n"
529					<< "\n"
530					<< "void main(void)\n"
531					<< "{\n"
532					<< "  gl_Position = gl_in[0].gl_Position;\n"
533					<< "}\n";
534
535				programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()) << buildOptions;
536			}
537
538			break;
539		}
540
541		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
542		{
543			{
544				std::ostringstream src;
545				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
546					<< "\n"
547					<< "layout(location = 0) in vec4 in_position;\n"
548					<< "out gl_PerVertex"
549					<< "{\n"
550					<< "  vec4 gl_Position;\n"
551					<< "};\n"
552					<< "\n"
553					<< "void main(void)\n"
554					<< "{\n"
555					<< "  gl_Position = in_position;\n"
556					<< "}\n";
557
558				programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << buildOptions;
559			}
560
561			{
562				std::ostringstream src;
563				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
564					<< "#extension GL_EXT_tessellation_shader : require\n"
565					<< "in gl_PerVertex\n"
566					<< "{\n"
567					<< "  vec4 gl_Position;\n"
568					<< "} gl_in[];\n"
569					<< "layout(vertices = 3) out;\n"
570					<< "out gl_PerVertex\n"
571					<< "{\n"
572					<< "  vec4 gl_Position;\n"
573					<< "} gl_out[];\n"
574					<< "\n"
575					<< "void main(void)\n"
576					<< "{\n"
577					<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
578					<< "  gl_TessLevelInner[0] = 1;\n"
579					<< "  gl_TessLevelInner[1] = 1;\n"
580					<< "  gl_TessLevelOuter[gl_InvocationID] = 1;\n"
581					<< "}\n";
582
583				programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()) << buildOptions;
584			}
585
586			{
587				std::ostringstream src;
588				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
589					<< "#extension GL_EXT_tessellation_shader : require\n"
590					<< "#extension GL_EXT_ray_query : require\n"
591					<< "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
592					<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
593					<< "layout(triangles, equal_spacing, ccw) in;\n"
594					<< "in gl_PerVertex\n"
595					<< "{\n"
596					<< "  vec4 gl_Position;\n"
597					<< "} gl_in[];\n"
598					<< "\n"
599					<< "void testFunc(ivec3 pos, ivec3 size)\n"
600					<< "{\n"
601					<< testShaderBody
602					<< "}\n"
603					<< "\n"
604					<< "void main(void)\n"
605					<< "{\n"
606					<< "	const ivec3 size = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n"
607					<< "	int index = int(gl_in[0].gl_Position.z);\n"
608					<< "	int x = index % size.x;\n"
609					<< "	int y = index / size.y;\n"
610					<< "	const ivec3 pos = ivec3(x, y, 0);\n"
611					<< "	testFunc(pos, size);\n"
612					<< "	gl_Position = gl_in[0].gl_Position;\n"
613					<< "}\n";
614
615				programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()) << buildOptions;
616			}
617
618			break;
619		}
620
621		case VK_SHADER_STAGE_GEOMETRY_BIT:
622		{
623			programCollection.glslSources.add("vert") << glu::VertexSource(getVertexPassthrough()) << buildOptions;
624
625			for (deUint32 i = 0; i < 2; ++i)
626			{
627				const bool writePointSize = i == 1;
628				std::string pointSize = writePointSize ? "    gl_PointSize = 1.0f;\n" : "";
629
630				std::ostringstream src;
631				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
632					<< "#extension GL_EXT_ray_query : require\n"
633					<< "layout(triangles) in;\n"
634					<< "layout(points, max_vertices = 1) out;\n"
635					<< "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
636					<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
637					<< "\n"
638					<< "void testFunc(ivec3 pos, ivec3 size)\n"
639					<< "{\n"
640					<< testShaderBody
641					<< "}\n"
642					<< "\n"
643					<< "void main(void)\n"
644					<< "{\n"
645					<< "  const int   posId    = int(gl_PrimitiveIDIn);\n"
646					<< "  const ivec3 size     = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n"
647					<< "  const ivec3 pos      = ivec3(posId % size.x, posId / size.x, 0);\n"
648					<< "\n"
649					<< "  testFunc(pos, size);\n"
650					<< pointSize
651					<< "}\n";
652
653				programCollection.glslSources.add(getGeomName(writePointSize)) << glu::GeometrySource(src.str()) << buildOptions;
654			}
655
656			break;
657		}
658
659		case VK_SHADER_STAGE_FRAGMENT_BIT:
660		{
661			programCollection.glslSources.add("vert") << glu::VertexSource(getVertexPassthrough()) << buildOptions;
662
663			{
664				std::ostringstream src;
665				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n"
666					<< "#extension GL_EXT_ray_query : require\n"
667					<< "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
668					<< "layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
669					<< "\n"
670					<< "void testFunc(ivec3 pos, ivec3 size)\n"
671					<< "{\n"
672					<< testShaderBody
673					<< "}\n"
674					<< "\n"
675					<< "void main(void)\n"
676					<< "{\n"
677					<< "  const ivec3 size     = ivec3(" << testParams.width << ", " << testParams.height << ", 1);\n"
678					<< "  const ivec3 pos      = ivec3(int(gl_FragCoord.x - 0.5f), int(gl_FragCoord.y - 0.5f), 0);\n"
679					<< "\n"
680					<< "  testFunc(pos, size);\n"
681					<< "}\n";
682
683				programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()) << buildOptions;
684			}
685
686			break;
687		}
688
689		default:
690			TCU_THROW(InternalError, "Unknown stage");
691	}
692}
693
694void GraphicsConfiguration::initVertexBuffer (Context&		context,
695											  TestParams&	testParams)
696{
697	const DeviceInterface&	vkd			= context.getDeviceInterface();
698	const VkDevice			device		= context.getDevice();
699	const deUint32			width		= testParams.width;
700	const deUint32			height		= testParams.height;
701	Allocator&				allocator	= context.getDefaultAllocator();
702	std::vector<tcu::Vec4>	vertices;
703
704	switch (testParams.stage)
705	{
706		case VK_SHADER_STAGE_VERTEX_BIT:
707		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
708		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
709		{
710			float z = 0.0f;
711			const float w = 1.0f;
712
713			vertices.reserve(3 * height * width);
714
715			for (deUint32 y = 0; y < height; ++y)
716			for (deUint32 x = 0; x < width; ++x)
717			{
718				const float	x0	= float(x + 0) / float(width);
719				const float	y0	= float(y + 0) / float(height);
720				const float	x1	= float(x + 1) / float(width);
721				const float	y1	= float(y + 1) / float(height);
722				const float	xm	= (x0 + x1) / 2.0f;
723				const float	ym	= (y0 + y1) / 2.0f;
724
725				vertices.push_back(tcu::Vec4(x0, y0, z, w));
726				vertices.push_back(tcu::Vec4(xm, y1, z, w));
727				vertices.push_back(tcu::Vec4(x1, ym, z, w));
728
729				z += 1.f;
730			}
731
732			break;
733		}
734
735		case VK_SHADER_STAGE_GEOMETRY_BIT:
736		{
737			const float z = 0.0f;
738			const float w = 1.0f;
739
740			vertices.reserve(3 * height * width);
741
742			for (deUint32 y = 0; y < height; ++y)
743			for (deUint32 x = 0; x < width; ++x)
744			{
745				const float	x0	= float(x + 0) / float(width);
746				const float	y0	= float(y + 0) / float(height);
747				const float	x1	= float(x + 1) / float(width);
748				const float	y1	= float(y + 1) / float(height);
749				const float	xm	= (x0 + x1) / 2.0f;
750				const float	ym	= (y0 + y1) / 2.0f;
751
752				vertices.push_back(tcu::Vec4(x0, y0, z, w));
753				vertices.push_back(tcu::Vec4(xm, y1, z, w));
754				vertices.push_back(tcu::Vec4(x1, ym, z, w));
755			}
756
757			break;
758		}
759
760		case VK_SHADER_STAGE_FRAGMENT_BIT:
761		{
762			const float		z = 1.0f;
763			const float		w = 1.0f;
764			const tcu::Vec4	a = tcu::Vec4(-1.0f, -1.0f, z, w);
765			const tcu::Vec4	b = tcu::Vec4(+1.0f, -1.0f, z, w);
766			const tcu::Vec4	c = tcu::Vec4(-1.0f, +1.0f, z, w);
767			const tcu::Vec4	d = tcu::Vec4(+1.0f, +1.0f, z, w);
768
769			vertices.push_back(a);
770			vertices.push_back(b);
771			vertices.push_back(c);
772
773			vertices.push_back(b);
774			vertices.push_back(c);
775			vertices.push_back(d);
776
777			break;
778		}
779
780		default:
781			TCU_THROW(InternalError, "Unknown stage");
782
783	}
784
785	// Initialize vertex buffer
786	{
787		const VkDeviceSize			vertexBufferSize		= sizeof(vertices[0][0]) * vertices[0].SIZE * vertices.size();
788		const VkBufferCreateInfo	vertexBufferCreateInfo	= makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
789
790		m_vertexCount		= static_cast<deUint32>(vertices.size());
791		m_vertexBuffer		= createBuffer(vkd, device, &vertexBufferCreateInfo);
792		m_vertexBufferAlloc	= bindBuffer(vkd, device, allocator, *m_vertexBuffer, vk::MemoryRequirement::HostVisible);
793
794		deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
795		flushAlloc(vkd, device, *m_vertexBufferAlloc);
796	}
797}
798
799Move<VkPipeline> GraphicsConfiguration::makeGraphicsPipeline (Context&		context,
800															  TestParams&	testParams)
801{
802	const DeviceInterface&			vkd					= context.getDeviceInterface();
803	const VkDevice					device				= context.getDevice();
804	const bool						tessStageTest		= (testParams.stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || testParams.stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
805	const VkPrimitiveTopology		topology			= tessStageTest ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
806	const deUint32					patchControlPoints	= tessStageTest ? 3 : 0;
807	const std::vector<VkViewport>	viewports			(1, makeViewport(testParams.width, testParams.height));
808	const std::vector<VkRect2D>		scissors			(1, makeRect2D(testParams.width, testParams.height));
809
810	return vk::makeGraphicsPipeline	(vkd,
811									 device,
812									 *m_pipelineLayout,
813									 *m_vertShaderModule,
814									 *m_tescShaderModule,
815									 *m_teseShaderModule,
816									 *m_geomShaderModule,
817									 *m_fragShaderModule,
818									 *m_renderPass,
819									 viewports,
820									 scissors,
821									 topology,
822									 0,
823									 patchControlPoints);
824}
825
826void GraphicsConfiguration::initConfiguration (Context&		context,
827											   TestParams&	testParams)
828{
829	const InstanceInterface&	vki				= context.getInstanceInterface();
830	const DeviceInterface&		vkd				= context.getDeviceInterface();
831	const VkDevice				device			= context.getDevice();
832	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
833	Allocator&					allocator		= context.getDefaultAllocator();
834	vk::BinaryCollection&		collection		= context.getBinaryCollection();
835	VkShaderStageFlags			shaders			= static_cast<VkShaderStageFlags>(0);
836	deUint32					shaderCount		= 0;
837
838	VkPhysicalDeviceFeatures features;
839	vki.getPhysicalDeviceFeatures(physicalDevice, &features);
840	const bool				pointSizeRequired = features.shaderTessellationAndGeometryPointSize;
841
842	if (collection.contains("vert")) shaders |= VK_SHADER_STAGE_VERTEX_BIT;
843	if (collection.contains(getGeomName(pointSizeRequired))) shaders |= VK_SHADER_STAGE_GEOMETRY_BIT;
844	if (collection.contains("tesc")) shaders |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
845	if (collection.contains("tese")) shaders |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
846	if (collection.contains("frag")) shaders |= VK_SHADER_STAGE_FRAGMENT_BIT;
847
848	for (BinaryCollection::Iterator it = collection.begin(); it != collection.end(); ++it)
849		shaderCount++;
850
851	if (collection.contains(getGeomName(!pointSizeRequired))) --shaderCount;
852
853	if (shaderCount != (deUint32)dePop32(shaders))
854		TCU_THROW(InternalError, "Unused shaders detected in the collection");
855
856	if (0 != (shaders & VK_SHADER_STAGE_VERTEX_BIT))					m_vertShaderModule = createShaderModule(vkd, device, collection.get("vert"), 0);
857	if (0 != (shaders & VK_SHADER_STAGE_GEOMETRY_BIT))					m_geomShaderModule = createShaderModule(vkd, device, collection.get(getGeomName(pointSizeRequired)), 0);
858	if (0 != (shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT))		m_tescShaderModule = createShaderModule(vkd, device, collection.get("tesc"), 0);
859	if (0 != (shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))	m_teseShaderModule = createShaderModule(vkd, device, collection.get("tese"), 0);
860	if (0 != (shaders & VK_SHADER_STAGE_FRAGMENT_BIT))					m_fragShaderModule = createShaderModule(vkd, device, collection.get("frag"), 0);
861
862	m_descriptorSetLayout	= DescriptorSetLayoutBuilder()
863								.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_ALL_GRAPHICS)
864								.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL_GRAPHICS)
865								.build(vkd, device);
866	m_descriptorPool		= DescriptorPoolBuilder()
867								.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
868								.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
869								.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
870	m_descriptorSet			= makeDescriptorSet		(vkd, device, *m_descriptorPool, *m_descriptorSetLayout);
871	m_framebufferImage		= makeImage				(vkd, device, makeImageCreateInfo(m_framebufferFormat, testParams.width, testParams.height, 1u, VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
872	m_framebufferImageAlloc	= bindImage				(vkd, device, allocator, *m_framebufferImage, MemoryRequirement::Any);
873	m_framebufferAttachment	= makeImageView			(vkd, device, *m_framebufferImage, VK_IMAGE_VIEW_TYPE_2D, m_framebufferFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
874	m_renderPass			= makeRenderPass		(vkd, device, m_framebufferFormat);
875	m_framebuffer			= makeFramebuffer		(vkd, device, *m_renderPass, *m_framebufferAttachment, testParams.width, testParams.height);
876	m_pipelineLayout		= makePipelineLayout	(vkd, device, m_descriptorSetLayout.get());
877	m_pipeline				= makeGraphicsPipeline	(context, testParams);
878
879	initVertexBuffer(context, testParams);
880}
881
882void GraphicsConfiguration::fillCommandBuffer (Context&								context,
883											   TestParams&							testParams,
884											   VkCommandBuffer						cmdBuffer,
885											   const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
886											   const VkDescriptorImageInfo&			resultImageInfo)
887{
888	const DeviceInterface&								vkd												= context.getDeviceInterface();
889	const VkDevice										device											= context.getDevice();
890	const VkDeviceSize									vertexBufferOffset								= 0;
891	const VkWriteDescriptorSetAccelerationStructureKHR	rayQueryAccelerationStructureWriteDescriptorSet	=
892	{
893		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
894		DE_NULL,															//  const void*							pNext;
895		1u,																	//  deUint32							accelerationStructureCount;
896		rayQueryTopAccelerationStructurePtr,								//  const VkAccelerationStructureKHR*	pAccelerationStructures;
897	};
898
899	DescriptorSetUpdateBuilder()
900		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
901		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
902		.update(vkd, device);
903
904	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
905	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
906	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
907
908	beginRenderPass(vkd, cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, testParams.width, testParams.height), tcu::UVec4());
909
910	vkd.cmdDraw(cmdBuffer, m_vertexCount, 1u, 0u, 0u);
911
912	endRenderPass(vkd, cmdBuffer);
913}
914
915class ComputeConfiguration : public PipelineConfiguration
916{
917public:
918								ComputeConfiguration	();
919	virtual						~ComputeConfiguration	() {}
920
921	static void					checkSupport			(Context&							context,
922														 const TestParams&					testParams);
923	static void					initPrograms			(SourceCollections&					programCollection,
924														 const TestParams&					testParams);
925
926	virtual void				initConfiguration		(Context&							context,
927														 TestParams&						testParams) override;
928	virtual void				fillCommandBuffer		(Context&							context,
929														 TestParams&						testParams,
930														 VkCommandBuffer					commandBuffer,
931														 const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
932														 const VkDescriptorImageInfo&		resultImageInfo) override;
933
934protected:
935	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
936	Move<VkDescriptorPool>		m_descriptorPool;
937	Move<VkDescriptorSet>		m_descriptorSet;
938	Move<VkPipelineLayout>		m_pipelineLayout;
939
940	Move<VkShaderModule>		m_shaderModule;
941
942	Move<VkPipeline>			m_pipeline;
943};
944
945ComputeConfiguration::ComputeConfiguration ()
946	: PipelineConfiguration	()
947	, m_descriptorSetLayout	()
948	, m_descriptorPool		()
949	, m_descriptorSet		()
950	, m_pipelineLayout		()
951
952	, m_shaderModule		()
953
954	, m_pipeline			()
955{
956}
957
958void ComputeConfiguration::checkSupport (Context&			context,
959										 const TestParams&	testParams)
960{
961	DE_UNREF(context);
962	DE_UNREF(testParams);
963}
964
965void ComputeConfiguration::initPrograms (SourceCollections&	programCollection,
966										 const TestParams&	testParams)
967{
968	const vk::ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
969	const std::string				testShaderBody		= testParams.testConfigShaderBodyText(testParams);
970	const std::string				testBody			=
971		"  ivec3       pos      = ivec3(gl_WorkGroupID);\n"
972		"  ivec3       size     = ivec3(gl_NumWorkGroups);\n"
973		+ testShaderBody;
974
975	switch (testParams.stage)
976	{
977		case VK_SHADER_STAGE_COMPUTE_BIT:
978		{
979			std::stringstream css;
980			css <<
981				"#version 460 core\n"
982				"#extension GL_EXT_ray_query : require\n"
983				"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
984				"layout(set = 0, binding = 1) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
985				"\n"
986				"void main()\n"
987				"{\n"
988				<< testBody <<
989				"}\n";
990
991			programCollection.glslSources.add("comp") << glu::ComputeSource(updateRayTracingGLSL(css.str())) << buildOptions;
992
993			break;
994		}
995
996		default:
997			TCU_THROW(InternalError, "Unknown stage");
998	}
999}
1000
1001void ComputeConfiguration::initConfiguration (Context&		context,
1002											  TestParams&	testParams)
1003{
1004	DE_UNREF(testParams);
1005
1006	const DeviceInterface&	vkd			= context.getDeviceInterface();
1007	const VkDevice			device		= context.getDevice();
1008	vk::BinaryCollection&	collection	= context.getBinaryCollection();
1009
1010	m_descriptorSetLayout	= DescriptorSetLayoutBuilder()
1011								.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1012								.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_COMPUTE_BIT)
1013								.build(vkd, device);
1014	m_descriptorPool		= DescriptorPoolBuilder()
1015								.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1016								.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1017								.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1018	m_descriptorSet			= makeDescriptorSet(vkd, device, *m_descriptorPool, *m_descriptorSetLayout);
1019	m_pipelineLayout		= makePipelineLayout(vkd, device, m_descriptorSetLayout.get());
1020	m_shaderModule			= createShaderModule(vkd, device, collection.get("comp"), 0);
1021	m_pipeline				= makeComputePipeline(vkd, device, *m_pipelineLayout, *m_shaderModule);
1022}
1023
1024void ComputeConfiguration::fillCommandBuffer (Context&							context,
1025											  TestParams&						testParams,
1026											  VkCommandBuffer					cmdBuffer,
1027											  const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
1028											  const VkDescriptorImageInfo&		resultImageInfo)
1029{
1030	const DeviceInterface&								vkd												= context.getDeviceInterface();
1031	const VkDevice										device											= context.getDevice();
1032	const VkWriteDescriptorSetAccelerationStructureKHR	rayQueryAccelerationStructureWriteDescriptorSet	=
1033	{
1034		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1035		DE_NULL,															//  const void*							pNext;
1036		1u,																	//  deUint32							accelerationStructureCount;
1037		rayQueryTopAccelerationStructurePtr,								//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1038	};
1039
1040	DescriptorSetUpdateBuilder()
1041		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
1042		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
1043		.update(vkd, device);
1044
1045	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
1046
1047	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline.get());
1048
1049	vkd.cmdDispatch(cmdBuffer, testParams.width, testParams.height, 1);
1050}
1051
1052class RayTracingConfiguration : public PipelineConfiguration
1053{
1054public:
1055													RayTracingConfiguration				();
1056	virtual											~RayTracingConfiguration			() {}
1057
1058	static void										checkSupport						(Context&							context,
1059																						 const TestParams&					testParams);
1060	static void										initPrograms						(SourceCollections&					programCollection,
1061																						 const TestParams&					testParams);
1062
1063	virtual void									initConfiguration					(Context&							context,
1064																						 TestParams&						testParams) override;
1065	virtual void									fillCommandBuffer					(Context&							context,
1066																						 TestParams&						testParams,
1067																						 VkCommandBuffer					commandBuffer,
1068																						 const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
1069																						 const VkDescriptorImageInfo&		resultImageInfo) override;
1070
1071protected:
1072	de::MovePtr<BufferWithMemory>					createShaderBindingTable			(const InstanceInterface&			vki,
1073																						 const DeviceInterface&				vkd,
1074																						 const VkDevice						device,
1075																						 const VkPhysicalDevice				physicalDevice,
1076																						 const VkPipeline					pipeline,
1077																						 Allocator&							allocator,
1078																						 de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
1079																						 const deUint32						group);
1080
1081protected:
1082	deUint32										m_shaders;
1083	deUint32										m_raygenShaderGroup;
1084	deUint32										m_missShaderGroup;
1085	deUint32										m_hitShaderGroup;
1086	deUint32										m_callableShaderGroup;
1087	deUint32										m_shaderGroupCount;
1088
1089	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
1090	Move<VkDescriptorPool>							m_descriptorPool;
1091	Move<VkDescriptorSet>							m_descriptorSet;
1092	Move<VkPipelineLayout>							m_pipelineLayout;
1093
1094	de::MovePtr<RayTracingPipeline>					m_rayTracingPipeline;
1095	Move<VkPipeline>								m_pipeline;
1096
1097	de::MovePtr<BufferWithMemory>					m_raygenShaderBindingTable;
1098	de::MovePtr<BufferWithMemory>					m_hitShaderBindingTable;
1099	de::MovePtr<BufferWithMemory>					m_missShaderBindingTable;
1100	de::MovePtr<BufferWithMemory>					m_callableShaderBindingTable;
1101
1102	VkStridedDeviceAddressRegionKHR					m_raygenShaderBindingTableRegion;
1103	VkStridedDeviceAddressRegionKHR					m_missShaderBindingTableRegion;
1104	VkStridedDeviceAddressRegionKHR					m_hitShaderBindingTableRegion;
1105	VkStridedDeviceAddressRegionKHR					m_callableShaderBindingTableRegion;
1106
1107	de::SharedPtr<BottomLevelAccelerationStructure>	m_bottomLevelAccelerationStructure;
1108	de::SharedPtr<TopLevelAccelerationStructure>	m_topLevelAccelerationStructure;
1109};
1110
1111RayTracingConfiguration::RayTracingConfiguration()
1112	: m_shaders								(0)
1113	, m_raygenShaderGroup					(~0u)
1114	, m_missShaderGroup						(~0u)
1115	, m_hitShaderGroup						(~0u)
1116	, m_callableShaderGroup					(~0u)
1117	, m_shaderGroupCount					(0)
1118
1119	, m_descriptorSetLayout					()
1120	, m_descriptorPool						()
1121	, m_descriptorSet						()
1122	, m_pipelineLayout						()
1123
1124	, m_rayTracingPipeline					()
1125	, m_pipeline							()
1126
1127	, m_raygenShaderBindingTable			()
1128	, m_hitShaderBindingTable				()
1129	, m_missShaderBindingTable				()
1130	, m_callableShaderBindingTable			()
1131
1132	, m_raygenShaderBindingTableRegion		()
1133	, m_missShaderBindingTableRegion		()
1134	, m_hitShaderBindingTableRegion			()
1135	, m_callableShaderBindingTableRegion	()
1136
1137	, m_bottomLevelAccelerationStructure	()
1138	, m_topLevelAccelerationStructure		()
1139{
1140}
1141
1142void RayTracingConfiguration::checkSupport (Context&			context,
1143											const TestParams&	testParams)
1144{
1145	DE_UNREF(testParams);
1146
1147	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1148	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
1149	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE)
1150		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
1151}
1152
1153void RayTracingConfiguration::initPrograms (SourceCollections&	programCollection,
1154											const TestParams&	testParams)
1155{
1156	const vk::ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1157
1158	const std::string				testShaderBody		= testParams.testConfigShaderBodyText(testParams);
1159	const std::string				testBody			=
1160		"  ivec3       pos      = ivec3(gl_LaunchIDEXT);\n"
1161		"  ivec3       size     = ivec3(gl_LaunchSizeEXT);\n"
1162		+ testShaderBody;
1163
1164	switch (testParams.stage)
1165	{
1166		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
1167		{
1168			std::stringstream css;
1169			css <<
1170				"#version 460 core\n"
1171				"#extension GL_EXT_ray_tracing : require\n"
1172				"#extension GL_EXT_ray_query : require\n"
1173				"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1174				"layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
1175				"\n"
1176				"void main()\n"
1177				"{\n"
1178				<< testBody <<
1179				"}\n";
1180
1181			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1182
1183			break;
1184		}
1185
1186		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1187		{
1188			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1189
1190			{
1191				std::stringstream css;
1192				css <<
1193					"#version 460 core\n"
1194					"#extension GL_EXT_ray_tracing : require\n"
1195					"#extension GL_EXT_ray_query : require\n"
1196					"hitAttributeEXT vec3 attribs;\n"
1197					"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1198					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1199					"layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
1200					"\n"
1201					"void main()\n"
1202					"{\n"
1203					<< testBody <<
1204					"}\n";
1205
1206				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1207			}
1208
1209			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1210			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1211
1212			break;
1213		}
1214
1215		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1216		{
1217			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1218
1219			{
1220				std::stringstream css;
1221				css <<
1222					"#version 460 core\n"
1223					"#extension GL_EXT_ray_tracing : require\n"
1224					"#extension GL_EXT_ray_query : require\n"
1225					"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1226					"hitAttributeEXT vec3 attribs;\n"
1227					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1228					"layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
1229					"\n"
1230					"void main()\n"
1231					"{\n"
1232					<< testBody <<
1233					"}\n";
1234
1235				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1236			}
1237
1238			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1239			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1240
1241			break;
1242		}
1243
1244		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1245		{
1246			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1247
1248			{
1249				std::stringstream css;
1250				css <<
1251					"#version 460 core\n"
1252					"#extension GL_EXT_ray_tracing : require\n"
1253					"#extension GL_EXT_ray_query : require\n"
1254					"hitAttributeEXT vec3 hitAttribute;\n"
1255					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1256					"layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
1257					"\n"
1258					"void main()\n"
1259					"{\n"
1260					<< testBody <<
1261					"  hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
1262					"  reportIntersectionEXT(1.0f, 0);\n"
1263					"}\n";
1264
1265				programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1266			}
1267
1268			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1269			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1270			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1271
1272			break;
1273		}
1274
1275		case VK_SHADER_STAGE_MISS_BIT_KHR:
1276		{
1277			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1278
1279			{
1280				std::stringstream css;
1281				css <<
1282					"#version 460 core\n"
1283					"#extension GL_EXT_ray_tracing : require\n"
1284					"#extension GL_EXT_ray_query : require\n"
1285					"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1286					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1287					"layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
1288					"\n"
1289					"void main()\n"
1290					"{\n"
1291					<< testBody <<
1292					"}\n";
1293
1294				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1295			}
1296
1297			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1298			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1299
1300			break;
1301		}
1302
1303		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
1304		{
1305			{
1306				std::stringstream css;
1307				css <<
1308					"#version 460 core\n"
1309					"#extension GL_EXT_ray_tracing : require\n"
1310					"#extension GL_EXT_ray_query : require\n"
1311					"layout(location = 0) callableDataEXT float dummy;"
1312					"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
1313					"\n"
1314					"void main()\n"
1315					"{\n"
1316					"  executeCallableEXT(0, 0);\n"
1317					"}\n";
1318
1319				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
1320			}
1321
1322			{
1323				std::stringstream css;
1324				css <<
1325					"#version 460 core\n"
1326					"#extension GL_EXT_ray_tracing : require\n"
1327					"#extension GL_EXT_ray_query : require\n"
1328					"layout(location = 0) callableDataInEXT float dummy;"
1329					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1330					"layout(set = 0, binding = 2) uniform accelerationStructureEXT rayQueryTopLevelAccelerationStructure;\n"
1331					"\n"
1332					"void main()\n"
1333					"{\n"
1334					<< testBody <<
1335					"}\n";
1336
1337				programCollection.glslSources.add("call") << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
1338			}
1339
1340			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1341			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1342			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1343
1344			break;
1345		}
1346
1347		default:
1348			TCU_THROW(InternalError, "Unknown stage");
1349	}
1350}
1351
1352de::MovePtr<BufferWithMemory> RayTracingConfiguration::createShaderBindingTable (const InstanceInterface&			vki,
1353																				 const DeviceInterface&				vkd,
1354																				 const VkDevice						device,
1355																				 const VkPhysicalDevice				physicalDevice,
1356																				 const VkPipeline					pipeline,
1357																				 Allocator&							allocator,
1358																				 de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
1359																				 const deUint32						group)
1360{
1361	de::MovePtr<BufferWithMemory>	shaderBindingTable;
1362
1363	if (group < m_shaderGroupCount)
1364	{
1365		const deUint32	shaderGroupHandleSize		= getShaderGroupHandleSize(vki, physicalDevice);
1366		const deUint32	shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
1367
1368		shaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, 1u);
1369	}
1370
1371	return shaderBindingTable;
1372}
1373
1374void RayTracingConfiguration::initConfiguration (Context&		context,
1375												 TestParams&	testParams)
1376{
1377	DE_UNREF(testParams);
1378
1379	const InstanceInterface&	vki						= context.getInstanceInterface();
1380	const DeviceInterface&		vkd						= context.getDeviceInterface();
1381	const VkDevice				device					= context.getDevice();
1382	const VkPhysicalDevice		physicalDevice			= context.getPhysicalDevice();
1383	vk::BinaryCollection&		collection				= context.getBinaryCollection();
1384	Allocator&					allocator				= context.getDefaultAllocator();
1385	const deUint32				shaderGroupHandleSize	= getShaderGroupHandleSize(vki, physicalDevice);
1386	const VkShaderStageFlags	hitStages				= VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
1387	deUint32					shaderCount				= 0;
1388
1389	m_shaderGroupCount = 0;
1390
1391	if (collection.contains("rgen")) m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
1392	if (collection.contains("ahit")) m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
1393	if (collection.contains("chit")) m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
1394	if (collection.contains("miss")) m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
1395	if (collection.contains("sect")) m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
1396	if (collection.contains("call")) m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
1397
1398	for (BinaryCollection::Iterator it = collection.begin(); it != collection.end(); ++it)
1399		shaderCount++;
1400
1401	if (shaderCount != (deUint32)dePop32(m_shaders))
1402		TCU_THROW(InternalError, "Unused shaders detected in the collection");
1403
1404	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
1405		m_raygenShaderGroup		= m_shaderGroupCount++;
1406
1407	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
1408		m_missShaderGroup		= m_shaderGroupCount++;
1409
1410	if (0 != (m_shaders & hitStages))
1411		m_hitShaderGroup		= m_shaderGroupCount++;
1412
1413	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
1414		m_callableShaderGroup	= m_shaderGroupCount++;
1415
1416	m_rayTracingPipeline				= de::newMovePtr<RayTracingPipeline>();
1417
1418	m_descriptorSetLayout				= DescriptorSetLayoutBuilder()
1419											.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1420											.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1421											.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1422											.build(vkd, device);
1423	m_descriptorPool					= DescriptorPoolBuilder()
1424											.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1425											.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1426											.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1427											.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1428	m_descriptorSet						= makeDescriptorSet(vkd, device, *m_descriptorPool, *m_descriptorSetLayout);
1429
1430	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))			m_rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR			, createShaderModule(vkd, device, collection.get("rgen"), 0), m_raygenShaderGroup);
1431	if (0 != (m_shaders & VK_SHADER_STAGE_ANY_HIT_BIT_KHR))			m_rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR			, createShaderModule(vkd, device, collection.get("ahit"), 0), m_hitShaderGroup);
1432	if (0 != (m_shaders & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))		m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR		, createShaderModule(vkd, device, collection.get("chit"), 0), m_hitShaderGroup);
1433	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))			m_rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR			, createShaderModule(vkd, device, collection.get("miss"), 0), m_missShaderGroup);
1434	if (0 != (m_shaders & VK_SHADER_STAGE_INTERSECTION_BIT_KHR))	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR	, createShaderModule(vkd, device, collection.get("sect"), 0), m_hitShaderGroup);
1435	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))		m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR		, createShaderModule(vkd, device, collection.get("call"), 0), m_callableShaderGroup);
1436
1437	m_pipelineLayout					= makePipelineLayout(vkd, device, m_descriptorSetLayout.get());
1438	m_pipeline							= m_rayTracingPipeline->createPipeline(vkd, device, *m_pipelineLayout);
1439
1440	m_raygenShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_raygenShaderGroup);
1441	m_missShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_missShaderGroup);
1442	m_hitShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_hitShaderGroup);
1443	m_callableShaderBindingTable		= createShaderBindingTable(vki, vkd, device, physicalDevice, *m_pipeline, allocator, m_rayTracingPipeline, m_callableShaderGroup);
1444
1445	m_raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_raygenShaderBindingTable),		shaderGroupHandleSize);
1446	m_missShaderBindingTableRegion		= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_missShaderBindingTable),		shaderGroupHandleSize);
1447	m_hitShaderBindingTableRegion		= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_hitShaderBindingTable),			shaderGroupHandleSize);
1448	m_callableShaderBindingTableRegion	= makeStridedDeviceAddressRegion(vkd, device, getVkBuffer(m_callableShaderBindingTable),	shaderGroupHandleSize);
1449}
1450
1451void RayTracingConfiguration::fillCommandBuffer (Context&							context,
1452												 TestParams&						testParams,
1453												 VkCommandBuffer					commandBuffer,
1454												 const VkAccelerationStructureKHR*	rayQueryTopAccelerationStructurePtr,
1455												 const VkDescriptorImageInfo&		resultImageInfo)
1456{
1457	const DeviceInterface&							vkd									= context.getDeviceInterface();
1458	const VkDevice									device								= context.getDevice();
1459	Allocator&										allocator							= context.getDefaultAllocator();
1460	de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure	= makeBottomLevelAccelerationStructure();
1461	de::MovePtr<TopLevelAccelerationStructure>		topLevelAccelerationStructure		= makeTopLevelAccelerationStructure();
1462
1463	m_bottomLevelAccelerationStructure = de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release());
1464	m_bottomLevelAccelerationStructure->setDefaultGeometryData(testParams.stage);
1465	m_bottomLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator);
1466
1467	m_topLevelAccelerationStructure = de::SharedPtr<TopLevelAccelerationStructure>(topLevelAccelerationStructure.release());
1468	m_topLevelAccelerationStructure->setInstanceCount(1);
1469	m_topLevelAccelerationStructure->addInstance(m_bottomLevelAccelerationStructure);
1470	m_topLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator);
1471
1472	const TopLevelAccelerationStructure*				topLevelAccelerationStructurePtr				= m_topLevelAccelerationStructure.get();
1473	const VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet			=
1474	{
1475		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1476		DE_NULL,															//  const void*							pNext;
1477		1u,																	//  deUint32							accelerationStructureCount;
1478		topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1479	};
1480	const VkWriteDescriptorSetAccelerationStructureKHR	rayQueryAccelerationStructureWriteDescriptorSet	=
1481	{
1482		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1483		DE_NULL,															//  const void*							pNext;
1484		1u,																	//  deUint32							accelerationStructureCount;
1485		rayQueryTopAccelerationStructurePtr,								//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1486	};
1487
1488	DescriptorSetUpdateBuilder()
1489		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
1490		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1491		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
1492		.update(vkd, device);
1493
1494	vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
1495
1496	vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, m_pipeline.get());
1497
1498	cmdTraceRays(vkd,
1499		commandBuffer,
1500		&m_raygenShaderBindingTableRegion,
1501		&m_missShaderBindingTableRegion,
1502		&m_hitShaderBindingTableRegion,
1503		&m_callableShaderBindingTableRegion,
1504		testParams.width, testParams.height, 1);
1505}
1506
1507
1508const std::string getShaderBodyText (const TestParams& testParams)
1509{
1510	if (testParams.geomType == GEOM_TYPE_AABBS)
1511	{
1512		const std::string result =
1513			"  uint        rayFlags = 0;\n"
1514			"  uint        cullMask = 0xFF;\n"
1515			"  float       tmin     = 0.0;\n"
1516			"  float       tmax     = 9.0;\n"
1517			"  vec3        origin   = vec3((float(pos.x) + 0.5f) / float(size.x), (float(pos.y) + 0.5f) / float(size.y), 0.0);\n"
1518			"  vec3        direct   = vec3(0.0, 0.0, -1.0);\n"
1519			"  uint        count    = 0;\n"
1520			"  rayQueryEXT rayQuery;\n"
1521			"\n"
1522			"  rayQueryInitializeEXT(rayQuery, rayQueryTopLevelAccelerationStructure, rayFlags, cullMask, origin, tmin, direct, tmax);\n"
1523			"\n"
1524			"  while(rayQueryProceedEXT(rayQuery))\n"
1525			"  {\n"
1526			"    if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCandidateIntersectionAABBEXT)\n"
1527			"    {\n"
1528			"      rayQueryGenerateIntersectionEXT(rayQuery, 0.5f);\n"
1529			"      count++;\n"
1530			"    }\n"
1531			"  }\n"
1532			"  imageStore(result, pos, ivec4(count, 0, 0, 0));\n"
1533			"\n";
1534
1535		return result;
1536	}
1537	else if (testParams.geomType == GEOM_TYPE_TRIANGLES)
1538	{
1539		const std::string result =
1540			"  uint        rayFlags = gl_RayFlagsNoOpaqueEXT;\n"
1541			"  uint        cullMask = 0xFF;\n"
1542			"  float       tmin     = 0.0;\n"
1543			"  float       tmax     = 9.0;\n"
1544			"  vec3        origin   = vec3((float(pos.x) + 0.5f) / float(size.x), (float(pos.y) + 0.5f) / float(size.y), 0.0);\n"
1545			"  vec3        direct   = vec3(0.0, 0.0, -1.0);\n"
1546			"  uint        count    = 0;\n"
1547			"  rayQueryEXT rayQuery;\n"
1548			"\n"
1549			"  rayQueryInitializeEXT(rayQuery, rayQueryTopLevelAccelerationStructure, rayFlags, cullMask, origin, tmin, direct, tmax);\n"
1550			"\n"
1551			"  while(rayQueryProceedEXT(rayQuery))\n"
1552			"  {\n"
1553			"    if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCandidateIntersectionTriangleEXT)\n"
1554			"    {\n"
1555			"      rayQueryConfirmIntersectionEXT(rayQuery);\n"
1556			"      count++;\n"
1557			"    }\n"
1558			"  }\n"
1559			"  imageStore(result, pos, ivec4(count, 0, 0, 0));\n"
1560			"\n";
1561
1562		return result;
1563	}
1564	else
1565	{
1566		TCU_THROW(InternalError, "Unknown geometry type");
1567	}
1568}
1569
1570
1571class TestConfigurationNoMiss : public TestConfiguration
1572{
1573public:
1574	virtual const VkAccelerationStructureKHR*	initAccelerationStructures	(Context&							context,
1575																			 TestParams&						testParams,
1576																			 VkCommandBuffer					cmdBuffer) override;
1577
1578	virtual bool								verify						(BufferWithMemory*					resultBuffer,
1579																			 Context&							context,
1580																			 TestParams&						testParams) override;
1581private:
1582	deUint32									chooseAABB					(de::Random&						rng,
1583																			 const std::vector<tcu::Vec2>&		vertices,
1584																			 const std::vector<tcu::UVec2>&		aabbs);
1585	deUint32									chooseTriangle				(de::Random&						rng,
1586																			 const std::vector<tcu::Vec2>&		vertices,
1587																			 const std::vector<tcu::UVec3>&		triangles);
1588};
1589
1590deUint32 TestConfigurationNoMiss::chooseAABB (de::Random&						rng,
1591											  const std::vector<tcu::Vec2>&		vertices,
1592											  const std::vector<tcu::UVec2>&	aabbs)
1593{
1594	while (true)
1595	{
1596		const deUint32		n	= (deUint32)rng.getInt(0, (deUint32)aabbs.size() - 1);
1597		const tcu::UVec2&	t	= aabbs[n];
1598		const tcu::Vec2&	a	= vertices[t.x()];
1599		const tcu::Vec2&	b	= vertices[t.y()];
1600
1601		if (deFloatAbs(a.x() - b.x()) < MIN_AABB_SIDE_LENGTH || deFloatAbs(a.y() - b.y()) < MIN_AABB_SIDE_LENGTH)
1602			continue;
1603
1604		return n;
1605	}
1606}
1607
1608deUint32 TestConfigurationNoMiss::chooseTriangle (de::Random&						rng,
1609												  const std::vector<tcu::Vec2>&		vertices,
1610												  const std::vector<tcu::UVec3>&	triangles)
1611{
1612	while (true)
1613	{
1614		const deUint32		n	= (deUint32)rng.getInt(0, (deUint32)triangles.size() - 1);
1615		const tcu::UVec3&	t	= triangles[n];
1616		const tcu::Vec2&	a	= vertices[t.x()];
1617		const tcu::Vec2&	b	= vertices[t.y()];
1618		const tcu::Vec2&	c	= vertices[t.z()];
1619		const float			ab	= triangleEdgeLength(a, b);
1620		const float			bc	= triangleEdgeLength(b, c);
1621		const float			ca	= triangleEdgeLength(c, a);
1622
1623		if (ab < MIN_TRIANGLE_EDGE_LENGTH || bc < MIN_TRIANGLE_EDGE_LENGTH || ca < MIN_TRIANGLE_EDGE_LENGTH || triangleArea(ab, bc, ca) < MIN_TRIANGLE_AREA_SIZE)
1624			continue;
1625
1626		return n;
1627	}
1628}
1629
1630const VkAccelerationStructureKHR* TestConfigurationNoMiss::initAccelerationStructures (Context&			context,
1631																					   TestParams&		testParams,
1632																					   VkCommandBuffer	cmdBuffer)
1633{
1634	const DeviceInterface&							vkd											= context.getDeviceInterface();
1635	const VkDevice									device										= context.getDevice();
1636	Allocator&										allocator									= context.getDefaultAllocator();
1637	const tcu::Vec2									centerPixelCenter							= tcu::Vec2(0.5f - 0.5f / float(testParams.width), 0.5f - 0.5f / float(testParams.height));
1638	de::MovePtr<BottomLevelAccelerationStructure>	rayQueryBottomLevelAccelerationStructure	= makeBottomLevelAccelerationStructure();
1639	de::MovePtr<TopLevelAccelerationStructure>		rayQueryTopLevelAccelerationStructure		= makeTopLevelAccelerationStructure();
1640	de::Random										rng											(testParams.randomSeed);
1641	std::vector<tcu::Vec3>							geometryData;
1642
1643	if (testParams.geomType == GEOM_TYPE_AABBS)
1644	{
1645		std::vector<tcu::UVec2>	aabbs;
1646		std::vector<tcu::Vec2>	vertices;
1647
1648		vertices.reserve(2u * testParams.squaresGroupCount);
1649		aabbs.reserve(testParams.squaresGroupCount);
1650
1651		{
1652			// a---g---+
1653			// |   |   |
1654			// e---d---h
1655			// |   |   |
1656			// +---f---b
1657			//
1658			// a-d, d-b, e-f, g-h
1659
1660			const tcu::Vec2		d	= centerPixelCenter;
1661			const tcu::Vec2		a	= tcu::Vec2(0.0f, 0.0f);
1662			const tcu::Vec2		b	= tcu::Vec2(1.0f, 1.0f);
1663			const tcu::Vec2		e	= tcu::Vec2(a.x(), d.y());
1664			const tcu::Vec2		f	= tcu::Vec2(d.x(), b.y());
1665			const tcu::Vec2		g	= tcu::Vec2(d.x(), a.y());
1666			const tcu::Vec2		h	= tcu::Vec2(b.x(), d.y());
1667			const deUint32		A	= 0;
1668			const deUint32		B	= 1;
1669			const deUint32		D	= 2;
1670			const deUint32		E	= 3;
1671			const deUint32		F	= 4;
1672			const deUint32		G	= 5;
1673			const deUint32		H	= 6;
1674
1675			vertices.push_back(a);
1676			vertices.push_back(b);
1677			vertices.push_back(d);
1678			vertices.push_back(e);
1679			vertices.push_back(f);
1680			vertices.push_back(g);
1681			vertices.push_back(h);
1682
1683			aabbs.push_back(tcu::UVec2(A, D));
1684			aabbs.push_back(tcu::UVec2(D, B));
1685			aabbs.push_back(tcu::UVec2(E, F));
1686			aabbs.push_back(tcu::UVec2(G, H));
1687		}
1688
1689		while (aabbs.size() < testParams.squaresGroupCount)
1690		{
1691			// a-------+      a---g---+
1692			// |       |      |   |   |
1693			// |       |  ->  e---d---h
1694			// |       |      |   |   |
1695			// +-------b      +---f---b
1696			//
1697			// a-b        ->  a-d, d-b, e-f, g-h
1698
1699			const deUint32		n		= chooseAABB(rng, vertices, aabbs);
1700			tcu::UVec2&			t		= aabbs[n];
1701			const tcu::Vec2&	a		= vertices[t.x()];
1702			const tcu::Vec2&	b		= vertices[t.y()];
1703			const float			alfa	= rng.getFloat(0.2f, 0.8f);
1704			const float			beta	= rng.getFloat(0.2f, 0.8f);
1705			const tcu::Vec2		d		= mixCoordsVec2(a, b, alfa, beta);
1706			const tcu::Vec2		e		= tcu::Vec2(a.x(), d.y());
1707			const tcu::Vec2		f		= tcu::Vec2(d.x(), b.y());
1708			const tcu::Vec2		g		= tcu::Vec2(d.x(), a.y());
1709			const tcu::Vec2		h		= tcu::Vec2(b.x(), d.y());
1710			const deUint32		B		= t.y();
1711			const deUint32		D		= (deUint32)vertices.size();
1712			const deUint32		E		= D + 1;
1713			const deUint32		F		= D + 2;
1714			const deUint32		G		= D + 3;
1715			const deUint32		H		= D + 4;
1716
1717			if (d.x() <= a.x() || d.x() >= b.x() || d.y() <= a.y() || d.y() >= b.y())
1718				continue;
1719
1720			vertices.push_back(d);
1721			vertices.push_back(e);
1722			vertices.push_back(f);
1723			vertices.push_back(g);
1724			vertices.push_back(h);
1725
1726			t.y() = D;
1727			aabbs.push_back(tcu::UVec2(D, B));
1728			aabbs.push_back(tcu::UVec2(E, F));
1729			aabbs.push_back(tcu::UVec2(G, H));
1730		}
1731
1732		geometryData.reserve(2u * aabbs.size());
1733
1734		for (size_t i = 0; i < aabbs.size(); ++i)
1735		{
1736			const tcu::Vec2&	a	= vertices[aabbs[i].x()];
1737			const tcu::Vec2&	b	= vertices[aabbs[i].y()];
1738			const float			az	= -rng.getFloat(0.1f, 0.5f);
1739			const float			bz	= az + 0.01f;
1740			const tcu::Vec3		A	= tcu::Vec3(a.x(), a.y(), az);
1741			const tcu::Vec3		B	= tcu::Vec3(b.x(), b.y(), bz);
1742
1743			geometryData.push_back(A);
1744			geometryData.push_back(B);
1745		}
1746	}
1747	else if (testParams.geomType == GEOM_TYPE_TRIANGLES)
1748	{
1749		std::vector<tcu::UVec3>	triangles;
1750		std::vector<tcu::Vec2>	vertices;
1751		std::vector<float>		verticesZ;
1752
1753		vertices.reserve(3u * testParams.squaresGroupCount);
1754		triangles.reserve(testParams.squaresGroupCount);
1755
1756		{
1757			// Initial triangle set: aeb, bec, cef, fei, ieh, heg, ged, dea
1758			// e - is not math middle, but centrum of one of the pixels
1759			// a---b---c
1760			// | \ | / |
1761			// d---e---f
1762			// | / | \ |
1763			// g---h---i
1764
1765			const tcu::Vec2		e	= centerPixelCenter;
1766			const tcu::Vec2		a	= tcu::Vec2( 0.0f,  0.0f);
1767			const tcu::Vec2		i	= tcu::Vec2( 1.0f,  1.0f);
1768			const tcu::Vec2		c	= tcu::Vec2(i.x(), a.y());
1769			const tcu::Vec2		g	= tcu::Vec2(a.x(), i.y());
1770			const tcu::Vec2		b	= tcu::Vec2(e.x(), a.y());
1771			const tcu::Vec2		d	= tcu::Vec2(a.x(), e.y());
1772			const tcu::Vec2		f	= tcu::Vec2(i.x(), e.y());
1773			const tcu::Vec2		h	= tcu::Vec2(e.x(), i.y());
1774			const deUint32		A	= 0;
1775			const deUint32		B	= 1;
1776			const deUint32		C	= 2;
1777			const deUint32		D	= 3;
1778			const deUint32		E	= 4;
1779			const deUint32		F	= 5;
1780			const deUint32		G	= 6;
1781			const deUint32		H	= 7;
1782			const deUint32		I	= 8;
1783
1784			vertices.push_back(a);
1785			vertices.push_back(b);
1786			vertices.push_back(c);
1787			vertices.push_back(d);
1788			vertices.push_back(e);
1789			vertices.push_back(f);
1790			vertices.push_back(g);
1791			vertices.push_back(h);
1792			vertices.push_back(i);
1793
1794			triangles.push_back(tcu::UVec3(A, E, B));
1795			triangles.push_back(tcu::UVec3(B, E, C));
1796			triangles.push_back(tcu::UVec3(C, E, F));
1797			triangles.push_back(tcu::UVec3(F, E, I));
1798			triangles.push_back(tcu::UVec3(I, E, H));
1799			triangles.push_back(tcu::UVec3(H, E, G));
1800			triangles.push_back(tcu::UVec3(G, E, D));
1801			triangles.push_back(tcu::UVec3(D, E, A));
1802		}
1803
1804		while (triangles.size() < testParams.squaresGroupCount)
1805		{
1806			const deUint32		n		= chooseTriangle(rng, vertices, triangles);
1807			tcu::UVec3&			t		= triangles[n];
1808			const tcu::Vec2&	a		= vertices[t.x()];
1809			const tcu::Vec2&	b		= vertices[t.y()];
1810			const tcu::Vec2&	c		= vertices[t.z()];
1811			const float			alfa	= rng.getFloat(0.2f, 0.8f);
1812			const float			beta	= rng.getFloat(0.2f, 0.8f);
1813			const tcu::Vec2		d		= mixVec2(mixVec2(a, b, alfa), c, beta);
1814			const deUint32&		p		= t.x();
1815			const deUint32&		q		= t.y();
1816			deUint32&			r		= t.z();
1817			const deUint32		R		= (deUint32)vertices.size();
1818
1819			vertices.push_back(d);
1820
1821			triangles.push_back(tcu::UVec3(q, r, R));
1822			triangles.push_back(tcu::UVec3(p, r, R));
1823			r = R;
1824		}
1825
1826		verticesZ.reserve(vertices.size());
1827		for (size_t i = 0; i < vertices.size(); ++i)
1828			verticesZ.push_back(-rng.getFloat(0.01f, 0.99f));
1829
1830		geometryData.reserve(3u * triangles.size());
1831
1832		for (size_t i = 0; i < triangles.size(); ++i)
1833		{
1834			const deUint32	a = triangles[i].x();
1835			const deUint32	b = triangles[i].y();
1836			const deUint32	c = triangles[i].z();
1837
1838			geometryData.push_back(tcu::Vec3(vertices[a].x(), vertices[a].y(), verticesZ[a]));
1839			geometryData.push_back(tcu::Vec3(vertices[b].x(), vertices[b].y(), verticesZ[b]));
1840			geometryData.push_back(tcu::Vec3(vertices[c].x(), vertices[c].y(), verticesZ[c]));
1841		}
1842	}
1843	else
1844	{
1845		TCU_THROW(InternalError, "Unknown geometry type");
1846	}
1847
1848	rayQueryBottomLevelAccelerationStructure->setGeometryCount(1u);
1849	rayQueryBottomLevelAccelerationStructure->addGeometry(geometryData, testParams.geomType == GEOM_TYPE_TRIANGLES);
1850	rayQueryBottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
1851	m_bottomAccelerationStructures.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(rayQueryBottomLevelAccelerationStructure.release()));
1852	m_topAccelerationStructure = de::SharedPtr<TopLevelAccelerationStructure>(rayQueryTopLevelAccelerationStructure.release());
1853	m_topAccelerationStructure->addInstance(m_bottomAccelerationStructures.back());
1854	m_topAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
1855
1856	return m_topAccelerationStructure.get()->getPtr();
1857}
1858
1859bool TestConfigurationNoMiss::verify (BufferWithMemory*					resultBuffer,
1860									  Context&							context,
1861									  TestParams&						testParams)
1862{
1863	tcu::TestLog&	log			= context.getTestContext().getLog();
1864	const deUint32	width		= testParams.width;
1865	const deUint32	height		= testParams.height;
1866	const deInt32*	resultPtr	= (deInt32*)resultBuffer->getAllocation().getHostPtr();
1867	deUint32		failures	= 0;
1868	deUint32		pos			= 0;
1869
1870	for (deUint32 y = 0; y < height; ++y)
1871	for (deUint32 x = 0; x < width; ++x)
1872	{
1873		if (resultPtr[pos] <= 0)
1874			failures++;
1875
1876		pos++;
1877	}
1878
1879	if (failures != 0)
1880	{
1881		std::stringstream	css;
1882
1883		pos = 0;
1884
1885		for (deUint32 y = 0; y < height; ++y)
1886		{
1887			for (deUint32 x = 0; x < width; ++x)
1888			{
1889				if (resultPtr[pos] <= 0)
1890					css << std::setw(3) << resultPtr[pos] << ",";
1891				else
1892					css << "___,";
1893
1894				pos++;
1895			}
1896
1897			css << std::endl;
1898		}
1899
1900		log << tcu::TestLog::Message << "Retrieved:" << tcu::TestLog::EndMessage;
1901		log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
1902	}
1903
1904	return (failures == 0);
1905}
1906
1907
1908class TestConfigurationSingleHit : public TestConfigurationNoMiss
1909{
1910public:
1911	virtual bool								verify						(BufferWithMemory*					resultBuffer,
1912																			 Context&							context,
1913																			 TestParams&						testParams) override;
1914};
1915
1916bool TestConfigurationSingleHit::verify (BufferWithMemory*					resultBuffer,
1917										 Context&							context,
1918										 TestParams&						testParams)
1919{
1920	tcu::TestLog&	log				= context.getTestContext().getLog();
1921	const deUint32	width			= testParams.width;
1922	const deUint32	height			= testParams.height;
1923	const deInt32*	resultPtr		= (deInt32*)resultBuffer->getAllocation().getHostPtr();
1924	const deInt32	expectedValue	= 1;
1925	deUint32		failures		= 0;
1926	deUint32		pos				= 0;
1927
1928	for (deUint32 y = 0; y < height; ++y)
1929	for (deUint32 x = 0; x < width; ++x)
1930	{
1931		if (resultPtr[pos] != expectedValue)
1932			failures++;
1933
1934		pos++;
1935	}
1936
1937	if (failures != 0)
1938	{
1939		std::stringstream	css;
1940
1941		pos = 0;
1942
1943		for (deUint32 y = 0; y < height; ++y)
1944		{
1945			for (deUint32 x = 0; x < width; ++x)
1946			{
1947				if (resultPtr[pos] != expectedValue)
1948					css << std::setw(3) << resultPtr[pos] << ",";
1949				else
1950					css << "___,";
1951
1952				pos++;
1953			}
1954
1955			css << std::endl;
1956		}
1957
1958		log << tcu::TestLog::Message << "Retrieved:" << tcu::TestLog::EndMessage;
1959		log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
1960	}
1961
1962	return (failures == 0);
1963}
1964
1965
1966class RayQueryBuiltinTestInstance : public TestInstance
1967{
1968public:
1969										RayQueryBuiltinTestInstance		(Context& context, const TestParams& data);
1970	virtual								~RayQueryBuiltinTestInstance	(void);
1971	tcu::TestStatus						iterate							(void);
1972
1973private:
1974	TestParams							m_data;
1975	de::MovePtr<TestConfiguration>		m_testConfig;
1976	de::MovePtr<PipelineConfiguration>	m_pipelineConfig;
1977};
1978
1979RayQueryBuiltinTestInstance::RayQueryBuiltinTestInstance (Context& context, const TestParams& data)
1980	: vkt::TestInstance		(context)
1981	, m_data				(data)
1982{
1983	switch (m_data.testType)
1984	{
1985		case TEST_TYPE_NO_MISS:		m_testConfig = de::MovePtr<TestConfiguration>(new TestConfigurationNoMiss());		break;
1986		case TEST_TYPE_SINGLE_HIT:	m_testConfig = de::MovePtr<TestConfiguration>(new TestConfigurationSingleHit());	break;
1987		default: TCU_THROW(InternalError, "Unknown test type");
1988	}
1989
1990	switch (m_data.stage)
1991	{
1992		case VK_SHADER_STAGE_VERTEX_BIT:
1993		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
1994		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
1995		case VK_SHADER_STAGE_GEOMETRY_BIT:
1996		case VK_SHADER_STAGE_FRAGMENT_BIT:
1997		{
1998			m_pipelineConfig = de::MovePtr<PipelineConfiguration>(new GraphicsConfiguration());
1999			break;
2000		}
2001
2002		case VK_SHADER_STAGE_COMPUTE_BIT:
2003		{
2004			m_pipelineConfig = de::MovePtr<PipelineConfiguration>(new ComputeConfiguration());
2005			break;
2006		}
2007
2008		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2009		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2010		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2011		case VK_SHADER_STAGE_MISS_BIT_KHR:
2012		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2013		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2014		{
2015			m_pipelineConfig = de::MovePtr<PipelineConfiguration>(new RayTracingConfiguration());
2016			break;
2017		}
2018
2019		default:
2020			TCU_THROW(InternalError, "Unknown shader stage");
2021	}
2022}
2023
2024RayQueryBuiltinTestInstance::~RayQueryBuiltinTestInstance (void)
2025{
2026}
2027
2028tcu::TestStatus RayQueryBuiltinTestInstance::iterate (void)
2029{
2030	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
2031	const VkDevice						device								= m_context.getDevice();
2032	const VkQueue						queue								= m_context.getUniversalQueue();
2033	Allocator&							allocator							= m_context.getDefaultAllocator();
2034	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
2035
2036	const deUint32						width								= m_data.width;
2037	const deUint32						height								= m_data.height;
2038	const deUint32						depth								= m_data.depth;
2039	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.format, width, height, depth);
2040	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2041	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
2042	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, m_data.format, imageSubresourceRange);
2043
2044	const deUint32						pixelSize							= mapVkFormat(m_data.format).getPixelSize();
2045	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(width * height * depth * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2046	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2047	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(width, height, depth), resultBufferImageSubresourceLayers);
2048	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
2049
2050	const VkDescriptorImageInfo			resultImageInfo						= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
2051
2052	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
2053	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2054	const VkAccelerationStructureKHR*	topAccelerationStructurePtr			= DE_NULL;
2055
2056	m_pipelineConfig->initConfiguration(m_context, m_data);
2057
2058	beginCommandBuffer(vkd, *cmdBuffer, 0u);
2059	{
2060		const VkImageMemoryBarrier	preImageBarrier			= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
2061		const VkClearValue			clearValue				= makeClearValueColorU32(0u, 0u, 0u, 0u);
2062		const VkImageMemoryBarrier	postImageBarrier		= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
2063		const VkMemoryBarrier		postTestMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2064		const VkMemoryBarrier		postCopyMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2065
2066		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
2067		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
2068		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
2069
2070		topAccelerationStructurePtr = m_testConfig->initAccelerationStructures(m_context, m_data, *cmdBuffer);
2071
2072		m_pipelineConfig->fillCommandBuffer(m_context, m_data, *cmdBuffer, topAccelerationStructurePtr, resultImageInfo);
2073
2074		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTestMemoryBarrier);
2075
2076		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
2077
2078		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
2079	}
2080	endCommandBuffer(vkd, *cmdBuffer);
2081
2082	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
2083
2084	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
2085
2086	if (m_testConfig->verify(resultBuffer.get(), m_context, m_data))
2087		return tcu::TestStatus::pass("Pass");
2088	else
2089		return tcu::TestStatus::fail("Fail");
2090}
2091
2092class RayQueryBuiltinTestCase : public TestCase
2093{
2094	public:
2095							RayQueryBuiltinTestCase		(tcu::TestContext& context, const char* name, const TestParams data);
2096							~RayQueryBuiltinTestCase	(void);
2097
2098	virtual void			checkSupport				(Context& context) const;
2099	virtual	void			initPrograms				(SourceCollections& programCollection) const;
2100	virtual TestInstance*	createInstance				(Context& context) const;
2101
2102private:
2103	TestParams				m_data;
2104};
2105
2106RayQueryBuiltinTestCase::RayQueryBuiltinTestCase (tcu::TestContext& context, const char* name, const TestParams data)
2107	: vkt::TestCase	(context, name)
2108	, m_data		(data)
2109{
2110}
2111
2112RayQueryBuiltinTestCase::~RayQueryBuiltinTestCase (void)
2113{
2114}
2115
2116void RayQueryBuiltinTestCase::checkSupport (Context& context) const
2117{
2118	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2119	context.requireDeviceFunctionality("VK_KHR_ray_query");
2120
2121	const VkPhysicalDeviceRayQueryFeaturesKHR&				rayQueryFeaturesKHR					= context.getRayQueryFeatures();
2122	if (rayQueryFeaturesKHR.rayQuery == DE_FALSE)
2123		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
2124
2125	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
2126	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
2127		TCU_THROW(TestError, "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
2128
2129	m_data.pipelineCheckSupport(context, m_data);
2130}
2131
2132TestInstance* RayQueryBuiltinTestCase::createInstance (Context& context) const
2133{
2134	return new RayQueryBuiltinTestInstance(context, m_data);
2135}
2136
2137void RayQueryBuiltinTestCase::initPrograms (SourceCollections& programCollection) const
2138{
2139	m_data.pipelineInitPrograms(programCollection, m_data);
2140}
2141
2142static inline CheckSupportFunc getPipelineCheckSupport (const VkShaderStageFlagBits stage)
2143{
2144	switch (stage)
2145	{
2146		case VK_SHADER_STAGE_VERTEX_BIT:
2147		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
2148		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
2149		case VK_SHADER_STAGE_GEOMETRY_BIT:
2150		case VK_SHADER_STAGE_FRAGMENT_BIT:
2151			return GraphicsConfiguration::checkSupport;
2152
2153		case VK_SHADER_STAGE_COMPUTE_BIT:
2154			return ComputeConfiguration::checkSupport;
2155
2156		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2157		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2158		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2159		case VK_SHADER_STAGE_MISS_BIT_KHR:
2160		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2161		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2162			return RayTracingConfiguration::checkSupport;
2163
2164		default:
2165			TCU_THROW(InternalError, "Unknown shader stage");
2166	}
2167}
2168
2169static inline InitProgramsFunc getPipelineInitPrograms (const VkShaderStageFlagBits stage)
2170{
2171	switch (stage)
2172	{
2173		case VK_SHADER_STAGE_VERTEX_BIT:
2174		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
2175		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
2176		case VK_SHADER_STAGE_GEOMETRY_BIT:
2177		case VK_SHADER_STAGE_FRAGMENT_BIT:
2178			return GraphicsConfiguration::initPrograms;
2179
2180		case VK_SHADER_STAGE_COMPUTE_BIT:
2181			return ComputeConfiguration::initPrograms;
2182
2183		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2184		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2185		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2186		case VK_SHADER_STAGE_MISS_BIT_KHR:
2187		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2188		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2189			return RayTracingConfiguration::initPrograms;
2190
2191		default:
2192			TCU_THROW(InternalError, "Unknown shader stage");
2193	}
2194}
2195
2196static inline ShaderBodyTextFunc getShaderBodyTextFunc (const TestType testType)
2197{
2198	switch (testType)
2199	{
2200		case TEST_TYPE_NO_MISS:		return getShaderBodyText;
2201		case TEST_TYPE_SINGLE_HIT:	return getShaderBodyText;
2202		default:					TCU_THROW(InternalError, "Unknown test type");
2203	}
2204}
2205
2206}	// anonymous
2207
2208tcu::TestCaseGroup*	createWatertightnessTests	(tcu::TestContext& testCtx)
2209{
2210	const deUint32					seed	= (deUint32)(testCtx.getCommandLine().getBaseSeed());
2211	// Tests watertightness of ray query
2212	de::MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(testCtx, "watertightness"));
2213
2214	const struct PipelineStages
2215	{
2216		VkShaderStageFlagBits	stage;
2217		const char*				name;
2218	}
2219	pipelineStages[] =
2220	{
2221		{ VK_SHADER_STAGE_VERTEX_BIT,					"vert"			},
2222		{ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		"tesc"			},
2223		{ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	"tese"			},
2224		{ VK_SHADER_STAGE_GEOMETRY_BIT,					"geom"			},
2225		{ VK_SHADER_STAGE_FRAGMENT_BIT,					"frag"			},
2226		{ VK_SHADER_STAGE_COMPUTE_BIT,					"comp"			},
2227		{ VK_SHADER_STAGE_RAYGEN_BIT_KHR,				"rgen"			},
2228		{ VK_SHADER_STAGE_ANY_HIT_BIT_KHR,				"ahit"			},
2229		{ VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,			"chit"			},
2230		{ VK_SHADER_STAGE_MISS_BIT_KHR,					"miss"			},
2231		{ VK_SHADER_STAGE_INTERSECTION_BIT_KHR,			"sect"			},
2232		{ VK_SHADER_STAGE_CALLABLE_BIT_KHR,				"call"			},
2233	};
2234	const struct TestTypes
2235	{
2236		TestType	testType;
2237		const char*	name;
2238	}
2239	testTypes[] =
2240	{
2241		{ TEST_TYPE_NO_MISS,							"nomiss"		},
2242		{ TEST_TYPE_SINGLE_HIT,							"singlehit"		},
2243	};
2244	const struct GeomTypes
2245	{
2246		GeomType	geomType;
2247		const char*	name;
2248	}
2249	geomTypes[] =
2250	{
2251		{ GEOM_TYPE_TRIANGLES,							"triangles"		},
2252		{ GEOM_TYPE_AABBS,								"aabbs"			},
2253	};
2254
2255	for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
2256	{
2257		de::MovePtr<tcu::TestCaseGroup>	testTypeGroup		(new tcu::TestCaseGroup(group->getTestContext(), testTypes[testTypeNdx].name));
2258		const TestType					testType			= testTypes[testTypeNdx].testType;
2259		const ShaderBodyTextFunc		shaderBodyTextFunc	= getShaderBodyTextFunc(testType);
2260		const deUint32					imageDepth			= 1;
2261
2262		for (size_t pipelineStageNdx = 0; pipelineStageNdx < DE_LENGTH_OF_ARRAY(pipelineStages); ++pipelineStageNdx)
2263		{
2264			de::MovePtr<tcu::TestCaseGroup>	sourceTypeGroup			(new tcu::TestCaseGroup(group->getTestContext(), pipelineStages[pipelineStageNdx].name));
2265			const VkShaderStageFlagBits		stage					= pipelineStages[pipelineStageNdx].stage;
2266			const CheckSupportFunc			pipelineCheckSupport	= getPipelineCheckSupport(stage);
2267			const InitProgramsFunc			pipelineInitPrograms	= getPipelineInitPrograms(stage);
2268			const deUint32					instancesGroupCount		= 1;
2269			const deUint32					geometriesGroupCount	= 1;
2270			const deUint32					squaresGroupCount		= (TEST_WIDTH * TEST_HEIGHT) / geometriesGroupCount / instancesGroupCount;
2271
2272			DE_ASSERT(instancesGroupCount * geometriesGroupCount * squaresGroupCount == TEST_WIDTH * TEST_HEIGHT);
2273
2274			for (size_t geomTypeNdx = 0; geomTypeNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypeNdx)
2275			{
2276				const GeomType		geomType	= geomTypes[geomTypeNdx].geomType;
2277				const TestParams	testParams	=
2278				{
2279					TEST_WIDTH,				//  deUint32				width;
2280					TEST_HEIGHT,			//  deUint32				height;
2281					imageDepth,				//  deUint32				depth;
2282					seed,					//  deUint32				randomSeed;
2283					testType,				//  TestType				testType;
2284					stage,					//  VkShaderStageFlagBits	stage;
2285					geomType,				//  GeomType				geomType;
2286					squaresGroupCount,		//  deUint32				squaresGroupCount;
2287					geometriesGroupCount,	//  deUint32				geometriesGroupCount;
2288					instancesGroupCount,	//  deUint32				instancesGroupCount;
2289					VK_FORMAT_R32_SINT,		//  VkFormat				format;
2290					pipelineCheckSupport,	//  CheckSupportFunc		pipelineCheckSupport;
2291					pipelineInitPrograms,	//  InitProgramsFunc		pipelineInitPrograms;
2292					shaderBodyTextFunc,		//  ShaderTestTextFunc		testConfigShaderBodyText;
2293				};
2294
2295				if (testType == TEST_TYPE_SINGLE_HIT && geomType == GEOM_TYPE_AABBS)
2296					continue;
2297
2298				sourceTypeGroup->addChild(new RayQueryBuiltinTestCase(group->getTestContext(), geomTypes[geomTypeNdx].name, testParams));
2299			}
2300
2301			testTypeGroup->addChild(sourceTypeGroup.release());
2302		}
2303
2304		group->addChild(testTypeGroup.release());
2305	}
2306
2307	return group.release();
2308}
2309
2310}	// RayQuery
2311}	// vkt
2312