1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *	  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Ray Tracing Builtin and specialization constant tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingBuiltinTests.hpp"
25 
26 #include "vkDefs.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkPipelineConstructionUtil.hpp"
38 
39 #include "vkRayTracingUtil.hpp"
40 
41 #include "tcuTestLog.hpp"
42 #include "tcuMatrix.hpp"
43 
44 #include "deMath.h"
45 
46 namespace vkt
47 {
48 namespace RayTracing
49 {
50 namespace
51 {
52 using namespace vk;
53 using namespace std;
54 
55 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
56 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
57 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
58 												| VK_SHADER_STAGE_MISS_BIT_KHR
59 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
60 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
61 
62 enum GeomType
63 {
64 	GEOM_TYPE_TRIANGLES,
65 	GEOM_TYPE_AABBS,
66 };
67 
68 enum TestId
69 {
70 	TEST_ID_LAUNCH_ID_EXT				= 0,
71 	TEST_ID_LAUNCH_SIZE_EXT,
72 	TEST_ID_PRIMITIVE_ID,
73 	TEST_ID_INSTANCE_ID,
74 	TEST_ID_INSTANCE_CUSTOM_INDEX_EXT,
75 	TEST_ID_GEOMETRY_INDEX_EXT,
76 	TEST_ID_WORLD_RAY_ORIGIN_EXT,
77 	TEST_ID_WORLD_RAY_DIRECTION_EXT,
78 	TEST_ID_OBJECT_RAY_ORIGIN_EXT,
79 	TEST_ID_OBJECT_RAY_DIRECTION_EXT,
80 	TEST_ID_RAY_T_MIN_EXT,
81 	TEST_ID_RAY_T_MAX_EXT,
82 	TEST_ID_INCOMING_RAY_FLAGS_EXT,
83 	TEST_ID_HIT_T_EXT,
84 	TEST_ID_HIT_KIND_EXT,
85 	TEST_ID_OBJECT_TO_WORLD_EXT,
86 	TEST_ID_OBJECT_TO_WORLD_3X4_EXT,
87 	TEST_ID_WORLD_TO_OBJECT_EXT,
88 	TEST_ID_WORLD_TO_OBJECT_3X4_EXT,
89 	TEST_ID_INDICES_INDIRECT,
90 	TEST_ID_TRANSFORMS_INDIRECT,
91 	TEST_ID_TMINMAX_INDIRECT,
92 	TEST_ID_INCOMING_RAY_FLAGS_INDIRECT,
93 	TEST_ID_HIT_KIND_INDIRECT,
94 	TEST_ID_LAST
95 };
96 
97 enum RayFlagBits
98 {
99 	RAY_FLAG_BIT_OPAQUE_EXT							= 0,	//  const uint gl_RayFlagsOpaqueEXT = 1U;
100 	RAY_FLAG_BIT_NO_OPAQUE_EXT						= 1,	//  const uint gl_RayFlagsNoOpaqueEXT = 2U;
101 	RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT			= 2,	//  const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;
102 	RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT		= 3,	//  const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;
103 	RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT		= 4,	//  const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;
104 	RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT	= 5,	//  const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;
105 	RAY_FLAG_BIT_CULL_OPAQUE_EXT					= 6,	//  const uint gl_RayFlagsCullOpaqueEXT = 64U;
106 	RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT					= 7,	//  const uint gl_RayFlagsCullNoOpaqueEXT = 128U;
107 	RAY_FLAG_BIT_LAST_PER_TEST,
108 	RAY_FLAG_BIT_SKIP_TRIANGLES_EXT					= 8,	//  const uint gl_RayFlagsSkipTrianglesEXT = 256U;
109 	RAY_FLAG_BIT_SKIP_AABB_EXT						= 9,	//  const uint gl_RayFlagsSkipAABBEXT = 512U;
110 	RAY_FLAG_BIT_LAST
111 };
112 
113 struct CaseDef
114 {
115 	TestId					id;
116 	const char*				name;
117 	deUint32				width;
118 	deUint32				height;
119 	deUint32				depth;
120 	deUint32				raysDepth;
121 	VkFormat				format;
122 	bool					fixedPointScalarOutput;
123 	bool					fixedPointVectorOutput;
124 	bool					fixedPointMatrixOutput;
125 	GeomType				geomType;
126 	deUint32				squaresGroupCount;
127 	deUint32				geometriesGroupCount;
128 	deUint32				instancesGroupCount;
129 	VkShaderStageFlagBits	stage;
130 	bool					rayFlagSkipTriangles;
131 	bool					rayFlagSkipAABSs;
132 	bool					opaque;
133 	bool					frontFace;
134 	VkPipelineCreateFlags	pipelineCreateFlags;
135 	bool					useSpecConstants;
136 	bool					skipClosestHit;
137 	bool					useMaintenance5;
138 };
139 
140 const deUint32	DEFAULT_UINT_CLEAR_VALUE	= 0x8000;
141 const deUint32	FIXED_POINT_DIVISOR			= 1024 * 1024;
142 const deUint32	FIXED_POINT_ALLOWED_ERROR	= 4;
143 
isPlain(const deUint32 width, const deUint32 height, const deUint32 depth)144 bool isPlain (const deUint32 width, const deUint32 height, const deUint32 depth)
145 {
146 	return (width == 1 || height == 1 || depth == 1);
147 }
148 
getShaderGroupSize(const InstanceInterface& vki, const VkPhysicalDevice physicalDevice)149 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
150 							 const VkPhysicalDevice		physicalDevice)
151 {
152 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
153 
154 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
155 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
156 }
157 
getShaderGroupBaseAlignment(const InstanceInterface& vki, const VkPhysicalDevice physicalDevice)158 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
159 									  const VkPhysicalDevice	physicalDevice)
160 {
161 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
162 
163 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
164 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
165 }
166 
makeImageCreateInfo(deUint32 width, deUint32 height, deUint32 depth, VkFormat format)167 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
168 {
169 	const VkImageType		imageType		= VK_IMAGE_TYPE_3D;
170 	const VkImageUsageFlags	usage			= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
171 	const VkImageCreateInfo	imageCreateInfo	=
172 	{
173 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
174 		DE_NULL,								// const void*				pNext;
175 		(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
176 		imageType,								// VkImageType				imageType;
177 		format,									// VkFormat					format;
178 		makeExtent3D(width, height, depth),		// VkExtent3D				extent;
179 		1u,										// deUint32					mipLevels;
180 		1u,										// deUint32					arrayLayers;
181 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
182 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
183 		usage,									// VkImageUsageFlags		usage;
184 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
185 		0u,										// deUint32					queueFamilyIndexCount;
186 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
187 		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
188 	};
189 
190 	return imageCreateInfo;
191 }
192 
193 class RayTracingBuiltinLaunchTestInstance : public TestInstance
194 {
195 public:
196 																RayTracingBuiltinLaunchTestInstance		(Context& context, const CaseDef& data);
197 																~RayTracingBuiltinLaunchTestInstance	(void);
198 	tcu::TestStatus												iterate									(void);
199 
200 protected:
201 	void														checkSupportInInstance					(void) const;
202 	Move<VkPipeline>											makePipeline							(de::MovePtr<RayTracingPipeline>&							rayTracingPipeline,
203 																										 VkPipelineLayout											pipelineLayout,
204 																										 const VkSpecializationInfo*								specializationInfo);
205 	std::vector<deInt32>										expectedIntValuesBuffer					(void);
206 	std::vector<float>											expectedFloatValuesBuffer				(void);
207 	std::vector<float>											expectedVectorValuesBuffer				(void);
208 	std::vector<float>											expectedMatrixValuesBuffer				(void);
209 	de::MovePtr<BufferWithMemory>								runTest									(void);
210 	de::MovePtr<BufferWithMemory>								createShaderBindingTable				(const InstanceInterface&									vki,
211 																										 const DeviceInterface&										vkd,
212 																										 const VkDevice												device,
213 																										 const VkPhysicalDevice										physicalDevice,
214 																										 const VkPipeline											pipeline,
215 																										 Allocator&													allocator,
216 																										 de::MovePtr<RayTracingPipeline>&							rayTracingPipeline,
217 																										 const deUint32												group);
218 
219 	bool														validateIntBuffer						(de::MovePtr<BufferWithMemory>								buffer);
220 	bool														validateFloatBuffer						(de::MovePtr<BufferWithMemory>								buffer);
221 	bool														validateVectorBuffer					(de::MovePtr<BufferWithMemory>								buffer);
222 	bool														validateMatrixBuffer					(de::MovePtr<BufferWithMemory>								buffer);
223 
224 	de::MovePtr<TopLevelAccelerationStructure>					initTopAccelerationStructure			(VkCommandBuffer											cmdBuffer,
225 																										 vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures);
226 	vector<de::SharedPtr<BottomLevelAccelerationStructure>	>	initBottomAccelerationStructures		(VkCommandBuffer	cmdBuffer);
227 	de::MovePtr<BottomLevelAccelerationStructure>				initBottomAccelerationStructure			(VkCommandBuffer	cmdBuffer,
228 																										 tcu::UVec2&		startPos);
229 
230 private:
231 	CaseDef														m_data;
232 	VkShaderStageFlags											m_shaders;
233 	deUint32													m_raygenShaderGroup;
234 	deUint32													m_missShaderGroup;
235 	deUint32													m_hitShaderGroup;
236 	deUint32													m_callableShaderGroup;
237 	deUint32													m_shaderGroupCount;
238 };
239 
RayTracingBuiltinLaunchTestInstance(Context& context, const CaseDef& data)240 RayTracingBuiltinLaunchTestInstance::RayTracingBuiltinLaunchTestInstance (Context& context, const CaseDef& data)
241 	: vkt::TestInstance		(context)
242 	, m_data				(data)
243 	, m_shaders				(0)
244 	, m_raygenShaderGroup	(~0u)
245 	, m_missShaderGroup		(~0u)
246 	, m_hitShaderGroup		(~0u)
247 	, m_callableShaderGroup	(~0u)
248 	, m_shaderGroupCount	(0)
249 {
250 	const VkShaderStageFlags	hitStages	= VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
251 	BinaryCollection&			collection	= m_context.getBinaryCollection();
252 	deUint32					group		= 0;
253 	deUint32					shaderCount	= 0;
254 
255 	if (collection.contains("rgen")) m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
256 	if (collection.contains("ahit")) m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
257 	if (collection.contains("chit")) m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
258 	if (collection.contains("miss")) m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
259 	if (collection.contains("sect")) m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
260 	if (collection.contains("call")) m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
261 
262 	for (BinaryCollection::Iterator it =  collection.begin(); it != collection.end(); ++it)
263 		shaderCount++;
264 
265 	if (shaderCount != (deUint32)dePop32(m_shaders))
266 		TCU_THROW(InternalError, "Unused shaders detected in the collection");
267 
268 	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
269 		m_raygenShaderGroup		= group++;
270 
271 	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
272 		m_missShaderGroup		= group++;
273 
274 	if (0 != (m_shaders & hitStages))
275 		m_hitShaderGroup		= group++;
276 
277 	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
278 		m_callableShaderGroup	= group++;
279 
280 	m_shaderGroupCount = group;
281 }
282 
~RayTracingBuiltinLaunchTestInstance(void)283 RayTracingBuiltinLaunchTestInstance::~RayTracingBuiltinLaunchTestInstance (void)
284 {
285 }
286 
287 class RayTracingTestCase : public TestCase
288 {
289 	public:
290 										RayTracingTestCase			(tcu::TestContext& context, const char* name, const CaseDef data);
291 										~RayTracingTestCase			(void);
292 
293 	virtual	void						initPrograms				(SourceCollections& programCollection) const;
294 	virtual TestInstance*				createInstance				(Context& context) const;
295 	virtual void						checkSupport				(Context& context) const;
296 
297 private:
298 	static inline const std::string		getIntersectionPassthrough	(void);
299 	static inline const std::string		getMissPassthrough			(void);
300 	static inline const std::string		getHitPassthrough			(void);
301 
302 	CaseDef								m_data;
303 };
304 
RayTracingTestCase(tcu::TestContext& context, const char* name, const CaseDef data)305 RayTracingTestCase::RayTracingTestCase (tcu::TestContext& context, const char* name, const CaseDef data)
306 	: vkt::TestCase	(context, name)
307 	, m_data		(data)
308 {
309 }
310 
~RayTracingTestCase(void)311 RayTracingTestCase::~RayTracingTestCase	(void)
312 {
313 }
314 
checkSupport(Context& context) const315 void RayTracingTestCase::checkSupport(Context& context) const
316 {
317 	const bool	pipelineFlagSkipTriangles	= ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0);
318 	const bool	pipelineFlagSkipAABSs		= ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0);
319 	const bool	cullingFlags				=  m_data.rayFlagSkipTriangles
320 											|| m_data.rayFlagSkipAABSs
321 											|| pipelineFlagSkipTriangles
322 											|| pipelineFlagSkipAABSs;
323 
324 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
325 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
326 
327 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
328 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
329 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
330 
331 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
332 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
333 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
334 
335 	if (cullingFlags && rayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling == DE_FALSE)
336 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling");
337 
338 	if (m_data.useMaintenance5)
339 		context.requireDeviceFunctionality("VK_KHR_maintenance5");
340 }
341 
getIntersectionPassthrough(void)342 const std::string RayTracingTestCase::getIntersectionPassthrough (void)
343 {
344 	const std::string intersectionPassthrough =
345 		"#version 460 core\n"
346 		"#extension GL_EXT_ray_tracing : require\n"
347 		"hitAttributeEXT vec3 hitAttribute;\n"
348 		"\n"
349 		"void main()\n"
350 		"{\n"
351 		"  reportIntersectionEXT(0.95f, 0x7Eu);\n"
352 		"}\n";
353 
354 	return intersectionPassthrough;
355 }
356 
getMissPassthrough(void)357 const std::string RayTracingTestCase::getMissPassthrough (void)
358 {
359 	const std::string missPassthrough =
360 		"#version 460 core\n"
361 		"#extension GL_EXT_ray_tracing : require\n"
362 		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
363 		"\n"
364 		"void main()\n"
365 		"{\n"
366 		"}\n";
367 
368 	return missPassthrough;
369 }
370 
getHitPassthrough(void)371 const std::string RayTracingTestCase::getHitPassthrough (void)
372 {
373 	const std::string hitPassthrough =
374 		"#version 460 core\n"
375 		"#extension GL_EXT_ray_tracing : require\n"
376 		"hitAttributeEXT vec3 attribs;\n"
377 		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
378 		"\n"
379 		"void main()\n"
380 		"{\n"
381 		"}\n";
382 
383 	return hitPassthrough;
384 }
385 
initPrograms(SourceCollections& programCollection) const386 void RayTracingTestCase::initPrograms (SourceCollections& programCollection) const
387 {
388 	const bool useSC = m_data.useSpecConstants;
389 	DE_ASSERT(!useSC || m_data.id == TEST_ID_LAUNCH_ID_EXT);
390 
391 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
392 
393 	if (m_data.id == TEST_ID_LAUNCH_ID_EXT || m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
394 	{
395 		const std::string	specConstants	=
396 			"layout (constant_id=0) const highp int factor1 = 1;\n"
397 			"layout (constant_id=1) const highp float factor2 = 2.0;\n"
398 			;
399 
400 		const std::string	updateImage		=
401 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
402 			"  ivec3 v = ivec3(gl_" + std::string(m_data.name) + ");\n"
403 			"  int   r = v.x + " + (useSC ? "factor1" : "256") + " * (v.y + " + (useSC ? "int(factor2)" : "256") + " * v.z) + 1;\n"
404 			"  ivec4 c = ivec4(r,0,0,1);\n"
405 			"  imageStore(result, p, c);\n";
406 
407 		switch (m_data.stage)
408 		{
409 			case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
410 			{
411 				std::stringstream css;
412 				css <<
413 					"#version 460 core\n"
414 					"#extension GL_EXT_ray_tracing : require\n"
415 					<< (useSC ? specConstants : "") <<
416 					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
417 					"\n"
418 					"void main()\n"
419 					"{\n"
420 					<< updateImage <<
421 					"}\n";
422 
423 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
424 
425 				break;
426 			}
427 
428 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
429 			{
430 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
431 
432 				{
433 					std::stringstream css;
434 					css <<
435 						"#version 460 core\n"
436 						"#extension GL_EXT_ray_tracing : require\n"
437 						<< (useSC ? specConstants : "") <<
438 						"hitAttributeEXT vec3 attribs;\n"
439 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
440 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
441 						"\n"
442 						"void main()\n"
443 						"{\n"
444 						<< updateImage <<
445 						"}\n";
446 
447 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
448 				}
449 
450 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
451 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
452 
453 				break;
454 			}
455 
456 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
457 			{
458 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
459 
460 				{
461 					std::stringstream css;
462 					css <<
463 						"#version 460 core\n"
464 						"#extension GL_EXT_ray_tracing : require\n"
465 						<< (useSC ? specConstants : "") <<
466 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
467 						"hitAttributeEXT vec3 attribs;\n"
468 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
469 						"\n"
470 						"void main()\n"
471 						"{\n"
472 						<< updateImage <<
473 						"}\n";
474 
475 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
476 				}
477 
478 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
479 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
480 
481 				break;
482 			}
483 
484 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
485 			{
486 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
487 
488 				{
489 					std::stringstream css;
490 					css <<
491 						"#version 460 core\n"
492 						"#extension GL_EXT_ray_tracing : require\n"
493 						<< (useSC ? specConstants : "") <<
494 						"hitAttributeEXT vec3 hitAttribute;\n"
495 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
496 						"\n"
497 						"void main()\n"
498 						"{\n"
499 						<< updateImage <<
500 						"  hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
501 						"  reportIntersectionEXT(1.0f, 0);\n"
502 						"}\n";
503 
504 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
505 				}
506 
507 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
508 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
509 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
510 
511 				break;
512 			}
513 
514 			case VK_SHADER_STAGE_MISS_BIT_KHR:
515 			{
516 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
517 
518 				{
519 					std::stringstream css;
520 					css <<
521 						"#version 460 core\n"
522 						"#extension GL_EXT_ray_tracing : require\n"
523 						<< (useSC ? specConstants : "") <<
524 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
525 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
526 						"\n"
527 						"void main()\n"
528 						"{\n"
529 						<< updateImage <<
530 						"}\n";
531 
532 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
533 				}
534 
535 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
536 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
537 
538 				break;
539 			}
540 
541 			case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
542 			{
543 				{
544 					std::stringstream css;
545 					css <<
546 						"#version 460 core\n"
547 						"#extension GL_EXT_ray_tracing : require\n"
548 						"layout(location = 0) callableDataEXT float dummy;"
549 						"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
550 						"\n"
551 						"void main()\n"
552 						"{\n"
553 						"  executeCallableEXT(0, 0);\n"
554 						"}\n";
555 
556 					programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
557 				}
558 
559 				{
560 					std::stringstream css;
561 					css <<
562 						"#version 460 core\n"
563 						"#extension GL_EXT_ray_tracing : require\n"
564 						<< (useSC ? specConstants : "") <<
565 						"layout(location = 0) callableDataInEXT float dummy;"
566 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
567 						"\n"
568 						"void main()\n"
569 						"{\n"
570 						<< updateImage <<
571 						"}\n";
572 
573 					programCollection.glslSources.add("call") << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
574 				}
575 
576 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
577 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
578 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
579 
580 				break;
581 			}
582 
583 			default:
584 				TCU_THROW(InternalError, "Unknown stage");
585 		}
586 	}
587 	else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT		||
588 			 m_data.id == TEST_ID_PRIMITIVE_ID				||
589 			 m_data.id == TEST_ID_INSTANCE_ID				||
590 			 m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT	||
591 			 m_data.id == TEST_ID_HIT_KIND_EXT				)
592 	{
593 		const std::string	conditionGeometryIndex	= "  int   n = int(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z));\n"
594 													  "  int   m = (n / " + de::toString(m_data.squaresGroupCount) + ") % " + de::toString(m_data.geometriesGroupCount) + ";\n"
595 													  "  if (r == m)";
596 		const std::string	conditionPrimitiveId	= "  int   n = int(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z));\n"
597 													  "  int   m = n % " + de::toString(m_data.squaresGroupCount) + ";\n"
598 													  "  if (r == m)";
599 		const std::string	condition				= (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT) && (m_data.geomType == GEOM_TYPE_AABBS) ? conditionGeometryIndex
600 													: (m_data.id == TEST_ID_PRIMITIVE_ID) && (m_data.geomType == GEOM_TYPE_AABBS) ? conditionPrimitiveId
601 													: "";
602 		const std::string	updateImage				=
603 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
604 			"  int   r = int(gl_" + std::string(m_data.name) + ");\n"
605 			"  ivec4 c = ivec4(r,0,0,1);\n"
606 			+ condition + "  imageStore(result, p, c);\n";
607 
608 		switch (m_data.stage)
609 		{
610 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
611 			{
612 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
613 
614 				{
615 					std::stringstream css;
616 					css <<
617 						"#version 460 core\n"
618 						"#extension GL_EXT_ray_tracing : require\n"
619 						"hitAttributeEXT vec3 attribs;\n"
620 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
621 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
622 						"\n"
623 						"void main()\n"
624 						"{\n"
625 						<< updateImage <<
626 						"}\n";
627 
628 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
629 				}
630 
631 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
632 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
633 
634 				if (m_data.geomType == GEOM_TYPE_AABBS)
635 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
636 
637 				break;
638 			}
639 
640 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
641 			{
642 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
643 
644 				{
645 					std::stringstream css;
646 					css <<
647 						"#version 460 core\n"
648 						"#extension GL_EXT_ray_tracing : require\n"
649 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
650 						"hitAttributeEXT vec3 attribs;\n"
651 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
652 						"\n"
653 						"void main()\n"
654 						"{\n"
655 						<< updateImage <<
656 						"}\n";
657 
658 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
659 				}
660 
661 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
662 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
663 
664 				if (m_data.geomType == GEOM_TYPE_AABBS)
665 				{
666 					const std::string intersectionShaderSingle	=
667 						"#version 460 core\n"
668 						"#extension GL_EXT_ray_tracing : require\n"
669 						"hitAttributeEXT vec3 hitAttribute;\n"
670 						"\n"
671 						"void main()\n"
672 						"{\n"
673 						"  int r = int(gl_" + std::string(m_data.name) + ");\n"
674 						+ condition + "  reportIntersectionEXT(0.95f, 0x7Eu);\n"
675 						"}\n";
676 					const std::string intersectionShader		= condition.empty() ? getIntersectionPassthrough() : intersectionShaderSingle;
677 
678 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
679 				}
680 
681 				break;
682 			}
683 
684 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
685 			{
686 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
687 
688 				{
689 					std::stringstream css;
690 					css <<
691 						"#version 460 core\n"
692 						"#extension GL_EXT_ray_tracing : require\n"
693 						"hitAttributeEXT vec3 hitAttribute;\n"
694 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
695 						"\n"
696 						"void main()\n"
697 						"{\n"
698 						<< updateImage <<
699 						"  reportIntersectionEXT(0.95f, 0);\n"
700 						"}\n";
701 
702 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
703 				}
704 
705 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
706 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
707 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
708 
709 				break;
710 			}
711 
712 			default:
713 				TCU_THROW(InternalError, "Unknown stage");
714 		}
715 	}
716 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
717 	{
718 		const bool			cullingFlags			= m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs;
719 		const std::string	cullingFlagsInit		= (m_data.rayFlagSkipTriangles && m_data.rayFlagSkipAABSs) ? "gl_RayFlagsSkipTrianglesEXT|gl_RayFlagsSkipAABBEXT"
720 													: m_data.rayFlagSkipTriangles ? "gl_RayFlagsSkipTrianglesEXT"
721 													: m_data.rayFlagSkipAABSs ? "gl_RayFlagsSkipAABBEXT"
722 													: "gl_RayFlagsNoneEXT";
723 		const std::string	updateImage				=
724 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
725 			"  int   r = int(gl_" + std::string(m_data.name) + ");\n"
726 			"  ivec4 c = ivec4(r,0,0,1);\n"
727 			"  imageStore(result, p, c);\n";
728 		const std::string	intersectionShader		=
729 			"#version 460 core\n"
730 			"#extension GL_EXT_ray_tracing : require\n"
731 			"hitAttributeEXT vec3 hitAttribute;\n"
732 			"\n"
733 			"void main()\n"
734 			"{\n"
735 			"  uint hitKind = " + std::string(m_data.frontFace ? "0x7Eu" : "0x7Fu") + ";\n"
736 			"  reportIntersectionEXT(0.95f, hitKind);\n"
737 			"}\n";
738 		const std::string	raygenFlagsFragment		=
739 			"\n"
740 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_OPAQUE_EXT                     ) + "))) f = f | gl_RayFlagsOpaqueEXT;\n"
741 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_NO_OPAQUE_EXT                  ) + "))) f = f | gl_RayFlagsNoOpaqueEXT;\n"
742 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_OPAQUE_EXT                ) + "))) f = f | gl_RayFlagsCullOpaqueEXT;\n"
743 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT             ) + "))) f = f | gl_RayFlagsCullNoOpaqueEXT;\n"
744 			"\n"
745 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT ) + "))) f = f | gl_RayFlagsCullBackFacingTrianglesEXT;\n"
746 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT) + "))) f = f | gl_RayFlagsCullFrontFacingTrianglesEXT;\n"
747 			"\n"
748 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT     ) + "))) f = f | gl_RayFlagsTerminateOnFirstHitEXT;\n"
749 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT    ) + "))) f = f | gl_RayFlagsSkipClosestHitShaderEXT;\n"
750 			"\n";
751 		const std::string	raygenShader			=
752 			"#version 460 core\n"
753 			"#extension GL_EXT_ray_tracing : require\n"
754 			+ (cullingFlags ? std::string("#extension GL_EXT_ray_flags_primitive_culling : require\n") : "") +
755 			"layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
756 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
757 			"\n"
758 			"void main()\n"
759 			"{\n"
760 			"  uint  n        = gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z);\n"
761 			"  uint  f        = " + cullingFlagsInit + ";\n"
762 			+ raygenFlagsFragment +
763 			"  uint  rayFlags = f;\n"
764 			"  uint  cullMask = 0xFF;\n"
765 			"  float tmin     = 0.0;\n"
766 			"  float tmax     = 9.0;\n"
767 			"  vec3  origin   = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), (float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n"
768 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
769 			"  traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
770 			"}\n";
771 
772 		switch (m_data.stage)
773 		{
774 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
775 			{
776 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
777 
778 				{
779 					std::stringstream css;
780 					css <<
781 						"#version 460 core\n"
782 						"#extension GL_EXT_ray_tracing : require\n"
783 						"hitAttributeEXT vec3 hitAttribute;\n"
784 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
785 						"\n"
786 						"void main()\n"
787 						"{\n"
788 						<< updateImage <<
789 						"}\n";
790 
791 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
792 				}
793 
794 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
795 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
796 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
797 
798 				break;
799 			}
800 
801 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
802 			{
803 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
804 
805 				{
806 					std::stringstream css;
807 					css <<
808 						"#version 460 core\n"
809 						"#extension GL_EXT_ray_tracing : require\n"
810 						"hitAttributeEXT vec3 attribs;\n"
811 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
812 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
813 						"\n"
814 						"void main()\n"
815 						"{\n"
816 						<< updateImage <<
817 						"}\n";
818 
819 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
820 				}
821 
822 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
823 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
824 
825 				if (m_data.geomType == GEOM_TYPE_AABBS)
826 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
827 
828 				break;
829 			}
830 
831 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
832 			{
833 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
834 
835 				{
836 					std::stringstream css;
837 					css <<
838 						"#version 460 core\n"
839 						"#extension GL_EXT_ray_tracing : require\n"
840 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
841 						"hitAttributeEXT vec3 attribs;\n"
842 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
843 						"\n"
844 						"void main()\n"
845 						"{\n"
846 						<< updateImage <<
847 						"}\n";
848 
849 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
850 				}
851 
852 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
853 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
854 
855 				if (m_data.geomType == GEOM_TYPE_AABBS)
856 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
857 
858 				break;
859 			}
860 
861 			case VK_SHADER_STAGE_MISS_BIT_KHR:
862 			{
863 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
864 
865 				{
866 					std::stringstream css;
867 					css <<
868 						"#version 460 core\n"
869 						"#extension GL_EXT_ray_tracing : require\n"
870 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
871 						"\n"
872 						"void main()\n"
873 						"{\n"
874 						<< updateImage <<
875 						"}\n";
876 
877 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
878 				}
879 
880 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
881 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
882 
883 				if (m_data.geomType == GEOM_TYPE_AABBS)
884 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
885 
886 				break;
887 			}
888 
889 			default:
890 				TCU_THROW(InternalError, "Unknown stage");
891 		}
892 	}
893 	else if (m_data.id == TEST_ID_HIT_T_EXT		||
894 			 m_data.id == TEST_ID_RAY_T_MIN_EXT	||
895 			 m_data.id == TEST_ID_RAY_T_MAX_EXT	)
896 	{
897 		const std::string	raygenShader		=
898 			"#version 460 core\n"
899 			"#extension GL_EXT_ray_tracing : require\n"
900 			"layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
901 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
902 			"\n"
903 			"void main()\n"
904 			"{\n"
905 			"  uint  cullMask = 0xFF;\n"
906 			"  float a      = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
907 			"  float b      = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
908 			"  float c      = 0.25f * a / b;\n"
909 			"  float tmin   = c;\n"
910 			"  float tmax   = 0.75f + c;\n"
911 			"  vec3  origin = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), (float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n"
912 			"  vec3  direct = vec3(0.0, 0.0, -1.0);\n"
913 			"  traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
914 			"}\n";
915 		const std::string	intersectionShader	=
916 			"#version 460 core\n"
917 			"#extension GL_EXT_ray_tracing : require\n"
918 			"hitAttributeEXT vec3 hitAttribute;\n"
919 			"\n"
920 			"void main()\n"
921 			"{\n"
922 			"  float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
923 			"  float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
924 			"  float c = 0.25f * a / b;\n"
925 			"  reportIntersectionEXT(0.03125f + c, 0);\n"
926 			"}\n";
927 		const std::string	updateImage			=
928 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
929 			"  int   r = int(" +de::toString(FIXED_POINT_DIVISOR) + ".0f * gl_" + std::string(m_data.name) + ");\n"
930 			"  ivec4 c = ivec4(r,0,0,1);\n"
931 			"  imageStore(result, p, c);\n";
932 
933 		switch (m_data.stage)
934 		{
935 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
936 			{
937 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
938 
939 				{
940 					std::stringstream css;
941 					css <<
942 						"#version 460 core\n"
943 						"#extension GL_EXT_ray_tracing : require\n"
944 						"hitAttributeEXT vec3 attribs;\n"
945 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
946 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
947 						"\n"
948 						"void main()\n"
949 						"{\n"
950 						<< updateImage <<
951 						"}\n";
952 
953 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
954 				}
955 
956 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
957 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
958 
959 				if (m_data.geomType == GEOM_TYPE_AABBS)
960 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
961 
962 				break;
963 			}
964 
965 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
966 			{
967 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
968 
969 				{
970 					std::stringstream css;
971 					css <<
972 						"#version 460 core\n"
973 						"#extension GL_EXT_ray_tracing : require\n"
974 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
975 						"hitAttributeEXT vec3 attribs;\n"
976 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
977 						"\n"
978 						"void main()\n"
979 						"{\n"
980 						<< updateImage <<
981 						"}\n";
982 
983 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
984 				}
985 
986 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
987 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
988 
989 				if (m_data.geomType == GEOM_TYPE_AABBS)
990 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
991 
992 				break;
993 			}
994 
995 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
996 			{
997 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
998 
999 				{
1000 					std::stringstream css;
1001 					css <<
1002 						"#version 460 core\n"
1003 						"#extension GL_EXT_ray_tracing : require\n"
1004 						"hitAttributeEXT vec3 hitAttribute;\n"
1005 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1006 						"\n"
1007 						"void main()\n"
1008 						"{\n"
1009 						<< updateImage <<
1010 						"\n"
1011 						"  float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
1012 						"  float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
1013 						"  reportIntersectionEXT(0.4375f + 0.25f * a / b, 0x7Eu);\n"
1014 						"}\n";
1015 
1016 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1017 				}
1018 
1019 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1020 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1021 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1022 
1023 				break;
1024 			}
1025 
1026 			case VK_SHADER_STAGE_MISS_BIT_KHR:
1027 			{
1028 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
1029 
1030 				{
1031 					std::stringstream css;
1032 					css <<
1033 						"#version 460 core\n"
1034 						"#extension GL_EXT_ray_tracing : require\n"
1035 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1036 						"\n"
1037 						"void main()\n"
1038 						"{\n"
1039 						<< updateImage <<
1040 						"}\n";
1041 
1042 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1043 				}
1044 
1045 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1046 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1047 
1048 				if (m_data.geomType == GEOM_TYPE_AABBS)
1049 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
1050 
1051 				break;
1052 			}
1053 
1054 			default:
1055 				TCU_THROW(InternalError, "Unknown stage");
1056 		}
1057 	}
1058 	else if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT		||
1059 			 m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT	||
1060 			 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT		||
1061 			 m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT	||
1062 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT		||
1063 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT		||
1064 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT	||
1065 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT	)
1066 	{
1067 		const bool			matrix4x3			= (m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT);
1068 		const bool			matrix3x4			= (m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT);
1069 		const bool			matrixOutput		= matrix4x3 || matrix3x4;
1070 		const std::string	vectorLoop			=
1071 			"  for (int ndx = 0; ndx < 3; ndx++)\n"
1072 			"  {\n";
1073 		const std::string	matrixLoop4x3		=
1074 			"  int ndx = -1;\n"
1075 			"  for (int row = 0; row < 3; row++)\n"
1076 			"  for (int col = 0; col < 4; col++)\n"
1077 			"  {\n"
1078 			"    ndx++;\n";
1079 		const std::string	matrixLoop3x4		=
1080 			"  int ndx = -1;\n"
1081 			"  for (int col = 0; col < 3; col++)\n"
1082 			"  for (int row = 0; row < 4; row++)\n"
1083 			"  {\n"
1084 			"    ndx++;\n";
1085 		const std::string	loop				=
1086 			matrix4x3 ? matrixLoop4x3 :
1087 			matrix3x4 ? matrixLoop3x4 :
1088 			vectorLoop;
1089 		const std::string	index				=
1090 			(matrixOutput ? "[col][row]" : "[ndx]");
1091 		const std::string	updateImage			=
1092 			"  float k = " +de::toString(FIXED_POINT_DIVISOR) + ".0f;\n"
1093 			+ loop +
1094 			"    ivec3 p = ivec3(gl_LaunchIDEXT.xy, ndx);\n"
1095 			"    float r = k * gl_" + std::string(m_data.name) + index + ";\n"
1096 			"    ivec4 c = ivec4(int(r),0,0,1);\n"
1097 			"    imageStore(result, p, c);\n"
1098 			"  }\n";
1099 
1100 		switch (m_data.stage)
1101 		{
1102 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1103 			{
1104 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1105 
1106 				{
1107 					std::stringstream css;
1108 					css <<
1109 						"#version 460 core\n"
1110 						"#extension GL_EXT_ray_tracing : require\n"
1111 						"hitAttributeEXT vec3 attribs;\n"
1112 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1113 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1114 						"\n"
1115 						"void main()\n"
1116 						"{\n"
1117 						<< updateImage <<
1118 						"}\n";
1119 
1120 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1121 				}
1122 
1123 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1124 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1125 
1126 				if (m_data.geomType == GEOM_TYPE_AABBS)
1127 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1128 
1129 				break;
1130 			}
1131 
1132 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1133 			{
1134 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1135 
1136 				{
1137 					std::stringstream css;
1138 					css <<
1139 						"#version 460 core\n"
1140 						"#extension GL_EXT_ray_tracing : require\n"
1141 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1142 						"hitAttributeEXT vec3 attribs;\n"
1143 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1144 						"\n"
1145 						"void main()\n"
1146 						"{\n"
1147 						<< updateImage <<
1148 						"}\n";
1149 
1150 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1151 				}
1152 
1153 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1154 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1155 
1156 				if (m_data.geomType == GEOM_TYPE_AABBS)
1157 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1158 
1159 				break;
1160 			}
1161 
1162 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1163 			{
1164 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1165 
1166 				{
1167 					std::stringstream css;
1168 					css <<
1169 						"#version 460 core\n"
1170 						"#extension GL_EXT_ray_tracing : require\n"
1171 						"hitAttributeEXT vec3 hitAttribute;\n"
1172 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1173 						"\n"
1174 						"void main()\n"
1175 						"{\n"
1176 						<< updateImage <<
1177 						"  reportIntersectionEXT(0.95f, 0);\n"
1178 						"}\n";
1179 
1180 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1181 				}
1182 
1183 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1184 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1185 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1186 
1187 				break;
1188 			}
1189 
1190 			case VK_SHADER_STAGE_MISS_BIT_KHR:
1191 			{
1192 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1193 
1194 				{
1195 					std::stringstream css;
1196 					css <<
1197 						"#version 460 core\n"
1198 						"#extension GL_EXT_ray_tracing : require\n"
1199 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1200 						"\n"
1201 						"void main()\n"
1202 						"{\n"
1203 						<< updateImage <<
1204 						"}\n";
1205 
1206 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1207 				}
1208 
1209 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1210 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1211 
1212 				if (m_data.geomType == GEOM_TYPE_AABBS)
1213 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1214 
1215 				break;
1216 			}
1217 
1218 			default:
1219 				TCU_THROW(InternalError, "Unknown stage");
1220 		}
1221 	}
1222 	else
1223 	{
1224 		TCU_THROW(InternalError, "Not implemented");
1225 	}
1226 }
1227 
createInstance(Context& context) const1228 TestInstance* RayTracingTestCase::createInstance (Context& context) const
1229 {
1230 	return new RayTracingBuiltinLaunchTestInstance(context, m_data);
1231 }
1232 
initTopAccelerationStructure(VkCommandBuffer cmdBuffer, vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)1233 de::MovePtr<TopLevelAccelerationStructure> RayTracingBuiltinLaunchTestInstance::initTopAccelerationStructure (VkCommandBuffer											cmdBuffer,
1234 																											  vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures)
1235 {
1236 	const DeviceInterface&						vkd				= m_context.getDeviceInterface();
1237 	const VkDevice								device			= m_context.getDevice();
1238 	Allocator&									allocator		= m_context.getDefaultAllocator();
1239 	de::MovePtr<TopLevelAccelerationStructure>	result			= makeTopLevelAccelerationStructure();
1240 	const bool									transformTest	=  m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT
1241 																|| m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT
1242 																|| m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT
1243 																|| m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT
1244 																|| m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT
1245 																|| m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT
1246 																|| m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT
1247 																|| m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT;
1248 
1249 	result->setInstanceCount(bottomLevelAccelerationStructures.size());
1250 
1251 	for (size_t structNdx = 0; structNdx < bottomLevelAccelerationStructures.size(); ++structNdx)
1252 	{
1253 		VkTransformMatrixKHR	transform	= identityMatrix3x4;
1254 
1255 		if (transformTest)
1256 		{
1257 			if (structNdx & 1)
1258 				transform.matrix[0][3] = (1.0f /  8.0f) / float(m_data.width);
1259 
1260 			if (structNdx & 2)
1261 				transform.matrix[1][3] = (1.0f / 16.0f) / float(m_data.height);
1262 		}
1263 
1264 		result->addInstance(bottomLevelAccelerationStructures[structNdx], transform, deUint32(2 * structNdx));
1265 	}
1266 
1267 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
1268 
1269 	return result;
1270 }
1271 
initBottomAccelerationStructure(VkCommandBuffer cmdBuffer, tcu::UVec2& startPos)1272 de::MovePtr<BottomLevelAccelerationStructure> RayTracingBuiltinLaunchTestInstance::initBottomAccelerationStructure (VkCommandBuffer	cmdBuffer,
1273 																													tcu::UVec2&		startPos)
1274 {
1275 	const DeviceInterface&							vkd			= m_context.getDeviceInterface();
1276 	const VkDevice									device		= m_context.getDevice();
1277 	Allocator&										allocator	= m_context.getDefaultAllocator();
1278 	de::MovePtr<BottomLevelAccelerationStructure>	result		= makeBottomLevelAccelerationStructure();
1279 
1280 	result->setGeometryCount(m_data.geometriesGroupCount);
1281 
1282 	if (m_data.id == TEST_ID_LAUNCH_ID_EXT || m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
1283 	{
1284 		result->setDefaultGeometryData(m_data.stage);
1285 	}
1286 	else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT		||
1287 			 m_data.id == TEST_ID_PRIMITIVE_ID				||
1288 			 m_data.id == TEST_ID_INSTANCE_ID				||
1289 			 m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT	)
1290 	{
1291 		const bool	triangles	= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1292 		const bool	missShader	= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1293 		const float	z			= !missShader ? -1.0f : -100.0f;
1294 
1295 		DE_ASSERT(m_data.squaresGroupCount != 1);
1296 
1297 		for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1298 		{
1299 			std::vector<tcu::Vec3>	geometryData;
1300 
1301 			geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1302 
1303 			for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1304 			{
1305 				const deUint32	n	= m_data.width * startPos.y() + startPos.x();
1306 				const float		x0	= float(startPos.x() + 0) / float(m_data.width);
1307 				const float		y0	= float(startPos.y() + 0) / float(m_data.height);
1308 				const float		x1	= float(startPos.x() + 1) / float(m_data.width);
1309 				const float		y1	= float(startPos.y() + 1) / float(m_data.height);
1310 				const deUint32	m	= n + 1;
1311 
1312 				if (triangles)
1313 				{
1314 					const float	xm	= (x0 + x1) / 2.0f;
1315 					const float	ym	= (y0 + y1) / 2.0f;
1316 
1317 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1318 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1319 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1320 				}
1321 				else
1322 				{
1323 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1324 					geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1325 				}
1326 
1327 				startPos.y() = m / m_data.width;
1328 				startPos.x() = m % m_data.width;
1329 			}
1330 
1331 			result->addGeometry(geometryData, triangles);
1332 		}
1333 	}
1334 	else if (m_data.id == TEST_ID_HIT_KIND_EXT)
1335 	{
1336 		const bool	triangles	= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1337 		const bool	missShader	= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1338 		const float	z			= !missShader ? -1.0f : -100.0f;
1339 
1340 		DE_ASSERT(m_data.squaresGroupCount != 1);
1341 		DE_ASSERT(m_data.geometriesGroupCount == 4);
1342 
1343 		std::vector<tcu::Vec3>	geometryDataOpaque;
1344 		std::vector<tcu::Vec3>	geometryDataNonOpaque;
1345 
1346 		geometryDataOpaque.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1347 		geometryDataNonOpaque.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1348 
1349 		for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1350 		{
1351 			const bool				cw				= ((geometryNdx & 1) == 0) ? true : false;
1352 			std::vector<tcu::Vec3>&	geometryData	= ((geometryNdx & 2) == 0) ? geometryDataOpaque : geometryDataNonOpaque;
1353 
1354 			for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1355 			{
1356 				const deUint32	n	= m_data.width * startPos.y() + startPos.x();
1357 				const deUint32	m	= n + 1;
1358 				const float		x0	= float(startPos.x() + 0) / float(m_data.width);
1359 				const float		y0	= float(startPos.y() + 0) / float(m_data.height);
1360 				const float		x1	= float(startPos.x() + 1) / float(m_data.width);
1361 				const float		y1	= float(startPos.y() + 1) / float(m_data.height);
1362 
1363 				if (triangles)
1364 				{
1365 					const float	xm	= (x0 + x1) / 2.0f;
1366 					const float	ym	= (y0 + y1) / 2.0f;
1367 
1368 					if (cw)
1369 					{
1370 						geometryData.push_back(tcu::Vec3(x0, y0, z));
1371 						geometryData.push_back(tcu::Vec3(x1, ym, z));
1372 						geometryData.push_back(tcu::Vec3(xm, y1, z));
1373 					}
1374 					else
1375 					{
1376 						geometryData.push_back(tcu::Vec3(x0, y0, z));
1377 						geometryData.push_back(tcu::Vec3(xm, y1, z));
1378 						geometryData.push_back(tcu::Vec3(x1, ym, z));
1379 					}
1380 				}
1381 				else
1382 				{
1383 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1384 					geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1385 				}
1386 
1387 				startPos.y() = m / m_data.width;
1388 				startPos.x() = m % m_data.width;
1389 			}
1390 		}
1391 
1392 		DE_ASSERT(startPos.y() == m_data.height && startPos.x() == 0);
1393 
1394 		result->addGeometry(geometryDataOpaque, triangles, (VkGeometryFlagsKHR)VK_GEOMETRY_OPAQUE_BIT_KHR);
1395 		result->addGeometry(geometryDataNonOpaque, triangles, (VkGeometryFlagsKHR)0);
1396 	}
1397 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
1398 	{
1399 		const bool					triangles		= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1400 		const bool					missShader		= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1401 		const float					z				= !missShader ? -1.0f : -100.0f;
1402 		const VkGeometryFlagsKHR	geometryFlags	= m_data.opaque ? static_cast<VkGeometryFlagsKHR>(VK_GEOMETRY_OPAQUE_BIT_KHR) : static_cast<VkGeometryFlagsKHR>(0);
1403 		const bool					cw				= m_data.frontFace;
1404 		std::vector<tcu::Vec3>		geometryData;
1405 
1406 		DE_ASSERT(m_data.geometriesGroupCount == 1);
1407 		DE_ASSERT(m_data.squaresGroupCount != 1);
1408 
1409 		geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1410 
1411 		for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1412 		{
1413 			const deUint32	n	= m_data.width * startPos.y() + startPos.x();
1414 			const deUint32	m	= n + 1;
1415 			const float		x0	= float(startPos.x() + 0) / float(m_data.width);
1416 			const float		y0	= float(startPos.y() + 0) / float(m_data.height);
1417 			const float		x1	= float(startPos.x() + 1) / float(m_data.width);
1418 			const float		y1	= float(startPos.y() + 1) / float(m_data.height);
1419 
1420 			if (triangles)
1421 			{
1422 				const float	xm	= (x0 + x1) / 2.0f;
1423 				const float	ym	= (y0 + y1) / 2.0f;
1424 
1425 				if (cw)
1426 				{
1427 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1428 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1429 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1430 				}
1431 				else
1432 				{
1433 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1434 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1435 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1436 				}
1437 			}
1438 			else
1439 			{
1440 				geometryData.push_back(tcu::Vec3(x0, y0, z));
1441 				geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1442 			}
1443 
1444 			startPos.y() = m / m_data.width;
1445 			startPos.x() = m % m_data.width;
1446 		}
1447 
1448 		DE_ASSERT(startPos.y() == m_data.height && startPos.x() == 0);
1449 
1450 		result->addGeometry(geometryData, triangles, geometryFlags);
1451 	}
1452 	else if (m_data.id == TEST_ID_HIT_T_EXT		||
1453 			 m_data.id == TEST_ID_RAY_T_MIN_EXT	||
1454 			 m_data.id == TEST_ID_RAY_T_MAX_EXT	)
1455 	{
1456 		const bool	triangles	= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1457 		const bool	missShader	= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1458 		const bool	sectShader	= (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
1459 		const bool	maxTTest	= (m_data.id == TEST_ID_RAY_T_MAX_EXT);
1460 
1461 		DE_ASSERT(m_data.squaresGroupCount != 1);
1462 
1463 		for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1464 		{
1465 			std::vector<tcu::Vec3>	geometryData;
1466 
1467 			geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1468 
1469 			for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1470 			{
1471 				const deUint32	n			= m_data.width * startPos.y() + startPos.x();
1472 				const deUint32	m			= n + 1;
1473 				const bool		shiftRight	= sectShader && maxTTest && (0 == (startPos.y() & 1)) && (0 == (startPos.x() & 1));
1474 				const deUint32	xo			= shiftRight ? 1 : 0;
1475 				const float		x0			= float(startPos.x() + 0 + xo) / float(m_data.width);
1476 				const float		y0			= float(startPos.y() + 0) / float(m_data.height);
1477 				const float		x1			= float(startPos.x() + 1 + xo) / float(m_data.width);
1478 				const float		y1			= float(startPos.y() + 1) / float(m_data.height);
1479 				const float		a			= x0;
1480 				const float		b			= 1.0f + y0;
1481 				const float		c			= 0.03125f + 0.25f * a / b;
1482 				const float		z			= !missShader ? -c : -100.0f;
1483 
1484 				if (triangles)
1485 				{
1486 					const float	xm	= (x0 + x1) / 2.0f;
1487 					const float	ym	= (y0 + y1) / 2.0f;
1488 
1489 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1490 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1491 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1492 				}
1493 				else
1494 				{
1495 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1496 					geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1497 				}
1498 
1499 				startPos.y() = m / m_data.width;
1500 				startPos.x() = m % m_data.width;
1501 			}
1502 
1503 			result->addGeometry(geometryData, triangles);
1504 		}
1505 	}
1506 	else if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT		||
1507 			 m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT	||
1508 			 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT		||
1509 			 m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT	||
1510 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT		||
1511 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT		||
1512 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT	||
1513 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT	)
1514 	{
1515 		const bool				triangles		= m_data.geomType == GEOM_TYPE_TRIANGLES;
1516 		const float				y0				= float(startPos.y() + 0) / float(m_data.height);
1517 		const float				y1				= float(startPos.y() + 1) / float(m_data.height);
1518 		const bool				missShader		= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1519 		const float				z				= !missShader ? -1.0f : -100.0f;
1520 		std::vector<tcu::Vec3>	geometryData;
1521 
1522 		if (triangles)
1523 		{
1524 			geometryData.push_back(tcu::Vec3(-1.0f, y1, z));
1525 			geometryData.push_back(tcu::Vec3(-1.0f, y0, z));
1526 			geometryData.push_back(tcu::Vec3(+1.0f, y0, z));
1527 			geometryData.push_back(tcu::Vec3(-1.0f, y1, z));
1528 			geometryData.push_back(tcu::Vec3(+1.0f, y0, z));
1529 			geometryData.push_back(tcu::Vec3(+1.0f, y1, z));
1530 		}
1531 		else
1532 		{
1533 			geometryData.reserve(2);
1534 
1535 			geometryData.push_back(tcu::Vec3(-1.0f, y0, z));
1536 			geometryData.push_back(tcu::Vec3(+1.0f, y1, z));
1537 		}
1538 
1539 		DE_ASSERT(startPos.y() < m_data.height);
1540 
1541 		startPos.y()++;
1542 
1543 		result->addGeometry(geometryData, triangles);
1544 	}
1545 	else
1546 	{
1547 		TCU_THROW(InternalError, "Not implemented");
1548 	}
1549 
1550 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
1551 
1552 	return result;
1553 }
1554 
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)1555 vector<de::SharedPtr<BottomLevelAccelerationStructure> > RayTracingBuiltinLaunchTestInstance::initBottomAccelerationStructures (VkCommandBuffer	cmdBuffer)
1556 {
1557 	tcu::UVec2													startPos;
1558 	vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
1559 
1560 	for (size_t instanceNdx = 0; instanceNdx < m_data.instancesGroupCount; ++instanceNdx)
1561 	{
1562 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure	= initBottomAccelerationStructure(cmdBuffer, startPos);
1563 
1564 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1565 	}
1566 
1567 	return result;
1568 }
1569 
makePipeline(de::MovePtr<RayTracingPipeline>& rayTracingPipeline, VkPipelineLayout pipelineLayout, const VkSpecializationInfo* specializationInfo)1570 Move<VkPipeline> RayTracingBuiltinLaunchTestInstance::makePipeline (de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
1571 																	VkPipelineLayout					pipelineLayout,
1572 																	const VkSpecializationInfo*			specializationInfo)
1573 {
1574 	const DeviceInterface&	vkd			= m_context.getDeviceInterface();
1575 	const VkDevice			device		= m_context.getDevice();
1576 	vk::BinaryCollection&	collection	= m_context.getBinaryCollection();
1577 
1578 	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))			rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR		, createShaderModule(vkd, device, collection.get("rgen"), 0), m_raygenShaderGroup, specializationInfo);
1579 	if (0 != (m_shaders & VK_SHADER_STAGE_ANY_HIT_BIT_KHR))			rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR		, createShaderModule(vkd, device, collection.get("ahit"), 0), m_hitShaderGroup, specializationInfo);
1580 	if (0 != (m_shaders & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))		rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR	, createShaderModule(vkd, device, collection.get("chit"), 0), m_hitShaderGroup, specializationInfo);
1581 	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))			rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR			, createShaderModule(vkd, device, collection.get("miss"), 0), m_missShaderGroup, specializationInfo);
1582 	if (0 != (m_shaders & VK_SHADER_STAGE_INTERSECTION_BIT_KHR))	rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR	, createShaderModule(vkd, device, collection.get("sect"), 0), m_hitShaderGroup, specializationInfo);
1583 	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))		rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR		, createShaderModule(vkd, device, collection.get("call"), 0), m_callableShaderGroup, specializationInfo);
1584 
1585 	if (m_data.pipelineCreateFlags != 0)
1586 	{
1587 		rayTracingPipeline->setCreateFlags(m_data.pipelineCreateFlags);
1588 		if (m_data.useMaintenance5)
1589 			rayTracingPipeline->setCreateFlags2(translateCreateFlag(m_data.pipelineCreateFlags));
1590 	}
1591 
1592 	Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
1593 
1594 	return pipeline;
1595 }
1596 
createShaderBindingTable(const InstanceInterface& vki, const DeviceInterface& vkd, const VkDevice device, const VkPhysicalDevice physicalDevice, const VkPipeline pipeline, Allocator& allocator, de::MovePtr<RayTracingPipeline>& rayTracingPipeline, const deUint32 group)1597 de::MovePtr<BufferWithMemory> RayTracingBuiltinLaunchTestInstance::createShaderBindingTable (const InstanceInterface&			vki,
1598 																							 const DeviceInterface&				vkd,
1599 																							 const VkDevice						device,
1600 																							 const VkPhysicalDevice				physicalDevice,
1601 																							 const VkPipeline					pipeline,
1602 																							 Allocator&							allocator,
1603 																							 de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
1604 																							 const deUint32						group)
1605 {
1606 	de::MovePtr<BufferWithMemory>	shaderBindingTable;
1607 
1608 	if (group < m_shaderGroupCount)
1609 	{
1610 		const deUint32	shaderGroupHandleSize		= getShaderGroupSize(vki, physicalDevice);
1611 		const deUint32	shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
1612 
1613 		shaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, 1u);
1614 	}
1615 
1616 	return shaderBindingTable;
1617 }
1618 
1619 // Provides two spec constants, one integer and one float, both with value 256.
1620 class SpecConstantsHelper
1621 {
1622 public:
1623 								SpecConstantsHelper		();
1624 	const VkSpecializationInfo&	getSpecializationInfo	(void) const;
1625 private:
1626 	std::vector<deUint8>					m_data;
1627 	std::vector<VkSpecializationMapEntry>	m_mapEntries;
1628 	VkSpecializationInfo					m_specInfo;
1629 };
1630 
SpecConstantsHelper()1631 SpecConstantsHelper::SpecConstantsHelper ()
1632 	: m_data		()
1633 	, m_mapEntries	()
1634 {
1635 	// To make things interesting, make both data unaligned and add some padding.
1636 	const deInt32	value1	= 256;
1637 	const float		value2	= 256.0f;
1638 
1639 	const size_t	offset1	= 1u;							// Offset of 1 byte.
1640 	const size_t	offset2	= 1u + sizeof(value1) + 2u;		// Offset of 3 bytes plus the size of value1.
1641 
1642 	m_data.resize(sizeof(value1) + sizeof(value2) + 5u);	// Some extra padding at the end too.
1643 	deMemcpy(&m_data[offset1], &value1, sizeof(value1));
1644 	deMemcpy(&m_data[offset2], &value2, sizeof(value2));
1645 
1646 	// Map entries.
1647 	m_mapEntries.reserve(2u);
1648 	m_mapEntries.push_back({ 0u, static_cast<deUint32>(offset1), static_cast<deUintptr>(sizeof(value1)) });
1649 	m_mapEntries.push_back({ 1u, static_cast<deUint32>(offset2), static_cast<deUintptr>(sizeof(value2))	});
1650 
1651 	// Specialization info.
1652 	m_specInfo.mapEntryCount	= static_cast<deUint32>(m_mapEntries.size());
1653 	m_specInfo.pMapEntries		= m_mapEntries.data();
1654 	m_specInfo.dataSize			= static_cast<deUintptr>(m_data.size());
1655 	m_specInfo.pData			= m_data.data();
1656 }
1657 
getSpecializationInfo(void) const1658 const VkSpecializationInfo& SpecConstantsHelper::getSpecializationInfo (void) const
1659 {
1660 	return m_specInfo;
1661 }
1662 
runTest(void)1663 de::MovePtr<BufferWithMemory> RayTracingBuiltinLaunchTestInstance::runTest (void)
1664 {
1665 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
1666 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
1667 	const VkDevice						device								= m_context.getDevice();
1668 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
1669 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
1670 	const VkQueue						queue								= m_context.getUniversalQueue();
1671 	Allocator&							allocator							= m_context.getDefaultAllocator();
1672 	const deUint32						shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
1673 	const VkFormat						format								= m_data.format;
1674 	const deUint32						pixelSize							= tcu::getPixelSize(mapVkFormat(format));
1675 	const deUint32						pixelCount							= m_data.width * m_data.height * m_data.depth;
1676 
1677 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
1678 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1679 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1680 																					.build(vkd, device);
1681 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
1682 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1683 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1684 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1685 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1686 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
1687 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
1688 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1689 
1690 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
1691 	const SpecConstantsHelper			specConstantHelper;
1692 	const VkSpecializationInfo*			specializationInfo					= (m_data.useSpecConstants ? &specConstantHelper.getSpecializationInfo() : nullptr);
1693 	const Move<VkPipeline>				pipeline							= makePipeline(rayTracingPipeline, *pipelineLayout, specializationInfo);
1694 	const de::MovePtr<BufferWithMemory>	raygenShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_raygenShaderGroup);
1695 	const de::MovePtr<BufferWithMemory>	missShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_missShaderGroup);
1696 	const de::MovePtr<BufferWithMemory>	hitShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_hitShaderGroup);
1697 	const de::MovePtr<BufferWithMemory>	callableShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_callableShaderGroup);
1698 
1699 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion		= raygenShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1700 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion		= missShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1701 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion			= hitShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1702 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion	= callableShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1703 
1704 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, m_data.depth, format);
1705 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1706 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1707 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, format, imageSubresourceRange);
1708 
1709 	const VkBufferCreateInfo			bufferCreateInfo					= makeBufferCreateInfo(pixelCount * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1710 	const VkImageSubresourceLayers		bufferImageSubresourceLayers		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1711 	const VkBufferImageCopy				bufferImageRegion					= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, m_data.depth), bufferImageSubresourceLayers);
1712 	de::MovePtr<BufferWithMemory>		buffer								= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1713 
1714 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1715 
1716 	const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1717 																				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1718 																				**image, imageSubresourceRange);
1719 	const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1720 																				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1721 																				**image, imageSubresourceRange);
1722 	const VkMemoryBarrier				postTraceMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1723 	const VkMemoryBarrier				postCopyMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1724 	const VkClearValue					clearValue							= makeClearValueColorU32(DEFAULT_UINT_CLEAR_VALUE, DEFAULT_UINT_CLEAR_VALUE, DEFAULT_UINT_CLEAR_VALUE, 255u);
1725 
1726 	vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
1727 	de::MovePtr<TopLevelAccelerationStructure>					topLevelAccelerationStructure;
1728 
1729 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
1730 	{
1731 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1732 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
1733 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1734 
1735 		bottomLevelAccelerationStructures	= initBottomAccelerationStructures(*cmdBuffer);
1736 		topLevelAccelerationStructure		= initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
1737 
1738 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
1739 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
1740 		{
1741 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1742 			DE_NULL,															//  const void*							pNext;
1743 			1u,																	//  deUint32							accelerationStructureCount;
1744 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1745 		};
1746 
1747 		DescriptorSetUpdateBuilder()
1748 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1749 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1750 			.update(vkd, device);
1751 
1752 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1753 
1754 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1755 
1756 		cmdTraceRays(vkd,
1757 			*cmdBuffer,
1758 			&raygenShaderBindingTableRegion,
1759 			&missShaderBindingTableRegion,
1760 			&hitShaderBindingTableRegion,
1761 			&callableShaderBindingTableRegion,
1762 			m_data.width, m_data.height, m_data.raysDepth);
1763 
1764 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1765 
1766 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
1767 
1768 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
1769 	}
1770 	endCommandBuffer(vkd, *cmdBuffer);
1771 
1772 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1773 
1774 	invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1775 
1776 	return buffer;
1777 }
1778 
checkFormatSupported(Context& context, VkFormat format, VkImageUsageFlags usage, const VkExtent3D& extent)1779 void checkFormatSupported(Context& context, VkFormat format, VkImageUsageFlags usage, const VkExtent3D& extent)
1780 {
1781 	VkResult					result;
1782 	VkImageFormatProperties		properties;
1783 
1784 	result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), format, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
1785 
1786 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
1787 	{
1788 		std::ostringstream msg;
1789 
1790 		msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
1791 
1792 		TCU_THROW(NotSupportedError, msg.str());
1793 	}
1794 
1795 	if (properties.maxExtent.width < extent.width || properties.maxExtent.height < extent.height || properties.maxExtent.depth < extent.depth)
1796 		TCU_THROW(NotSupportedError, "Image size is too large for this format");
1797 
1798 	VK_CHECK(result);
1799 }
1800 
checkSupportInInstance(void) const1801 void RayTracingBuiltinLaunchTestInstance::checkSupportInInstance (void) const
1802 {
1803 	const InstanceInterface&				vki						= m_context.getInstanceInterface();
1804 	const VkPhysicalDevice					physicalDevice			= m_context.getPhysicalDevice();
1805 	const vk::VkPhysicalDeviceProperties&	properties				= m_context.getDeviceProperties();
1806 	const deUint32							requiredAllocations		= 8u
1807 																	+ TopLevelAccelerationStructure::getRequiredAllocationCount()
1808 																	+ m_data.instancesGroupCount * BottomLevelAccelerationStructure::getRequiredAllocationCount();
1809 	const de::MovePtr<RayTracingProperties>	rayTracingProperties	= makeRayTracingProperties(vki, physicalDevice);
1810 	const VkExtent3D						extent					= makeExtent3D(m_data.width, m_data.height, m_data.depth);
1811 
1812 	checkFormatSupported(m_context, m_data.format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, extent);
1813 
1814 	if (rayTracingProperties->getMaxPrimitiveCount() < 2 * m_data.squaresGroupCount)
1815 		TCU_THROW(NotSupportedError, "Triangles required more than supported");
1816 
1817 	if (rayTracingProperties->getMaxGeometryCount() < m_data.geometriesGroupCount)
1818 		TCU_THROW(NotSupportedError, "Geometries required more than supported");
1819 
1820 	if (rayTracingProperties->getMaxInstanceCount() < m_data.instancesGroupCount)
1821 		TCU_THROW(NotSupportedError, "Instances required more than supported");
1822 
1823 	if (properties.limits.maxMemoryAllocationCount < requiredAllocations)
1824 		TCU_THROW(NotSupportedError, "Test requires more allocations allowed");
1825 }
1826 
expectedIntValuesBuffer(void)1827 std::vector<deInt32> RayTracingBuiltinLaunchTestInstance::expectedIntValuesBuffer (void)
1828 {
1829 	deUint32				pos		= 0;
1830 	std::vector<deInt32>	result;
1831 
1832 	result.reserve(m_data.depth * m_data.height * m_data.width);
1833 
1834 	if (m_data.id == TEST_ID_LAUNCH_ID_EXT)
1835 	{
1836 		for (deUint32 z = 0; z < m_data.depth; ++z)
1837 		for (deUint32 y = 0; y < m_data.height; ++y)
1838 		for (deUint32 x = 0; x < m_data.width; ++x)
1839 			result.push_back(deInt32(x + 256 * (y + 256 * z)) + 1);
1840 	}
1841 	else if (m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
1842 	{
1843 		const deUint32				expectedValue	= m_data.width + 256 * (m_data.height + 256 * m_data.depth);
1844 		const std::vector<deInt32>	result2			(m_data.depth * m_data.height * m_data.width, deInt32(expectedValue) + 1);
1845 
1846 		result = result2;
1847 	}
1848 	else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT)
1849 	{
1850 		for (deUint32 z = 0; z < m_data.depth; ++z)
1851 		for (deUint32 y = 0; y < m_data.height; ++y)
1852 		for (deUint32 x = 0; x < m_data.width; ++x)
1853 			result.push_back(deInt32((pos++ / m_data.squaresGroupCount) % m_data.geometriesGroupCount));
1854 	}
1855 	else if (m_data.id == TEST_ID_PRIMITIVE_ID)
1856 	{
1857 		for (deUint32 z = 0; z < m_data.depth; ++z)
1858 		for (deUint32 y = 0; y < m_data.height; ++y)
1859 		for (deUint32 x = 0; x < m_data.width; ++x)
1860 			result.push_back(deInt32(pos++ % m_data.squaresGroupCount));
1861 	}
1862 	else if (m_data.id == TEST_ID_INSTANCE_ID)
1863 	{
1864 		for (deUint32 z = 0; z < m_data.depth; ++z)
1865 		for (deUint32 y = 0; y < m_data.height; ++y)
1866 		for (deUint32 x = 0; x < m_data.width; ++x)
1867 			result.push_back(deInt32(pos++ / (m_data.squaresGroupCount * m_data.geometriesGroupCount)));
1868 	}
1869 	else if (m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT)
1870 	{
1871 		for (deUint32 z = 0; z < m_data.depth; ++z)
1872 		for (deUint32 y = 0; y < m_data.height; ++y)
1873 		for (deUint32 x = 0; x < m_data.width; ++x)
1874 			result.push_back(deInt32(2 * (pos++ / (m_data.squaresGroupCount * m_data.geometriesGroupCount))));
1875 	}
1876 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
1877 	{
1878 		DE_ASSERT(m_data.squaresGroupCount == (1<<RAY_FLAG_BIT_LAST_PER_TEST));
1879 		DE_ASSERT(DEFAULT_UINT_CLEAR_VALUE != (1<<RAY_FLAG_BIT_LAST_PER_TEST));
1880 
1881 		for (deUint32 z = 0; z < m_data.depth; ++z)
1882 		for (deUint32 y = 0; y < m_data.height; ++y)
1883 		for (deUint32 x = 0; x < m_data.width; ++x)
1884 		{
1885 			const deUint32	n						= x + m_data.width * (y + m_data.height * z);
1886 			const bool		rayOpaque				= (0 != (n & (1<<RAY_FLAG_BIT_OPAQUE_EXT                     )));
1887 			const bool		rayNoOpaque				= (0 != (n & (1<<RAY_FLAG_BIT_NO_OPAQUE_EXT                  ))) && !rayOpaque;
1888 			const bool		rayTerminateOnFirstHit	= (0 != (n & (1<<RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT     )));
1889 			const bool		raySkipClosestHitShader	= (0 != (n & (1<<RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT    )));
1890 			const bool		rayCullBack				= (0 != (n & (1<<RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT )));
1891 			const bool		rayCullFront			= (0 != (n & (1<<RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT))) && !rayCullBack;
1892 			const bool		rayCullOpaque			= (0 != (n & (1<<RAY_FLAG_BIT_CULL_OPAQUE_EXT                ))) && !rayOpaque && !rayNoOpaque;
1893 			const bool		rayCullNoOpaque			= (0 != (n & (1<<RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT             ))) && !rayOpaque && !rayNoOpaque && !rayCullOpaque;
1894 			const bool		raySkipTriangles		= m_data.rayFlagSkipTriangles;
1895 			const bool		raySkipAABBs			= m_data.rayFlagSkipAABSs;
1896 			const bool		pipelineSkipTriangles	= (m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0;
1897 			const bool		pipelineSkipAABBs		= (m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0;
1898 			const bool		cullingTest				= m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs || pipelineSkipTriangles || pipelineSkipAABBs;
1899 			const bool		geometryFrontFace		= m_data.frontFace;
1900 			const bool		geometryOpaque			= m_data.opaque;
1901 			const bool		geometryTriangles		= (m_data.geomType == GEOM_TYPE_TRIANGLES) ? true : false;
1902 			const bool		geometryAABBs			= (m_data.geomType == GEOM_TYPE_AABBS) ? true : false;
1903 			deUint32		v						= 0
1904 													| (rayOpaque                ? (1<<RAY_FLAG_BIT_OPAQUE_EXT                     ) : 0)
1905 													| (rayNoOpaque              ? (1<<RAY_FLAG_BIT_NO_OPAQUE_EXT                  ) : 0)
1906 													| (rayTerminateOnFirstHit   ? (1<<RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT     ) : 0)
1907 													| (raySkipClosestHitShader  ? (1<<RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT    ) : 0)
1908 													| (rayCullBack              ? (1<<RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT ) : 0)
1909 													| (rayCullFront             ? (1<<RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT) : 0)
1910 													| (rayCullOpaque            ? (1<<RAY_FLAG_BIT_CULL_OPAQUE_EXT                ) : 0)
1911 													| (rayCullNoOpaque          ? (1<<RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT             ) : 0)
1912 													| (raySkipTriangles         ? (1<<RAY_FLAG_BIT_SKIP_TRIANGLES_EXT             ) : 0)
1913 													| (raySkipAABBs             ? (1<<RAY_FLAG_BIT_SKIP_AABB_EXT                  ) : 0);
1914 
1915 			if (m_data.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR && raySkipClosestHitShader)
1916 				v = DEFAULT_UINT_CLEAR_VALUE;
1917 
1918 			if (m_data.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR && (rayOpaque || (geometryOpaque && !rayOpaque && !rayNoOpaque)))
1919 				v = DEFAULT_UINT_CLEAR_VALUE;
1920 
1921 			if (geometryOpaque)
1922 			{
1923 				if (rayCullOpaque)
1924 					if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1925 						v = DEFAULT_UINT_CLEAR_VALUE;
1926 			}
1927 			else
1928 			{
1929 				if (rayCullNoOpaque)
1930 					if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1931 						v = DEFAULT_UINT_CLEAR_VALUE;
1932 			}
1933 
1934 			if (geometryTriangles)
1935 			{
1936 				if (geometryFrontFace)
1937 				{
1938 					if (rayCullFront)
1939 						if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1940 							v = DEFAULT_UINT_CLEAR_VALUE;
1941 				}
1942 				else
1943 				{
1944 					if (rayCullBack)
1945 						if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1946 							v = DEFAULT_UINT_CLEAR_VALUE;
1947 				}
1948 			}
1949 
1950 			if (cullingTest)
1951 			{
1952 				if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1953 				{
1954 					if (geometryTriangles)
1955 					{
1956 						if (raySkipTriangles || pipelineSkipTriangles)
1957 							v = DEFAULT_UINT_CLEAR_VALUE;
1958 					}
1959 
1960 					if (geometryAABBs)
1961 					{
1962 						if (raySkipAABBs || pipelineSkipAABBs)
1963 							v = DEFAULT_UINT_CLEAR_VALUE;
1964 					}
1965 				}
1966 			}
1967 
1968 			result.push_back(deInt32(v));
1969 		}
1970 	}
1971 	else if (m_data.id == TEST_ID_HIT_KIND_EXT)
1972 	{
1973 		for (deUint32 z = 0; z < m_data.depth; ++z)
1974 		for (deUint32 y = 0; y < m_data.height; ++y)
1975 		for (deUint32 x = 0; x < m_data.width; ++x)
1976 		{
1977 			const deUint32	n				= x + m_data.width * (y + m_data.height * z);
1978 			const deUint32	geometryNdx		= n / m_data.squaresGroupCount;
1979 			const deUint32	hitKind			= ((geometryNdx & 1) == 0) ? 0xFEu : 0xFFu;
1980 			const bool		geometryOpaque	= ((geometryNdx & 2) == 0) ? true : false;
1981 			deUint32		v				= (m_data.geomType == GEOM_TYPE_TRIANGLES) ? hitKind : 0x7Eu;
1982 
1983 			if (m_data.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR && geometryOpaque)
1984 				v = DEFAULT_UINT_CLEAR_VALUE;
1985 
1986 			result.push_back(deInt32(v));
1987 		}
1988 	}
1989 	else
1990 	{
1991 		TCU_THROW(InternalError, "Not implemented");
1992 	}
1993 
1994 	return result;
1995 }
1996 
expectedFloatValuesBuffer(void)1997 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedFloatValuesBuffer (void)
1998 {
1999 	std::vector<float>	result;
2000 
2001 	result.reserve(m_data.depth * m_data.height * m_data.width);
2002 
2003 	if (m_data.id == TEST_ID_HIT_T_EXT)
2004 	{
2005 		for (deUint32 z = 0; z < m_data.depth; ++z)
2006 		for (deUint32 y = 0; y < m_data.height; ++y)
2007 		for (deUint32 x = 0; x < m_data.width; ++x)
2008 		{
2009 			const float	a	= float(x) / float(m_data.width);
2010 			const float	b	= 1.0f + float(y) / float(m_data.height);
2011 			const float	f	= 0.03125f + 0.25f * a / b;
2012 
2013 			result.push_back(f);
2014 		}
2015 	}
2016 	else if (m_data.id == TEST_ID_RAY_T_MIN_EXT)
2017 	{
2018 		for (deUint32 z = 0; z < m_data.depth; ++z)
2019 		for (deUint32 y = 0; y < m_data.height; ++y)
2020 		for (deUint32 x = 0; x < m_data.width; ++x)
2021 		{
2022 			const float	a	= float(x) / float(m_data.width);
2023 			const float	b	= 1.0f + float(y) / float(m_data.height);
2024 			const float	f	= 0.25f * a / b;
2025 
2026 			result.push_back(f);
2027 		}
2028 	}
2029 	else if (m_data.id == TEST_ID_RAY_T_MAX_EXT)
2030 	{
2031 		for (deUint32 z = 0; z < m_data.depth; ++z)
2032 		for (deUint32 y = 0; y < m_data.height; ++y)
2033 		for (deUint32 x = 0; x < m_data.width; ++x)
2034 		{
2035 			const float	a				= float(x) / float(m_data.width);
2036 			const float	b				= 1.0f + float(y) / float(m_data.height);
2037 			const float	c				= 0.25f * a / b;
2038 			// In a miss shader, the value is identical to the parameter passed into traceRayEXT().
2039 			const float	m				= 0.75f + c;
2040 			// In the closest-hit shader, the value reflects the closest distance to the intersected primitive.
2041 			// In the any-hit shader, it reflects the distance to the primitive currently being intersected.
2042 			// In the intersection shader, it reflects the distance to the closest primitive intersected so far.
2043 			const float	n				= 0.03125f + c;
2044 			const bool	normalRow		= (y & 1) != 0;
2045 			const bool	doublePrimitive	= (x & 1) != 0;
2046 			const float	s				= normalRow ? m
2047 										: doublePrimitive ? 0.4375f + c
2048 										: float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR);
2049 			const float	f				= (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR) ? s
2050 										: (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR) ? m
2051 										: n;
2052 
2053 			result.push_back(f);
2054 		}
2055 	}
2056 	else
2057 	{
2058 		TCU_THROW(InternalError, "Not implemented");
2059 	}
2060 
2061 	return result;
2062 }
2063 
expectedVectorValuesBuffer(void)2064 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedVectorValuesBuffer (void)
2065 {
2066 	const deUint32		imageDepth		= 4;
2067 	const deUint32		expectedFloats	= imageDepth * m_data.height * m_data.width;
2068 	std::vector<float>	result			(expectedFloats, float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR));
2069 
2070 	if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT)
2071 	{
2072 		deUint32	pos	= 0;
2073 
2074 		for (deUint32 y = 0; y < m_data.height; ++y)
2075 		for (deUint32 x = 0; x < m_data.width; ++x)
2076 			result[pos++] = (0.5f + float(x)) / float(m_data.width);
2077 
2078 		for (deUint32 y = 0; y < m_data.height; ++y)
2079 		for (deUint32 x = 0; x < m_data.width; ++x)
2080 			result[pos++] = (0.5f + float(y)) / float(m_data.height);
2081 
2082 		for (deUint32 y = 0; y < m_data.height; ++y)
2083 		for (deUint32 x = 0; x < m_data.width; ++x)
2084 			result[pos++] = 0.0f;
2085 	}
2086 	else if (m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT)
2087 	{
2088 		deUint32	pos	= 0;
2089 
2090 		for (deUint32 y = 0; y < m_data.height; ++y)
2091 		for (deUint32 x = 0; x < m_data.width; ++x)
2092 			result[pos++] = 0.0f;
2093 
2094 		for (deUint32 y = 0; y < m_data.height; ++y)
2095 		for (deUint32 x = 0; x < m_data.width; ++x)
2096 			result[pos++] = 0.0f;
2097 
2098 		for (deUint32 y = 0; y < m_data.height; ++y)
2099 		for (deUint32 x = 0; x < m_data.width; ++x)
2100 			result[pos++] = -1.0f;
2101 	}
2102 	else if (m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT)
2103 	{
2104 		deUint32	pos	= 0;
2105 
2106 		for (deUint32 y = 0; y < m_data.height; ++y)
2107 		for (deUint32 x = 0; x < m_data.width; ++x)
2108 		{
2109 			const deUint32	instanceId	= y / (m_data.height / m_data.instancesGroupCount);
2110 			const float		offset		= (instanceId & 1) ? 1.0f / 8.0f : 0.0f;
2111 
2112 			result[pos++] = (0.5f + float(x) - offset) / float(m_data.width);
2113 		}
2114 
2115 		for (deUint32 y = 0; y < m_data.height; ++y)
2116 		for (deUint32 x = 0; x < m_data.width; ++x)
2117 		{
2118 			const deUint32	instanceId	= y / (m_data.height / m_data.instancesGroupCount);
2119 			const float		offset		= (instanceId & 2) ? 1.0f / 16.0f : 0.0f;
2120 
2121 			result[pos++] = (0.5f + float(y) - offset) / float(m_data.height);
2122 		}
2123 
2124 		for (deUint32 y = 0; y < m_data.height; ++y)
2125 		for (deUint32 x = 0; x < m_data.width; ++x)
2126 			result[pos++] = 0.0f;
2127 	}
2128 	else if (m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT)
2129 	{
2130 		deUint32	pos	= 0;
2131 
2132 		for (deUint32 y = 0; y < m_data.height; ++y)
2133 		for (deUint32 x = 0; x < m_data.width; ++x)
2134 			result[pos++] = 0.0f;
2135 
2136 		for (deUint32 y = 0; y < m_data.height; ++y)
2137 		for (deUint32 x = 0; x < m_data.width; ++x)
2138 			result[pos++] = 0.0f;
2139 
2140 		for (deUint32 y = 0; y < m_data.height; ++y)
2141 		for (deUint32 x = 0; x < m_data.width; ++x)
2142 			result[pos++] = -1.0f;
2143 	}
2144 	else
2145 	{
2146 		TCU_THROW(InternalError, "Not implemented");
2147 	}
2148 
2149 	return result;
2150 }
2151 
expectedMatrixValuesBuffer(void)2152 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedMatrixValuesBuffer (void)
2153 {
2154 	const deUint32		colCount		= 4;
2155 	const deUint32		rowCount		= 3;
2156 	const deUint32		imageDepth		= 4 * 4;
2157 	const deUint32		zStride			= m_data.height * m_data.width;
2158 	const deUint32		expectedFloats	= imageDepth * m_data.height * m_data.width;
2159 	std::vector<float>	result			(expectedFloats, float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR));
2160 
2161 	if (m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT ||
2162 		m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT ||
2163 		m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT ||
2164 		m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT)
2165 	{
2166 		const int	translateColumnNumber	= 3;
2167 		const float translateSign			= (m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT) ? -1.0f : +1.0f;
2168 		const float translateX				= translateSign * (1.0f / 8.0f) / float(m_data.width);
2169 		const float translateY				= translateSign * (1.0f / 16.0f) / float(m_data.height);
2170 
2171 		for (deUint32 y = 0; y < m_data.height; ++y)
2172 		{
2173 			const deUint32	instanceId	= y / (m_data.height / m_data.instancesGroupCount);
2174 
2175 			for (deUint32 x = 0; x < m_data.width; ++x)
2176 			{
2177 				tcu::Matrix<float, rowCount, colCount>	m;
2178 				const deUint32							elem0Pos	= x + m_data.width * y;
2179 
2180 				if (instanceId & 1)
2181 					m[translateColumnNumber][0] = translateX;
2182 
2183 				if (instanceId & 2)
2184 					m[translateColumnNumber][1] = translateY;
2185 
2186 				for (deUint32 rowNdx = 0; rowNdx < rowCount; ++rowNdx)
2187 				for (deUint32 colNdx = 0; colNdx < colCount; ++colNdx)
2188 				{
2189 					const deUint32	z	= rowNdx * colCount + colNdx;
2190 					const deUint32	pos	= elem0Pos + zStride * z;
2191 
2192 					result[pos] = m[colNdx][rowNdx];
2193 				}
2194 			}
2195 		}
2196 	}
2197 	else
2198 	{
2199 		TCU_THROW(InternalError, "Not implemented");
2200 	}
2201 
2202 	return result;
2203 }
2204 
validateIntBuffer(de::MovePtr<BufferWithMemory> buffer)2205 bool RayTracingBuiltinLaunchTestInstance::validateIntBuffer (de::MovePtr<BufferWithMemory> buffer)
2206 {
2207 	const deInt32*			bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2208 	const vector<deInt32>	expectedValues	= expectedIntValuesBuffer();
2209 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
2210 	deUint32				failures		= 0;
2211 	deUint32				pos				= 0;
2212 
2213 	for (deUint32 z = 0; z < m_data.depth; ++z)
2214 	for (deUint32 y = 0; y < m_data.height; ++y)
2215 	for (deUint32 x = 0; x < m_data.width; ++x)
2216 	{
2217 		if (bufferPtr[pos] != expectedValues[pos])
2218 			failures++;
2219 
2220 		++pos;
2221 	}
2222 
2223 	if (failures != 0)
2224 	{
2225 		const char * names[] = { "Retrieved:", "Expected:" };
2226 		for (deUint32 n = 0; n < 2; ++n)
2227 		{
2228 			const deInt32*		loggedData = (n == 0) ? bufferPtr : expectedValues.data();
2229 			std::stringstream	css;
2230 
2231 			pos = 0;
2232 
2233 			for (deUint32 z = 0; z < m_data.depth; ++z)
2234 			for (deUint32 y = 0; y < m_data.height; ++y)
2235 			{
2236 				for (deUint32 x = 0; x < m_data.width; ++x)
2237 				{
2238 					if (bufferPtr[pos] == expectedValues[pos])
2239 						css << "____,";
2240 					else
2241 						css << std::hex << std::setw(4) << loggedData[pos] << ",";
2242 
2243 					pos++;
2244 				}
2245 
2246 				css << std::endl;
2247 			}
2248 
2249 			log << tcu::TestLog::Message << names[n] << tcu::TestLog::EndMessage;
2250 			log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2251 		}
2252 	}
2253 
2254 	return failures == 0;
2255 }
2256 
validateFloatBuffer(de::MovePtr<BufferWithMemory> buffer)2257 bool RayTracingBuiltinLaunchTestInstance::validateFloatBuffer (de::MovePtr<BufferWithMemory> buffer)
2258 {
2259 	const float			eps				= float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2260 	const deInt32*		bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2261 	const vector<float>	expectedValues	= expectedFloatValuesBuffer();
2262 	tcu::TestLog&		log				= m_context.getTestContext().getLog();
2263 	deUint32			failures		= 0;
2264 	deUint32			pos				= 0;
2265 
2266 	for (deUint32 z = 0; z < m_data.depth; ++z)
2267 	for (deUint32 y = 0; y < m_data.height; ++y)
2268 	for (deUint32 x = 0; x < m_data.width; ++x)
2269 	{
2270 		const float retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2271 
2272 		if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2273 			failures++;
2274 
2275 		++pos;
2276 	}
2277 
2278 	if (failures != 0)
2279 	{
2280 		const char * names[] = { "Retrieved:", "Expected:" };
2281 
2282 		for (deUint32 n = 0; n < 2; ++n)
2283 		{
2284 			std::stringstream	css;
2285 
2286 			pos = 0;
2287 
2288 			for (deUint32 z = 0; z < m_data.depth; ++z)
2289 			for (deUint32 y = 0; y < m_data.height; ++y)
2290 			{
2291 				for (deUint32 x = 0; x < m_data.width; ++x)
2292 				{
2293 					const float	retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2294 					const float	expectedValue	= expectedValues[pos];
2295 
2296 					if (deFloatAbs(retrievedValue - expectedValue) > eps)
2297 						css << std::setprecision(8) << std::setw(12) << (n == 0 ? retrievedValue : expectedValue) << ",";
2298 					else
2299 						css << "____________,";
2300 
2301 					pos++;
2302 				}
2303 
2304 				css << std::endl;
2305 			}
2306 
2307 			log << tcu::TestLog::Message << names[n] << tcu::TestLog::EndMessage;
2308 			log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2309 		}
2310 	}
2311 
2312 	return failures == 0;
2313 }
2314 
validateVectorBuffer(de::MovePtr<BufferWithMemory> buffer)2315 bool RayTracingBuiltinLaunchTestInstance::validateVectorBuffer (de::MovePtr<BufferWithMemory> buffer)
2316 {
2317 	const float			eps				= float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2318 	const deInt32*		bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2319 	const vector<float>	expectedValues	= expectedVectorValuesBuffer();
2320 	const deUint32		depth			= 3u; // vec3
2321 	tcu::TestLog&		log				= m_context.getTestContext().getLog();
2322 	deUint32			failures		= 0;
2323 	deUint32			pos				= 0;
2324 
2325 	DE_ASSERT(depth <= m_data.depth);
2326 
2327 	for (deUint32 z = 0; z < depth; ++z)
2328 	for (deUint32 y = 0; y < m_data.height; ++y)
2329 	for (deUint32 x = 0; x < m_data.width; ++x)
2330 	{
2331 		const float retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2332 
2333 		if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2334 			failures++;
2335 
2336 		++pos;
2337 	}
2338 
2339 	if (failures != 0)
2340 	{
2341 		const char*			names[] = { "Retrieved", "Expected " };
2342 		std::stringstream	css;
2343 
2344 		for (deUint32 y = 0; y < m_data.height; ++y)
2345 		{
2346 			for (deUint32 x = 0; x < m_data.width; ++x)
2347 			{
2348 				for (deUint32 n = 0; n < 2; ++n)
2349 				{
2350 					css << names[n] << " at (" << x << "," << y << ") {";
2351 
2352 					for (deUint32 z = 0; z < depth; ++z)
2353 					{
2354 						pos = x + m_data.width * (y + m_data.height * z);
2355 
2356 						const float	retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2357 						const float	expectedValue	= expectedValues[pos];
2358 
2359 						if (deFloatAbs(retrievedValue - expectedValue) > eps)
2360 							css << std::setprecision(8) << std::setw(12) << (n == 0 ? retrievedValue : expectedValue) << ",";
2361 						else
2362 							css << "____________,";
2363 					}
2364 
2365 					css << "}" << std::endl;
2366 				}
2367 			}
2368 		}
2369 
2370 		log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2371 	}
2372 
2373 	return failures == 0;
2374 }
2375 
validateMatrixBuffer(de::MovePtr<BufferWithMemory> buffer)2376 bool RayTracingBuiltinLaunchTestInstance::validateMatrixBuffer (de::MovePtr<BufferWithMemory> buffer)
2377 {
2378 	const float			eps				= float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2379 	const deInt32*		bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2380 	const vector<float>	expectedValues	= expectedMatrixValuesBuffer();
2381 	const deUint32		depth			= 12u; // mat3x4 or mat4x3
2382 	tcu::TestLog&		log				= m_context.getTestContext().getLog();
2383 	deUint32			failures		= 0;
2384 	deUint32			pos				= 0;
2385 
2386 	DE_ASSERT(depth <= m_data.depth);
2387 
2388 	for (deUint32 z = 0; z < depth; ++z)
2389 	for (deUint32 y = 0; y < m_data.height; ++y)
2390 	for (deUint32 x = 0; x < m_data.width; ++x)
2391 	{
2392 		const float retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2393 
2394 		if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2395 			failures++;
2396 
2397 		++pos;
2398 	}
2399 
2400 	if (failures != 0)
2401 	{
2402 		const char*			names[] = { "Retrieved", "Expected" };
2403 		std::stringstream	css;
2404 
2405 		for (deUint32 y = 0; y < m_data.height; ++y)
2406 		{
2407 			for (deUint32 x = 0; x < m_data.width; ++x)
2408 			{
2409 				css << "At (" << x << "," << y << ")" << std::endl;
2410 				for (deUint32 n = 0; n < 2; ++n)
2411 				{
2412 					css << names[n] << std::endl << "{" << std::endl;
2413 
2414 					for (deUint32 z = 0; z < depth; ++z)
2415 					{
2416 						pos = x + m_data.width * (y + m_data.height * z);
2417 
2418 						const float	retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2419 						const float	expectedValue	= expectedValues[pos];
2420 
2421 						if (z % 4 == 0)
2422 							css << "    {";
2423 
2424 						if (deFloatAbs(retrievedValue - expectedValue) > eps)
2425 							css << std::setprecision(5) << std::setw(9) << (n == 0 ? retrievedValue : expectedValue) << ",";
2426 						else
2427 							css << "_________,";
2428 
2429 						if (z % 4 == 3)
2430 							css << "}" << std::endl;
2431 					}
2432 
2433 					css << "}" << std::endl;
2434 				}
2435 			}
2436 		}
2437 
2438 		log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2439 	}
2440 
2441 	return failures == 0;
2442 }
2443 
iterate(void)2444 tcu::TestStatus RayTracingBuiltinLaunchTestInstance::iterate (void)
2445 {
2446 	checkSupportInInstance();
2447 
2448 	de::MovePtr<BufferWithMemory>	buffer	= runTest();
2449 	const bool						ok		= m_data.fixedPointMatrixOutput ? validateMatrixBuffer(buffer)
2450 											: m_data.fixedPointVectorOutput ? validateVectorBuffer(buffer)
2451 											: m_data.fixedPointScalarOutput ? validateFloatBuffer(buffer)
2452 											: validateIntBuffer(buffer);
2453 
2454 	if (ok)
2455 		return tcu::TestStatus::pass("pass");
2456 	else
2457 		return tcu::TestStatus::fail("fail");
2458 }
2459 
2460 enum ShaderSourceFlag
2461 {
2462 	DEFINE_RAY = 0x1,
2463 	DEFINE_RESULT_BUFFER = 0x2,
2464 	DEFINE_SCENE = 0x4,
2465 	DEFINE_RAY_BUFFER = 0x8,
2466 	DEFINE_SIMPLE_BINDINGS = DEFINE_RESULT_BUFFER | DEFINE_SCENE | DEFINE_RAY_BUFFER
2467 };
2468 
generateShaderSource(const char* body, const char* resultType = �, deUint32 flags = 0, const char* prefix = �)2469 std::string generateShaderSource(const char* body, const char* resultType = "", deUint32 flags = 0, const char* prefix = "")
2470 {
2471 	std::ostringstream src;
2472 	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n";
2473 
2474 	src << "#extension GL_EXT_ray_tracing : enable\n";
2475 
2476 	src << prefix << "\n";
2477 
2478 	if (flags & DEFINE_SIMPLE_BINDINGS)
2479 		flags |= DEFINE_RAY_BUFFER;
2480 
2481 	if (flags & DEFINE_RAY_BUFFER)
2482 		flags |= DEFINE_RAY;
2483 
2484 	if (flags & DEFINE_RAY)
2485 	{
2486 		src << "struct Ray { vec3 pos; float tmin; vec3 dir; float tmax; };\n";
2487 	}
2488 
2489 	if (flags & DEFINE_RESULT_BUFFER)
2490 		src << "layout(std430, set = 0, binding = " << 0 << ") buffer Results { " << resultType << " results[]; };\n";
2491 
2492 	if (flags & DEFINE_SCENE)
2493 	{
2494 		src << "layout(set = 0, binding = " << 1 << ") uniform accelerationStructureEXT scene;\n";
2495 	}
2496 
2497 	if (flags & DEFINE_RAY_BUFFER)
2498 		src << "layout(std430, set = 0, binding = " << 2 << ") buffer Rays { Ray rays[]; };\n";
2499 
2500 	src << "uint launchIndex() { return gl_LaunchIDEXT.z*gl_LaunchSizeEXT.x*gl_LaunchSizeEXT.y + gl_LaunchIDEXT.y*gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x; }\n";
2501 
2502 	src << body;
2503 
2504 	return src.str();
2505 }
2506 
getShaderIdentifier(const CaseDef& params, VkShaderStageFlagBits stage)2507 std::string getShaderIdentifier(const CaseDef& params, VkShaderStageFlagBits stage)
2508 {
2509 	std::string testStage;
2510 
2511 	switch (params.stage)
2512 	{
2513 	case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2514 		testStage = "raygen";
2515 		break;
2516 	case VK_SHADER_STAGE_MISS_BIT_KHR:
2517 		testStage = "-miss";
2518 		break;
2519 	case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2520 		testStage = "-closest-hit";
2521 		break;
2522 	case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2523 		testStage = "-any_hit";
2524 		break;
2525 	case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2526 		testStage = "-closest_hit";
2527 		break;
2528 	case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2529 		testStage = "-callable";
2530 		break;
2531 	default:
2532 		DE_ASSERT(false);
2533 		return std::string();
2534 	}
2535 
2536 	switch (stage)
2537 	{
2538 	case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2539 		return testStage + "-rgen";
2540 	case VK_SHADER_STAGE_MISS_BIT_KHR:
2541 		return testStage + "-miss";
2542 	case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2543 		return testStage + "-closest_hit";
2544 	case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2545 		return testStage + "-any_hit";
2546 	case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2547 		return testStage + "-isect";
2548 	case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2549 		return testStage + "-callable";
2550 	default:
2551 		DE_ASSERT(false);
2552 		return std::string();
2553 	}
2554 }
2555 
replaceString(std::string text, const std::string& search, const std::string& replace)2556 std::string replaceString(std::string text, const std::string& search, const std::string& replace)
2557 {
2558 	size_t found;
2559 
2560 	while ((found = text.find(search)) != std::string::npos)
2561 	{
2562 		text = text.replace(found, search.length(), replace);
2563 	}
2564 
2565 	return text;
2566 }
2567 
addBuiltInShaderSource(SourceCollections& programCollection, VkShaderStageFlagBits stage, const std::string& body, const CaseDef& params, std::string builtInType)2568 template<typename T> inline void addBuiltInShaderSource(SourceCollections& programCollection,
2569 														VkShaderStageFlagBits stage,
2570 														const std::string& body,
2571 														const CaseDef& params,
2572 														std::string builtInType)
2573 {
2574 	std::string identifier = getShaderIdentifier(params, stage);
2575 
2576 	deUint32 flags = 0;
2577 
2578 	if (stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)
2579 		flags |= DEFINE_RAY | DEFINE_SIMPLE_BINDINGS;
2580 
2581 	std::string text = generateShaderSource(body.c_str(), builtInType.c_str(), flags, "");
2582 
2583 	text = replaceString(text, "$builtInType$", builtInType);
2584 
2585 	const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
2586 	programCollection.glslSources.add(identifier) << T(text) << buildOptions;
2587 }
2588 
2589 class RayTracingIndirectTestInstance : public TestInstance
2590 {
2591 public:
2592 																RayTracingIndirectTestInstance			(Context& context, const CaseDef& data);
2593 																~RayTracingIndirectTestInstance			(void);
2594 	tcu::TestStatus												iterate									(void);
2595 
2596 private:
2597 	void														checkSupportInInstance					(void) const;
2598 	Move<VkPipeline>											createPipelineAndShaderBindingTables	(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
2599 																										 bool aabb,
2600 																										VkPipelineLayout pipelineLayout);
2601 
2602 	void														createPipelineLayoutAndSet				(deUint32 setCount,
2603 																										vk::Move<VkDescriptorPool>& descriptorPool,
2604 																										vk::Move<VkDescriptorSetLayout>& descriptorSetLayout,
2605 																										std::vector<vk::Move<VkDescriptorSet>>& descriptorSets,
2606 																										vk::Move<VkPipelineLayout>& pipelineLayout);
2607 
2608 	de::SharedPtr<TopLevelAccelerationStructure>				initTopAccelerationStructure			(std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures);
2609 	vector<de::SharedPtr<BottomLevelAccelerationStructure>>		initBottomAccelerationStructures		(void);
2610 	void														initializeParameters					(void);
2611 	bool														verifyResults							(void);
2612 
2613 private:
2614 	CaseDef														m_data;
2615 	std::vector<std::vector<tcu::Vec3>>							m_geomData;
2616 	de::MovePtr<BufferWithMemory>								m_resultBuffer;
2617 	de::MovePtr<BufferWithMemory>								m_rayBuffer;
2618 	deUint32													m_numGeoms;
2619 	deUint32													m_primsPerGeometry;
2620 	deUint32													m_geomsPerInstance;
2621 
2622 	de::MovePtr<BufferWithMemory>								m_raygenShaderBindingTable;
2623 	de::MovePtr<BufferWithMemory>								m_missShaderBindingTable;
2624 	de::MovePtr<BufferWithMemory>								m_hitShaderBindingTable;
2625 
2626 	VkStridedDeviceAddressRegionKHR								m_raygenShaderBindingTableRegion;
2627 	VkStridedDeviceAddressRegionKHR								m_missShaderBindingTableRegion;
2628 	VkStridedDeviceAddressRegionKHR								m_hitShaderBindingTableRegion;
2629 	VkStridedDeviceAddressRegionKHR								m_callableShaderBindingTableRegion;
2630 };
2631 
RayTracingIndirectTestInstance(Context& context, const CaseDef& data)2632 RayTracingIndirectTestInstance::RayTracingIndirectTestInstance (Context& context, const CaseDef& data)
2633 	: vkt::TestInstance		(context)
2634 	, m_data				(data)
2635 	, m_numGeoms			(0)
2636 	, m_primsPerGeometry	(0)
2637 	, m_geomsPerInstance	(0)
2638 {
2639 }
2640 
~RayTracingIndirectTestInstance(void)2641 RayTracingIndirectTestInstance::~RayTracingIndirectTestInstance(void)
2642 {
2643 }
2644 
2645 class RayTracingIndirectTestCase : public TestCase
2646 {
2647 	public:
2648 										RayTracingIndirectTestCase			(tcu::TestContext& context, const char* name, const CaseDef data);
2649 										~RayTracingIndirectTestCase			(void);
2650 
2651 	virtual	void						initPrograms				(SourceCollections& programCollection) const;
2652 	virtual TestInstance*				createInstance				(Context& context) const;
2653 	virtual void						checkSupport				(Context& context) const;
2654 
2655 private:
2656 	static inline const std::string		getIntersectionPassthrough	(void);
2657 	static inline const std::string		getMissPassthrough			(void);
2658 	static inline const std::string		getHitPassthrough			(void);
2659 
2660 	CaseDef								m_data;
2661 };
2662 
RayTracingIndirectTestCase(tcu::TestContext& context, const char* name, const CaseDef data)2663 RayTracingIndirectTestCase::RayTracingIndirectTestCase (tcu::TestContext& context, const char* name, const CaseDef data)
2664 	: vkt::TestCase	(context, name)
2665 	, m_data		(data)
2666 {
2667 }
2668 
~RayTracingIndirectTestCase(void)2669 RayTracingIndirectTestCase::~RayTracingIndirectTestCase	(void)
2670 {
2671 }
2672 
checkSupport(Context& context) const2673 void RayTracingIndirectTestCase::checkSupport(Context& context) const
2674 {
2675 	const bool	pipelineFlagSkipTriangles	= ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0);
2676 	const bool	pipelineFlagSkipAABSs		= ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0);
2677 	const bool	cullingFlags				=  m_data.rayFlagSkipTriangles
2678 											|| m_data.rayFlagSkipAABSs
2679 											|| pipelineFlagSkipTriangles
2680 											|| pipelineFlagSkipAABSs;
2681 
2682 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2683 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
2684 
2685 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
2686 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
2687 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
2688 
2689 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
2690 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
2691 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
2692 
2693 	if (cullingFlags && rayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling == DE_FALSE)
2694 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling");
2695 }
2696 
initPrograms(SourceCollections& programCollection) const2697 void RayTracingIndirectTestCase::initPrograms (SourceCollections& programCollection) const
2698 {
2699 	if (m_data.id == TEST_ID_INDICES_INDIRECT)
2700 	{
2701 		std::ostringstream raygenSrc;
2702 		raygenSrc
2703 			<< "struct Payload { uvec4 data; };\n"
2704 			<< "layout(location = 0) rayPayloadEXT Payload payload;\n"
2705 			<< "void main() {\n"
2706 			<< "	uint index = launchIndex();\n"
2707 			<< "	payload.data = uvec4(0, 0, 0, 0);\n"
2708 			<< "	Ray ray = rays[index];\n"
2709 			<< "	traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
2710 			<< "	results[index] = payload.data;\n"
2711 			<< "}";
2712 		const std::string raygen = raygenSrc.str();
2713 		addBuiltInShaderSource<glu::RaygenSource>(programCollection, VK_SHADER_STAGE_RAYGEN_BIT_KHR, raygen, m_data, "uvec4");
2714 
2715 		std::ostringstream missSrc;
2716 		missSrc
2717 			<< "struct Payload { uvec4 data; };\n"
2718 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2719 			<< "void main() {\n"
2720 			<< "	payload.data = uvec4(111, 222, 333, 444);\n"
2721 			<< "}";
2722 		const std::string miss = missSrc.str();
2723 		addBuiltInShaderSource<glu::MissSource>(programCollection, VK_SHADER_STAGE_MISS_BIT_KHR, miss, m_data, "uvec4");
2724 
2725 		std::ostringstream closestHitSrc;
2726 		closestHitSrc
2727 			<< "struct Payload { uvec4 data; };\n"
2728 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2729 			<< "hitAttributeEXT vec2 attribs;\n"
2730 			<< "void main() {\n"
2731 			<< "	payload.data = uvec4(gl_PrimitiveID, 0, gl_InstanceID, gl_InstanceCustomIndexEXT);\n"
2732 			<< "}";
2733 		const std::string closestHit = closestHitSrc.str();
2734 		addBuiltInShaderSource<glu::ClosestHitSource>(programCollection, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, closestHit, m_data, "uvec4");
2735 
2736 		std::ostringstream anyHitSrc;
2737 		anyHitSrc
2738 			<< "struct Payload { uvec4 data; };\n"
2739 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2740 			<< "hitAttributeEXT vec2 attribs;\n"
2741 			<< "void main() {\n"
2742 			<< "	payload.data = uvec4(gl_PrimitiveID, 0, gl_InstanceID, gl_InstanceCustomIndexEXT);\n"
2743 			<< "}";
2744 		const std::string anyHit = anyHitSrc.str();
2745 		addBuiltInShaderSource<glu::AnyHitSource>(programCollection, VK_SHADER_STAGE_ANY_HIT_BIT_KHR, anyHit, m_data, "uvec4");
2746 
2747 		std::ostringstream isectSrc;
2748 		isectSrc
2749 			<< "hitAttributeEXT vec2 dummy;\n"
2750 			<< "void main() {\n"
2751 			<< "	reportIntersectionEXT(0.0, 0u);\n"
2752 			<< "}";
2753 		const std::string isect = isectSrc.str();
2754 		addBuiltInShaderSource<glu::IntersectionSource>(programCollection, VK_SHADER_STAGE_INTERSECTION_BIT_KHR, isect, m_data, "uvec4");
2755 	}
2756 	else if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
2757 	{
2758 		const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
2759 
2760 		std::ostringstream preambleSrc;
2761 		preambleSrc
2762 			<< "struct ResultData { Ray ray; vec4 worldRayOrig; vec4 worldRayDir; vec4 objectRayOrig; vec4 objectRayDir;\n"
2763 			<< "vec4 objectToWorld[4]; vec4 worldToObject[4];\n"
2764 			<< "uint missResult; uint closestHitResult; uint anyHitResult; uint isectResult; };\n"
2765 			<< "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
2766 			<< "\n"
2767 			<< "#ifdef CHECKS\n"
2768 			<< "bool fuzzy_check(vec3 a, vec3 b) {\n"
2769 			<< "	float eps = 0.00001;\n"
2770 			<< "	return abs(a.x - b.x) <= eps && abs(a.y - b.y) <= eps && abs(a.z - b.z) <= eps;\n"
2771 			<< "}\n"
2772 			<< "bool check_all() {\n"
2773 			<< "	if (fuzzy_check(results.worldRayOrig.xyz, gl_WorldRayOriginEXT) == false)\n"
2774 			<< "		return false;\n"
2775 			<< "	if (fuzzy_check(results.worldRayDir.xyz, gl_WorldRayDirectionEXT) == false)\n"
2776 			<< "		return false;\n"
2777 			<< "#ifndef MISS_SHADER\n"
2778 			<< "	if (fuzzy_check(results.objectRayOrig.xyz, gl_ObjectRayOriginEXT) == false)\n"
2779 			<< "		return false;\n"
2780 			<< "	if (fuzzy_check(results.objectRayDir.xyz, gl_WorldRayDirectionEXT) == false)\n"
2781 			<< "		return false;\n"
2782 			<< "	if (fuzzy_check(results.objectToWorld[0].xyz, gl_ObjectToWorldEXT[0]) == false)\n"
2783 			<< "		return false;\n"
2784 			<< "	if (fuzzy_check(results.objectToWorld[1].xyz, gl_ObjectToWorldEXT[1]) == false)\n"
2785 			<< "		return false;\n"
2786 			<< "	if (fuzzy_check(results.objectToWorld[2].xyz, gl_ObjectToWorldEXT[2]) == false)\n"
2787 			<< "		return false;\n"
2788 			<< "	if (fuzzy_check(results.objectToWorld[3].xyz, gl_ObjectToWorldEXT[3]) == false)\n"
2789 			<< "		return false;\n"
2790 			<< "	if (fuzzy_check(results.worldToObject[0].xyz, gl_WorldToObjectEXT[0]) == false)\n"
2791 			<< "		return false;\n"
2792 			<< "	if (fuzzy_check(results.worldToObject[1].xyz, gl_WorldToObjectEXT[1]) == false)\n"
2793 			<< "		return false;\n"
2794 			<< "	if (fuzzy_check(results.worldToObject[2].xyz, gl_WorldToObjectEXT[2]) == false)\n"
2795 			<< "		return false;\n"
2796 			<< "	if (fuzzy_check(results.worldToObject[3].xyz, gl_WorldToObjectEXT[3]) == false)\n"
2797 			<< "		return false;\n"
2798 			<< "#endif\n"
2799 			<< "	return true;\n"
2800 			<< "};\n"
2801 			<< "#endif\n";
2802 		const std::string preamble = preambleSrc.str();
2803 
2804 		std::ostringstream raygenSrc;
2805 		raygenSrc
2806 			<< "$preamble$\n"
2807 			<< "struct Payload { uint x; };\n"
2808 			<< "layout(location = 0) rayPayloadEXT Payload payload;\n"
2809 			<< "void main() {\n"
2810 			<< "	payload.x = 0;\n"
2811 			<< "	results.missResult = 0;\n"
2812 			<< "	results.closestHitResult = 0;\n"
2813 			<< "	results.anyHitResult = 0;\n"
2814 			<< "	results.isectResult = 0;\n"
2815 			<< "	Ray ray = results.ray;\n"
2816 			<< "	traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
2817 			<< "}";
2818 		std::string raygen = raygenSrc.str();
2819 		raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
2820 		raygen = replaceString(raygen, "$preamble$", preamble);
2821 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR)) << glu::RaygenSource(raygen) << buildOptions;
2822 
2823 		std::ostringstream missSrc;
2824 		missSrc
2825 			<< "#define CHECKS\n"
2826 			<< "#define MISS_SHADER\n"
2827 			<< "$preamble$\n"
2828 			<< "struct Payload { uint x; };\n"
2829 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2830 			<< "void main() {\n"
2831 			<< "	if (check_all())\n"
2832 			<< "		results.missResult = 1;\n"
2833 			<< "}";
2834 		std::string miss = missSrc.str();
2835 		miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
2836 		miss = replaceString(miss, "$preamble$", preamble);
2837 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR)) << glu::MissSource(miss) << buildOptions;
2838 
2839 		std::ostringstream closestHitSrc;
2840 		closestHitSrc
2841 			<< "#define CHECKS\n"
2842 			<< "$preamble$\n"
2843 			<< "struct Payload { uint x; };\n"
2844 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2845 			<< "hitAttributeEXT vec2 attribs; "
2846 			<< "void main() {\n"
2847 			<< "	if (check_all())\n"
2848 			<< "		results.closestHitResult = 1;\n"
2849 			<< "}";
2850 		std::string closestHit = closestHitSrc.str();
2851 		closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
2852 		closestHit = replaceString(closestHit, "$preamble$", preamble);
2853 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)) << glu::ClosestHitSource(closestHit) << buildOptions;
2854 
2855 		std::ostringstream anyHitSrc;
2856 		anyHitSrc
2857 			<< "#define CHECKS\n"
2858 			<< "$preamble$\n"
2859 			<< "struct Payload { uint x; };\n"
2860 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2861 			<< "hitAttributeEXT vec2 attribs; "
2862 			<< "void main() {\n"
2863 			<< "	if (check_all())\n"
2864 			<< "		results.anyHitResult = 1;\n"
2865 			<< "}";
2866 		std::string anyHit = anyHitSrc.str();
2867 		anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
2868 		anyHit = replaceString(anyHit, "$preamble$", preamble);
2869 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR)) << glu::AnyHitSource(anyHit) << buildOptions;
2870 
2871 		std::ostringstream isectSrc;
2872 		isectSrc
2873 			<< "#define CHECKS\n"
2874 			<< "$preamble$\n"
2875 			<< "hitAttributeEXT vec2 dummy;\n"
2876 			<< "void main() {\n"
2877 			<< "	if (check_all())\n"
2878 			<< "		results.isectResult = 1;\n"
2879 			<< "	reportIntersectionEXT(0.0, 0u);\n"
2880 			<< "}";
2881 		std::string isect = isectSrc.str();
2882 		isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
2883 		isect = replaceString(isect, "$preamble$", preamble);
2884 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) << glu::IntersectionSource(isect) << buildOptions;
2885 	}
2886 	else if (m_data.id == TEST_ID_TMINMAX_INDIRECT)
2887 	{
2888 		const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
2889 
2890 		std::ostringstream preambleSrc;
2891 		preambleSrc
2892 			<< "struct ResultData { Ray ray; float miss_maxt; float chit_maxt; float ahit_maxt; float isect_maxt;\n"
2893 			<< "uint missResult; uint closestHitResult; uint anyHitResult; uint isectResult; float debug; };\n"
2894 			<< "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
2895 			<< "\n"
2896 			<< "#ifdef CHECKS\n"
2897 			<< "bool fuzzy_check(float a, float b) {\n"
2898 			<< "	float eps = 0.0001;\n"
2899 			<< "	return abs(a - b) <= eps;\n"
2900 			<< "}\n"
2901 			<< "bool check_all() {\n"
2902 			<< "	if (fuzzy_check(results.ray.tmin, gl_RayTminEXT) == false)\n"
2903 			<< "		return false;\n"
2904 			<< "#ifdef MISS_SHADER\n"
2905 			<< "	if (fuzzy_check(results.miss_maxt, gl_RayTmaxEXT) == false)\n"
2906 			<< "		return false;\n"
2907 			<< "#endif\n"
2908 			<< "#ifdef CHIT_SHADER\n"
2909 			<< "	if (fuzzy_check(results.chit_maxt, gl_RayTmaxEXT) == false)\n"
2910 			<< "		return false;\n"
2911 			<< "#endif\n"
2912 			<< "#ifdef AHIT_SHADER\n"
2913 			<< "	if (fuzzy_check(results.ahit_maxt, gl_RayTmaxEXT) == false)\n"
2914 			<< "		return false;\n"
2915 			<< "#endif\n"
2916 			<< "#ifdef ISECT_SHADER\n"
2917 			<< "	if (fuzzy_check(results.isect_maxt, gl_RayTmaxEXT) == false)\n"
2918 			<< "		return false;\n"
2919 			<< "#endif\n"
2920 			<< "	return true;\n"
2921 			<< "};\n"
2922 			<< "#endif\n";
2923 		const std::string preamble = preambleSrc.str();
2924 
2925 		std::ostringstream raygenSrc;
2926 		raygenSrc
2927 			<< "$preamble$\n"
2928 			<< "struct Payload { uint x; };\n"
2929 			<< "layout(location = 0) rayPayloadEXT Payload payload;\n"
2930 			<< "void main() {\n"
2931 			<< "	payload.x = 0;\n"
2932 			<< "	results.missResult = 0;\n"
2933 			<< "	results.closestHitResult = 0;\n"
2934 			<< "	results.anyHitResult = 0;\n"
2935 			<< "	results.isectResult = 0;\n"
2936 			<< "	Ray ray = results.ray;\n"
2937 			<< "	traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
2938 			<< "}";
2939 		std::string raygen = raygenSrc.str();
2940 		raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
2941 		raygen = replaceString(raygen, "$preamble$", preamble);
2942 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR)) << glu::RaygenSource(raygen) << buildOptions;
2943 
2944 		std::ostringstream missSrc;
2945 		missSrc
2946 			<< "#define CHECKS\n"
2947 			<< "#define MISS_SHADER\n"
2948 			<< "$preamble$\n"
2949 			<< "struct Payload { uint x; };\n"
2950 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2951 			<< "void main() {\n"
2952 			<< "	if (check_all())\n"
2953 			<< "		results.missResult = 1;\n"
2954 			<< "}";
2955 		std::string miss = missSrc.str();
2956 		miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
2957 		miss = replaceString(miss, "$preamble$", preamble);
2958 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR)) << glu::MissSource(miss) << buildOptions;
2959 
2960 		std::ostringstream cloesetHitSrc;
2961 		cloesetHitSrc
2962 			<< "#define CHECKS\n"
2963 			<< "#define CHIT_SHADER\n"
2964 			<< "$preamble$\n"
2965 			<< "struct Payload { uint x; };\n"
2966 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2967 			<< "hitAttributeEXT vec2 attribs; "
2968 			<< "void main() {\n"
2969 			<< "	if (check_all())\n"
2970 			<< "		results.closestHitResult = 1;\n"
2971 			<< "}";
2972 		std::string closestHit = cloesetHitSrc.str();
2973 		closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
2974 		closestHit = replaceString(closestHit, "$preamble$", preamble);
2975 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)) << glu::ClosestHitSource(closestHit) << buildOptions;
2976 
2977 		std::ostringstream anyHitSrc;
2978 		anyHitSrc
2979 			<< "#define CHECKS\n"
2980 			<< "#define AHIT_SHADER\n"
2981 			<< "$preamble$\n"
2982 			<< "struct Payload { uint x; };\n"
2983 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2984 			<< "hitAttributeEXT vec2 attribs; "
2985 			<< "void main() {\n"
2986 			<< "	if (check_all())\n"
2987 			<< "		results.anyHitResult = 1;\n"
2988 			<< "}";
2989 		std::string anyHit = anyHitSrc.str();
2990 		anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
2991 		anyHit = replaceString(anyHit, "$preamble$", preamble);
2992 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR)) << glu::AnyHitSource(anyHit) << buildOptions;
2993 
2994 		std::ostringstream isectSrc;
2995 		isectSrc
2996 			<< "#define CHECKS\n"
2997 			<< "#define ISECT_SHADER\n"
2998 			<< "$preamble$\n"
2999 			<< "hitAttributeEXT vec2 dummy;\n"
3000 			<< "void main() {\n"
3001 			<< "	results.debug = gl_RayTmaxEXT;\n"
3002 			<< "	if (check_all())\n"
3003 			<< "		results.isectResult = 1;\n"
3004 			<< "	reportIntersectionEXT(results.chit_maxt, 0u);\n"
3005 			<< "}";
3006 		std::string isect = isectSrc.str();
3007 		isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3008 		isect = replaceString(isect, "$preamble$", preamble);
3009 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) << glu::IntersectionSource(isect) << buildOptions;
3010 	}
3011 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT)
3012 	{
3013 		const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
3014 
3015 		std::ostringstream preambleSrc;
3016 		preambleSrc
3017 			<< "struct ResultData { Ray ray[2]; uint flags; uint miss[2]; uint chit[2]; uint ahit[2]; uint isect[2]; };\n"
3018 			<< "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
3019 			<< "\n"
3020 			<< "#ifdef CHECKS\n"
3021 			<< "bool check_all() {\n"
3022 			<< "	if (gl_IncomingRayFlagsEXT != results.flags)\n"
3023 			<< "		return false;\n"
3024 			<< "	return true;\n"
3025 			<< "}\n"
3026 			<< "#endif\n";
3027 		const std::string preamble = preambleSrc.str();
3028 
3029 		std::ostringstream raygenSrc;
3030 		raygenSrc
3031 			<< "$preamble$\n"
3032 			<< "struct Payload { uint x; };\n"
3033 			<< "layout(location = 0) rayPayloadEXT Payload payload;\n"
3034 			<< "void main() {\n"
3035 			<< "	payload.x = 0;\n"
3036 			<< "	results.miss[gl_LaunchIDEXT.x] = 0;\n"
3037 			<< "	results.chit[gl_LaunchIDEXT.x] = 0;\n"
3038 			<< "	results.ahit[gl_LaunchIDEXT.x] = 0;\n"
3039 			<< "	results.isect[gl_LaunchIDEXT.x] = 0;\n"
3040 			<< "	Ray ray = results.ray[gl_LaunchIDEXT.x];\n"
3041 			<< "	traceRayEXT(scene, results.flags, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
3042 			<< "}";
3043 		std::string raygen = raygenSrc.str();
3044 		raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
3045 		raygen = replaceString(raygen, "$preamble$", preamble);
3046 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR)) << glu::RaygenSource(raygen) << buildOptions;
3047 
3048 		std::ostringstream missSrc;
3049 		missSrc
3050 			<< "#define CHECKS\n"
3051 			<< "#define MISS_SHADER\n"
3052 			<< "$preamble$\n"
3053 			<< "struct Payload { uint x; };\n"
3054 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3055 			<< "void main() {\n"
3056 			<< "	if (check_all())\n"
3057 			<< "		results.miss[gl_LaunchIDEXT.x]++;\n"
3058 			<< "}";
3059 		std::string miss = missSrc.str();
3060 		miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
3061 		miss = replaceString(miss, "$preamble$", preamble);
3062 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR)) << glu::MissSource(miss) << buildOptions;
3063 
3064 		std::ostringstream closestHitSrc;
3065 		closestHitSrc
3066 			<< "#define CHECKS\n"
3067 			<< "#define CHIT_SHADER\n"
3068 			<< "$preamble$\n"
3069 			<< "struct Payload { uint x; };\n"
3070 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3071 			<< "hitAttributeEXT vec2 attribs; "
3072 			<< "void main() {\n"
3073 			<< "	if (check_all())\n"
3074 			<< "		results.chit[gl_LaunchIDEXT.x]++;\n"
3075 			<< "}";
3076 		std::string closestHit = closestHitSrc.str();
3077 		closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
3078 		closestHit = replaceString(closestHit, "$preamble$", preamble);
3079 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)) << glu::ClosestHitSource(closestHit) << buildOptions;
3080 
3081 		std::ostringstream anyHitSrc;
3082 		anyHitSrc
3083 			<< "#define CHECKS\n"
3084 			<< "#define AHIT_SHADER\n"
3085 			<< "$preamble$\n"
3086 			<< "struct Payload { uint x; };\n"
3087 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3088 			<< "hitAttributeEXT vec2 attribs; "
3089 			<< "void main() {\n"
3090 			<< "	if (check_all())\n"
3091 			<< "		results.ahit[gl_LaunchIDEXT.x]++;\n"
3092 			<< "}";
3093 		std::string anyHit = anyHitSrc.str();
3094 		anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
3095 		anyHit = replaceString(anyHit, "$preamble$", preamble);
3096 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR)) << glu::AnyHitSource(anyHit) << buildOptions;
3097 
3098 		std::ostringstream isectSrc;
3099 		isectSrc
3100 			<< "#define CHECKS\n"
3101 			<< "#define ISECT_SHADER\n"
3102 			<< "$preamble$\n"
3103 			<< "hitAttributeEXT vec2 dummy;\n"
3104 			<< "void main() {\n"
3105 			<< "	if (check_all())\n"
3106 			<< "		results.isect[gl_LaunchIDEXT.x]++;\n"
3107 			<< "	reportIntersectionEXT(gl_RayTminEXT, 0u);\n"
3108 			<< "}";
3109 		std::string isect = isectSrc.str();
3110 		isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3111 		isect = replaceString(isect, "$preamble$", preamble);
3112 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) << glu::IntersectionSource(isect) << buildOptions;
3113 	}
3114 	else if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3115 	{
3116 		const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
3117 
3118 		std::ostringstream preambleSrc;
3119 		preambleSrc
3120 			<< "struct ResultData { Ray ray[2]; uint kind[2]; uint chit[2]; uint ahit[2]; uint debug[2]; };\n"
3121 			<< "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
3122 			<< "\n"
3123 			<< "#ifdef CHECKS\n"
3124 			<< "bool check_all() {\n"
3125 			<< "#if defined(CHIT_SHADER) || defined(AHIT_SHADER)\n"
3126 			<< "	if (gl_HitKindEXT != results.kind[gl_LaunchIDEXT.x])\n"
3127 			<< "		return false;\n"
3128 			<< "#endif\n"
3129 			<< "	return true;\n"
3130 			<< "}\n"
3131 			<< "#endif\n";
3132 		const std::string preamble = preambleSrc.str();
3133 
3134 		std::ostringstream raygenSrc;
3135 		raygenSrc
3136 			<< "$preamble$\n"
3137 			<< "struct Payload { uint x; };\n"
3138 			<< "layout(location = 0) rayPayloadEXT Payload payload;\n"
3139 			<< "void main() {\n"
3140 			<< "	payload.x = 0;\n"
3141 			<< "	uint i = gl_LaunchIDEXT.x;\n"
3142 			<< "	results.chit[i] = 0;\n"
3143 			<< "	results.ahit[i] = 0;\n"
3144 			<< "	Ray ray = results.ray[i];\n"
3145 			<< "	traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
3146 			<< "}";
3147 		std::string raygen = raygenSrc.str();
3148 		raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
3149 		raygen = replaceString(raygen, "$preamble$", preamble);
3150 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR)) << glu::RaygenSource(raygen) << buildOptions;
3151 
3152 		std::ostringstream missSrc;
3153 		missSrc
3154 			<< "#define CHECKS\n"
3155 			<< "#define MISS_SHADER\n"
3156 			<< "$preamble$\n"
3157 			<< "struct Payload { uint x; };\n"
3158 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3159 			<< "void main() {\n"
3160 			<< "}";
3161 		std::string miss = missSrc.str();
3162 		miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
3163 		miss = replaceString(miss, "$preamble$", preamble);
3164 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR)) << glu::MissSource(miss) << buildOptions;
3165 
3166 		std::ostringstream closestHitSrc;
3167 		closestHitSrc
3168 			<< "#define CHECKS\n"
3169 			<< "#define CHIT_SHADER\n"
3170 			<< "$preamble$\n"
3171 			<< "struct Payload { uint x; };\n"
3172 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3173 			<< "hitAttributeEXT vec2 attribs; "
3174 			<< "void main() {\n"
3175 			<< "	results.debug[gl_LaunchIDEXT.x] = gl_HitKindEXT;\n"
3176 			<< "	if (check_all())\n"
3177 			<< "		results.chit[gl_LaunchIDEXT.x] = 1;\n"
3178 			<< "}";
3179 		std::string closestHit = closestHitSrc.str();
3180 		closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
3181 		closestHit = replaceString(closestHit, "$preamble$", preamble);
3182 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)) << glu::ClosestHitSource(closestHit) << buildOptions;
3183 
3184 		std::ostringstream anyHitSrc;
3185 		anyHitSrc
3186 			<< "#define CHECKS\n"
3187 			<< "#define AHIT_SHADER\n"
3188 			<< "$preamble$\n"
3189 			<< "struct Payload { uint x; };\n"
3190 			<< "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3191 			<< "hitAttributeEXT vec2 attribs; "
3192 			<< "void main() {\n"
3193 			<< "	if (check_all())\n"
3194 			<< "		results.ahit[gl_LaunchIDEXT.x] = 1;\n"
3195 			<< "}";
3196 		std::string anyHit = anyHitSrc.str();
3197 		anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
3198 		anyHit = replaceString(anyHit, "$preamble$", preamble);
3199 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR)) << glu::AnyHitSource(anyHit) << buildOptions;
3200 
3201 		std::ostringstream isectSrc;
3202 		isectSrc
3203 			<< "#define CHECKS\n"
3204 			<< "#define ISECT_SHADER\n"
3205 			<< "$preamble$\n"
3206 			<< "hitAttributeEXT vec2 dummy;\n"
3207 			<< "void main() {\n"
3208 			<< "	reportIntersectionEXT(gl_RayTminEXT, results.kind[gl_LaunchIDEXT.x]);\n"
3209 			<< "}";
3210 		std::string isect = isectSrc.str();
3211 		isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3212 		isect = replaceString(isect, "$preamble$", preamble);
3213 		programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) << glu::IntersectionSource(isect) << buildOptions;
3214 	}
3215 }
3216 
createInstance(Context& context) const3217 TestInstance* RayTracingIndirectTestCase::createInstance (Context& context) const
3218 {
3219 	return new RayTracingIndirectTestInstance(context, m_data);
3220 }
3221 
createPipelineAndShaderBindingTables(de::MovePtr<RayTracingPipeline>& rayTracingPipeline, bool aabb, VkPipelineLayout pipelineLayout)3222 Move<VkPipeline> RayTracingIndirectTestInstance::createPipelineAndShaderBindingTables (de::MovePtr<RayTracingPipeline>& rayTracingPipeline, bool aabb, VkPipelineLayout pipelineLayout)
3223 {
3224 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
3225 	const DeviceInterface&				vk									= m_context.getDeviceInterface();
3226 	const VkDevice						device								= m_context.getDevice();
3227 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
3228 	Allocator&							allocator							= m_context.getDefaultAllocator();
3229 
3230 	const deUint32	shaderGroupHandleSize		= getShaderGroupSize(vki, physicalDevice);
3231 	const deUint32	shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
3232 
3233 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vk, device, m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR)), 0), 0);
3234 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vk, device, m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR)), 0), 1);
3235 	for (deUint32 g = 0; g < m_numGeoms; ++g)
3236 	{
3237 		rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vk, device, m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)), 0), 2 + g);
3238 		rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,		createShaderModule(vk, device, m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR)), 0), 2 + g);
3239 
3240 		if (aabb)
3241 		{
3242 			rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vk, device, m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR)), 0), 2 + g);
3243 		}
3244 	}
3245 	Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vk, device, pipelineLayout);
3246 
3247 	m_raygenShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
3248 	m_missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
3249 	m_hitShaderBindingTable					= rayTracingPipeline->createShaderBindingTable(vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, m_numGeoms);
3250 
3251 	m_raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vk, device, m_raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
3252 	m_missShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vk, device, m_missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
3253 	m_hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vk, device, m_hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
3254 	m_callableShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
3255 
3256 	return pipeline;
3257 }
3258 
createPipelineLayoutAndSet(deUint32 setCount, vk::Move<VkDescriptorPool>& descriptorPool, vk::Move<VkDescriptorSetLayout>& descriptorSetLayout, std::vector<vk::Move<VkDescriptorSet>>& descriptorSets, vk::Move<VkPipelineLayout>& pipelineLayout)3259 void RayTracingIndirectTestInstance::createPipelineLayoutAndSet (deUint32 setCount,
3260 																 vk::Move<VkDescriptorPool>& descriptorPool,
3261 																 vk::Move<VkDescriptorSetLayout>& descriptorSetLayout,
3262 																 std::vector<vk::Move<VkDescriptorSet>>& descriptorSets,
3263 																 vk::Move<VkPipelineLayout>& pipelineLayout)
3264 {
3265 	const DeviceInterface& vk = m_context.getDeviceInterface();
3266 	const VkDevice device = m_context.getDevice();
3267 
3268 	vk::DescriptorPoolBuilder descriptorPoolBuilder;
3269 
3270 	deUint32 storageBufCount = 2 * setCount;
3271 
3272 	const VkDescriptorType accelType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
3273 
3274 	descriptorPoolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufCount);
3275 	descriptorPoolBuilder.addType(accelType, setCount);
3276 
3277 	descriptorPool = descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setCount);
3278 
3279 	vk::DescriptorSetLayoutBuilder setLayoutBuilder;
3280 
3281 	setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES);
3282 	setLayoutBuilder.addSingleBinding(accelType, ALL_RAY_TRACING_STAGES);
3283 	setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES);
3284 
3285 	descriptorSetLayout = setLayoutBuilder.build(vk, device);
3286 
3287 	const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
3288 	{
3289 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
3290 		DE_NULL,											// const void*					pNext;
3291 		*descriptorPool,									// VkDescriptorPool				descriptorPool;
3292 		1u,													// deUint32						setLayoutCount;
3293 		&descriptorSetLayout.get()							// const VkDescriptorSetLayout*	pSetLayouts;
3294 	};
3295 
3296 	for (uint32_t i = 0; i < setCount; ++i)
3297 		descriptorSets.push_back(allocateDescriptorSet(vk, device, &descriptorSetAllocateInfo));
3298 
3299 	const VkPipelineLayoutCreateInfo pipelineLayoutInfo =
3300 	{
3301 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
3302 		DE_NULL,											// const void*					pNext;
3303 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
3304 		1u,													// deUint32						setLayoutCount;
3305 		&descriptorSetLayout.get(),							// const VkDescriptorSetLayout*	pSetLayouts;
3306 		0u,													// deUint32						pushConstantRangeCount;
3307 		nullptr,											// const VkPushConstantRange*	pPushConstantRanges;
3308 	};
3309 
3310 	pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutInfo);
3311 }
3312 
initTopAccelerationStructure(std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>& blas)3313 de::SharedPtr<TopLevelAccelerationStructure> RayTracingIndirectTestInstance::initTopAccelerationStructure (std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>& blas)
3314 {
3315 	de::SharedPtr<TopLevelAccelerationStructure> tlas = de::SharedPtr<TopLevelAccelerationStructure>(makeTopLevelAccelerationStructure().release());
3316 
3317 	VkTransformMatrixKHR transform = identityMatrix3x4;
3318 	if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
3319 	{
3320 		tcu::Vec3 instanceOffset = tcu::Vec3(2.0f, 4.0f, 8.0f);
3321 		transform.matrix[0][3] = instanceOffset[0];
3322 		transform.matrix[1][3] = instanceOffset[1];
3323 		transform.matrix[2][3] = instanceOffset[2];
3324 	}
3325 
3326 	for (size_t i = 0; i < blas.size(); ++i)
3327 	{
3328 		tlas->addInstance(blas[i], transform, 1000 + static_cast<deUint32>(i));
3329 	}
3330 
3331 	return tlas;
3332 }
3333 
initBottomAccelerationStructures()3334 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> RayTracingIndirectTestInstance::initBottomAccelerationStructures()
3335 {
3336 	const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3337 
3338 	deUint32 numInstances = m_data.id == TEST_ID_INDICES_INDIRECT ? 5 : 1;
3339 
3340 	if (m_data.id == TEST_ID_INDICES_INDIRECT || m_data.id == TEST_ID_TRANSFORMS_INDIRECT || m_data.id == TEST_ID_TMINMAX_INDIRECT)
3341 	{
3342 		m_geomsPerInstance = m_data.id == TEST_ID_INDICES_INDIRECT ? 3 : 1;
3343 		m_primsPerGeometry = m_data.id == TEST_ID_INDICES_INDIRECT ? 4 : 1;
3344 
3345 		m_numGeoms = numInstances * m_geomsPerInstance;
3346 
3347 		for (deUint32 i = 0; i < m_numGeoms; ++i)
3348 		{
3349 			std::vector<tcu::Vec3> geomPrims;
3350 
3351 			for (deUint32 j = 0; j < m_primsPerGeometry; ++j)
3352 			{
3353 				const deUint32 primId = (i * m_primsPerGeometry) + j;
3354 				float dx = 10.0f * static_cast<float>(primId);
3355 				if (aabb == false)
3356 				{
3357 					geomPrims.push_back(tcu::Vec3(dx + -1.0f, -1.0f, 1.0f));
3358 					geomPrims.push_back(tcu::Vec3(dx + 1.0f, -1.0f, 1.0f));
3359 					geomPrims.push_back(tcu::Vec3(dx + 0.0f, 1.0f, 1.0f));
3360 				}
3361 				else
3362 				{
3363 					geomPrims.push_back(tcu::Vec3(dx - 1.0f, -1.0f, 1.0f)); // min x/y/z
3364 					geomPrims.push_back(tcu::Vec3(dx + 1.0f, 1.0f, 2.0f)); // max x/y/z
3365 				}
3366 			}
3367 			m_geomData.push_back(geomPrims);
3368 		}
3369 	}
3370 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT || m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3371 	{
3372 		m_geomsPerInstance = m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT ? 2 : 1;
3373 		m_primsPerGeometry = 1;
3374 
3375 		m_numGeoms = numInstances * m_geomsPerInstance;
3376 
3377 		for (deUint32 i = 0; i < m_numGeoms; ++i)
3378 		{
3379 			std::vector<tcu::Vec3> geomPrims;
3380 
3381 			for (deUint32 j = 0; j < m_primsPerGeometry; ++j)
3382 			{
3383 				const deUint32 primId = (i * m_primsPerGeometry) + j;
3384 				float z = 1.0f + 10.0f * static_cast<float>(primId);
3385 
3386 				bool ccw = (primId % 2) == 0;
3387 
3388 				if (aabb == false)
3389 				{
3390 					if (ccw)
3391 					{
3392 						geomPrims.push_back(tcu::Vec3(-1.0f, -1.0f, z));
3393 						geomPrims.push_back(tcu::Vec3( 1.0f, -1.0f, z));
3394 						geomPrims.push_back(tcu::Vec3( 0.0f,  1.0f, z));
3395 					}
3396 					else
3397 					{
3398 						geomPrims.push_back(tcu::Vec3( 1.0f, -1.0f, z));
3399 						geomPrims.push_back(tcu::Vec3(-1.0f, -1.0f, z));
3400 						geomPrims.push_back(tcu::Vec3( 0.0f,  1.0f, z));
3401 					}
3402 				}
3403 				else
3404 				{
3405 					geomPrims.push_back(tcu::Vec3(-1.0f, -1.0f, z)); // min x/y/z
3406 					geomPrims.push_back(tcu::Vec3( 1.0f,  1.0f, z + 1.0f)); // max x/y/z
3407 				}
3408 			}
3409 			m_geomData.push_back(geomPrims);
3410 		}
3411 	}
3412 
3413 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> blas;
3414 
3415 	if (!m_geomData.empty())
3416 	{
3417 		for (deUint32 i = 0; i < numInstances; ++i)
3418 		{
3419 			de::SharedPtr<BottomLevelAccelerationStructure>	accel = de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3420 			for (deUint32 j = 0; j < m_geomsPerInstance; ++j)
3421 			{
3422 				accel->addGeometry(m_geomData[(i * m_geomsPerInstance) + j], !aabb, 0U);
3423 			}
3424 			blas.push_back(accel);
3425 		}
3426 	}
3427 	return blas;
3428 }
3429 
3430 struct Ray
3431 {
Rayvkt::RayTracing::__anon28502::Ray3432 	Ray() : o(0.0f), tmin(0.0f), d(0.0f), tmax(0.0f){}
Rayvkt::RayTracing::__anon28502::Ray3433 	Ray(const tcu::Vec3& io, float imin, const tcu::Vec3& id, float imax): o(io), tmin(imin), d(id), tmax(imax){}
3434 	tcu::Vec3 o;
3435 	float tmin;
3436 	tcu::Vec3 d;
3437 	float tmax;
3438 };
3439 
3440 struct TransformResultData {
3441 
TransformResultDatavkt::RayTracing::__anon28502::TransformResultData3442 	TransformResultData(): ray(), worldRayOrig(0.f), padding0(0.f), worldRayDir(0.f), padding1(0.f),
3443 	objectRayOrig(0.f), padding2(0.f), objectRayDir(0.f), padding3(0.f), objectToWorld0(0.f), padding4(0.f),
3444 	objectToWorld1(0.f), padding5(0.f), objectToWorld2(0.f), padding6(0.f), objectToWorld3(0.f), padding7(0.f),
3445 	worldToObject0(0.f), padding8(0.f), worldToObject1(0.f), padding9(0.f), worldToObject2(0.f), padding10(0.f),
3446 	worldToObject3(0.f), padding11(0.f), missResult(0), closestHitResult(0), anyHitResult(0), isectResult(0) {}
3447 
3448 	Ray ray;
3449 	tcu::Vec3 worldRayOrig; float padding0;
3450 	tcu::Vec3 worldRayDir; float padding1;
3451 	tcu::Vec3 objectRayOrig; float padding2;
3452 	tcu::Vec3 objectRayDir; float padding3;
3453 	tcu::Vec3 objectToWorld0; float padding4;
3454 	tcu::Vec3 objectToWorld1; float padding5;
3455 	tcu::Vec3 objectToWorld2; float padding6;
3456 	tcu::Vec3 objectToWorld3; float padding7;
3457 	tcu::Vec3 worldToObject0; float padding8;
3458 	tcu::Vec3 worldToObject1; float padding9;
3459 	tcu::Vec3 worldToObject2; float padding10;
3460 	tcu::Vec3 worldToObject3; float padding11;
3461 	deUint32 missResult;
3462 	deUint32 closestHitResult;
3463 	deUint32 anyHitResult;
3464 	deUint32 isectResult;
3465 };
3466 
3467 struct TMinMaxResultData {
3468 	Ray ray;
3469 	float miss_maxt;
3470 	float chit_maxt;
3471 	float ahit_maxt;
3472 	float isect_maxt;
3473 	deUint32 missResult;
3474 	deUint32 closestHitResult;
3475 	deUint32 anyHitResult;
3476 	deUint32 isectResult;
3477 	float debug;
3478 };
3479 
3480 struct IncomingFlagsResultData {
3481 	Ray ray[2];
3482 	deUint32 flags;
3483 	deUint32 miss[2];
3484 	deUint32 chit[2];
3485 	deUint32 ahit[2];
3486 	deUint32 isect[2];
3487 };
3488 
3489 struct HitKindResultData {
3490 	Ray ray[2];
3491 	deUint32 kind[2];
3492 	deUint32 chit[2];
3493 	deUint32 ahit[2];
3494 	deUint32 debug[2];
3495 };
3496 
initializeParameters()3497 void RayTracingIndirectTestInstance::initializeParameters()
3498 {
3499 	const VkDevice device = m_context.getDevice();
3500 	const DeviceInterface& vk = m_context.getDeviceInterface();
3501 	Allocator& allocator = m_context.getDefaultAllocator();
3502 
3503 	const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3504 
3505 	if (m_data.id == TEST_ID_INDICES_INDIRECT)
3506 	{
3507 		std::vector<Ray> rays;
3508 		for (deUint32 g = 0; g < m_numGeoms; ++g)
3509 		{
3510 			for (deUint32 p = 0; p < m_primsPerGeometry; ++p)
3511 			{
3512 				tcu::Vec3 center = aabb ?
3513 							(m_geomData[g][2 * p + 0] + m_geomData[g][2 * p + 1]) * 0.5f :
3514 							(m_geomData[g][3 * p + 0] + m_geomData[g][3 * p + 1] + m_geomData[g][3 * p + 2]) * (1.0f / 3.0f);
3515 
3516 				Ray r;
3517 
3518 				r.o = tcu::Vec3(center[0], center[1], 0.0f);
3519 				r.d = tcu::Vec3(0.0f, 0.0f, 1.0f);
3520 				r.tmin = 0.0f;
3521 				r.tmax = 1000.0f;
3522 
3523 				rays.push_back(r);
3524 			}
3525 		}
3526 		const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(rays.size() * sizeof(deUint32) * 8, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3527 		m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3528 
3529 		const VkBufferCreateInfo rayBufferCreateInfo = makeBufferCreateInfo(rays.size() * sizeof(Ray), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3530 		m_rayBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, rayBufferCreateInfo, MemoryRequirement::HostVisible));
3531 
3532 		memcpy(m_rayBuffer->getAllocation().getHostPtr(), &rays[0], rays.size() * sizeof(Ray));
3533 		flushMappedMemoryRange(vk, device, m_rayBuffer->getAllocation().getMemory(), m_rayBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
3534 	}
3535 	else if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
3536 	{
3537 		const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(sizeof(TransformResultData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3538 		m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3539 
3540 		TransformResultData* resultData = (TransformResultData*)m_resultBuffer->getAllocation().getHostPtr();
3541 		*resultData = {};
3542 
3543 		VkTransformMatrixKHR transform = identityMatrix3x4;
3544 		tcu::Vec3 instanceOffset = tcu::Vec3(2.0f, 4.0f, 8.0f);
3545 		transform.matrix[0][3] = instanceOffset[0];
3546 		transform.matrix[1][3] = instanceOffset[1];
3547 		transform.matrix[2][3] = instanceOffset[2];
3548 
3549 		{
3550 			tcu::Vec3 center = aabb ?
3551 				(m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3552 				(m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3553 
3554 			center = center + instanceOffset;
3555 
3556 			Ray r;
3557 
3558 			r.o = tcu::Vec3(center[0], center[1], 0.0f);
3559 			r.d = tcu::Vec3(0.0f, 0.0f, 1.0f);
3560 			r.tmin = 0.0f;
3561 			r.tmax = 1000.0f;
3562 
3563 			if (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR)
3564 			{
3565 				r.d[2] = -1.0f;
3566 			}
3567 
3568 			resultData->ray = r;
3569 		}
3570 
3571 		resultData->worldRayOrig  = resultData->ray.o;
3572 		resultData->worldRayDir   = resultData->ray.d;
3573 		resultData->objectRayOrig = resultData->worldRayOrig - instanceOffset;
3574 		resultData->objectRayDir  = resultData->worldRayDir;
3575 
3576 		resultData->objectToWorld0 = tcu::Vec3(transform.matrix[0][0], transform.matrix[1][0], transform.matrix[2][0]);
3577 		resultData->objectToWorld1 = tcu::Vec3(transform.matrix[0][1], transform.matrix[1][1], transform.matrix[2][1]);
3578 		resultData->objectToWorld2 = tcu::Vec3(transform.matrix[0][2], transform.matrix[1][2], transform.matrix[2][2]);
3579 		resultData->objectToWorld3 = tcu::Vec3(transform.matrix[0][3], transform.matrix[1][3], transform.matrix[2][3]);
3580 
3581 		resultData->worldToObject0 = tcu::Vec3(transform.matrix[0][0], transform.matrix[0][1], transform.matrix[0][2]);
3582 		resultData->worldToObject1 = tcu::Vec3(transform.matrix[1][0], transform.matrix[1][1], transform.matrix[1][2]);
3583 		resultData->worldToObject2 = tcu::Vec3(transform.matrix[2][0], transform.matrix[2][1], transform.matrix[2][2]);
3584 		resultData->worldToObject3 = tcu::Vec3(-transform.matrix[0][3], -transform.matrix[1][3], -transform.matrix[2][3]);
3585 	}
3586 	else if (m_data.id == TEST_ID_TMINMAX_INDIRECT)
3587 	{
3588 		const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(sizeof(TMinMaxResultData) * m_numGeoms * m_primsPerGeometry, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3589 		m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3590 
3591 		TMinMaxResultData* resultData = (TMinMaxResultData*)m_resultBuffer->getAllocation().getHostPtr();
3592 		*resultData = {};
3593 		{
3594 			tcu::Vec3 center = aabb ?
3595 				(m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3596 				(m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3597 
3598 			Ray r;
3599 
3600 			r.o = tcu::Vec3(center[0], center[1], 0.0f);
3601 			r.d = tcu::Vec3(0.0f, 0.0f, 1.0f);
3602 			r.tmin = 0.05f;
3603 			r.tmax = 1000.0f;
3604 
3605 			if (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR)
3606 			{
3607 				r.d[2] = -1.0f;
3608 			}
3609 
3610 			resultData->ray = r;
3611 		}
3612 
3613 		resultData->miss_maxt  = resultData->ray.tmax;
3614 		resultData->isect_maxt = resultData->ray.tmax;
3615 		resultData->chit_maxt  = aabb ? 1.5f : 1.0f;
3616 		resultData->ahit_maxt  = aabb ? 1.5f : 1.0f;
3617 		resultData->isect_maxt = resultData->ray.tmax;
3618 		resultData->debug = -2.0f;
3619 	}
3620 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT)
3621 	{
3622 		const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(sizeof(IncomingFlagsResultData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3623 		m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3624 
3625 		IncomingFlagsResultData* resultData = (IncomingFlagsResultData*)m_resultBuffer->getAllocation().getHostPtr();
3626 		*resultData = {};
3627 
3628 		for (deUint32 i = 0; i < 2; ++i)
3629 		{
3630 			tcu::Vec3 center = aabb ?
3631 				(m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3632 				(m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3633 
3634 			Ray r;
3635 
3636 			r.o = tcu::Vec3(center[0], center[1], 0.0f);
3637 			r.d = tcu::Vec3(0.0f, 0.0f, (i == 0) ? -1.0f : 1.0f);
3638 			r.tmin = 0.05f;
3639 			r.tmax = 1000.0f;
3640 
3641 			resultData->ray[i] = r;
3642 		}
3643 
3644 		if (m_data.opaque)
3645 			resultData->flags |= (1 << RAY_FLAG_BIT_OPAQUE_EXT);
3646 		if (m_data.skipClosestHit)
3647 			resultData->flags |= (1 << RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT);
3648 	}
3649 	else if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3650 	{
3651 		const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(sizeof(HitKindResultData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3652 		m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3653 
3654 		HitKindResultData* resultData = (HitKindResultData*)m_resultBuffer->getAllocation().getHostPtr();
3655 		*resultData = {};
3656 
3657 		for (deUint32 i = 0; i < 2; ++i)
3658 		{
3659 			tcu::Vec3 center = aabb ?
3660 				(m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3661 				(m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3662 
3663 			Ray r;
3664 
3665 			r.o = tcu::Vec3(center[0], center[1], 0.0f);
3666 			r.d = tcu::Vec3(0.0f, 0.0f, (i == 1) ? -1.0f : 1.0f);
3667 
3668 			if (i == 1)
3669 				r.o += tcu::Vec3(0, 0, 100.0f);
3670 
3671 			r.tmin = 0.05f;
3672 			r.tmax = 1000.0f;
3673 
3674 			resultData->ray[i] = r;
3675 		}
3676 
3677 		resultData->kind[0] = 255;
3678 		resultData->kind[1] = 254;
3679 	}
3680 }
3681 
verifyResults()3682 bool RayTracingIndirectTestInstance::verifyResults()
3683 {
3684 	const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3685 
3686 	if (m_data.id == TEST_ID_INDICES_INDIRECT)
3687 	{
3688 		deUint32* resultData = (deUint32*)m_resultBuffer->getAllocation().getHostPtr();
3689 		for (deUint32 r = 0; r < m_numGeoms * m_primsPerGeometry; ++r)
3690 		{
3691 			deUint32 primitiveId = r % m_primsPerGeometry;
3692 			deUint32 instanceId = (r / m_primsPerGeometry) / m_geomsPerInstance;
3693 			deUint32 instanceCustomIndex = 1000 + instanceId;
3694 
3695 			if (resultData[4 * r + 0] != primitiveId)
3696 				return false;
3697 
3698 			if (resultData[4 * r + 2] != instanceId)
3699 				return false;
3700 
3701 			if (resultData[4 * r + 3] != instanceCustomIndex)
3702 				return false;
3703 		}
3704 	}
3705 	else if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
3706 	{
3707 		TransformResultData* resultData = (TransformResultData*)m_resultBuffer->getAllocation().getHostPtr();
3708 		if (resultData->anyHitResult != 1 || resultData->closestHitResult != 1)
3709 		{
3710 			return false;
3711 		}
3712 
3713 		if (aabb && resultData->isectResult != 1)
3714 		{
3715 			return false;
3716 		}
3717 	}
3718 	else if (m_data.id == TEST_ID_TMINMAX_INDIRECT)
3719 	{
3720 		TMinMaxResultData* resultData = (TMinMaxResultData*)m_resultBuffer->getAllocation().getHostPtr();
3721 		if (resultData->anyHitResult != 1 || resultData->closestHitResult != 1)
3722 		{
3723 			return false;
3724 		}
3725 
3726 		if (aabb && resultData->isectResult != 1)
3727 		{
3728 			return false;
3729 		}
3730 	}
3731 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT)
3732 	{
3733 		IncomingFlagsResultData* resultData = (IncomingFlagsResultData*)m_resultBuffer->getAllocation().getHostPtr();
3734 
3735 		deUint32 miss[2] = { 1, 0 };
3736 		deUint32 chitMin[2] = { 0, 1 };
3737 		deUint32 chitMax[2] = { 0, 1 };
3738 		deUint32 ahitMin[2] = { 0, 1 };
3739 		deUint32 ahitMax[2] = { 0, 2 };
3740 		deUint32 isectMin[2] = { 0, 0 };
3741 		deUint32 isectMax[2] = { 0, 0 };
3742 
3743 		if (aabb)
3744 		{
3745 			isectMin[1] = 1;
3746 			isectMax[1] = 2;
3747 		}
3748 
3749 		if (m_data.opaque)
3750 		{
3751 			ahitMin[1] = 0;
3752 			ahitMax[1] = 0;
3753 		}
3754 
3755 		if (m_data.skipClosestHit)
3756 		{
3757 			chitMin[1] = 0;
3758 			chitMax[1] = 0;
3759 		}
3760 
3761 		for (deUint32 i = 0; i < 2; ++i)
3762 		{
3763 			if (resultData->miss[i] != miss[i])
3764 				return false;
3765 			if (resultData->chit[i] < chitMin[i])
3766 				return false;
3767 			if (resultData->chit[i] > chitMax[i])
3768 				return false;
3769 			if (resultData->ahit[i] < ahitMin[i])
3770 				return false;
3771 			if (resultData->ahit[i] > ahitMax[i])
3772 				return false;
3773 			if (resultData->isect[i] < isectMin[i])
3774 				return false;
3775 			if (resultData->isect[i] > isectMax[i])
3776 				return false;
3777 		}
3778 	}
3779 	else if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3780 	{
3781 		HitKindResultData* resultData = (HitKindResultData*)m_resultBuffer->getAllocation().getHostPtr();
3782 		for (deUint32 i = 0; i < 2; ++i)
3783 		{
3784 			if (resultData->chit[i] != 1)
3785 				return false;
3786 
3787 			if (resultData->ahit[i]  != 1)
3788 				return false;
3789 		}
3790 	}
3791 	else
3792 	{
3793 		return false;
3794 	}
3795 	return true;
3796 }
3797 
iterate(void)3798 tcu::TestStatus RayTracingIndirectTestInstance::iterate (void)
3799 {
3800 	const VkDevice device = m_context.getDevice();
3801 	const DeviceInterface& vk = m_context.getDeviceInterface();
3802 	const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
3803 	Allocator& allocator = m_context.getDefaultAllocator();
3804 
3805 	const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3806 
3807 	vk::Move<VkDescriptorPool>		descriptorPool;
3808 	vk::Move<VkDescriptorSetLayout> descriptorSetLayout;
3809 	std::vector<vk::Move<VkDescriptorSet>>		descriptorSet;
3810 	vk::Move<VkPipelineLayout>		pipelineLayout;
3811 
3812 	createPipelineLayoutAndSet(1u, descriptorPool, descriptorSetLayout, descriptorSet, pipelineLayout);
3813 
3814 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> blas = initBottomAccelerationStructures();
3815 
3816 	de::SharedPtr<TopLevelAccelerationStructure> tlas = initTopAccelerationStructure(blas);
3817 
3818 	de::MovePtr<RayTracingPipeline>	rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
3819 	Move<VkPipeline> pipeline = createPipelineAndShaderBindingTables(rayTracingPipeline, aabb, *pipelineLayout);
3820 
3821 	initializeParameters();
3822 
3823 	const VkDescriptorBufferInfo		resultDescriptorInfo			= makeDescriptorBufferInfo(m_resultBuffer->get(), 0, VK_WHOLE_SIZE);
3824 
3825 	const Move<VkCommandPool>			cmdPool							= createCommandPool(vk, device, 0, queueFamilyIndex);
3826 	const Move<VkCommandBuffer>			cmdBuffer						= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3827 
3828 	beginCommandBuffer(vk, *cmdBuffer);
3829 
3830 	for (const auto& accel : blas)
3831 	{
3832 		accel->createAndBuild(vk, device, *cmdBuffer, allocator);
3833 	}
3834 	tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
3835 
3836 	VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
3837 	{
3838 		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
3839 		DE_NULL,															//  const void*							pNext;
3840 		1u,																	//  deUint32							accelerationStructureCount;
3841 		tlas->getPtr(),														//  const VkAccelerationStructureKHR*	pAccelerationStructures;
3842 	};
3843 
3844 	if (m_rayBuffer)
3845 	{
3846 		const VkDescriptorBufferInfo		rayDescriptorInfo				= makeDescriptorBufferInfo(m_rayBuffer->get(), 0, VK_WHOLE_SIZE);
3847 
3848 		DescriptorSetUpdateBuilder()
3849 			.writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
3850 			.writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
3851 			.writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &rayDescriptorInfo)
3852 			.update(vk, device);
3853 	}
3854 	else
3855 	{
3856 		DescriptorSetUpdateBuilder()
3857 			.writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
3858 			.writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
3859 			.update(vk, device);
3860 	}
3861 
3862 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet[0].get(), 0, DE_NULL);
3863 
3864 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
3865 
3866 	deUint32 rayCount = m_numGeoms * m_primsPerGeometry;
3867 	if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3868 	{
3869 		rayCount *= 2;
3870 	}
3871 
3872 	VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo = { rayCount, 1, 1, 0};
3873 
3874 	VkBufferCreateInfo indirectBufferCreateInfo		= makeBufferCreateInfo(sizeof(VkAccelerationStructureBuildRangeInfoKHR), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
3875 	de::MovePtr<BufferWithMemory> indirectBuffer	= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, indirectBufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
3876 
3877 	deMemcpy(indirectBuffer->getAllocation().getHostPtr(), (void*)&buildRangeInfo, sizeof(VkAccelerationStructureBuildRangeInfoKHR));
3878 	invalidateMappedMemoryRange(vk, device, indirectBuffer->getAllocation().getMemory(), indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
3879 
3880 	cmdTraceRaysIndirect(vk, *cmdBuffer, &m_raygenShaderBindingTableRegion, &m_missShaderBindingTableRegion, &m_hitShaderBindingTableRegion, &m_callableShaderBindingTableRegion, getBufferDeviceAddress(vk, device, indirectBuffer->get(), 0));
3881 
3882 	endCommandBuffer(vk, *cmdBuffer);
3883 
3884 	submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
3885 
3886 	invalidateMappedMemoryRange(vk, device, m_resultBuffer->getAllocation().getMemory(), m_resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
3887 
3888 	return verifyResults() ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Invalid results");
3889 }
3890 
3891 static const struct Stages
3892 {
3893 	const char*				name;
3894 	VkShaderStageFlagBits	stage;
3895 }
3896 stages[]
3897 {
3898 	{ "rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR		},
3899 	{ "ahit", VK_SHADER_STAGE_ANY_HIT_BIT_KHR		},
3900 	{ "chit", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR	},
3901 	{ "sect", VK_SHADER_STAGE_INTERSECTION_BIT_KHR	},
3902 	{ "miss", VK_SHADER_STAGE_MISS_BIT_KHR			},
3903 	{ "call", VK_SHADER_STAGE_CALLABLE_BIT_KHR		},
3904 };
3905 
3906 static const struct GeomTypes
3907 {
3908 	const char*	name;
3909 	GeomType	geomType;
3910 }
3911 geomTypes[] =
3912 {
3913 	{ "triangles",	GEOM_TYPE_TRIANGLES	},
3914 	{ "aabs",		GEOM_TYPE_AABBS		},
3915 };
3916 
createLaunchTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)3917 void createLaunchTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
3918 {
3919 	const struct
3920 	{
3921 		deUint32	width;
3922 		deUint32	height;
3923 		deUint32	depth;
3924 	}
3925 	sizes[] =
3926 	{
3927 		{     1,     1,     1 },
3928 		{    16,    16,    16 },
3929 		{   256,   256,     1 },
3930 		{ 16384,     1,     1 },
3931 		{     1, 16384,     1 },
3932 		{     1,     1, 16384 },
3933 		{   128,   128,   128 },
3934 		{  2048,  4096,     1 },
3935 		{   317,  3331,     1 },
3936 		{     1,  1331,   111 },
3937 	};
3938 
3939 	de::MovePtr<tcu::TestCaseGroup>		group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
3940 
3941 	for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
3942 	{
3943 		if ((shaderStageFlags & stages[stageNdx].stage) == 0)
3944 			continue;
3945 
3946 		for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
3947 		{
3948 			const deUint32	width					= sizes[sizeNdx].width;
3949 			const deUint32	height					= sizes[sizeNdx].height;
3950 			const deUint32	depth					= sizes[sizeNdx].depth;
3951 			const bool		plain					= isPlain(width, height, depth);
3952 			const deUint32	k						= (plain ? 1 : 6);
3953 			const deUint32	largestGroup			= k * width * height * depth;
3954 			const deUint32	squaresGroupCount		= largestGroup;
3955 			const deUint32	geometriesGroupCount	= 1;
3956 			const deUint32	instancesGroupCount		= 1;
3957 			const CaseDef	caseDef					=
3958 			{
3959 				id,						//  TestId					id;
3960 				name,					//  const char*				name;
3961 				width,					//  deUint32				width;
3962 				height,					//  deUint32				height;
3963 				depth,					//  deUint32				depth;
3964 				depth,					//  deUint32				raysDepth;
3965 				VK_FORMAT_R32_SINT,		//  VkFormat				format;
3966 				false,					//  bool					fixedPointScalarOutput;
3967 				false,					//  bool					fixedPointVectorOutput;
3968 				false,					//  bool					fixedPointMatrixOutput;
3969 				GEOM_TYPE_TRIANGLES,	//  GeomType				geomType;
3970 				squaresGroupCount,		//  deUint32				squaresGroupCount;
3971 				geometriesGroupCount,	//  deUint32				geometriesGroupCount;
3972 				instancesGroupCount,	//  deUint32				instancesGroupCount;
3973 				stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
3974 				false,					//  bool					skipTriangles;
3975 				false,					//  bool					skipAABSs;
3976 				false,					//  bool					opaque;
3977 				false,					//  bool					frontFace;
3978 				0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
3979 				false,					//	bool					useSpecConstants;
3980 				false,					//	bool					skipClosestHit;
3981 				false,					//  bool					useMaintenance5;
3982 			};
3983 			const std::string	suffix		= de::toString(caseDef.width) + '_' + de::toString(caseDef.height) + '_' + de::toString(caseDef.depth);
3984 			const std::string	testName	= string(stages[stageNdx].name) + '_' + suffix;
3985 
3986 			group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
3987 		}
3988 	}
3989 
3990 	builtinGroup->addChild(group.release());
3991 }
3992 
createScalarTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)3993 void createScalarTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
3994 {
3995 	const struct
3996 	{
3997 		deUint32	width;
3998 		deUint32	height;
3999 		TestId		id;
4000 	}
4001 	sizes[] =
4002 	{
4003 		{  16,  16, TEST_ID_HIT_KIND_EXT	},
4004 		{  16,  16, TEST_ID_HIT_T_EXT		},
4005 		{  16,  16, TEST_ID_RAY_T_MIN_EXT	},
4006 		{  16,  16, TEST_ID_RAY_T_MAX_EXT	},
4007 		{  32,  32, TEST_ID_LAST			},
4008 		{  64,  64, TEST_ID_LAST			},
4009 		{ 256, 256, TEST_ID_LAST			},
4010 	};
4011 	const bool		fourGeometryGroups		=  id == TEST_ID_HIT_KIND_EXT
4012 											|| id == TEST_ID_HIT_T_EXT
4013 											|| id == TEST_ID_RAY_T_MIN_EXT
4014 											|| id == TEST_ID_RAY_T_MAX_EXT;
4015 	const bool		fixedPointScalarOutput	=  id == TEST_ID_HIT_T_EXT
4016 											|| id == TEST_ID_RAY_T_MIN_EXT
4017 											|| id == TEST_ID_RAY_T_MAX_EXT;
4018 	const deUint32	imageDepth				= 1;
4019 	const deUint32	rayDepth				= 1;
4020 
4021 	de::MovePtr<tcu::TestCaseGroup>		group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4022 
4023 	for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
4024 	for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4025 	{
4026 		const GeomType	geomType	= geomTypes[geomTypesNdx].geomType;
4027 
4028 		if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4029 			continue;
4030 
4031 		if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR && geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
4032 			continue;
4033 
4034 		bool testAdded				= false;
4035 		bool generalTestsStarted	= false;
4036 
4037 		for (size_t sizesNdx = 0; sizesNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizesNdx)
4038 		{
4039 			const bool		specializedTest			= (sizes[sizesNdx].id != TEST_ID_LAST);
4040 			const deUint32	width					= sizes[sizesNdx].width;
4041 			const deUint32	height					= sizes[sizesNdx].height;
4042 			const deUint32	instancesGroupCount		= fourGeometryGroups ? 1 : 4;
4043 			const deUint32	geometriesGroupCount	= fourGeometryGroups ? 4 : 8;
4044 			const deUint32	largestGroup			= width * height / geometriesGroupCount / instancesGroupCount;
4045 			const deUint32	squaresGroupCount		= largestGroup;
4046 			const CaseDef	caseDef					=
4047 			{
4048 				id,						//  TestId					id;
4049 				name,					//  const char*				name;
4050 				width,					//  deUint32				width;
4051 				height,					//  deUint32				height;
4052 				imageDepth,				//  deUint32				depth;
4053 				rayDepth,				//  deUint32				raysDepth;
4054 				VK_FORMAT_R32_SINT,		//  VkFormat				format;
4055 				fixedPointScalarOutput,	//  bool					fixedPointScalarOutput;
4056 				false,					//  bool					fixedPointVectorOutput;
4057 				false,					//  bool					fixedPointMatrixOutput;
4058 				geomType,				//  GeomType				geomType;
4059 				squaresGroupCount,		//  deUint32				squaresGroupCount;
4060 				geometriesGroupCount,	//  deUint32				geometriesGroupCount;
4061 				instancesGroupCount,	//  deUint32				instancesGroupCount;
4062 				stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
4063 				false,					//  bool					skipTriangles;
4064 				false,					//  bool					skipAABSs;
4065 				false,					//  bool					opaque;
4066 				false,					//  bool					frontFace;
4067 				0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
4068 				false,					//	bool					useSpecConstants;
4069 				false,					//	bool					skipClosestHit;
4070 				false,					//  bool					useMaintenance5;
4071 			};
4072 			const std::string	suffix		= '_' + de::toString(caseDef.width) + '_' + de::toString(caseDef.height);
4073 			const std::string	testName	= string(stages[stageNdx].name) + '_' + geomTypes[geomTypesNdx].name + (specializedTest ? "" : suffix);
4074 
4075 			if (specializedTest)
4076 			{
4077 				DE_UNREF(generalTestsStarted);
4078 				DE_ASSERT(!generalTestsStarted);
4079 
4080 				if (sizes[sizesNdx].id != id)
4081 					continue;
4082 			}
4083 			else
4084 			{
4085 				generalTestsStarted = true;
4086 			}
4087 
4088 			group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4089 			testAdded = true;
4090 
4091 			if (specializedTest)
4092 				break;
4093 		}
4094 
4095 		DE_ASSERT(testAdded);
4096 		DE_UNREF(testAdded);
4097 	}
4098 
4099 	builtinGroup->addChild(group.release());
4100 }
4101 
createRayFlagsTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)4102 void createRayFlagsTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
4103 {
4104 	const deUint32	width		= 16;
4105 	const deUint32	height		= 16;
4106 	const deUint32	imageDepth	= 1;
4107 	const deUint32	rayDepth	= 1;
4108 
4109 	const struct Opaques
4110 	{
4111 		const char*	name;
4112 		bool		flag;
4113 	}
4114 	opaques[] =
4115 	{
4116 		{ "opaque",		true	},
4117 		{ "noopaque",	false	},
4118 	};
4119 	const struct Faces
4120 	{
4121 		const char*	name;
4122 		bool		flag;
4123 	}
4124 	faces[] =
4125 	{
4126 		{ "frontface",	true	},
4127 		{ "backface",	false	},
4128 	};
4129 	const struct SkipRayFlags
4130 	{
4131 		const char*	name;
4132 		bool		skipTriangles;
4133 		bool		skipAABBs;
4134 	}
4135 	skipRayFlags[] =
4136 	{
4137 		{ "raynoskipflags",			false,	false	},
4138 		{ "rayskiptriangles",		true,	false	},
4139 		{ "rayskipaabbs",			false,	true	},
4140 	};
4141 	const struct PipelineFlags
4142 	{
4143 		const char*				name;
4144 		VkPipelineCreateFlags	flag;
4145 	}
4146 	pipelineFlags[] =
4147 	{
4148 		{ "pipelinenoskipflags",	static_cast<VkPipelineCreateFlags>(0)																		},
4149 		{ "pipelineskiptriangles",	VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR														},
4150 		{ "pipelineskipaabbs",		VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR															},
4151 	};
4152 
4153 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4154 
4155 	for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
4156 	{
4157 		const GeomType					geomType	= geomTypes[geomTypesNdx].geomType;
4158 		de::MovePtr<tcu::TestCaseGroup>	geomGroup	(new tcu::TestCaseGroup(testCtx, geomTypes[geomTypesNdx].name));
4159 
4160 		for (size_t skipRayFlagsNdx = 0; skipRayFlagsNdx < DE_LENGTH_OF_ARRAY(skipRayFlags); ++skipRayFlagsNdx)
4161 		{
4162 			de::MovePtr<tcu::TestCaseGroup>	rayFlagsGroup	(new tcu::TestCaseGroup(testCtx, skipRayFlags[skipRayFlagsNdx].name));
4163 
4164 			for (size_t pipelineFlagsNdx = 0; pipelineFlagsNdx < DE_LENGTH_OF_ARRAY(pipelineFlags); ++pipelineFlagsNdx)
4165 			{
4166 				const bool skipTriangles	= (skipRayFlags[skipRayFlagsNdx].skipTriangles	|| (pipelineFlags[pipelineFlagsNdx].flag & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR));
4167 				const bool skipAABBs		= (skipRayFlags[skipRayFlagsNdx].skipAABBs		|| (pipelineFlags[pipelineFlagsNdx].flag & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR));
4168 
4169 				// Skipping both triangles and AABBs is not legal according to the spec.
4170 				if (skipTriangles && skipAABBs)
4171 					continue;
4172 
4173 				// Skipping - SkipTrianglesKHR is mutually exclusive with CullBackFacingTrianglesKHR and CullFrontFacingTrianglesKHR
4174 				if ((geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES) && skipRayFlags[skipRayFlagsNdx].skipTriangles &&
4175 					(pipelineFlags[pipelineFlagsNdx].flag == static_cast<VkPipelineCreateFlags>(0)))
4176 				{
4177 					continue;
4178 				}
4179 
4180 				de::MovePtr<tcu::TestCaseGroup>	pipelineFlagsGroup	(new tcu::TestCaseGroup(testCtx, pipelineFlags[pipelineFlagsNdx].name));
4181 
4182 				for (size_t opaquesNdx = 0; opaquesNdx < DE_LENGTH_OF_ARRAY(opaques); ++opaquesNdx)
4183 				for (size_t facesNdx = 0; facesNdx < DE_LENGTH_OF_ARRAY(faces); ++facesNdx)
4184 				{
4185 					const std::string				geomPropertiesGroupName	= string(opaques[opaquesNdx].name) + '_' + string(faces[facesNdx].name);
4186 					de::MovePtr<tcu::TestCaseGroup>	geomPropertiesGroup		(new tcu::TestCaseGroup(testCtx, geomPropertiesGroupName.c_str()));
4187 
4188 					for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4189 					{
4190 						if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4191 							continue;
4192 
4193 						if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR && geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
4194 							continue;
4195 
4196 						const deUint32		instancesGroupCount		= 1;
4197 						const deUint32		geometriesGroupCount	= 1;
4198 						const deUint32		squaresGroupCount		= width * height / geometriesGroupCount / instancesGroupCount;
4199 						const CaseDef		caseDef =
4200 						{
4201 							id,												//  TestId					id;
4202 							name,											//  const char*				name;
4203 							width,											//  deUint32				width;
4204 							height,											//  deUint32				height;
4205 							imageDepth,										//  deUint32				depth;
4206 							rayDepth,										//  deUint32				raysDepth;
4207 							VK_FORMAT_R32_SINT,								//  VkFormat				format;
4208 							false,											//  bool					fixedPointScalarOutput;
4209 							false,											//  bool					fixedPointVectorOutput;
4210 							false,											//  bool					fixedPointMatrixOutput;
4211 							geomType,										//  GeomType				geomType;
4212 							squaresGroupCount,								//  deUint32				squaresGroupCount;
4213 							geometriesGroupCount,							//  deUint32				geometriesGroupCount;
4214 							instancesGroupCount,							//  deUint32				instancesGroupCount;
4215 							stages[stageNdx].stage,							//  VkShaderStageFlagBits	stage;
4216 							skipRayFlags[skipRayFlagsNdx].skipTriangles,	//  bool					skipTriangles;
4217 							skipRayFlags[skipRayFlagsNdx].skipAABBs,		//  bool					skipAABSs;
4218 							opaques[opaquesNdx].flag,						//  bool					opaque;
4219 							faces[facesNdx].flag,							//  bool					frontFace;
4220 							pipelineFlags[pipelineFlagsNdx].flag,			//  VkPipelineCreateFlags	pipelineCreateFlags;
4221 							false,											//	bool					useSpecConstants;
4222 							false,											//	bool					skipClosestHit;
4223 							false,											//	bool					useMaintenance5;
4224 						};
4225 						const std::string	testName				= string(stages[stageNdx].name) ;
4226 
4227 						geomPropertiesGroup->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4228 					}
4229 
4230 					pipelineFlagsGroup->addChild(geomPropertiesGroup.release());
4231 				}
4232 
4233 				rayFlagsGroup->addChild(pipelineFlagsGroup.release());
4234 			}
4235 
4236 			geomGroup->addChild(rayFlagsGroup.release());
4237 		}
4238 
4239 		group->addChild(geomGroup.release());
4240 	}
4241 
4242 	{
4243 		de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc", ""));
4244 		CaseDef caseDef
4245 		{
4246 			TEST_ID_INCOMING_RAY_FLAGS_EXT,								//  TestId					id;
4247 			name,														//  const char*				name;
4248 			width,														//  deUint32				width;
4249 			height,														//  deUint32				height;
4250 			imageDepth,													//  deUint32				depth;
4251 			rayDepth,													//  deUint32				raysDepth;
4252 			VK_FORMAT_R32_SINT,											//  VkFormat				format;
4253 			false,														//  bool					fixedPointScalarOutput;
4254 			false,														//  bool					fixedPointVectorOutput;
4255 			false,														//  bool					fixedPointMatrixOutput;
4256 			GEOM_TYPE_TRIANGLES,										//  GeomType				geomType;
4257 			width * height,												//  deUint32				squaresGroupCount;
4258 			1,															//  deUint32				geometriesGroupCount;
4259 			1,															//  deUint32				instancesGroupCount;
4260 			VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,						//  VkShaderStageFlagBits	stage;
4261 			false,														//  bool					skipTriangles;
4262 			false,														//  bool					skipAABSs;
4263 			false,														//  bool					opaque;
4264 			true,														//  bool					frontFace;
4265 			VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR,		//  VkPipelineCreateFlags	pipelineCreateFlags;
4266 			false,														//	bool					useSpecConstants;
4267 			false,														//	bool					skipClosestHit;
4268 			true,														//	bool					useMaintenance5;
4269 		};
4270 
4271 		miscGroup->addChild(new RayTracingTestCase(testCtx, "pipelineskiptriangles_maintenance5", caseDef));
4272 		caseDef.pipelineCreateFlags = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR;
4273 		miscGroup->addChild(new RayTracingTestCase(testCtx, "pipelineskipaabbs_maintenance5", caseDef));
4274 
4275 		group->addChild(miscGroup.release());
4276 	}
4277 
4278 	builtinGroup->addChild(group.release());
4279 }
4280 
createMultiOutputTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)4281 void createMultiOutputTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
4282 {
4283 	const bool		fixedPointVectorOutput	=  id == TEST_ID_WORLD_RAY_ORIGIN_EXT
4284 											|| id == TEST_ID_WORLD_RAY_DIRECTION_EXT
4285 											|| id == TEST_ID_OBJECT_RAY_ORIGIN_EXT
4286 											|| id == TEST_ID_OBJECT_RAY_DIRECTION_EXT;
4287 	const bool		fixedPointMatrixOutput	=  id == TEST_ID_OBJECT_TO_WORLD_EXT
4288 											|| id == TEST_ID_WORLD_TO_OBJECT_EXT
4289 											|| id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT
4290 											|| id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT;
4291 	const deUint32	imageDepth				= fixedPointMatrixOutput ? 4 * 4
4292 											: fixedPointVectorOutput ? 4
4293 											: 0;
4294 	const deUint32	rayDepth				= 1;
4295 
4296 	de::MovePtr<tcu::TestCaseGroup>		group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4297 
4298 	DE_ASSERT(imageDepth != 0);
4299 
4300 	for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
4301 	for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4302 	{
4303 		const GeomType	geomType	= geomTypes[geomTypesNdx].geomType;
4304 
4305 		if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4306 			continue;
4307 
4308 		if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR && geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
4309 			continue;
4310 
4311 		const deUint32		width					= 4;
4312 		const deUint32		height					= 4;
4313 		const deUint32		instancesGroupCount		= 4;
4314 		const deUint32		geometriesGroupCount	= 1;
4315 		const deUint32		largestGroup			= width * height / geometriesGroupCount / instancesGroupCount;
4316 		const deUint32		squaresGroupCount		= largestGroup;
4317 		const CaseDef		caseDef					=
4318 		{
4319 			id,						//  TestId					id;
4320 			name,					//  const char*				name;
4321 			width,					//  deUint32				width;
4322 			height,					//  deUint32				height;
4323 			imageDepth,				//  deUint32				depth;
4324 			rayDepth,				//  deUint32				raysDepth;
4325 			VK_FORMAT_R32_SINT,		//  VkFormat				format;
4326 			false,					//  bool					fixedPointScalarOutput;
4327 			fixedPointVectorOutput,	//  bool					fixedPointVectorOutput;
4328 			fixedPointMatrixOutput,	//  bool					fixedPointMatrixOutput;
4329 			geomType,				//  GeomType				geomType;
4330 			squaresGroupCount,		//  deUint32				squaresGroupCount;
4331 			geometriesGroupCount,	//  deUint32				geometriesGroupCount;
4332 			instancesGroupCount,	//  deUint32				instancesGroupCount;
4333 			stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
4334 			false,					//  bool					rayFlagSkipTriangles;
4335 			false,					//  bool					rayFlagSkipAABSs;
4336 			false,					//  bool					opaque;
4337 			false,					//  bool					frontFace;
4338 			0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
4339 			false,					//	bool					useSpecConstants;
4340 			false,					//	bool					skipClosestHit;
4341 			false,					//	bool					useMaintenance5;
4342 		};
4343 		const std::string	testName				= string(stages[stageNdx].name) + '_' + geomTypes[geomTypesNdx].name;
4344 
4345 		group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4346 	}
4347 
4348 	builtinGroup->addChild(group.release());
4349 }
4350 
createIndirectTestCases(tcu::TestContext& testCtx, tcu::TestCaseGroup* indirectGroup, TestId id, const char* name)4351 void createIndirectTestCases(tcu::TestContext& testCtx, tcu::TestCaseGroup* indirectGroup, TestId id, const char* name)
4352 {
4353 	const struct
4354 	{
4355 		VkShaderStageFlagBits	stage;
4356 		const char*				name;
4357 	}
4358 	types[] =
4359 	{
4360 		{ VK_SHADER_STAGE_RAYGEN_BIT_KHR,		"triangles"	},
4361 		{ VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	"aabbs"		},
4362 	};
4363 
4364 	const CaseDef caseDef =
4365 	{
4366 		id,									//  TestId					id;
4367 		"",									//  const char*				name;
4368 		0,									//  deUint32				width;
4369 		0,									//  deUint32				height;
4370 		0,									//  deUint32				depth;
4371 		0,									//  deUint32				raysDepth;
4372 		VK_FORMAT_R32_SINT,					//  VkFormat				format;
4373 		false,								//  bool					fixedPointScalarOutput;
4374 		false,								//  bool					fixedPointVectorOutput;
4375 		false,								//  bool					fixedPointMatrixOutput;
4376 		GEOM_TYPE_TRIANGLES,				//  GeomType				geomType;
4377 		0,									//  deUint32				squaresGroupCount;
4378 		0,									//  deUint32				geometriesGroupCount;
4379 		0,									//  deUint32				instancesGroupCount;
4380 		VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM,	//  VkShaderStageFlagBits	stage;
4381 		false,								//  bool					rayFlagSkipTriangles;
4382 		false,								//  bool					rayFlagSkipAABSs;
4383 		false,								//  bool					opaque;
4384 		false,								//  bool					frontFace;
4385 		0u,									//  VkPipelineCreateFlags	pipelineCreateFlags;
4386 		false,								//	bool					useSpecConstants;
4387 		false,								//	bool					skipClosestHit;
4388 		false,								//	bool					useMaintenance5;
4389 	};
4390 
4391 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name));
4392 
4393 	for (size_t typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
4394 	{
4395 		CaseDef params = caseDef;
4396 		params.stage = types[typeNdx].stage;
4397 		group->addChild(new RayTracingIndirectTestCase(testCtx, types[typeNdx].name, params));
4398 	}
4399 	indirectGroup->addChild(group.release());
4400 }
4401 
createIndirectFlagsTestCases(tcu::TestContext& testCtx, tcu::TestCaseGroup* indirectGroup, TestId id, const char* name)4402 void createIndirectFlagsTestCases(tcu::TestContext& testCtx, tcu::TestCaseGroup* indirectGroup, TestId id, const char* name)
4403 {
4404 	const struct
4405 	{
4406 		VkShaderStageFlagBits	stage;
4407 		const char*				name;
4408 	}
4409 	types[] =
4410 	{
4411 		{ VK_SHADER_STAGE_RAYGEN_BIT_KHR,		"triangles"	},
4412 		{ VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	"aabbs"		},
4413 	};
4414 
4415 	const struct
4416 	{
4417 		bool			opaque;
4418 		bool			skipClosestHit;
4419 		const char*		name;
4420 	}
4421 	flags[] =
4422 	{
4423 		{ false,	false,	"none"				},
4424 		{ true,		false,	"opaque"			},
4425 		{ false,	true,	"skip_closest_hit"	},
4426 	};
4427 
4428 	const CaseDef caseDef =
4429 	{
4430 		id,									//  TestId					id;
4431 		"",									//  const char*				name;
4432 		0,									//  deUint32				width;
4433 		0,									//  deUint32				height;
4434 		0,									//  deUint32				depth;
4435 		0,									//  deUint32				raysDepth;
4436 		VK_FORMAT_R32_SINT,					//  VkFormat				format;
4437 		false,								//  bool					fixedPointScalarOutput;
4438 		false,								//  bool					fixedPointVectorOutput;
4439 		false,								//  bool					fixedPointMatrixOutput;
4440 		GEOM_TYPE_TRIANGLES,				//  GeomType				geomType;
4441 		0,									//  deUint32				squaresGroupCount;
4442 		0,									//  deUint32				geometriesGroupCount;
4443 		0,									//  deUint32				instancesGroupCount;
4444 		VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM,	//  VkShaderStageFlagBits	stage;
4445 		false,								//  bool					rayFlagSkipTriangles;
4446 		false,								//  bool					rayFlagSkipAABSs;
4447 		false,								//  bool					opaque;
4448 		false,								//  bool					frontFace;
4449 		0u,									//  VkPipelineCreateFlags	pipelineCreateFlags;
4450 		false,								//	bool					useSpecConstants;
4451 		false,								//	bool					skipClosestHit;
4452 		false,								//	bool					useMaintenance5;
4453 	};
4454 
4455 	de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, name));
4456 
4457 	for (size_t typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
4458 	{
4459 		CaseDef params = caseDef;
4460 		params.stage = types[typeNdx].stage;
4461 		de::MovePtr<tcu::TestCaseGroup> typeGroup (new tcu::TestCaseGroup(testCtx, types[typeNdx].name));
4462 
4463 		for (size_t flagsNdx = 0; flagsNdx < DE_LENGTH_OF_ARRAY(flags); ++flagsNdx)
4464 		{
4465 			params.opaque = flags[flagsNdx].opaque;
4466 			params.skipClosestHit = flags[flagsNdx].skipClosestHit;
4467 			typeGroup->addChild(new RayTracingIndirectTestCase(testCtx, flags[flagsNdx].name, params));
4468 		}
4469 		testGroup->addChild(typeGroup.release());
4470 	}
4471 	indirectGroup->addChild(testGroup.release());
4472 }
4473 
createIndirectTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup)4474 void createIndirectTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup)
4475 {
4476 	typedef void CreateIndirectTestsFunc (tcu::TestContext& testCtx, tcu::TestCaseGroup* group, TestId id, const char* name);
4477 
4478 	const struct
4479 	{
4480 		TestId						id;
4481 		const char*					name;
4482 		CreateIndirectTestsFunc*	createTestsFunc;
4483 	}
4484 	tests[] =
4485 	{
4486 		{ TEST_ID_INDICES_INDIRECT,				"indices",		createIndirectTestCases		},
4487 		{ TEST_ID_TRANSFORMS_INDIRECT,			"transforms",	createIndirectTestCases			},
4488 		{ TEST_ID_TMINMAX_INDIRECT,				"t_min_max",	createIndirectTestCases		},
4489 		{ TEST_ID_INCOMING_RAY_FLAGS_INDIRECT,	"incoming_flag",createIndirectFlagsTestCases	},
4490 		{ TEST_ID_HIT_KIND_INDIRECT,			"hit_kind",		createIndirectTestCases			},
4491 	};
4492 
4493 	// Test builtins using indirect trace rays
4494 	de::MovePtr<tcu::TestCaseGroup> indirectGroup (new tcu::TestCaseGroup(testCtx, "indirect"));
4495 
4496 	for (size_t testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
4497 	{
4498 		tests[testNdx].createTestsFunc(testCtx, indirectGroup.get(), tests[testNdx].id, tests[testNdx].name);
4499 	}
4500 	builtinGroup->addChild(indirectGroup.release());
4501 }
4502 }	// anonymous
4503 
createBuiltinTests(tcu::TestContext& testCtx)4504 tcu::TestCaseGroup*	createBuiltinTests (tcu::TestContext& testCtx)
4505 {
4506 	typedef void CreateBuiltinTestsFunc (tcu::TestContext& testCtx, tcu::TestCaseGroup* group, TestId id, const char* name, const VkShaderStageFlags);
4507 
4508 	const VkShaderStageFlagBits	R	= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
4509 	const VkShaderStageFlagBits	A	= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
4510 	const VkShaderStageFlagBits	C	= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
4511 	const VkShaderStageFlagBits	M	= VK_SHADER_STAGE_MISS_BIT_KHR;
4512 	const VkShaderStageFlagBits	I	= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
4513 	const VkShaderStageFlagBits	L	= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
4514 
4515 	const struct
4516 	{
4517 		TestId					id;
4518 		const char*				name;
4519 		VkShaderStageFlags		stages;
4520 		CreateBuiltinTestsFunc*	createBuiltinTestsFunc;
4521 	}
4522 	tests[] =
4523 	{
4524 		{ TEST_ID_LAUNCH_ID_EXT,				"LaunchIDEXT"			,	R	|	A	|	C	|	I	|	M	|	L	, createLaunchTests			},
4525 		{ TEST_ID_LAUNCH_SIZE_EXT,				"LaunchSizeEXT"			,	R	|	A	|	C	|	I	|	M	|	L	, createLaunchTests			},
4526 		{ TEST_ID_PRIMITIVE_ID,					"PrimitiveID"			,			A	|	C	|	I					, createScalarTests			},
4527 		{ TEST_ID_INSTANCE_ID,					"InstanceID"			,			A	|	C	|	I					, createScalarTests			},
4528 		{ TEST_ID_INSTANCE_CUSTOM_INDEX_EXT,	"InstanceCustomIndexEXT",			A	|	C	|	I					, createScalarTests			},
4529 		{ TEST_ID_GEOMETRY_INDEX_EXT,			"GeometryIndexEXT"		,			A	|	C	|	I					, createScalarTests			},
4530 		{ TEST_ID_WORLD_RAY_ORIGIN_EXT,			"WorldRayOriginEXT"		,			A	|	C	|	I	|	M			, createMultiOutputTests	},
4531 		{ TEST_ID_WORLD_RAY_DIRECTION_EXT,		"WorldRayDirectionEXT"	,			A	|	C	|	I	|	M			, createMultiOutputTests	},
4532 		{ TEST_ID_OBJECT_RAY_ORIGIN_EXT,		"ObjectRayOriginEXT"	,			A	|	C	|	I					, createMultiOutputTests	},
4533 		{ TEST_ID_OBJECT_RAY_DIRECTION_EXT,		"ObjectRayDirectionEXT"	,			A	|	C	|	I					, createMultiOutputTests	},
4534 		{ TEST_ID_RAY_T_MIN_EXT,				"RayTminEXT"			,			A	|	C	|	I	|	M			, createScalarTests			},
4535 		{ TEST_ID_RAY_T_MAX_EXT,				"RayTmaxEXT"			,			A	|	C	|	I	|	M			, createScalarTests			},
4536 		{ TEST_ID_INCOMING_RAY_FLAGS_EXT,		"IncomingRayFlagsEXT"	,			A	|	C	|	I	|	M			, createRayFlagsTests		},
4537 		{ TEST_ID_HIT_T_EXT,					"HitTEXT"				,			A	|	C							, createScalarTests			},
4538 		{ TEST_ID_HIT_KIND_EXT,					"HitKindEXT"			,			A	|	C							, createScalarTests			},
4539 		{ TEST_ID_OBJECT_TO_WORLD_EXT,			"ObjectToWorldEXT"		,			A	|	C	|	I					, createMultiOutputTests	},
4540 		{ TEST_ID_WORLD_TO_OBJECT_EXT,			"WorldToObjectEXT"		,			A	|	C	|	I					, createMultiOutputTests	},
4541 		{ TEST_ID_OBJECT_TO_WORLD_3X4_EXT,		"ObjectToWorld3x4EXT"	,			A	|	C	|	I					, createMultiOutputTests	},
4542 		{ TEST_ID_WORLD_TO_OBJECT_3X4_EXT,		"WorldToObject3x4EXT"	,			A	|	C	|	I					, createMultiOutputTests	},
4543 	};
4544 
4545 	de::MovePtr<tcu::TestCaseGroup> builtinGroup(new tcu::TestCaseGroup(testCtx, "builtin", "Ray tracing shader builtin tests"));
4546 
4547 	for (size_t testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
4548 	{
4549 		tests[testNdx].createBuiltinTestsFunc(testCtx, builtinGroup.get(), tests[testNdx].id, tests[testNdx].name, tests[testNdx].stages);
4550 	}
4551 
4552 	{
4553 		createIndirectTests(testCtx, builtinGroup.get());
4554 	}
4555 
4556 	return builtinGroup.release();
4557 }
4558 
createSpecConstantTests(tcu::TestContext& testCtx)4559 tcu::TestCaseGroup* createSpecConstantTests	(tcu::TestContext& testCtx)
4560 {
4561 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "spec_constants", "Test using spec constants in ray tracing shader stages"));
4562 
4563 	const VkShaderStageFlags	stageFlags				= VK_SHADER_STAGE_RAYGEN_BIT_KHR
4564 														| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
4565 														| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
4566 														| VK_SHADER_STAGE_MISS_BIT_KHR
4567 														| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
4568 														| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
4569 	const deUint32				width					= 256u;
4570 	const deUint32				height					= 256u;
4571 	const deUint32				depth					= 1u;
4572 	const bool					plain					= isPlain(width, height, depth);
4573 	const deUint32				k						= (plain ? 1 : 6);
4574 	const deUint32				largestGroup			= k * width * height * depth;
4575 	const deUint32				squaresGroupCount		= largestGroup;
4576 	const deUint32				geometriesGroupCount	= 1;
4577 	const deUint32				instancesGroupCount		= 1;
4578 
4579 	for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4580 	{
4581 		if ((stageFlags & stages[stageNdx].stage) == 0)
4582 			continue;
4583 
4584 		const CaseDef caseDef =
4585 		{
4586 			TEST_ID_LAUNCH_ID_EXT,	//  TestId					id;
4587 			"LaunchIDEXT",			//  const char*				name;
4588 			width,					//  deUint32				width;
4589 			height,					//  deUint32				height;
4590 			depth,					//  deUint32				depth;
4591 			depth,					//  deUint32				raysDepth;
4592 			VK_FORMAT_R32_SINT,		//  VkFormat				format;
4593 			false,					//  bool					fixedPointScalarOutput;
4594 			false,					//  bool					fixedPointVectorOutput;
4595 			false,					//  bool					fixedPointMatrixOutput;
4596 			GEOM_TYPE_TRIANGLES,	//  GeomType				geomType;
4597 			squaresGroupCount,		//  deUint32				squaresGroupCount;
4598 			geometriesGroupCount,	//  deUint32				geometriesGroupCount;
4599 			instancesGroupCount,	//  deUint32				instancesGroupCount;
4600 			stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
4601 			false,					//  bool					skipTriangles;
4602 			false,					//  bool					skipAABSs;
4603 			false,					//  bool					opaque;
4604 			false,					//  bool					frontFace;
4605 			0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
4606 			true,					//	bool					useSpecConstants;
4607 			false,					//	bool					skipClosestHit;
4608 			false,					//	bool					useMaintenance5;
4609 		};
4610 
4611 		group->addChild(new RayTracingTestCase(testCtx, stages[stageNdx].name, caseDef));
4612 	}
4613 
4614 	return group.release();
4615 }
4616 
4617 }	// RayTracing
4618 }	// vkt
4619