• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *	  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Ray Tracing 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 
38 #include "vkRayTracingUtil.hpp"
39 
40 #include "tcuTestLog.hpp"
41 #include "tcuMatrix.hpp"
42 
43 #include "deMath.h"
44 
45 namespace vkt
46 {
47 namespace RayTracing
48 {
49 namespace
50 {
51 using namespace vk;
52 using namespace std;
53 
54 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
55 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
56 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
57 												| VK_SHADER_STAGE_MISS_BIT_KHR
58 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
59 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
60 
61 enum GeomType
62 {
63 	GEOM_TYPE_TRIANGLES,
64 	GEOM_TYPE_AABBS,
65 };
66 
67 enum TestId
68 {
69 	TEST_ID_LAUNCH_ID_EXT				= 0,
70 	TEST_ID_LAUNCH_SIZE_EXT,
71 	TEST_ID_PRIMITIVE_ID,
72 	TEST_ID_INSTANCE_ID,
73 	TEST_ID_INSTANCE_CUSTOM_INDEX_EXT,
74 	TEST_ID_GEOMETRY_INDEX_EXT,
75 	TEST_ID_WORLD_RAY_ORIGIN_EXT,
76 	TEST_ID_WORLD_RAY_DIRECTION_EXT,
77 	TEST_ID_OBJECT_RAY_ORIGIN_EXT,
78 	TEST_ID_OBJECT_RAY_DIRECTION_EXT,
79 	TEST_ID_RAY_T_MIN_EXT,
80 	TEST_ID_RAY_T_MAX_EXT,
81 	TEST_ID_INCOMING_RAY_FLAGS_EXT,
82 	TEST_ID_HIT_T_EXT,
83 	TEST_ID_HIT_KIND_EXT,
84 	TEST_ID_OBJECT_TO_WORLD_EXT,
85 	TEST_ID_OBJECT_TO_WORLD_3X4_EXT,
86 	TEST_ID_WORLD_TO_OBJECT_EXT,
87 	TEST_ID_WORLD_TO_OBJECT_3X4_EXT,
88 	TEST_ID_LAST
89 };
90 
91 enum RayFlagBits
92 {
93 	RAY_FLAG_BIT_OPAQUE_EXT							= 0,	//  const uint gl_RayFlagsOpaqueEXT = 1U;
94 	RAY_FLAG_BIT_NO_OPAQUE_EXT						= 1,	//  const uint gl_RayFlagsNoOpaqueEXT = 2U;
95 	RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT			= 2,	//  const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;
96 	RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT		= 3,	//  const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;
97 	RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT		= 4,	//  const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;
98 	RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT	= 5,	//  const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;
99 	RAY_FLAG_BIT_CULL_OPAQUE_EXT					= 6,	//  const uint gl_RayFlagsCullOpaqueEXT = 64U;
100 	RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT					= 7,	//  const uint gl_RayFlagsCullNoOpaqueEXT = 128U;
101 	RAY_FLAG_BIT_LAST_PER_TEST,
102 	RAY_FLAG_BIT_SKIP_TRIANGLES_EXT					= 8,	//  const uint gl_RayFlagsSkipTrianglesEXT = 256U;
103 	RAY_FLAG_BIT_SKIP_AABB_EXT						= 9,	//  const uint gl_RayFlagsSkipAABBEXT = 512U;
104 	RAY_FLAG_BIT_LAST
105 };
106 
107 struct CaseDef
108 {
109 	TestId					id;
110 	const char*				name;
111 	deUint32				width;
112 	deUint32				height;
113 	deUint32				depth;
114 	deUint32				raysDepth;
115 	VkFormat				format;
116 	bool					fixedPointScalarOutput;
117 	bool					fixedPointVectorOutput;
118 	bool					fixedPointMatrixOutput;
119 	GeomType				geomType;
120 	deUint32				squaresGroupCount;
121 	deUint32				geometriesGroupCount;
122 	deUint32				instancesGroupCount;
123 	VkShaderStageFlagBits	stage;
124 	bool					rayFlagSkipTriangles;
125 	bool					rayFlagSkipAABSs;
126 	bool					opaque;
127 	bool					frontFace;
128 	VkPipelineCreateFlags	pipelineCreateFlags;
129 	bool					useSpecConstants;
130 };
131 
132 const deUint32	DEFAULT_UINT_CLEAR_VALUE	= 0x8000;
133 const deUint32	FIXED_POINT_DIVISOR			= 1024 * 1024;
134 const deUint32	FIXED_POINT_ALLOWED_ERROR	= 4;
135 
isPlain(const deUint32 width,const deUint32 height,const deUint32 depth)136 bool isPlain (const deUint32 width, const deUint32 height, const deUint32 depth)
137 {
138 	return (width == 1 || height == 1 || depth == 1);
139 }
140 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)141 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
142 							 const VkPhysicalDevice		physicalDevice)
143 {
144 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
145 
146 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
147 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
148 }
149 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)150 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
151 									  const VkPhysicalDevice	physicalDevice)
152 {
153 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
154 
155 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
156 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
157 }
158 
makeImageCreateInfo(deUint32 width,deUint32 height,deUint32 depth,VkFormat format)159 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
160 {
161 	const VkImageType		imageType		= VK_IMAGE_TYPE_3D;
162 	const VkImageUsageFlags	usage			= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
163 	const VkImageCreateInfo	imageCreateInfo	=
164 	{
165 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
166 		DE_NULL,								// const void*				pNext;
167 		(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
168 		imageType,								// VkImageType				imageType;
169 		format,									// VkFormat					format;
170 		makeExtent3D(width, height, depth),		// VkExtent3D				extent;
171 		1u,										// deUint32					mipLevels;
172 		1u,										// deUint32					arrayLayers;
173 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
174 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
175 		usage,									// VkImageUsageFlags		usage;
176 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
177 		0u,										// deUint32					queueFamilyIndexCount;
178 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
179 		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
180 	};
181 
182 	return imageCreateInfo;
183 }
184 
185 class RayTracingBuiltinLaunchTestInstance : public TestInstance
186 {
187 public:
188 																RayTracingBuiltinLaunchTestInstance		(Context& context, const CaseDef& data);
189 																~RayTracingBuiltinLaunchTestInstance	(void);
190 	tcu::TestStatus												iterate									(void);
191 
192 protected:
193 	void														checkSupportInInstance					(void) const;
194 	Move<VkPipeline>											makePipeline							(de::MovePtr<RayTracingPipeline>&							rayTracingPipeline,
195 																										 VkPipelineLayout											pipelineLayout,
196 																										 const VkSpecializationInfo*								specializationInfo);
197 	std::vector<deInt32>										expectedIntValuesBuffer					(void);
198 	std::vector<float>											expectedFloatValuesBuffer				(void);
199 	std::vector<float>											expectedVectorValuesBuffer				(void);
200 	std::vector<float>											expectedMatrixValuesBuffer				(void);
201 	de::MovePtr<BufferWithMemory>								runTest									(void);
202 	de::MovePtr<BufferWithMemory>								createShaderBindingTable				(const InstanceInterface&									vki,
203 																										 const DeviceInterface&										vkd,
204 																										 const VkDevice												device,
205 																										 const VkPhysicalDevice										physicalDevice,
206 																										 const VkPipeline											pipeline,
207 																										 Allocator&													allocator,
208 																										 de::MovePtr<RayTracingPipeline>&							rayTracingPipeline,
209 																										 const deUint32												group);
210 
211 	bool														validateIntBuffer						(de::MovePtr<BufferWithMemory>								buffer);
212 	bool														validateFloatBuffer						(de::MovePtr<BufferWithMemory>								buffer);
213 	bool														validateVectorBuffer					(de::MovePtr<BufferWithMemory>								buffer);
214 	bool														validateMatrixBuffer					(de::MovePtr<BufferWithMemory>								buffer);
215 
216 	de::MovePtr<TopLevelAccelerationStructure>					initTopAccelerationStructure			(VkCommandBuffer											cmdBuffer,
217 																										 vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures);
218 	vector<de::SharedPtr<BottomLevelAccelerationStructure>	>	initBottomAccelerationStructures		(VkCommandBuffer	cmdBuffer);
219 	de::MovePtr<BottomLevelAccelerationStructure>				initBottomAccelerationStructure			(VkCommandBuffer	cmdBuffer,
220 																										 tcu::UVec2&		startPos);
221 
222 private:
223 	CaseDef														m_data;
224 	VkShaderStageFlags											m_shaders;
225 	deUint32													m_raygenShaderGroup;
226 	deUint32													m_missShaderGroup;
227 	deUint32													m_hitShaderGroup;
228 	deUint32													m_callableShaderGroup;
229 	deUint32													m_shaderGroupCount;
230 };
231 
RayTracingBuiltinLaunchTestInstance(Context & context,const CaseDef & data)232 RayTracingBuiltinLaunchTestInstance::RayTracingBuiltinLaunchTestInstance (Context& context, const CaseDef& data)
233 	: vkt::TestInstance		(context)
234 	, m_data				(data)
235 	, m_shaders				(0)
236 	, m_raygenShaderGroup	(~0u)
237 	, m_missShaderGroup		(~0u)
238 	, m_hitShaderGroup		(~0u)
239 	, m_callableShaderGroup	(~0u)
240 	, m_shaderGroupCount	(0)
241 {
242 	const VkShaderStageFlags	hitStages	= VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
243 	BinaryCollection&			collection	= m_context.getBinaryCollection();
244 	deUint32					group		= 0;
245 	deUint32					shaderCount	= 0;
246 
247 	if (collection.contains("rgen")) m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
248 	if (collection.contains("ahit")) m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
249 	if (collection.contains("chit")) m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
250 	if (collection.contains("miss")) m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
251 	if (collection.contains("sect")) m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
252 	if (collection.contains("call")) m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
253 
254 	for (BinaryCollection::Iterator it =  collection.begin(); it != collection.end(); ++it)
255 		shaderCount++;
256 
257 	if (shaderCount != (deUint32)dePop32(m_shaders))
258 		TCU_THROW(InternalError, "Unused shaders detected in the collection");
259 
260 	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
261 		m_raygenShaderGroup		= group++;
262 
263 	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
264 		m_missShaderGroup		= group++;
265 
266 	if (0 != (m_shaders & hitStages))
267 		m_hitShaderGroup		= group++;
268 
269 	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
270 		m_callableShaderGroup	= group++;
271 
272 	m_shaderGroupCount = group;
273 }
274 
~RayTracingBuiltinLaunchTestInstance(void)275 RayTracingBuiltinLaunchTestInstance::~RayTracingBuiltinLaunchTestInstance (void)
276 {
277 }
278 
279 class RayTracingTestCase : public TestCase
280 {
281 	public:
282 										RayTracingTestCase			(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
283 										~RayTracingTestCase			(void);
284 
285 	virtual	void						initPrograms				(SourceCollections& programCollection) const;
286 	virtual TestInstance*				createInstance				(Context& context) const;
287 	virtual void						checkSupport				(Context& context) const;
288 
289 private:
290 	static inline const std::string		getIntersectionPassthrough	(void);
291 	static inline const std::string		getMissPassthrough			(void);
292 	static inline const std::string		getHitPassthrough			(void);
293 
294 	CaseDef								m_data;
295 };
296 
RayTracingTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)297 RayTracingTestCase::RayTracingTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
298 	: vkt::TestCase	(context, name, desc)
299 	, m_data		(data)
300 {
301 }
302 
~RayTracingTestCase(void)303 RayTracingTestCase::~RayTracingTestCase	(void)
304 {
305 }
306 
checkSupport(Context & context) const307 void RayTracingTestCase::checkSupport(Context& context) const
308 {
309 	const bool	pipelineFlagSkipTriangles	= ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0);
310 	const bool	pipelineFlagSkipAABSs		= ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0);
311 	const bool	cullingFlags				=  m_data.rayFlagSkipTriangles
312 											|| m_data.rayFlagSkipAABSs
313 											|| pipelineFlagSkipTriangles
314 											|| pipelineFlagSkipAABSs;
315 
316 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
317 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
318 
319 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
320 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
321 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
322 
323 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
324 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
325 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
326 
327 	if (cullingFlags && rayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling == DE_FALSE)
328 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling");
329 }
330 
getIntersectionPassthrough(void)331 const std::string RayTracingTestCase::getIntersectionPassthrough (void)
332 {
333 	const std::string intersectionPassthrough =
334 		"#version 460 core\n"
335 		"#extension GL_EXT_ray_tracing : require\n"
336 		"hitAttributeEXT vec3 hitAttribute;\n"
337 		"\n"
338 		"void main()\n"
339 		"{\n"
340 		"  reportIntersectionEXT(0.95f, 0x7Eu);\n"
341 		"}\n";
342 
343 	return intersectionPassthrough;
344 }
345 
getMissPassthrough(void)346 const std::string RayTracingTestCase::getMissPassthrough (void)
347 {
348 	const std::string missPassthrough =
349 		"#version 460 core\n"
350 		"#extension GL_EXT_ray_tracing : require\n"
351 		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
352 		"\n"
353 		"void main()\n"
354 		"{\n"
355 		"}\n";
356 
357 	return missPassthrough;
358 }
359 
getHitPassthrough(void)360 const std::string RayTracingTestCase::getHitPassthrough (void)
361 {
362 	const std::string hitPassthrough =
363 		"#version 460 core\n"
364 		"#extension GL_EXT_ray_tracing : require\n"
365 		"hitAttributeEXT vec3 attribs;\n"
366 		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
367 		"\n"
368 		"void main()\n"
369 		"{\n"
370 		"}\n";
371 
372 	return hitPassthrough;
373 }
374 
initPrograms(SourceCollections & programCollection) const375 void RayTracingTestCase::initPrograms (SourceCollections& programCollection) const
376 {
377 	const bool useSC = m_data.useSpecConstants;
378 	DE_ASSERT(!useSC || m_data.id == TEST_ID_LAUNCH_ID_EXT);
379 
380 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
381 
382 	if (m_data.id == TEST_ID_LAUNCH_ID_EXT || m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
383 	{
384 		const std::string	specConstants	=
385 			"layout (constant_id=0) const highp int factor1 = 1;\n"
386 			"layout (constant_id=1) const highp float factor2 = 2.0;\n"
387 			;
388 
389 		const std::string	updateImage		=
390 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
391 			"  ivec3 v = ivec3(gl_" + std::string(m_data.name) + ");\n"
392 			"  int   r = v.x + " + (useSC ? "factor1" : "256") + " * (v.y + " + (useSC ? "int(factor2)" : "256") + " * v.z) + 1;\n"
393 			"  ivec4 c = ivec4(r,0,0,1);\n"
394 			"  imageStore(result, p, c);\n";
395 
396 		switch (m_data.stage)
397 		{
398 			case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
399 			{
400 				std::stringstream css;
401 				css <<
402 					"#version 460 core\n"
403 					"#extension GL_EXT_ray_tracing : require\n"
404 					<< (useSC ? specConstants : "") <<
405 					"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
406 					"\n"
407 					"void main()\n"
408 					"{\n"
409 					<< updateImage <<
410 					"}\n";
411 
412 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
413 
414 				break;
415 			}
416 
417 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
418 			{
419 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
420 
421 				{
422 					std::stringstream css;
423 					css <<
424 						"#version 460 core\n"
425 						"#extension GL_EXT_ray_tracing : require\n"
426 						<< (useSC ? specConstants : "") <<
427 						"hitAttributeEXT vec3 attribs;\n"
428 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
429 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
430 						"\n"
431 						"void main()\n"
432 						"{\n"
433 						<< updateImage <<
434 						"}\n";
435 
436 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
437 				}
438 
439 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
440 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
441 
442 				break;
443 			}
444 
445 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
446 			{
447 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
448 
449 				{
450 					std::stringstream css;
451 					css <<
452 						"#version 460 core\n"
453 						"#extension GL_EXT_ray_tracing : require\n"
454 						<< (useSC ? specConstants : "") <<
455 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
456 						"hitAttributeEXT vec3 attribs;\n"
457 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
458 						"\n"
459 						"void main()\n"
460 						"{\n"
461 						<< updateImage <<
462 						"}\n";
463 
464 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
465 				}
466 
467 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
468 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
469 
470 				break;
471 			}
472 
473 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
474 			{
475 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
476 
477 				{
478 					std::stringstream css;
479 					css <<
480 						"#version 460 core\n"
481 						"#extension GL_EXT_ray_tracing : require\n"
482 						<< (useSC ? specConstants : "") <<
483 						"hitAttributeEXT vec3 hitAttribute;\n"
484 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
485 						"\n"
486 						"void main()\n"
487 						"{\n"
488 						<< updateImage <<
489 						"  hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
490 						"  reportIntersectionEXT(1.0f, 0);\n"
491 						"}\n";
492 
493 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
494 				}
495 
496 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
497 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
498 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
499 
500 				break;
501 			}
502 
503 			case VK_SHADER_STAGE_MISS_BIT_KHR:
504 			{
505 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
506 
507 				{
508 					std::stringstream css;
509 					css <<
510 						"#version 460 core\n"
511 						"#extension GL_EXT_ray_tracing : require\n"
512 						<< (useSC ? specConstants : "") <<
513 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
514 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
515 						"\n"
516 						"void main()\n"
517 						"{\n"
518 						<< updateImage <<
519 						"}\n";
520 
521 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
522 				}
523 
524 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
525 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
526 
527 				break;
528 			}
529 
530 			case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
531 			{
532 				{
533 					std::stringstream css;
534 					css <<
535 						"#version 460 core\n"
536 						"#extension GL_EXT_ray_tracing : require\n"
537 						"layout(location = 0) callableDataEXT float dummy;"
538 						"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
539 						"\n"
540 						"void main()\n"
541 						"{\n"
542 						"  executeCallableEXT(0, 0);\n"
543 						"}\n";
544 
545 					programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
546 				}
547 
548 				{
549 					std::stringstream css;
550 					css <<
551 						"#version 460 core\n"
552 						"#extension GL_EXT_ray_tracing : require\n"
553 						<< (useSC ? specConstants : "") <<
554 						"layout(location = 0) callableDataInEXT float dummy;"
555 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
556 						"\n"
557 						"void main()\n"
558 						"{\n"
559 						<< updateImage <<
560 						"}\n";
561 
562 					programCollection.glslSources.add("call") << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
563 				}
564 
565 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
566 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
567 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
568 
569 				break;
570 			}
571 
572 			default:
573 				TCU_THROW(InternalError, "Unknown stage");
574 		}
575 	}
576 	else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT		||
577 			 m_data.id == TEST_ID_PRIMITIVE_ID				||
578 			 m_data.id == TEST_ID_INSTANCE_ID				||
579 			 m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT	||
580 			 m_data.id == TEST_ID_HIT_KIND_EXT				)
581 	{
582 		const std::string	conditionGeometryIndex	= "  int   n = int(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z));\n"
583 													  "  int   m = (n / " + de::toString(m_data.squaresGroupCount) + ") % " + de::toString(m_data.geometriesGroupCount) + ";\n"
584 													  "  if (r == m)";
585 		const std::string	conditionPrimitiveId	= "  int   n = int(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z));\n"
586 													  "  int   m = n % " + de::toString(m_data.squaresGroupCount) + ";\n"
587 													  "  if (r == m)";
588 		const std::string	condition				= (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT) && (m_data.geomType == GEOM_TYPE_AABBS) ? conditionGeometryIndex
589 													: (m_data.id == TEST_ID_PRIMITIVE_ID) && (m_data.geomType == GEOM_TYPE_AABBS) ? conditionPrimitiveId
590 													: "";
591 		const std::string	updateImage				=
592 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
593 			"  int   r = int(gl_" + std::string(m_data.name) + ");\n"
594 			"  ivec4 c = ivec4(r,0,0,1);\n"
595 			+ condition + "  imageStore(result, p, c);\n";
596 
597 		switch (m_data.stage)
598 		{
599 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
600 			{
601 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
602 
603 				{
604 					std::stringstream css;
605 					css <<
606 						"#version 460 core\n"
607 						"#extension GL_EXT_ray_tracing : require\n"
608 						"hitAttributeEXT vec3 attribs;\n"
609 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
610 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
611 						"\n"
612 						"void main()\n"
613 						"{\n"
614 						<< updateImage <<
615 						"}\n";
616 
617 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
618 				}
619 
620 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
621 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
622 
623 				if (m_data.geomType == GEOM_TYPE_AABBS)
624 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
625 
626 				break;
627 			}
628 
629 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
630 			{
631 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
632 
633 				{
634 					std::stringstream css;
635 					css <<
636 						"#version 460 core\n"
637 						"#extension GL_EXT_ray_tracing : require\n"
638 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
639 						"hitAttributeEXT vec3 attribs;\n"
640 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
641 						"\n"
642 						"void main()\n"
643 						"{\n"
644 						<< updateImage <<
645 						"}\n";
646 
647 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
648 				}
649 
650 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
651 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
652 
653 				if (m_data.geomType == GEOM_TYPE_AABBS)
654 				{
655 					const std::string intersectionShaderSingle	=
656 						"#version 460 core\n"
657 						"#extension GL_EXT_ray_tracing : require\n"
658 						"hitAttributeEXT vec3 hitAttribute;\n"
659 						"\n"
660 						"void main()\n"
661 						"{\n"
662 						"  int r = int(gl_" + std::string(m_data.name) + ");\n"
663 						+ condition + "  reportIntersectionEXT(0.95f, 0x7Eu);\n"
664 						"}\n";
665 					const std::string intersectionShader		= condition.empty() ? getIntersectionPassthrough() : intersectionShaderSingle;
666 
667 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
668 				}
669 
670 				break;
671 			}
672 
673 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
674 			{
675 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
676 
677 				{
678 					std::stringstream css;
679 					css <<
680 						"#version 460 core\n"
681 						"#extension GL_EXT_ray_tracing : require\n"
682 						"hitAttributeEXT vec3 hitAttribute;\n"
683 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
684 						"\n"
685 						"void main()\n"
686 						"{\n"
687 						<< updateImage <<
688 						"  reportIntersectionEXT(0.95f, 0);\n"
689 						"}\n";
690 
691 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
692 				}
693 
694 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
695 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
696 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
697 
698 				break;
699 			}
700 
701 			default:
702 				TCU_THROW(InternalError, "Unknown stage");
703 		}
704 	}
705 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
706 	{
707 		const bool			cullingFlags			= m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs;
708 		const std::string	cullingFlagsInit		= (m_data.rayFlagSkipTriangles && m_data.rayFlagSkipAABSs) ? "gl_RayFlagsSkipTrianglesEXT|gl_RayFlagsSkipAABBEXT"
709 													: m_data.rayFlagSkipTriangles ? "gl_RayFlagsSkipTrianglesEXT"
710 													: m_data.rayFlagSkipAABSs ? "gl_RayFlagsSkipAABBEXT"
711 													: "gl_RayFlagsNoneEXT";
712 		const std::string	updateImage				=
713 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
714 			"  int   r = int(gl_" + std::string(m_data.name) + ");\n"
715 			"  ivec4 c = ivec4(r,0,0,1);\n"
716 			"  imageStore(result, p, c);\n";
717 		const std::string	intersectionShader		=
718 			"#version 460 core\n"
719 			"#extension GL_EXT_ray_tracing : require\n"
720 			"hitAttributeEXT vec3 hitAttribute;\n"
721 			"\n"
722 			"void main()\n"
723 			"{\n"
724 			"  uint hitKind = " + std::string(m_data.frontFace ? "0x7Eu" : "0x7Fu") + ";\n"
725 			"  reportIntersectionEXT(0.95f, hitKind);\n"
726 			"}\n";
727 		const std::string	raygenFlagsFragment		=
728 			"\n"
729 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_OPAQUE_EXT                     ) + "))) f = f | gl_RayFlagsOpaqueEXT;\n"
730 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_NO_OPAQUE_EXT                  ) + "))) f = f | gl_RayFlagsNoOpaqueEXT;\n"
731 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_OPAQUE_EXT                ) + "))) f = f | gl_RayFlagsCullOpaqueEXT;\n"
732 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT             ) + "))) f = f | gl_RayFlagsCullNoOpaqueEXT;\n"
733 			"\n"
734 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT ) + "))) f = f | gl_RayFlagsCullBackFacingTrianglesEXT;\n"
735 			"  else if (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT) + "))) f = f | gl_RayFlagsCullFrontFacingTrianglesEXT;\n"
736 			"\n"
737 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT     ) + "))) f = f | gl_RayFlagsTerminateOnFirstHitEXT;\n"
738 			"  if      (0 != (n & (1<<" + de::toString(RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT    ) + "))) f = f | gl_RayFlagsSkipClosestHitShaderEXT;\n"
739 			"\n";
740 		const std::string	raygenShader			=
741 			"#version 460 core\n"
742 			"#extension GL_EXT_ray_tracing : require\n"
743 			+ (cullingFlags ? std::string("#extension GL_EXT_ray_flags_primitive_culling : require\n") : "") +
744 			"layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
745 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
746 			"\n"
747 			"void main()\n"
748 			"{\n"
749 			"  uint  n        = gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z);\n"
750 			"  uint  f        = " + cullingFlagsInit + ";\n"
751 			+ raygenFlagsFragment +
752 			"  uint  rayFlags = f;\n"
753 			"  uint  cullMask = 0xFF;\n"
754 			"  float tmin     = 0.0;\n"
755 			"  float tmax     = 9.0;\n"
756 			"  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"
757 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
758 			"  traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
759 			"}\n";
760 
761 		switch (m_data.stage)
762 		{
763 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
764 			{
765 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
766 
767 				{
768 					std::stringstream css;
769 					css <<
770 						"#version 460 core\n"
771 						"#extension GL_EXT_ray_tracing : require\n"
772 						"hitAttributeEXT vec3 hitAttribute;\n"
773 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
774 						"\n"
775 						"void main()\n"
776 						"{\n"
777 						<< updateImage <<
778 						"}\n";
779 
780 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
781 				}
782 
783 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
784 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
785 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
786 
787 				break;
788 			}
789 
790 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
791 			{
792 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
793 
794 				{
795 					std::stringstream css;
796 					css <<
797 						"#version 460 core\n"
798 						"#extension GL_EXT_ray_tracing : require\n"
799 						"hitAttributeEXT vec3 attribs;\n"
800 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
801 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
802 						"\n"
803 						"void main()\n"
804 						"{\n"
805 						<< updateImage <<
806 						"}\n";
807 
808 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
809 				}
810 
811 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
812 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
813 
814 				if (m_data.geomType == GEOM_TYPE_AABBS)
815 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
816 
817 				break;
818 			}
819 
820 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
821 			{
822 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
823 
824 				{
825 					std::stringstream css;
826 					css <<
827 						"#version 460 core\n"
828 						"#extension GL_EXT_ray_tracing : require\n"
829 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
830 						"hitAttributeEXT vec3 attribs;\n"
831 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
832 						"\n"
833 						"void main()\n"
834 						"{\n"
835 						<< updateImage <<
836 						"}\n";
837 
838 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
839 				}
840 
841 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
842 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
843 
844 				if (m_data.geomType == GEOM_TYPE_AABBS)
845 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
846 
847 				break;
848 			}
849 
850 			case VK_SHADER_STAGE_MISS_BIT_KHR:
851 			{
852 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
853 
854 				{
855 					std::stringstream css;
856 					css <<
857 						"#version 460 core\n"
858 						"#extension GL_EXT_ray_tracing : require\n"
859 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
860 						"\n"
861 						"void main()\n"
862 						"{\n"
863 						<< updateImage <<
864 						"}\n";
865 
866 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
867 				}
868 
869 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
870 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
871 
872 				if (m_data.geomType == GEOM_TYPE_AABBS)
873 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
874 
875 				break;
876 			}
877 
878 			default:
879 				TCU_THROW(InternalError, "Unknown stage");
880 		}
881 	}
882 	else if (m_data.id == TEST_ID_HIT_T_EXT		||
883 			 m_data.id == TEST_ID_RAY_T_MIN_EXT	||
884 			 m_data.id == TEST_ID_RAY_T_MAX_EXT	)
885 	{
886 		const std::string	raygenShader		=
887 			"#version 460 core\n"
888 			"#extension GL_EXT_ray_tracing : require\n"
889 			"layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
890 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
891 			"\n"
892 			"void main()\n"
893 			"{\n"
894 			"  uint  cullMask = 0xFF;\n"
895 			"  float a      = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
896 			"  float b      = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
897 			"  float c      = 0.25f * a / b;\n"
898 			"  float tmin   = c;\n"
899 			"  float tmax   = 0.75f + c;\n"
900 			"  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"
901 			"  vec3  direct = vec3(0.0, 0.0, -1.0);\n"
902 			"  traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
903 			"}\n";
904 		const std::string	intersectionShader	=
905 			"#version 460 core\n"
906 			"#extension GL_EXT_ray_tracing : require\n"
907 			"hitAttributeEXT vec3 hitAttribute;\n"
908 			"\n"
909 			"void main()\n"
910 			"{\n"
911 			"  float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
912 			"  float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
913 			"  float c = 0.25f * a / b;\n"
914 			"  reportIntersectionEXT(0.03125f + c, 0);\n"
915 			"}\n";
916 		const std::string	updateImage			=
917 			"  ivec3 p = ivec3(gl_LaunchIDEXT);\n"
918 			"  int   r = int(" +de::toString(FIXED_POINT_DIVISOR) + ".0f * gl_" + std::string(m_data.name) + ");\n"
919 			"  ivec4 c = ivec4(r,0,0,1);\n"
920 			"  imageStore(result, p, c);\n";
921 
922 		switch (m_data.stage)
923 		{
924 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
925 			{
926 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
927 
928 				{
929 					std::stringstream css;
930 					css <<
931 						"#version 460 core\n"
932 						"#extension GL_EXT_ray_tracing : require\n"
933 						"hitAttributeEXT vec3 attribs;\n"
934 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
935 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
936 						"\n"
937 						"void main()\n"
938 						"{\n"
939 						<< updateImage <<
940 						"}\n";
941 
942 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
943 				}
944 
945 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
946 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
947 
948 				if (m_data.geomType == GEOM_TYPE_AABBS)
949 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
950 
951 				break;
952 			}
953 
954 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
955 			{
956 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
957 
958 				{
959 					std::stringstream css;
960 					css <<
961 						"#version 460 core\n"
962 						"#extension GL_EXT_ray_tracing : require\n"
963 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
964 						"hitAttributeEXT vec3 attribs;\n"
965 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
966 						"\n"
967 						"void main()\n"
968 						"{\n"
969 						<< updateImage <<
970 						"}\n";
971 
972 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
973 				}
974 
975 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
976 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
977 
978 				if (m_data.geomType == GEOM_TYPE_AABBS)
979 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
980 
981 				break;
982 			}
983 
984 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
985 			{
986 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
987 
988 				{
989 					std::stringstream css;
990 					css <<
991 						"#version 460 core\n"
992 						"#extension GL_EXT_ray_tracing : require\n"
993 						"hitAttributeEXT vec3 hitAttribute;\n"
994 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
995 						"\n"
996 						"void main()\n"
997 						"{\n"
998 						<< updateImage <<
999 						"\n"
1000 						"  float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
1001 						"  float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
1002 						"  reportIntersectionEXT(0.4375f + 0.25f * a / b, 0x7Eu);\n"
1003 						"}\n";
1004 
1005 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1006 				}
1007 
1008 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1009 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1010 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1011 
1012 				break;
1013 			}
1014 
1015 			case VK_SHADER_STAGE_MISS_BIT_KHR:
1016 			{
1017 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
1018 
1019 				{
1020 					std::stringstream css;
1021 					css <<
1022 						"#version 460 core\n"
1023 						"#extension GL_EXT_ray_tracing : require\n"
1024 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1025 						"\n"
1026 						"void main()\n"
1027 						"{\n"
1028 						<< updateImage <<
1029 						"}\n";
1030 
1031 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1032 				}
1033 
1034 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1035 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1036 
1037 				if (m_data.geomType == GEOM_TYPE_AABBS)
1038 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
1039 
1040 				break;
1041 			}
1042 
1043 			default:
1044 				TCU_THROW(InternalError, "Unknown stage");
1045 		}
1046 	}
1047 	else if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT		||
1048 			 m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT	||
1049 			 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT		||
1050 			 m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT	||
1051 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT		||
1052 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT		||
1053 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT	||
1054 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT	)
1055 	{
1056 		const bool			matrix4x3			= (m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT);
1057 		const bool			matrix3x4			= (m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT);
1058 		const bool			matrixOutput		= matrix4x3 || matrix3x4;
1059 		const std::string	vectorLoop			=
1060 			"  for (int ndx = 0; ndx < 3; ndx++)\n"
1061 			"  {\n";
1062 		const std::string	matrixLoop4x3		=
1063 			"  int ndx = -1;\n"
1064 			"  for (int row = 0; row < 3; row++)\n"
1065 			"  for (int col = 0; col < 4; col++)\n"
1066 			"  {\n"
1067 			"    ndx++;\n";
1068 		const std::string	matrixLoop3x4		=
1069 			"  int ndx = -1;\n"
1070 			"  for (int col = 0; col < 3; col++)\n"
1071 			"  for (int row = 0; row < 4; row++)\n"
1072 			"  {\n"
1073 			"    ndx++;\n";
1074 		const std::string	loop				=
1075 			matrix4x3 ? matrixLoop4x3 :
1076 			matrix3x4 ? matrixLoop3x4 :
1077 			vectorLoop;
1078 		const std::string	index				=
1079 			(matrixOutput ? "[col][row]" : "[ndx]");
1080 		const std::string	updateImage			=
1081 			"  float k = " +de::toString(FIXED_POINT_DIVISOR) + ".0f;\n"
1082 			+ loop +
1083 			"    ivec3 p = ivec3(gl_LaunchIDEXT.xy, ndx);\n"
1084 			"    float r = k * gl_" + std::string(m_data.name) + index + ";\n"
1085 			"    ivec4 c = ivec4(int(r),0,0,1);\n"
1086 			"    imageStore(result, p, c);\n"
1087 			"  }\n";
1088 
1089 		switch (m_data.stage)
1090 		{
1091 			case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1092 			{
1093 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1094 
1095 				{
1096 					std::stringstream css;
1097 					css <<
1098 						"#version 460 core\n"
1099 						"#extension GL_EXT_ray_tracing : require\n"
1100 						"hitAttributeEXT vec3 attribs;\n"
1101 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1102 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1103 						"\n"
1104 						"void main()\n"
1105 						"{\n"
1106 						<< updateImage <<
1107 						"}\n";
1108 
1109 					programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1110 				}
1111 
1112 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1113 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1114 
1115 				if (m_data.geomType == GEOM_TYPE_AABBS)
1116 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1117 
1118 				break;
1119 			}
1120 
1121 			case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1122 			{
1123 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1124 
1125 				{
1126 					std::stringstream css;
1127 					css <<
1128 						"#version 460 core\n"
1129 						"#extension GL_EXT_ray_tracing : require\n"
1130 						"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1131 						"hitAttributeEXT vec3 attribs;\n"
1132 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1133 						"\n"
1134 						"void main()\n"
1135 						"{\n"
1136 						<< updateImage <<
1137 						"}\n";
1138 
1139 					programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1140 				}
1141 
1142 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1143 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1144 
1145 				if (m_data.geomType == GEOM_TYPE_AABBS)
1146 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1147 
1148 				break;
1149 			}
1150 
1151 			case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1152 			{
1153 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1154 
1155 				{
1156 					std::stringstream css;
1157 					css <<
1158 						"#version 460 core\n"
1159 						"#extension GL_EXT_ray_tracing : require\n"
1160 						"hitAttributeEXT vec3 hitAttribute;\n"
1161 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1162 						"\n"
1163 						"void main()\n"
1164 						"{\n"
1165 						<< updateImage <<
1166 						"  reportIntersectionEXT(0.95f, 0);\n"
1167 						"}\n";
1168 
1169 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1170 				}
1171 
1172 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1173 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1174 				programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1175 
1176 				break;
1177 			}
1178 
1179 			case VK_SHADER_STAGE_MISS_BIT_KHR:
1180 			{
1181 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1182 
1183 				{
1184 					std::stringstream css;
1185 					css <<
1186 						"#version 460 core\n"
1187 						"#extension GL_EXT_ray_tracing : require\n"
1188 						"layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1189 						"\n"
1190 						"void main()\n"
1191 						"{\n"
1192 						<< updateImage <<
1193 						"}\n";
1194 
1195 					programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1196 				}
1197 
1198 				programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1199 				programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1200 
1201 				if (m_data.geomType == GEOM_TYPE_AABBS)
1202 					programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1203 
1204 				break;
1205 			}
1206 
1207 			default:
1208 				TCU_THROW(InternalError, "Unknown stage");
1209 		}
1210 	}
1211 	else
1212 	{
1213 		TCU_THROW(InternalError, "Not implemented");
1214 	}
1215 }
1216 
createInstance(Context & context) const1217 TestInstance* RayTracingTestCase::createInstance (Context& context) const
1218 {
1219 	return new RayTracingBuiltinLaunchTestInstance(context, m_data);
1220 }
1221 
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)1222 de::MovePtr<TopLevelAccelerationStructure> RayTracingBuiltinLaunchTestInstance::initTopAccelerationStructure (VkCommandBuffer											cmdBuffer,
1223 																											  vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures)
1224 {
1225 	const DeviceInterface&						vkd				= m_context.getDeviceInterface();
1226 	const VkDevice								device			= m_context.getDevice();
1227 	Allocator&									allocator		= m_context.getDefaultAllocator();
1228 	de::MovePtr<TopLevelAccelerationStructure>	result			= makeTopLevelAccelerationStructure();
1229 	const bool									transformTest	=  m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT
1230 																|| m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT
1231 																|| m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT
1232 																|| m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT
1233 																|| m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT
1234 																|| m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT
1235 																|| m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT
1236 																|| m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT;
1237 
1238 	result->setInstanceCount(bottomLevelAccelerationStructures.size());
1239 
1240 	for (size_t structNdx = 0; structNdx < bottomLevelAccelerationStructures.size(); ++structNdx)
1241 	{
1242 		VkTransformMatrixKHR	transform	= identityMatrix3x4;
1243 
1244 		if (transformTest)
1245 		{
1246 			if (structNdx & 1)
1247 				transform.matrix[0][3] = (1.0f /  8.0f) / float(m_data.width);
1248 
1249 			if (structNdx & 2)
1250 				transform.matrix[1][3] = (1.0f / 16.0f) / float(m_data.height);
1251 		}
1252 
1253 		result->addInstance(bottomLevelAccelerationStructures[structNdx], transform, deUint32(2 * structNdx));
1254 	}
1255 
1256 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
1257 
1258 	return result;
1259 }
1260 
initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,tcu::UVec2 & startPos)1261 de::MovePtr<BottomLevelAccelerationStructure> RayTracingBuiltinLaunchTestInstance::initBottomAccelerationStructure (VkCommandBuffer	cmdBuffer,
1262 																													tcu::UVec2&		startPos)
1263 {
1264 	const DeviceInterface&							vkd			= m_context.getDeviceInterface();
1265 	const VkDevice									device		= m_context.getDevice();
1266 	Allocator&										allocator	= m_context.getDefaultAllocator();
1267 	de::MovePtr<BottomLevelAccelerationStructure>	result		= makeBottomLevelAccelerationStructure();
1268 
1269 	result->setGeometryCount(m_data.geometriesGroupCount);
1270 
1271 	if (m_data.id == TEST_ID_LAUNCH_ID_EXT || m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
1272 	{
1273 		result->setDefaultGeometryData(m_data.stage);
1274 	}
1275 	else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT		||
1276 			 m_data.id == TEST_ID_PRIMITIVE_ID				||
1277 			 m_data.id == TEST_ID_INSTANCE_ID				||
1278 			 m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT	)
1279 	{
1280 		const bool	triangles	= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1281 		const bool	missShader	= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1282 		const float	z			= !missShader ? -1.0f : -100.0f;
1283 
1284 		DE_ASSERT(m_data.squaresGroupCount != 1);
1285 
1286 		for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1287 		{
1288 			std::vector<tcu::Vec3>	geometryData;
1289 
1290 			geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1291 
1292 			for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1293 			{
1294 				const deUint32	n	= m_data.width * startPos.y() + startPos.x();
1295 				const float		x0	= float(startPos.x() + 0) / float(m_data.width);
1296 				const float		y0	= float(startPos.y() + 0) / float(m_data.height);
1297 				const float		x1	= float(startPos.x() + 1) / float(m_data.width);
1298 				const float		y1	= float(startPos.y() + 1) / float(m_data.height);
1299 				const deUint32	m	= n + 1;
1300 
1301 				if (triangles)
1302 				{
1303 					const float	xm	= (x0 + x1) / 2.0f;
1304 					const float	ym	= (y0 + y1) / 2.0f;
1305 
1306 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1307 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1308 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1309 				}
1310 				else
1311 				{
1312 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1313 					geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1314 				}
1315 
1316 				startPos.y() = m / m_data.width;
1317 				startPos.x() = m % m_data.width;
1318 			}
1319 
1320 			result->addGeometry(geometryData, triangles);
1321 		}
1322 	}
1323 	else if (m_data.id == TEST_ID_HIT_KIND_EXT)
1324 	{
1325 		const bool	triangles	= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1326 		const bool	missShader	= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1327 		const float	z			= !missShader ? -1.0f : -100.0f;
1328 
1329 		DE_ASSERT(m_data.squaresGroupCount != 1);
1330 		DE_ASSERT(m_data.geometriesGroupCount == 4);
1331 
1332 		std::vector<tcu::Vec3>	geometryDataOpaque;
1333 		std::vector<tcu::Vec3>	geometryDataNonOpaque;
1334 
1335 		geometryDataOpaque.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1336 		geometryDataNonOpaque.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1337 
1338 		for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1339 		{
1340 			const bool				cw				= ((geometryNdx & 1) == 0) ? true : false;
1341 			std::vector<tcu::Vec3>&	geometryData	= ((geometryNdx & 2) == 0) ? geometryDataOpaque : geometryDataNonOpaque;
1342 
1343 			for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1344 			{
1345 				const deUint32	n	= m_data.width * startPos.y() + startPos.x();
1346 				const deUint32	m	= n + 1;
1347 				const float		x0	= float(startPos.x() + 0) / float(m_data.width);
1348 				const float		y0	= float(startPos.y() + 0) / float(m_data.height);
1349 				const float		x1	= float(startPos.x() + 1) / float(m_data.width);
1350 				const float		y1	= float(startPos.y() + 1) / float(m_data.height);
1351 
1352 				if (triangles)
1353 				{
1354 					const float	xm	= (x0 + x1) / 2.0f;
1355 					const float	ym	= (y0 + y1) / 2.0f;
1356 
1357 					if (cw)
1358 					{
1359 						geometryData.push_back(tcu::Vec3(x0, y0, z));
1360 						geometryData.push_back(tcu::Vec3(x1, ym, z));
1361 						geometryData.push_back(tcu::Vec3(xm, y1, z));
1362 					}
1363 					else
1364 					{
1365 						geometryData.push_back(tcu::Vec3(x0, y0, z));
1366 						geometryData.push_back(tcu::Vec3(xm, y1, z));
1367 						geometryData.push_back(tcu::Vec3(x1, ym, z));
1368 					}
1369 				}
1370 				else
1371 				{
1372 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1373 					geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1374 				}
1375 
1376 				startPos.y() = m / m_data.width;
1377 				startPos.x() = m % m_data.width;
1378 			}
1379 		}
1380 
1381 		DE_ASSERT(startPos.y() == m_data.height && startPos.x() == 0);
1382 
1383 		result->addGeometry(geometryDataOpaque, triangles, (VkGeometryFlagsKHR)VK_GEOMETRY_OPAQUE_BIT_KHR);
1384 		result->addGeometry(geometryDataNonOpaque, triangles, (VkGeometryFlagsKHR)0);
1385 	}
1386 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
1387 	{
1388 		const bool					triangles		= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1389 		const bool					missShader		= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1390 		const float					z				= !missShader ? -1.0f : -100.0f;
1391 		const VkGeometryFlagsKHR	geometryFlags	= m_data.opaque ? static_cast<VkGeometryFlagsKHR>(VK_GEOMETRY_OPAQUE_BIT_KHR) : static_cast<VkGeometryFlagsKHR>(0);
1392 		const bool					cw				= m_data.frontFace;
1393 		std::vector<tcu::Vec3>		geometryData;
1394 
1395 		DE_ASSERT(m_data.geometriesGroupCount == 1);
1396 		DE_ASSERT(m_data.squaresGroupCount != 1);
1397 
1398 		geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1399 
1400 		for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1401 		{
1402 			const deUint32	n	= m_data.width * startPos.y() + startPos.x();
1403 			const deUint32	m	= n + 1;
1404 			const float		x0	= float(startPos.x() + 0) / float(m_data.width);
1405 			const float		y0	= float(startPos.y() + 0) / float(m_data.height);
1406 			const float		x1	= float(startPos.x() + 1) / float(m_data.width);
1407 			const float		y1	= float(startPos.y() + 1) / float(m_data.height);
1408 
1409 			if (triangles)
1410 			{
1411 				const float	xm	= (x0 + x1) / 2.0f;
1412 				const float	ym	= (y0 + y1) / 2.0f;
1413 
1414 				if (cw)
1415 				{
1416 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1417 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1418 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1419 				}
1420 				else
1421 				{
1422 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1423 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1424 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1425 				}
1426 			}
1427 			else
1428 			{
1429 				geometryData.push_back(tcu::Vec3(x0, y0, z));
1430 				geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1431 			}
1432 
1433 			startPos.y() = m / m_data.width;
1434 			startPos.x() = m % m_data.width;
1435 		}
1436 
1437 		DE_ASSERT(startPos.y() == m_data.height && startPos.x() == 0);
1438 
1439 		result->addGeometry(geometryData, triangles, geometryFlags);
1440 	}
1441 	else if (m_data.id == TEST_ID_HIT_T_EXT		||
1442 			 m_data.id == TEST_ID_RAY_T_MIN_EXT	||
1443 			 m_data.id == TEST_ID_RAY_T_MAX_EXT	)
1444 	{
1445 		const bool	triangles	= (m_data.geomType == GEOM_TYPE_TRIANGLES);
1446 		const bool	missShader	= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1447 		const bool	sectShader	= (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
1448 		const bool	maxTTest	= (m_data.id == TEST_ID_RAY_T_MAX_EXT);
1449 
1450 		DE_ASSERT(m_data.squaresGroupCount != 1);
1451 
1452 		for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1453 		{
1454 			std::vector<tcu::Vec3>	geometryData;
1455 
1456 			geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1457 
1458 			for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1459 			{
1460 				const deUint32	n			= m_data.width * startPos.y() + startPos.x();
1461 				const deUint32	m			= n + 1;
1462 				const bool		shiftRight	= sectShader && maxTTest && (0 == (startPos.y() & 1)) && (0 == (startPos.x() & 1));
1463 				const deUint32	xo			= shiftRight ? 1 : 0;
1464 				const float		x0			= float(startPos.x() + 0 + xo) / float(m_data.width);
1465 				const float		y0			= float(startPos.y() + 0) / float(m_data.height);
1466 				const float		x1			= float(startPos.x() + 1 + xo) / float(m_data.width);
1467 				const float		y1			= float(startPos.y() + 1) / float(m_data.height);
1468 				const float		a			= x0;
1469 				const float		b			= 1.0f + y0;
1470 				const float		c			= 0.03125f + 0.25f * a / b;
1471 				const float		z			= !missShader ? -c : -100.0f;
1472 
1473 				if (triangles)
1474 				{
1475 					const float	xm	= (x0 + x1) / 2.0f;
1476 					const float	ym	= (y0 + y1) / 2.0f;
1477 
1478 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1479 					geometryData.push_back(tcu::Vec3(xm, y1, z));
1480 					geometryData.push_back(tcu::Vec3(x1, ym, z));
1481 				}
1482 				else
1483 				{
1484 					geometryData.push_back(tcu::Vec3(x0, y0, z));
1485 					geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1486 				}
1487 
1488 				startPos.y() = m / m_data.width;
1489 				startPos.x() = m % m_data.width;
1490 			}
1491 
1492 			result->addGeometry(geometryData, triangles);
1493 		}
1494 	}
1495 	else if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT		||
1496 			 m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT	||
1497 			 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT		||
1498 			 m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT	||
1499 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT		||
1500 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT		||
1501 			 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT	||
1502 			 m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT	)
1503 	{
1504 		const bool				triangles		= m_data.geomType == GEOM_TYPE_TRIANGLES;
1505 		const float				y0				= float(startPos.y() + 0) / float(m_data.height);
1506 		const float				y1				= float(startPos.y() + 1) / float(m_data.height);
1507 		const bool				missShader		= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1508 		const float				z				= !missShader ? -1.0f : -100.0f;
1509 		std::vector<tcu::Vec3>	geometryData;
1510 
1511 		if (triangles)
1512 		{
1513 			geometryData.push_back(tcu::Vec3(-1.0f, y1, z));
1514 			geometryData.push_back(tcu::Vec3(-1.0f, y0, z));
1515 			geometryData.push_back(tcu::Vec3(+1.0f, y0, z));
1516 			geometryData.push_back(tcu::Vec3(-1.0f, y1, z));
1517 			geometryData.push_back(tcu::Vec3(+1.0f, y0, z));
1518 			geometryData.push_back(tcu::Vec3(+1.0f, y1, z));
1519 		}
1520 		else
1521 		{
1522 			geometryData.reserve(2);
1523 
1524 			geometryData.push_back(tcu::Vec3(-1.0f, y0, z));
1525 			geometryData.push_back(tcu::Vec3(+1.0f, y1, z));
1526 		}
1527 
1528 		DE_ASSERT(startPos.y() < m_data.height);
1529 
1530 		startPos.y()++;
1531 
1532 		result->addGeometry(geometryData, triangles);
1533 	}
1534 	else
1535 	{
1536 		TCU_THROW(InternalError, "Not implemented");
1537 	}
1538 
1539 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
1540 
1541 	return result;
1542 }
1543 
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)1544 vector<de::SharedPtr<BottomLevelAccelerationStructure> > RayTracingBuiltinLaunchTestInstance::initBottomAccelerationStructures (VkCommandBuffer	cmdBuffer)
1545 {
1546 	tcu::UVec2													startPos;
1547 	vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
1548 
1549 	for (size_t instanceNdx = 0; instanceNdx < m_data.instancesGroupCount; ++instanceNdx)
1550 	{
1551 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure	= initBottomAccelerationStructure(cmdBuffer, startPos);
1552 
1553 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1554 	}
1555 
1556 	return result;
1557 }
1558 
makePipeline(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,VkPipelineLayout pipelineLayout,const VkSpecializationInfo * specializationInfo)1559 Move<VkPipeline> RayTracingBuiltinLaunchTestInstance::makePipeline (de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
1560 																	VkPipelineLayout					pipelineLayout,
1561 																	const VkSpecializationInfo*			specializationInfo)
1562 {
1563 	const DeviceInterface&	vkd			= m_context.getDeviceInterface();
1564 	const VkDevice			device		= m_context.getDevice();
1565 	vk::BinaryCollection&	collection	= m_context.getBinaryCollection();
1566 
1567 	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);
1568 	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);
1569 	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);
1570 	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);
1571 	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);
1572 	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);
1573 
1574 	if (m_data.pipelineCreateFlags != 0)
1575 		rayTracingPipeline->setCreateFlags(m_data.pipelineCreateFlags);
1576 
1577 	Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
1578 
1579 	return pipeline;
1580 }
1581 
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)1582 de::MovePtr<BufferWithMemory> RayTracingBuiltinLaunchTestInstance::createShaderBindingTable (const InstanceInterface&			vki,
1583 																							 const DeviceInterface&				vkd,
1584 																							 const VkDevice						device,
1585 																							 const VkPhysicalDevice				physicalDevice,
1586 																							 const VkPipeline					pipeline,
1587 																							 Allocator&							allocator,
1588 																							 de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
1589 																							 const deUint32						group)
1590 {
1591 	de::MovePtr<BufferWithMemory>	shaderBindingTable;
1592 
1593 	if (group < m_shaderGroupCount)
1594 	{
1595 		const deUint32	shaderGroupHandleSize		= getShaderGroupSize(vki, physicalDevice);
1596 		const deUint32	shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
1597 
1598 		shaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, 1u);
1599 	}
1600 
1601 	return shaderBindingTable;
1602 }
1603 
1604 // Provides two spec constants, one integer and one float, both with value 256.
1605 class SpecConstantsHelper
1606 {
1607 public:
1608 								SpecConstantsHelper		();
1609 	const VkSpecializationInfo&	getSpecializationInfo	(void) const;
1610 private:
1611 	std::vector<deUint8>					m_data;
1612 	std::vector<VkSpecializationMapEntry>	m_mapEntries;
1613 	VkSpecializationInfo					m_specInfo;
1614 };
1615 
SpecConstantsHelper()1616 SpecConstantsHelper::SpecConstantsHelper ()
1617 	: m_data		()
1618 	, m_mapEntries	()
1619 {
1620 	// To make things interesting, make both data unaligned and add some padding.
1621 	const deInt32	value1	= 256;
1622 	const float		value2	= 256.0f;
1623 
1624 	const size_t	offset1	= 1u;							// Offset of 1 byte.
1625 	const size_t	offset2	= 1u + sizeof(value1) + 2u;		// Offset of 3 bytes plus the size of value1.
1626 
1627 	m_data.resize(sizeof(value1) + sizeof(value2) + 5u);	// Some extra padding at the end too.
1628 	deMemcpy(&m_data[offset1], &value1, sizeof(value1));
1629 	deMemcpy(&m_data[offset2], &value2, sizeof(value2));
1630 
1631 	// Map entries.
1632 	m_mapEntries.reserve(2u);
1633 	m_mapEntries.push_back({ 0u, static_cast<deUint32>(offset1), static_cast<deUintptr>(sizeof(value1)) });
1634 	m_mapEntries.push_back({ 1u, static_cast<deUint32>(offset2), static_cast<deUintptr>(sizeof(value2))	});
1635 
1636 	// Specialization info.
1637 	m_specInfo.mapEntryCount	= static_cast<deUint32>(m_mapEntries.size());
1638 	m_specInfo.pMapEntries		= m_mapEntries.data();
1639 	m_specInfo.dataSize			= static_cast<deUintptr>(m_data.size());
1640 	m_specInfo.pData			= m_data.data();
1641 }
1642 
getSpecializationInfo(void) const1643 const VkSpecializationInfo& SpecConstantsHelper::getSpecializationInfo (void) const
1644 {
1645 	return m_specInfo;
1646 }
1647 
runTest(void)1648 de::MovePtr<BufferWithMemory> RayTracingBuiltinLaunchTestInstance::runTest (void)
1649 {
1650 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
1651 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
1652 	const VkDevice						device								= m_context.getDevice();
1653 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
1654 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
1655 	const VkQueue						queue								= m_context.getUniversalQueue();
1656 	Allocator&							allocator							= m_context.getDefaultAllocator();
1657 	const deUint32						shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
1658 	const VkFormat						format								= m_data.format;
1659 	const deUint32						pixelSize							= tcu::getPixelSize(mapVkFormat(format));
1660 	const deUint32						pixelCount							= m_data.width * m_data.height * m_data.depth;
1661 
1662 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
1663 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1664 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1665 																					.build(vkd, device);
1666 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
1667 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1668 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1669 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1670 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1671 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
1672 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
1673 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1674 
1675 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
1676 	const SpecConstantsHelper			specConstantHelper;
1677 	const VkSpecializationInfo*			specializationInfo					= (m_data.useSpecConstants ? &specConstantHelper.getSpecializationInfo() : nullptr);
1678 	const Move<VkPipeline>				pipeline							= makePipeline(rayTracingPipeline, *pipelineLayout, specializationInfo);
1679 	const de::MovePtr<BufferWithMemory>	raygenShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_raygenShaderGroup);
1680 	const de::MovePtr<BufferWithMemory>	missShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_missShaderGroup);
1681 	const de::MovePtr<BufferWithMemory>	hitShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_hitShaderGroup);
1682 	const de::MovePtr<BufferWithMemory>	callableShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_callableShaderGroup);
1683 
1684 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion		= raygenShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1685 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion		= missShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1686 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion			= hitShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1687 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion	= callableShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1688 
1689 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, m_data.depth, format);
1690 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1691 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1692 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, format, imageSubresourceRange);
1693 
1694 	const VkBufferCreateInfo			bufferCreateInfo					= makeBufferCreateInfo(pixelCount * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1695 	const VkImageSubresourceLayers		bufferImageSubresourceLayers		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1696 	const VkBufferImageCopy				bufferImageRegion					= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, m_data.depth), bufferImageSubresourceLayers);
1697 	de::MovePtr<BufferWithMemory>		buffer								= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1698 
1699 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1700 
1701 	const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1702 																				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1703 																				**image, imageSubresourceRange);
1704 	const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1705 																				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1706 																				**image, imageSubresourceRange);
1707 	const VkMemoryBarrier				postTraceMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1708 	const VkMemoryBarrier				postCopyMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1709 	const VkClearValue					clearValue							= makeClearValueColorU32(DEFAULT_UINT_CLEAR_VALUE, DEFAULT_UINT_CLEAR_VALUE, DEFAULT_UINT_CLEAR_VALUE, 255u);
1710 
1711 	vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
1712 	de::MovePtr<TopLevelAccelerationStructure>					topLevelAccelerationStructure;
1713 
1714 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
1715 	{
1716 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1717 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
1718 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1719 
1720 		bottomLevelAccelerationStructures	= initBottomAccelerationStructures(*cmdBuffer);
1721 		topLevelAccelerationStructure		= initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
1722 
1723 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
1724 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
1725 		{
1726 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1727 			DE_NULL,															//  const void*							pNext;
1728 			1u,																	//  deUint32							accelerationStructureCount;
1729 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1730 		};
1731 
1732 		DescriptorSetUpdateBuilder()
1733 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1734 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1735 			.update(vkd, device);
1736 
1737 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1738 
1739 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1740 
1741 		cmdTraceRays(vkd,
1742 			*cmdBuffer,
1743 			&raygenShaderBindingTableRegion,
1744 			&missShaderBindingTableRegion,
1745 			&hitShaderBindingTableRegion,
1746 			&callableShaderBindingTableRegion,
1747 			m_data.width, m_data.height, m_data.raysDepth);
1748 
1749 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1750 
1751 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
1752 
1753 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
1754 	}
1755 	endCommandBuffer(vkd, *cmdBuffer);
1756 
1757 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1758 
1759 	invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1760 
1761 	return buffer;
1762 }
1763 
checkFormatSupported(Context & context,VkFormat format,VkImageUsageFlags usage,const VkExtent3D & extent)1764 void checkFormatSupported(Context& context, VkFormat format, VkImageUsageFlags usage, const VkExtent3D& extent)
1765 {
1766 	VkResult					result;
1767 	VkImageFormatProperties		properties;
1768 
1769 	result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), format, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
1770 
1771 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
1772 	{
1773 		std::ostringstream msg;
1774 
1775 		msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
1776 
1777 		TCU_THROW(NotSupportedError, msg.str());
1778 	}
1779 
1780 	if (properties.maxExtent.width < extent.width || properties.maxExtent.height < extent.height || properties.maxExtent.depth < extent.depth)
1781 		TCU_THROW(NotSupportedError, "Image size is too large for this format");
1782 
1783 	VK_CHECK(result);
1784 }
1785 
checkSupportInInstance(void) const1786 void RayTracingBuiltinLaunchTestInstance::checkSupportInInstance (void) const
1787 {
1788 	const InstanceInterface&				vki						= m_context.getInstanceInterface();
1789 	const VkPhysicalDevice					physicalDevice			= m_context.getPhysicalDevice();
1790 	const vk::VkPhysicalDeviceProperties&	properties				= m_context.getDeviceProperties();
1791 	const deUint32							requiredAllocations		= 8u
1792 																	+ TopLevelAccelerationStructure::getRequiredAllocationCount()
1793 																	+ m_data.instancesGroupCount * BottomLevelAccelerationStructure::getRequiredAllocationCount();
1794 	const de::MovePtr<RayTracingProperties>	rayTracingProperties	= makeRayTracingProperties(vki, physicalDevice);
1795 	const VkExtent3D						extent					= makeExtent3D(m_data.width, m_data.height, m_data.depth);
1796 
1797 	checkFormatSupported(m_context, m_data.format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, extent);
1798 
1799 	if (rayTracingProperties->getMaxPrimitiveCount() < 2 * m_data.squaresGroupCount)
1800 		TCU_THROW(NotSupportedError, "Triangles required more than supported");
1801 
1802 	if (rayTracingProperties->getMaxGeometryCount() < m_data.geometriesGroupCount)
1803 		TCU_THROW(NotSupportedError, "Geometries required more than supported");
1804 
1805 	if (rayTracingProperties->getMaxInstanceCount() < m_data.instancesGroupCount)
1806 		TCU_THROW(NotSupportedError, "Instances required more than supported");
1807 
1808 	if (properties.limits.maxMemoryAllocationCount < requiredAllocations)
1809 		TCU_THROW(NotSupportedError, "Test requires more allocations allowed");
1810 }
1811 
expectedIntValuesBuffer(void)1812 std::vector<deInt32> RayTracingBuiltinLaunchTestInstance::expectedIntValuesBuffer (void)
1813 {
1814 	deUint32				pos		= 0;
1815 	std::vector<deInt32>	result;
1816 
1817 	result.reserve(m_data.depth * m_data.height * m_data.width);
1818 
1819 	if (m_data.id == TEST_ID_LAUNCH_ID_EXT)
1820 	{
1821 		for (deUint32 z = 0; z < m_data.depth; ++z)
1822 		for (deUint32 y = 0; y < m_data.height; ++y)
1823 		for (deUint32 x = 0; x < m_data.width; ++x)
1824 			result.push_back(deInt32(x + 256 * (y + 256 * z)) + 1);
1825 	}
1826 	else if (m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
1827 	{
1828 		const deUint32				expectedValue	= m_data.width + 256 * (m_data.height + 256 * m_data.depth);
1829 		const std::vector<deInt32>	result2			(m_data.depth * m_data.height * m_data.width, deInt32(expectedValue) + 1);
1830 
1831 		result = result2;
1832 	}
1833 	else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT)
1834 	{
1835 		for (deUint32 z = 0; z < m_data.depth; ++z)
1836 		for (deUint32 y = 0; y < m_data.height; ++y)
1837 		for (deUint32 x = 0; x < m_data.width; ++x)
1838 			result.push_back(deInt32((pos++ / m_data.squaresGroupCount) % m_data.geometriesGroupCount));
1839 	}
1840 	else if (m_data.id == TEST_ID_PRIMITIVE_ID)
1841 	{
1842 		for (deUint32 z = 0; z < m_data.depth; ++z)
1843 		for (deUint32 y = 0; y < m_data.height; ++y)
1844 		for (deUint32 x = 0; x < m_data.width; ++x)
1845 			result.push_back(deInt32(pos++ % m_data.squaresGroupCount));
1846 	}
1847 	else if (m_data.id == TEST_ID_INSTANCE_ID)
1848 	{
1849 		for (deUint32 z = 0; z < m_data.depth; ++z)
1850 		for (deUint32 y = 0; y < m_data.height; ++y)
1851 		for (deUint32 x = 0; x < m_data.width; ++x)
1852 			result.push_back(deInt32(pos++ / (m_data.squaresGroupCount * m_data.geometriesGroupCount)));
1853 	}
1854 	else if (m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT)
1855 	{
1856 		for (deUint32 z = 0; z < m_data.depth; ++z)
1857 		for (deUint32 y = 0; y < m_data.height; ++y)
1858 		for (deUint32 x = 0; x < m_data.width; ++x)
1859 			result.push_back(deInt32(2 * (pos++ / (m_data.squaresGroupCount * m_data.geometriesGroupCount))));
1860 	}
1861 	else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
1862 	{
1863 		DE_ASSERT(m_data.squaresGroupCount == (1<<RAY_FLAG_BIT_LAST_PER_TEST));
1864 		DE_ASSERT(DEFAULT_UINT_CLEAR_VALUE != (1<<RAY_FLAG_BIT_LAST_PER_TEST));
1865 
1866 		for (deUint32 z = 0; z < m_data.depth; ++z)
1867 		for (deUint32 y = 0; y < m_data.height; ++y)
1868 		for (deUint32 x = 0; x < m_data.width; ++x)
1869 		{
1870 			const deUint32	n						= x + m_data.width * (y + m_data.height * z);
1871 			const bool		rayOpaque				= (0 != (n & (1<<RAY_FLAG_BIT_OPAQUE_EXT                     )));
1872 			const bool		rayNoOpaque				= (0 != (n & (1<<RAY_FLAG_BIT_NO_OPAQUE_EXT                  ))) && !rayOpaque;
1873 			const bool		rayTerminateOnFirstHit	= (0 != (n & (1<<RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT     )));
1874 			const bool		raySkipClosestHitShader	= (0 != (n & (1<<RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT    )));
1875 			const bool		rayCullBack				= (0 != (n & (1<<RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT )));
1876 			const bool		rayCullFront			= (0 != (n & (1<<RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT))) && !rayCullBack;
1877 			const bool		rayCullOpaque			= (0 != (n & (1<<RAY_FLAG_BIT_CULL_OPAQUE_EXT                ))) && !rayOpaque && !rayNoOpaque;
1878 			const bool		rayCullNoOpaque			= (0 != (n & (1<<RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT             ))) && !rayOpaque && !rayNoOpaque && !rayCullOpaque;
1879 			const bool		raySkipTriangles		= m_data.rayFlagSkipTriangles;
1880 			const bool		raySkipAABBs			= m_data.rayFlagSkipAABSs;
1881 			const bool		pipelineSkipTriangles	= (m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0;
1882 			const bool		pipelineSkipAABBs		= (m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0;
1883 			const bool		cullingTest				= m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs || pipelineSkipTriangles || pipelineSkipAABBs;
1884 			const bool		geometryFrontFace		= m_data.frontFace;
1885 			const bool		geometryOpaque			= m_data.opaque;
1886 			const bool		geometryTriangles		= (m_data.geomType == GEOM_TYPE_TRIANGLES) ? true : false;
1887 			const bool		geometryAABBs			= (m_data.geomType == GEOM_TYPE_AABBS) ? true : false;
1888 			deUint32		v						= 0
1889 													| (rayOpaque                ? (1<<RAY_FLAG_BIT_OPAQUE_EXT                     ) : 0)
1890 													| (rayNoOpaque              ? (1<<RAY_FLAG_BIT_NO_OPAQUE_EXT                  ) : 0)
1891 													| (rayTerminateOnFirstHit   ? (1<<RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT     ) : 0)
1892 													| (raySkipClosestHitShader  ? (1<<RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT    ) : 0)
1893 													| (rayCullBack              ? (1<<RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT ) : 0)
1894 													| (rayCullFront             ? (1<<RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT) : 0)
1895 													| (rayCullOpaque            ? (1<<RAY_FLAG_BIT_CULL_OPAQUE_EXT                ) : 0)
1896 													| (rayCullNoOpaque          ? (1<<RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT             ) : 0)
1897 													| (raySkipTriangles         ? (1<<RAY_FLAG_BIT_SKIP_TRIANGLES_EXT             ) : 0)
1898 													| (raySkipAABBs             ? (1<<RAY_FLAG_BIT_SKIP_AABB_EXT                  ) : 0);
1899 
1900 			if (m_data.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR && raySkipClosestHitShader)
1901 				v = DEFAULT_UINT_CLEAR_VALUE;
1902 
1903 			if (m_data.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR && (rayOpaque || (geometryOpaque && !rayOpaque && !rayNoOpaque)))
1904 				v = DEFAULT_UINT_CLEAR_VALUE;
1905 
1906 			if (geometryOpaque)
1907 			{
1908 				if (rayCullOpaque)
1909 					if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1910 						v = DEFAULT_UINT_CLEAR_VALUE;
1911 			}
1912 			else
1913 			{
1914 				if (rayCullNoOpaque)
1915 					if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1916 						v = DEFAULT_UINT_CLEAR_VALUE;
1917 			}
1918 
1919 			if (geometryTriangles)
1920 			{
1921 				if (geometryFrontFace)
1922 				{
1923 					if (rayCullFront)
1924 						if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1925 							v = DEFAULT_UINT_CLEAR_VALUE;
1926 				}
1927 				else
1928 				{
1929 					if (rayCullBack)
1930 						if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1931 							v = DEFAULT_UINT_CLEAR_VALUE;
1932 				}
1933 			}
1934 
1935 			if (cullingTest)
1936 			{
1937 				if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
1938 				{
1939 					if (geometryTriangles)
1940 					{
1941 						if (raySkipTriangles || pipelineSkipTriangles)
1942 							v = DEFAULT_UINT_CLEAR_VALUE;
1943 					}
1944 
1945 					if (geometryAABBs)
1946 					{
1947 						if (raySkipAABBs || pipelineSkipAABBs)
1948 							v = DEFAULT_UINT_CLEAR_VALUE;
1949 					}
1950 				}
1951 			}
1952 
1953 			result.push_back(deInt32(v));
1954 		}
1955 	}
1956 	else if (m_data.id == TEST_ID_HIT_KIND_EXT)
1957 	{
1958 		for (deUint32 z = 0; z < m_data.depth; ++z)
1959 		for (deUint32 y = 0; y < m_data.height; ++y)
1960 		for (deUint32 x = 0; x < m_data.width; ++x)
1961 		{
1962 			const deUint32	n				= x + m_data.width * (y + m_data.height * z);
1963 			const deUint32	geometryNdx		= n / m_data.squaresGroupCount;
1964 			const deUint32	hitKind			= ((geometryNdx & 1) == 0) ? 0xFEu : 0xFFu;
1965 			const bool		geometryOpaque	= ((geometryNdx & 2) == 0) ? true : false;
1966 			deUint32		v				= (m_data.geomType == GEOM_TYPE_TRIANGLES) ? hitKind : 0x7Eu;
1967 
1968 			if (m_data.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR && geometryOpaque)
1969 				v = DEFAULT_UINT_CLEAR_VALUE;
1970 
1971 			result.push_back(deInt32(v));
1972 		}
1973 	}
1974 	else
1975 	{
1976 		TCU_THROW(InternalError, "Not implemented");
1977 	}
1978 
1979 	return result;
1980 }
1981 
expectedFloatValuesBuffer(void)1982 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedFloatValuesBuffer (void)
1983 {
1984 	std::vector<float>	result;
1985 
1986 	result.reserve(m_data.depth * m_data.height * m_data.width);
1987 
1988 	if (m_data.id == TEST_ID_HIT_T_EXT)
1989 	{
1990 		for (deUint32 z = 0; z < m_data.depth; ++z)
1991 		for (deUint32 y = 0; y < m_data.height; ++y)
1992 		for (deUint32 x = 0; x < m_data.width; ++x)
1993 		{
1994 			const float	a	= float(x) / float(m_data.width);
1995 			const float	b	= 1.0f + float(y) / float(m_data.height);
1996 			const float	f	= 0.03125f + 0.25f * a / b;
1997 
1998 			result.push_back(f);
1999 		}
2000 	}
2001 	else if (m_data.id == TEST_ID_RAY_T_MIN_EXT)
2002 	{
2003 		for (deUint32 z = 0; z < m_data.depth; ++z)
2004 		for (deUint32 y = 0; y < m_data.height; ++y)
2005 		for (deUint32 x = 0; x < m_data.width; ++x)
2006 		{
2007 			const float	a	= float(x) / float(m_data.width);
2008 			const float	b	= 1.0f + float(y) / float(m_data.height);
2009 			const float	f	= 0.25f * a / b;
2010 
2011 			result.push_back(f);
2012 		}
2013 	}
2014 	else if (m_data.id == TEST_ID_RAY_T_MAX_EXT)
2015 	{
2016 		for (deUint32 z = 0; z < m_data.depth; ++z)
2017 		for (deUint32 y = 0; y < m_data.height; ++y)
2018 		for (deUint32 x = 0; x < m_data.width; ++x)
2019 		{
2020 			const float	a				= float(x) / float(m_data.width);
2021 			const float	b				= 1.0f + float(y) / float(m_data.height);
2022 			const float	c				= 0.25f * a / b;
2023 			// In a miss shader, the value is identical to the parameter passed into traceRayEXT().
2024 			const float	m				= 0.75f + c;
2025 			// In the closest-hit shader, the value reflects the closest distance to the intersected primitive.
2026 			// In the any-hit shader, it reflects the distance to the primitive currently being intersected.
2027 			// In the intersection shader, it reflects the distance to the closest primitive intersected so far.
2028 			const float	n				= 0.03125f + c;
2029 			const bool	normalRow		= (y & 1) != 0;
2030 			const bool	doublePrimitive	= (x & 1) != 0;
2031 			const float	s				= normalRow ? m
2032 										: doublePrimitive ? 0.4375f + c
2033 										: float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR);
2034 			const float	f				= (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR) ? s
2035 										: (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR) ? m
2036 										: n;
2037 
2038 			result.push_back(f);
2039 		}
2040 	}
2041 	else
2042 	{
2043 		TCU_THROW(InternalError, "Not implemented");
2044 	}
2045 
2046 	return result;
2047 }
2048 
expectedVectorValuesBuffer(void)2049 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedVectorValuesBuffer (void)
2050 {
2051 	const deUint32		imageDepth		= 4;
2052 	const deUint32		expectedFloats	= imageDepth * m_data.height * m_data.width;
2053 	std::vector<float>	result			(expectedFloats, float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR));
2054 
2055 	if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT)
2056 	{
2057 		deUint32	pos	= 0;
2058 
2059 		for (deUint32 y = 0; y < m_data.height; ++y)
2060 		for (deUint32 x = 0; x < m_data.width; ++x)
2061 			result[pos++] = (0.5f + float(x)) / float(m_data.width);
2062 
2063 		for (deUint32 y = 0; y < m_data.height; ++y)
2064 		for (deUint32 x = 0; x < m_data.width; ++x)
2065 			result[pos++] = (0.5f + float(y)) / float(m_data.height);
2066 
2067 		for (deUint32 y = 0; y < m_data.height; ++y)
2068 		for (deUint32 x = 0; x < m_data.width; ++x)
2069 			result[pos++] = 0.0f;
2070 	}
2071 	else if (m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT)
2072 	{
2073 		deUint32	pos	= 0;
2074 
2075 		for (deUint32 y = 0; y < m_data.height; ++y)
2076 		for (deUint32 x = 0; x < m_data.width; ++x)
2077 			result[pos++] = 0.0f;
2078 
2079 		for (deUint32 y = 0; y < m_data.height; ++y)
2080 		for (deUint32 x = 0; x < m_data.width; ++x)
2081 			result[pos++] = 0.0f;
2082 
2083 		for (deUint32 y = 0; y < m_data.height; ++y)
2084 		for (deUint32 x = 0; x < m_data.width; ++x)
2085 			result[pos++] = -1.0f;
2086 	}
2087 	else if (m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT)
2088 	{
2089 		deUint32	pos	= 0;
2090 
2091 		for (deUint32 y = 0; y < m_data.height; ++y)
2092 		for (deUint32 x = 0; x < m_data.width; ++x)
2093 		{
2094 			const deUint32	instanceId	= y / (m_data.height / m_data.instancesGroupCount);
2095 			const float		offset		= (instanceId & 1) ? 1.0f / 8.0f : 0.0f;
2096 
2097 			result[pos++] = (0.5f + float(x) - offset) / float(m_data.width);
2098 		}
2099 
2100 		for (deUint32 y = 0; y < m_data.height; ++y)
2101 		for (deUint32 x = 0; x < m_data.width; ++x)
2102 		{
2103 			const deUint32	instanceId	= y / (m_data.height / m_data.instancesGroupCount);
2104 			const float		offset		= (instanceId & 2) ? 1.0f / 16.0f : 0.0f;
2105 
2106 			result[pos++] = (0.5f + float(y) - offset) / float(m_data.height);
2107 		}
2108 
2109 		for (deUint32 y = 0; y < m_data.height; ++y)
2110 		for (deUint32 x = 0; x < m_data.width; ++x)
2111 			result[pos++] = 0.0f;
2112 	}
2113 	else if (m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT)
2114 	{
2115 		deUint32	pos	= 0;
2116 
2117 		for (deUint32 y = 0; y < m_data.height; ++y)
2118 		for (deUint32 x = 0; x < m_data.width; ++x)
2119 			result[pos++] = 0.0f;
2120 
2121 		for (deUint32 y = 0; y < m_data.height; ++y)
2122 		for (deUint32 x = 0; x < m_data.width; ++x)
2123 			result[pos++] = 0.0f;
2124 
2125 		for (deUint32 y = 0; y < m_data.height; ++y)
2126 		for (deUint32 x = 0; x < m_data.width; ++x)
2127 			result[pos++] = -1.0f;
2128 	}
2129 	else
2130 	{
2131 		TCU_THROW(InternalError, "Not implemented");
2132 	}
2133 
2134 	return result;
2135 }
2136 
expectedMatrixValuesBuffer(void)2137 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedMatrixValuesBuffer (void)
2138 {
2139 	const deUint32		colCount		= 4;
2140 	const deUint32		rowCount		= 3;
2141 	const deUint32		imageDepth		= 4 * 4;
2142 	const deUint32		zStride			= m_data.height * m_data.width;
2143 	const deUint32		expectedFloats	= imageDepth * m_data.height * m_data.width;
2144 	std::vector<float>	result			(expectedFloats, float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR));
2145 
2146 	if (m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT ||
2147 		m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT ||
2148 		m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT ||
2149 		m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT)
2150 	{
2151 		const int	translateColumnNumber	= 3;
2152 		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;
2153 		const float translateX				= translateSign * (1.0f / 8.0f) / float(m_data.width);
2154 		const float translateY				= translateSign * (1.0f / 16.0f) / float(m_data.height);
2155 
2156 		for (deUint32 y = 0; y < m_data.height; ++y)
2157 		{
2158 			const deUint32	instanceId	= y / (m_data.height / m_data.instancesGroupCount);
2159 
2160 			for (deUint32 x = 0; x < m_data.width; ++x)
2161 			{
2162 				tcu::Matrix<float, rowCount, colCount>	m;
2163 				const deUint32							elem0Pos	= x + m_data.width * y;
2164 
2165 				if (instanceId & 1)
2166 					m[translateColumnNumber][0] = translateX;
2167 
2168 				if (instanceId & 2)
2169 					m[translateColumnNumber][1] = translateY;
2170 
2171 				for (deUint32 rowNdx = 0; rowNdx < rowCount; ++rowNdx)
2172 				for (deUint32 colNdx = 0; colNdx < colCount; ++colNdx)
2173 				{
2174 					const deUint32	z	= rowNdx * colCount + colNdx;
2175 					const deUint32	pos	= elem0Pos + zStride * z;
2176 
2177 					result[pos] = m[colNdx][rowNdx];
2178 				}
2179 			}
2180 		}
2181 	}
2182 	else
2183 	{
2184 		TCU_THROW(InternalError, "Not implemented");
2185 	}
2186 
2187 	return result;
2188 }
2189 
validateIntBuffer(de::MovePtr<BufferWithMemory> buffer)2190 bool RayTracingBuiltinLaunchTestInstance::validateIntBuffer (de::MovePtr<BufferWithMemory> buffer)
2191 {
2192 	const deInt32*			bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2193 	const vector<deInt32>	expectedValues	= expectedIntValuesBuffer();
2194 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
2195 	deUint32				failures		= 0;
2196 	deUint32				pos				= 0;
2197 
2198 	for (deUint32 z = 0; z < m_data.depth; ++z)
2199 	for (deUint32 y = 0; y < m_data.height; ++y)
2200 	for (deUint32 x = 0; x < m_data.width; ++x)
2201 	{
2202 		if (bufferPtr[pos] != expectedValues[pos])
2203 			failures++;
2204 
2205 		++pos;
2206 	}
2207 
2208 	if (failures != 0)
2209 	{
2210 		const char * names[] = { "Retrieved:", "Expected:" };
2211 		for (deUint32 n = 0; n < 2; ++n)
2212 		{
2213 			const deInt32*		loggedData = (n == 0) ? bufferPtr : expectedValues.data();
2214 			std::stringstream	css;
2215 
2216 			pos = 0;
2217 
2218 			for (deUint32 z = 0; z < m_data.depth; ++z)
2219 			for (deUint32 y = 0; y < m_data.height; ++y)
2220 			{
2221 				for (deUint32 x = 0; x < m_data.width; ++x)
2222 				{
2223 					if (bufferPtr[pos] == expectedValues[pos])
2224 						css << "____,";
2225 					else
2226 						css << std::hex << std::setw(4) << loggedData[pos] << ",";
2227 
2228 					pos++;
2229 				}
2230 
2231 				css << std::endl;
2232 			}
2233 
2234 			log << tcu::TestLog::Message << names[n] << tcu::TestLog::EndMessage;
2235 			log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2236 		}
2237 	}
2238 
2239 	return failures == 0;
2240 }
2241 
validateFloatBuffer(de::MovePtr<BufferWithMemory> buffer)2242 bool RayTracingBuiltinLaunchTestInstance::validateFloatBuffer (de::MovePtr<BufferWithMemory> buffer)
2243 {
2244 	const float			eps				= float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2245 	const deInt32*		bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2246 	const vector<float>	expectedValues	= expectedFloatValuesBuffer();
2247 	tcu::TestLog&		log				= m_context.getTestContext().getLog();
2248 	deUint32			failures		= 0;
2249 	deUint32			pos				= 0;
2250 
2251 	for (deUint32 z = 0; z < m_data.depth; ++z)
2252 	for (deUint32 y = 0; y < m_data.height; ++y)
2253 	for (deUint32 x = 0; x < m_data.width; ++x)
2254 	{
2255 		const float retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2256 
2257 		if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2258 			failures++;
2259 
2260 		++pos;
2261 	}
2262 
2263 	if (failures != 0)
2264 	{
2265 		const char * names[] = { "Retrieved:", "Expected:" };
2266 
2267 		for (deUint32 n = 0; n < 2; ++n)
2268 		{
2269 			std::stringstream	css;
2270 
2271 			pos = 0;
2272 
2273 			for (deUint32 z = 0; z < m_data.depth; ++z)
2274 			for (deUint32 y = 0; y < m_data.height; ++y)
2275 			{
2276 				for (deUint32 x = 0; x < m_data.width; ++x)
2277 				{
2278 					const float	retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2279 					const float	expectedValue	= expectedValues[pos];
2280 
2281 					if (deFloatAbs(retrievedValue - expectedValue) > eps)
2282 						css << std::setprecision(8) << std::setw(12) << (n == 0 ? retrievedValue : expectedValue) << ",";
2283 					else
2284 						css << "____________,";
2285 
2286 					pos++;
2287 				}
2288 
2289 				css << std::endl;
2290 			}
2291 
2292 			log << tcu::TestLog::Message << names[n] << tcu::TestLog::EndMessage;
2293 			log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2294 		}
2295 	}
2296 
2297 	return failures == 0;
2298 }
2299 
validateVectorBuffer(de::MovePtr<BufferWithMemory> buffer)2300 bool RayTracingBuiltinLaunchTestInstance::validateVectorBuffer (de::MovePtr<BufferWithMemory> buffer)
2301 {
2302 	const float			eps				= float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2303 	const deInt32*		bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2304 	const vector<float>	expectedValues	= expectedVectorValuesBuffer();
2305 	const deUint32		depth			= 3u; // vec3
2306 	tcu::TestLog&		log				= m_context.getTestContext().getLog();
2307 	deUint32			failures		= 0;
2308 	deUint32			pos				= 0;
2309 
2310 	DE_ASSERT(depth <= m_data.depth);
2311 
2312 	for (deUint32 z = 0; z < depth; ++z)
2313 	for (deUint32 y = 0; y < m_data.height; ++y)
2314 	for (deUint32 x = 0; x < m_data.width; ++x)
2315 	{
2316 		const float retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2317 
2318 		if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2319 			failures++;
2320 
2321 		++pos;
2322 	}
2323 
2324 	if (failures != 0)
2325 	{
2326 		const char*			names[] = { "Retrieved", "Expected " };
2327 		std::stringstream	css;
2328 
2329 		for (deUint32 y = 0; y < m_data.height; ++y)
2330 		{
2331 			for (deUint32 x = 0; x < m_data.width; ++x)
2332 			{
2333 				for (deUint32 n = 0; n < 2; ++n)
2334 				{
2335 					css << names[n] << " at (" << x << "," << y << ") {";
2336 
2337 					for (deUint32 z = 0; z < depth; ++z)
2338 					{
2339 						pos = x + m_data.width * (y + m_data.height * z);
2340 
2341 						const float	retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2342 						const float	expectedValue	= expectedValues[pos];
2343 
2344 						if (deFloatAbs(retrievedValue - expectedValue) > eps)
2345 							css << std::setprecision(8) << std::setw(12) << (n == 0 ? retrievedValue : expectedValue) << ",";
2346 						else
2347 							css << "____________,";
2348 					}
2349 
2350 					css << "}" << std::endl;
2351 				}
2352 			}
2353 		}
2354 
2355 		log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2356 	}
2357 
2358 	return failures == 0;
2359 }
2360 
validateMatrixBuffer(de::MovePtr<BufferWithMemory> buffer)2361 bool RayTracingBuiltinLaunchTestInstance::validateMatrixBuffer (de::MovePtr<BufferWithMemory> buffer)
2362 {
2363 	const float			eps				= float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2364 	const deInt32*		bufferPtr		= (deInt32*)buffer->getAllocation().getHostPtr();
2365 	const vector<float>	expectedValues	= expectedMatrixValuesBuffer();
2366 	const deUint32		depth			= 12u; // mat3x4 or mat4x3
2367 	tcu::TestLog&		log				= m_context.getTestContext().getLog();
2368 	deUint32			failures		= 0;
2369 	deUint32			pos				= 0;
2370 
2371 	DE_ASSERT(depth <= m_data.depth);
2372 
2373 	for (deUint32 z = 0; z < depth; ++z)
2374 	for (deUint32 y = 0; y < m_data.height; ++y)
2375 	for (deUint32 x = 0; x < m_data.width; ++x)
2376 	{
2377 		const float retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2378 
2379 		if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2380 			failures++;
2381 
2382 		++pos;
2383 	}
2384 
2385 	if (failures != 0)
2386 	{
2387 		const char*			names[] = { "Retrieved", "Expected" };
2388 		std::stringstream	css;
2389 
2390 		for (deUint32 y = 0; y < m_data.height; ++y)
2391 		{
2392 			for (deUint32 x = 0; x < m_data.width; ++x)
2393 			{
2394 				css << "At (" << x << "," << y << ")" << std::endl;
2395 				for (deUint32 n = 0; n < 2; ++n)
2396 				{
2397 					css << names[n] << std::endl << "{" << std::endl;
2398 
2399 					for (deUint32 z = 0; z < depth; ++z)
2400 					{
2401 						pos = x + m_data.width * (y + m_data.height * z);
2402 
2403 						const float	retrievedValue	= float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2404 						const float	expectedValue	= expectedValues[pos];
2405 
2406 						if (z % 4 == 0)
2407 							css << "    {";
2408 
2409 						if (deFloatAbs(retrievedValue - expectedValue) > eps)
2410 							css << std::setprecision(5) << std::setw(9) << (n == 0 ? retrievedValue : expectedValue) << ",";
2411 						else
2412 							css << "_________,";
2413 
2414 						if (z % 4 == 3)
2415 							css << "}" << std::endl;
2416 					}
2417 
2418 					css << "}" << std::endl;
2419 				}
2420 			}
2421 		}
2422 
2423 		log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2424 	}
2425 
2426 	return failures == 0;
2427 }
2428 
iterate(void)2429 tcu::TestStatus RayTracingBuiltinLaunchTestInstance::iterate (void)
2430 {
2431 	checkSupportInInstance();
2432 
2433 	de::MovePtr<BufferWithMemory>	buffer	= runTest();
2434 	const bool						ok		= m_data.fixedPointMatrixOutput ? validateMatrixBuffer(buffer)
2435 											: m_data.fixedPointVectorOutput ? validateVectorBuffer(buffer)
2436 											: m_data.fixedPointScalarOutput ? validateFloatBuffer(buffer)
2437 											: validateIntBuffer(buffer);
2438 
2439 	if (ok)
2440 		return tcu::TestStatus::pass("pass");
2441 	else
2442 		return tcu::TestStatus::fail("fail");
2443 }
2444 
2445 static const struct Stages
2446 {
2447 	const char*				name;
2448 	VkShaderStageFlagBits	stage;
2449 }
2450 stages[]
2451 {
2452 	{ "rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR		},
2453 	{ "ahit", VK_SHADER_STAGE_ANY_HIT_BIT_KHR		},
2454 	{ "chit", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR	},
2455 	{ "sect", VK_SHADER_STAGE_INTERSECTION_BIT_KHR	},
2456 	{ "miss", VK_SHADER_STAGE_MISS_BIT_KHR			},
2457 	{ "call", VK_SHADER_STAGE_CALLABLE_BIT_KHR		},
2458 };
2459 
2460 static const struct GeomTypes
2461 {
2462 	const char*	name;
2463 	GeomType	geomType;
2464 }
2465 geomTypes[] =
2466 {
2467 	{ "triangles",	GEOM_TYPE_TRIANGLES	},
2468 	{ "aabs",		GEOM_TYPE_AABBS		},
2469 };
2470 
createLaunchTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)2471 void createLaunchTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
2472 {
2473 	const struct
2474 	{
2475 		deUint32	width;
2476 		deUint32	height;
2477 		deUint32	depth;
2478 	}
2479 	sizes[] =
2480 	{
2481 		{     1,     1,     1 },
2482 		{    16,    16,    16 },
2483 		{   256,   256,     1 },
2484 		{ 16384,     1,     1 },
2485 		{     1, 16384,     1 },
2486 		{     1,     1, 16384 },
2487 		{   128,   128,   128 },
2488 		{  2048,  4096,     1 },
2489 		{   317,  3331,     1 },
2490 		{     1,  1331,   111 },
2491 	};
2492 
2493 	de::MovePtr<tcu::TestCaseGroup>		group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str(), ""));
2494 
2495 	for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2496 	{
2497 		if ((shaderStageFlags & stages[stageNdx].stage) == 0)
2498 			continue;
2499 
2500 		for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
2501 		{
2502 			const deUint32	width					= sizes[sizeNdx].width;
2503 			const deUint32	height					= sizes[sizeNdx].height;
2504 			const deUint32	depth					= sizes[sizeNdx].depth;
2505 			const bool		plain					= isPlain(width, height, depth);
2506 			const deUint32	k						= (plain ? 1 : 6);
2507 			const deUint32	largestGroup			= k * width * height * depth;
2508 			const deUint32	squaresGroupCount		= largestGroup;
2509 			const deUint32	geometriesGroupCount	= 1;
2510 			const deUint32	instancesGroupCount		= 1;
2511 			const CaseDef	caseDef					=
2512 			{
2513 				id,						//  TestId					id;
2514 				name,					//  const char*				name;
2515 				width,					//  deUint32				width;
2516 				height,					//  deUint32				height;
2517 				depth,					//  deUint32				depth;
2518 				depth,					//  deUint32				raysDepth;
2519 				VK_FORMAT_R32_SINT,		//  VkFormat				format;
2520 				false,					//  bool					fixedPointScalarOutput;
2521 				false,					//  bool					fixedPointVectorOutput;
2522 				false,					//  bool					fixedPointMatrixOutput;
2523 				GEOM_TYPE_TRIANGLES,	//  GeomType				geomType;
2524 				squaresGroupCount,		//  deUint32				squaresGroupCount;
2525 				geometriesGroupCount,	//  deUint32				geometriesGroupCount;
2526 				instancesGroupCount,	//  deUint32				instancesGroupCount;
2527 				stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
2528 				false,					//  bool					skipTriangles;
2529 				false,					//  bool					skipAABSs;
2530 				false,					//  bool					opaque;
2531 				false,					//  bool					frontFace;
2532 				0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
2533 				false,					//	bool					useSpecConstants;
2534 			};
2535 			const std::string	suffix		= de::toString(caseDef.width) + '_' + de::toString(caseDef.height) + '_' + de::toString(caseDef.depth);
2536 			const std::string	testName	= string(stages[stageNdx].name) + '_' + suffix;
2537 
2538 			group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), "", caseDef));
2539 		}
2540 	}
2541 
2542 	builtinGroup->addChild(group.release());
2543 }
2544 
createScalarTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)2545 void createScalarTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
2546 {
2547 	const struct
2548 	{
2549 		deUint32	width;
2550 		deUint32	height;
2551 		TestId		id;
2552 	}
2553 	sizes[] =
2554 	{
2555 		{  16,  16, TEST_ID_HIT_KIND_EXT	},
2556 		{  16,  16, TEST_ID_HIT_T_EXT		},
2557 		{  16,  16, TEST_ID_RAY_T_MIN_EXT	},
2558 		{  16,  16, TEST_ID_RAY_T_MAX_EXT	},
2559 		{  32,  32, TEST_ID_LAST			},
2560 		{  64,  64, TEST_ID_LAST			},
2561 		{ 256, 256, TEST_ID_LAST			},
2562 	};
2563 	const bool		fourGeometryGroups		=  id == TEST_ID_HIT_KIND_EXT
2564 											|| id == TEST_ID_HIT_T_EXT
2565 											|| id == TEST_ID_RAY_T_MIN_EXT
2566 											|| id == TEST_ID_RAY_T_MAX_EXT;
2567 	const bool		fixedPointScalarOutput	=  id == TEST_ID_HIT_T_EXT
2568 											|| id == TEST_ID_RAY_T_MIN_EXT
2569 											|| id == TEST_ID_RAY_T_MAX_EXT;
2570 	const deUint32	imageDepth				= 1;
2571 	const deUint32	rayDepth				= 1;
2572 
2573 	de::MovePtr<tcu::TestCaseGroup>		group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str(), ""));
2574 
2575 	for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
2576 	for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2577 	{
2578 		const GeomType	geomType	= geomTypes[geomTypesNdx].geomType;
2579 
2580 		if ((shaderStageFlags & stages[stageNdx].stage) == 0)
2581 			continue;
2582 
2583 		if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR && geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
2584 			continue;
2585 
2586 		bool testAdded				= false;
2587 		bool generalTestsStarted	= false;
2588 
2589 		for (size_t sizesNdx = 0; sizesNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizesNdx)
2590 		{
2591 			const bool		specializedTest			= (sizes[sizesNdx].id != TEST_ID_LAST);
2592 			const deUint32	width					= sizes[sizesNdx].width;
2593 			const deUint32	height					= sizes[sizesNdx].height;
2594 			const deUint32	instancesGroupCount		= fourGeometryGroups ? 1 : 4;
2595 			const deUint32	geometriesGroupCount	= fourGeometryGroups ? 4 : 8;
2596 			const deUint32	largestGroup			= width * height / geometriesGroupCount / instancesGroupCount;
2597 			const deUint32	squaresGroupCount		= largestGroup;
2598 			const CaseDef	caseDef					=
2599 			{
2600 				id,						//  TestId					id;
2601 				name,					//  const char*				name;
2602 				width,					//  deUint32				width;
2603 				height,					//  deUint32				height;
2604 				imageDepth,				//  deUint32				depth;
2605 				rayDepth,				//  deUint32				raysDepth;
2606 				VK_FORMAT_R32_SINT,		//  VkFormat				format;
2607 				fixedPointScalarOutput,	//  bool					fixedPointScalarOutput;
2608 				false,					//  bool					fixedPointVectorOutput;
2609 				false,					//  bool					fixedPointMatrixOutput;
2610 				geomType,				//  GeomType				geomType;
2611 				squaresGroupCount,		//  deUint32				squaresGroupCount;
2612 				geometriesGroupCount,	//  deUint32				geometriesGroupCount;
2613 				instancesGroupCount,	//  deUint32				instancesGroupCount;
2614 				stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
2615 				false,					//  bool					skipTriangles;
2616 				false,					//  bool					skipAABSs;
2617 				false,					//  bool					opaque;
2618 				false,					//  bool					frontFace;
2619 				0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
2620 				false,					//	bool					useSpecConstants;
2621 			};
2622 			const std::string	suffix		= '_' + de::toString(caseDef.width) + '_' + de::toString(caseDef.height);
2623 			const std::string	testName	= string(stages[stageNdx].name) + '_' + geomTypes[geomTypesNdx].name + (specializedTest ? "" : suffix);
2624 
2625 			if (specializedTest)
2626 			{
2627 				DE_UNREF(generalTestsStarted);
2628 				DE_ASSERT(!generalTestsStarted);
2629 
2630 				if (sizes[sizesNdx].id != id)
2631 					continue;
2632 			}
2633 			else
2634 			{
2635 				generalTestsStarted = true;
2636 			}
2637 
2638 			group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), "", caseDef));
2639 			testAdded = true;
2640 
2641 			if (specializedTest)
2642 				break;
2643 		}
2644 
2645 		DE_ASSERT(testAdded);
2646 		DE_UNREF(testAdded);
2647 	}
2648 
2649 	builtinGroup->addChild(group.release());
2650 }
2651 
createRayFlagsTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)2652 void createRayFlagsTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
2653 {
2654 	const deUint32	width		= 16;
2655 	const deUint32	height		= 16;
2656 	const deUint32	imageDepth	= 1;
2657 	const deUint32	rayDepth	= 1;
2658 
2659 	const struct Opaques
2660 	{
2661 		const char*	name;
2662 		bool		flag;
2663 	}
2664 	opaques[] =
2665 	{
2666 		{ "opaque",		true	},
2667 		{ "noopaque",	false	},
2668 	};
2669 	const struct Faces
2670 	{
2671 		const char*	name;
2672 		bool		flag;
2673 	}
2674 	faces[] =
2675 	{
2676 		{ "frontface",	true	},
2677 		{ "backface",	false	},
2678 	};
2679 	const struct SkipRayFlags
2680 	{
2681 		const char*	name;
2682 		bool		skipTriangles;
2683 		bool		skipAABBs;
2684 	}
2685 	skipRayFlags[] =
2686 	{
2687 		{ "raynoskipflags",			false,	false	},
2688 		{ "rayskiptriangles",		true,	false	},
2689 		{ "rayskipaabbs",			false,	true	},
2690 		{ "rayskipboth",			true,	true	},
2691 	};
2692 	const struct PipelineFlags
2693 	{
2694 		const char*				name;
2695 		VkPipelineCreateFlags	flag;
2696 	}
2697 	pipelineFlags[] =
2698 	{
2699 		{ "pipelinenoskipflags",	static_cast<VkPipelineCreateFlags>(0)																		},
2700 		{ "pipelineskiptriangles",	VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR														},
2701 		{ "pipelineskipaabbs",		VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR															},
2702 		{ "pipelineskipboth",		VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR | VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR	},
2703 	};
2704 
2705 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str(), ""));
2706 
2707 	for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
2708 	{
2709 		const GeomType					geomType	= geomTypes[geomTypesNdx].geomType;
2710 		de::MovePtr<tcu::TestCaseGroup>	geomGroup	(new tcu::TestCaseGroup(testCtx, geomTypes[geomTypesNdx].name, ""));
2711 
2712 		for (size_t skipRayFlagsNdx = 0; skipRayFlagsNdx < DE_LENGTH_OF_ARRAY(skipRayFlags); ++skipRayFlagsNdx)
2713 		{
2714 			de::MovePtr<tcu::TestCaseGroup>	rayFlagsGroup	(new tcu::TestCaseGroup(testCtx, skipRayFlags[skipRayFlagsNdx].name, ""));
2715 
2716 			for (size_t pipelineFlagsNdx = 0; pipelineFlagsNdx < DE_LENGTH_OF_ARRAY(pipelineFlags); ++pipelineFlagsNdx)
2717 			{
2718 				de::MovePtr<tcu::TestCaseGroup>	pipelineFlagsGroup	(new tcu::TestCaseGroup(testCtx, pipelineFlags[pipelineFlagsNdx].name, ""));
2719 
2720 				for (size_t opaquesNdx = 0; opaquesNdx < DE_LENGTH_OF_ARRAY(opaques); ++opaquesNdx)
2721 				for (size_t facesNdx = 0; facesNdx < DE_LENGTH_OF_ARRAY(faces); ++facesNdx)
2722 				{
2723 					const std::string				geomPropertiesGroupName	= string(opaques[opaquesNdx].name) + '_' + string(faces[facesNdx].name);
2724 					de::MovePtr<tcu::TestCaseGroup>	geomPropertiesGroup		(new tcu::TestCaseGroup(testCtx, geomPropertiesGroupName.c_str(), ""));
2725 
2726 					for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2727 					{
2728 						if ((shaderStageFlags & stages[stageNdx].stage) == 0)
2729 							continue;
2730 
2731 						if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR && geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
2732 							continue;
2733 
2734 						const deUint32		instancesGroupCount		= 1;
2735 						const deUint32		geometriesGroupCount	= 1;
2736 						const deUint32		largestGroup			= width * height / geometriesGroupCount / instancesGroupCount;
2737 						const deUint32		squaresGroupCount		= largestGroup;
2738 						const CaseDef		caseDef					=
2739 						{
2740 							id,												//  TestId					id;
2741 							name,											//  const char*				name;
2742 							width,											//  deUint32				width;
2743 							height,											//  deUint32				height;
2744 							imageDepth,										//  deUint32				depth;
2745 							rayDepth,										//  deUint32				raysDepth;
2746 							VK_FORMAT_R32_SINT,								//  VkFormat				format;
2747 							false,											//  bool					fixedPointScalarOutput;
2748 							false,											//  bool					fixedPointVectorOutput;
2749 							false,											//  bool					fixedPointMatrixOutput;
2750 							geomType,										//  GeomType				geomType;
2751 							squaresGroupCount,								//  deUint32				squaresGroupCount;
2752 							geometriesGroupCount,							//  deUint32				geometriesGroupCount;
2753 							instancesGroupCount,							//  deUint32				instancesGroupCount;
2754 							stages[stageNdx].stage,							//  VkShaderStageFlagBits	stage;
2755 							skipRayFlags[skipRayFlagsNdx].skipTriangles,	//  bool					skipTriangles;
2756 							skipRayFlags[skipRayFlagsNdx].skipAABBs,		//  bool					skipAABSs;
2757 							opaques[opaquesNdx].flag,						//  bool					opaque;
2758 							faces[facesNdx].flag,							//  bool					frontFace;
2759 							pipelineFlags[pipelineFlagsNdx].flag,			//  VkPipelineCreateFlags	pipelineCreateFlags;
2760 							false,											//	bool					useSpecConstants;
2761 						};
2762 						const std::string	testName				= string(stages[stageNdx].name) ;
2763 
2764 						geomPropertiesGroup->addChild(new RayTracingTestCase(testCtx, testName.c_str(), "", caseDef));
2765 					}
2766 
2767 					pipelineFlagsGroup->addChild(geomPropertiesGroup.release());
2768 				}
2769 
2770 				rayFlagsGroup->addChild(pipelineFlagsGroup.release());
2771 			}
2772 
2773 			geomGroup->addChild(rayFlagsGroup.release());
2774 		}
2775 
2776 		group->addChild(geomGroup.release());
2777 	}
2778 
2779 	builtinGroup->addChild(group.release());
2780 }
2781 
createMultiOutputTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)2782 void createMultiOutputTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* builtinGroup, TestId id, const char* name, const VkShaderStageFlags shaderStageFlags)
2783 {
2784 	const bool		fixedPointVectorOutput	=  id == TEST_ID_WORLD_RAY_ORIGIN_EXT
2785 											|| id == TEST_ID_WORLD_RAY_DIRECTION_EXT
2786 											|| id == TEST_ID_OBJECT_RAY_ORIGIN_EXT
2787 											|| id == TEST_ID_OBJECT_RAY_DIRECTION_EXT;
2788 	const bool		fixedPointMatrixOutput	=  id == TEST_ID_OBJECT_TO_WORLD_EXT
2789 											|| id == TEST_ID_WORLD_TO_OBJECT_EXT
2790 											|| id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT
2791 											|| id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT;
2792 	const deUint32	imageDepth				= fixedPointMatrixOutput ? 4 * 4
2793 											: fixedPointVectorOutput ? 4
2794 											: 0;
2795 	const deUint32	rayDepth				= 1;
2796 
2797 	de::MovePtr<tcu::TestCaseGroup>		group	(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str(), ""));
2798 
2799 	DE_ASSERT(imageDepth != 0);
2800 
2801 	for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
2802 	for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2803 	{
2804 		const GeomType	geomType	= geomTypes[geomTypesNdx].geomType;
2805 
2806 		if ((shaderStageFlags & stages[stageNdx].stage) == 0)
2807 			continue;
2808 
2809 		if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR && geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
2810 			continue;
2811 
2812 		const deUint32		width					= 4;
2813 		const deUint32		height					= 4;
2814 		const deUint32		instancesGroupCount		= 4;
2815 		const deUint32		geometriesGroupCount	= 1;
2816 		const deUint32		largestGroup			= width * height / geometriesGroupCount / instancesGroupCount;
2817 		const deUint32		squaresGroupCount		= largestGroup;
2818 		const CaseDef		caseDef					=
2819 		{
2820 			id,						//  TestId					id;
2821 			name,					//  const char*				name;
2822 			width,					//  deUint32				width;
2823 			height,					//  deUint32				height;
2824 			imageDepth,				//  deUint32				depth;
2825 			rayDepth,				//  deUint32				raysDepth;
2826 			VK_FORMAT_R32_SINT,		//  VkFormat				format;
2827 			false,					//  bool					fixedPointScalarOutput;
2828 			fixedPointVectorOutput,	//  bool					fixedPointVectorOutput;
2829 			fixedPointMatrixOutput,	//  bool					fixedPointMatrixOutput;
2830 			geomType,				//  GeomType				geomType;
2831 			squaresGroupCount,		//  deUint32				squaresGroupCount;
2832 			geometriesGroupCount,	//  deUint32				geometriesGroupCount;
2833 			instancesGroupCount,	//  deUint32				instancesGroupCount;
2834 			stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
2835 			false,					//  bool					rayFlagSkipTriangles;
2836 			false,					//  bool					rayFlagSkipAABSs;
2837 			false,					//  bool					opaque;
2838 			false,					//  bool					frontFace;
2839 			0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
2840 			false,					//	bool					useSpecConstants;
2841 		};
2842 		const std::string	testName				= string(stages[stageNdx].name) + '_' + geomTypes[geomTypesNdx].name;
2843 
2844 		group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), "", caseDef));
2845 	}
2846 
2847 	builtinGroup->addChild(group.release());
2848 }
2849 }	// anonymous
2850 
createBuiltinTests(tcu::TestContext & testCtx)2851 tcu::TestCaseGroup*	createBuiltinTests (tcu::TestContext& testCtx)
2852 {
2853 	typedef void CreateBuiltinTestsFunc (tcu::TestContext& testCtx, tcu::TestCaseGroup* group, TestId id, const char* name, const VkShaderStageFlags);
2854 
2855 	const VkShaderStageFlagBits	R	= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
2856 	const VkShaderStageFlagBits	A	= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
2857 	const VkShaderStageFlagBits	C	= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
2858 	const VkShaderStageFlagBits	M	= VK_SHADER_STAGE_MISS_BIT_KHR;
2859 	const VkShaderStageFlagBits	I	= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
2860 	const VkShaderStageFlagBits	L	= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
2861 
2862 	const struct
2863 	{
2864 		TestId					id;
2865 		const char*				name;
2866 		VkShaderStageFlags		stages;
2867 		CreateBuiltinTestsFunc*	createBuiltinTestsFunc;
2868 	}
2869 	tests[] =
2870 	{
2871 		{ TEST_ID_LAUNCH_ID_EXT,				"LaunchIDEXT"			,	R	|	A	|	C	|	I	|	M	|	L	, createLaunchTests			},
2872 		{ TEST_ID_LAUNCH_SIZE_EXT,				"LaunchSizeEXT"			,	R	|	A	|	C	|	I	|	M	|	L	, createLaunchTests			},
2873 		{ TEST_ID_PRIMITIVE_ID,					"PrimitiveID"			,			A	|	C	|	I					, createScalarTests			},
2874 		{ TEST_ID_INSTANCE_ID,					"InstanceID"			,			A	|	C	|	I					, createScalarTests			},
2875 		{ TEST_ID_INSTANCE_CUSTOM_INDEX_EXT,	"InstanceCustomIndexEXT",			A	|	C	|	I					, createScalarTests			},
2876 		{ TEST_ID_GEOMETRY_INDEX_EXT,			"GeometryIndexEXT"		,			A	|	C	|	I					, createScalarTests			},
2877 		{ TEST_ID_WORLD_RAY_ORIGIN_EXT,			"WorldRayOriginEXT"		,			A	|	C	|	I	|	M			, createMultiOutputTests	},
2878 		{ TEST_ID_WORLD_RAY_DIRECTION_EXT,		"WorldRayDirectionEXT"	,			A	|	C	|	I	|	M			, createMultiOutputTests	},
2879 		{ TEST_ID_OBJECT_RAY_ORIGIN_EXT,		"ObjectRayOriginEXT"	,			A	|	C	|	I					, createMultiOutputTests	},
2880 		{ TEST_ID_OBJECT_RAY_DIRECTION_EXT,		"ObjectRayDirectionEXT"	,			A	|	C	|	I					, createMultiOutputTests	},
2881 		{ TEST_ID_RAY_T_MIN_EXT,				"RayTminEXT"			,			A	|	C	|	I	|	M			, createScalarTests			},
2882 		{ TEST_ID_RAY_T_MAX_EXT,				"RayTmaxEXT"			,			A	|	C	|	I	|	M			, createScalarTests			},
2883 		{ TEST_ID_INCOMING_RAY_FLAGS_EXT,		"IncomingRayFlagsEXT"	,			A	|	C	|	I	|	M			, createRayFlagsTests		},
2884 		{ TEST_ID_HIT_T_EXT,					"HitTEXT"				,			A	|	C							, createScalarTests			},
2885 		{ TEST_ID_HIT_KIND_EXT,					"HitKindEXT"			,			A	|	C							, createScalarTests			},
2886 		{ TEST_ID_OBJECT_TO_WORLD_EXT,			"ObjectToWorldEXT"		,			A	|	C	|	I					, createMultiOutputTests	},
2887 		{ TEST_ID_WORLD_TO_OBJECT_EXT,			"WorldToObjectEXT"		,			A	|	C	|	I					, createMultiOutputTests	},
2888         { TEST_ID_OBJECT_TO_WORLD_3X4_EXT,		"ObjectToWorld3x4EXT"	,			A	|	C	|	I					, createMultiOutputTests	},
2889         { TEST_ID_WORLD_TO_OBJECT_3X4_EXT,		"WorldToObject3x4EXT"	,			A	|	C	|	I					, createMultiOutputTests	},
2890 	};
2891 
2892 	de::MovePtr<tcu::TestCaseGroup> builtinGroup(new tcu::TestCaseGroup(testCtx, "builtin", "Ray tracing shader builtin tests"));
2893 
2894 	for (size_t testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
2895 		tests[testNdx].createBuiltinTestsFunc(testCtx, builtinGroup.get(), tests[testNdx].id, tests[testNdx].name, tests[testNdx].stages);
2896 
2897 	return builtinGroup.release();
2898 }
2899 
createSpecConstantTests(tcu::TestContext & testCtx)2900 tcu::TestCaseGroup* createSpecConstantTests	(tcu::TestContext& testCtx)
2901 {
2902 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "spec_constants", "Test using spec constants in ray tracing shader stages"));
2903 
2904 	const VkShaderStageFlags	stageFlags				= VK_SHADER_STAGE_RAYGEN_BIT_KHR
2905 														| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
2906 														| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
2907 														| VK_SHADER_STAGE_MISS_BIT_KHR
2908 														| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
2909 														| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
2910 	const deUint32				width					= 256u;
2911 	const deUint32				height					= 256u;
2912 	const deUint32				depth					= 1u;
2913 	const bool					plain					= isPlain(width, height, depth);
2914 	const deUint32				k						= (plain ? 1 : 6);
2915 	const deUint32				largestGroup			= k * width * height * depth;
2916 	const deUint32				squaresGroupCount		= largestGroup;
2917 	const deUint32				geometriesGroupCount	= 1;
2918 	const deUint32				instancesGroupCount		= 1;
2919 
2920 	for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2921 	{
2922 		if ((stageFlags & stages[stageNdx].stage) == 0)
2923 			continue;
2924 
2925 		const CaseDef caseDef =
2926 		{
2927 			TEST_ID_LAUNCH_ID_EXT,	//  TestId					id;
2928 			"LaunchIDEXT",			//  const char*				name;
2929 			width,					//  deUint32				width;
2930 			height,					//  deUint32				height;
2931 			depth,					//  deUint32				depth;
2932 			depth,					//  deUint32				raysDepth;
2933 			VK_FORMAT_R32_SINT,		//  VkFormat				format;
2934 			false,					//  bool					fixedPointScalarOutput;
2935 			false,					//  bool					fixedPointVectorOutput;
2936 			false,					//  bool					fixedPointMatrixOutput;
2937 			GEOM_TYPE_TRIANGLES,	//  GeomType				geomType;
2938 			squaresGroupCount,		//  deUint32				squaresGroupCount;
2939 			geometriesGroupCount,	//  deUint32				geometriesGroupCount;
2940 			instancesGroupCount,	//  deUint32				instancesGroupCount;
2941 			stages[stageNdx].stage,	//  VkShaderStageFlagBits	stage;
2942 			false,					//  bool					skipTriangles;
2943 			false,					//  bool					skipAABSs;
2944 			false,					//  bool					opaque;
2945 			false,					//  bool					frontFace;
2946 			0u,						//  VkPipelineCreateFlags	pipelineCreateFlags;
2947 			true,					//	bool					useSpecConstants;
2948 		};
2949 
2950 		group->addChild(new RayTracingTestCase(testCtx, stages[stageNdx].name, "", caseDef));
2951 	}
2952 
2953 	return group.release();
2954 }
2955 
2956 }	// RayTracing
2957 }	// vkt
2958