• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 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 Watertightness tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingWatertightnessTests.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 
37 #include "vkRayTracingUtil.hpp"
38 
39 #include "deRandom.hpp"
40 
41 namespace vkt
42 {
43 namespace RayTracing
44 {
45 namespace
46 {
47 using namespace vk;
48 using namespace std;
49 
50 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
51 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
52 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
53 												| VK_SHADER_STAGE_MISS_BIT_KHR
54 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
55 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
56 
57 enum TestType
58 {
59 	TEST_TYPE_INSIDE_STAGE,
60 	TEST_TYPE_BETWEEN_STAGES,
61 };
62 
63 
64 struct CaseDef
65 {
66 	TestType				testType;
67 	VkShaderStageFlagBits	stage;
68 	deUint32				width;
69 	deUint32				height;
70 	deUint32				squaresGroupCount;
71 	deUint32				geometriesGroupCount;
72 	deUint32				instancesGroupCount;
73 };
74 
75 enum ShaderGroups
76 {
77 	FIRST_GROUP		= 0,
78 	RAYGEN_GROUP	= FIRST_GROUP,
79 	MISS_GROUP,
80 	HIT_GROUP,
81 	GROUP_COUNT
82 };
83 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)84 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
85 							 const VkPhysicalDevice		physicalDevice)
86 {
87 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
88 
89 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
90 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
91 }
92 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)93 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
94 									  const VkPhysicalDevice	physicalDevice)
95 {
96 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
97 
98 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
99 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
100 }
101 
makeImageCreateInfo(deUint32 width,deUint32 height,VkFormat format)102 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, VkFormat format)
103 {
104 	const VkImageUsageFlags	usage			= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
105 	const VkImageCreateInfo	imageCreateInfo	=
106 	{
107 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
108 		DE_NULL,								// const void*				pNext;
109 		(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
110 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
111 		format,									// VkFormat					format;
112 		makeExtent3D(width, height, 1u),		// VkExtent3D				extent;
113 		1u,										// deUint32					mipLevels;
114 		1u,										// deUint32					arrayLayers;
115 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
116 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
117 		usage,									// VkImageUsageFlags		usage;
118 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
119 		0u,										// deUint32					queueFamilyIndexCount;
120 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
121 		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
122 	};
123 
124 	return imageCreateInfo;
125 }
126 
127 class RayTracingBuildTestInstance : public TestInstance
128 {
129 public:
130 																RayTracingBuildTestInstance			(Context& context, const CaseDef& data);
131 																~RayTracingBuildTestInstance		(void);
132 	tcu::TestStatus												iterate								(void);
133 
134 protected:
135 	void														checkSupportInInstance				(void) const;
136 	de::MovePtr<BufferWithMemory>								runTest								(void);
137 	Move<VkPipeline>											makePipeline						(de::MovePtr<RayTracingPipeline>&							rayTracingPipeline,
138 																									 VkPipelineLayout											pipelineLayout);
139 	de::MovePtr<BufferWithMemory>								createShaderBindingTable			 (const InstanceInterface&									vki,
140 																									 const DeviceInterface&										vkd,
141 																									 const VkDevice												device,
142 																									 const VkPhysicalDevice										physicalDevice,
143 																									 const VkPipeline											pipeline,
144 																									 Allocator&													allocator,
145 																									 de::MovePtr<RayTracingPipeline>&							rayTracingPipeline,
146 																									 const deUint32												group,
147 																									 const deUint32												groupCount = 1u);
148 	de::MovePtr<TopLevelAccelerationStructure>					initTopAccelerationStructure		(VkCommandBuffer											cmdBuffer,
149 																									 vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures);
150 	vector<de::SharedPtr<BottomLevelAccelerationStructure>	>	initBottomAccelerationStructures	(VkCommandBuffer											cmdBuffer);
151 	de::MovePtr<BottomLevelAccelerationStructure>				initBottomAccelerationStructure		(VkCommandBuffer											cmdBuffer,
152 																									 tcu::UVec2&												startPos);
153 
154 private:
155 	CaseDef														m_data;
156 	VkShaderStageFlags											m_shaders;
157 	VkShaderStageFlags											m_extraCallShaders;
158 	deUint32													m_raygenShaderGroup;
159 	deUint32													m_missShaderGroup;
160 	deUint32													m_hitShaderGroup;
161 	deUint32													m_callableShaderGroup;
162 	deUint32													m_shaderGroupCount;
163 };
164 
RayTracingBuildTestInstance(Context & context,const CaseDef & data)165 RayTracingBuildTestInstance::RayTracingBuildTestInstance (Context& context, const CaseDef& data)
166 	: vkt::TestInstance		(context)
167 	, m_data				(data)
168 	, m_shaders				(0)
169 	, m_extraCallShaders	(0)
170 	, m_raygenShaderGroup	(~0u)
171 	, m_missShaderGroup		(~0u)
172 	, m_hitShaderGroup		(~0u)
173 	, m_callableShaderGroup	(~0u)
174 	, m_shaderGroupCount	(0)
175 {
176 	const VkShaderStageFlags	hitStages	= VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
177 	BinaryCollection&			collection	= m_context.getBinaryCollection();
178 	deUint32					group		= 0;
179 	deUint32					shaderCount	= 0;
180 
181 	if (collection.contains("rgen")) m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
182 	if (collection.contains("ahit")) m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
183 	if (collection.contains("chit")) m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
184 	if (collection.contains("miss")) m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
185 	if (collection.contains("sect")) m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
186 	if (collection.contains("call")) m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
187 
188 	if (collection.contains("cal0")) m_extraCallShaders++;
189 
190 	for (BinaryCollection::Iterator it =  collection.begin(); it != collection.end(); ++it)
191 		shaderCount++;
192 
193 	if (shaderCount != m_extraCallShaders + (deUint32)dePop32(m_shaders))
194 		TCU_THROW(InternalError, "Unused shaders detected in the collection");
195 
196 	if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
197 		m_raygenShaderGroup		= group++;
198 
199 	if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
200 		m_missShaderGroup		= group++;
201 
202 	if (0 != (m_shaders & hitStages))
203 		m_hitShaderGroup		= group++;
204 
205 	if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR) || m_extraCallShaders > 0)
206 		m_callableShaderGroup	= group++;
207 
208 	m_shaderGroupCount = group;
209 }
210 
~RayTracingBuildTestInstance(void)211 RayTracingBuildTestInstance::~RayTracingBuildTestInstance (void)
212 {
213 }
214 
215 class RayTracingTestCase : public TestCase
216 {
217 	public:
218 										RayTracingTestCase			(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
219 										~RayTracingTestCase			(void);
220 
221 	virtual	void						initPrograms				(SourceCollections& programCollection) const;
222 	virtual TestInstance*				createInstance				(Context& context) const;
223 	virtual void						checkSupport				(Context& context) const;
224 
225 private:
226 	static inline const std::string		getIntersectionPassthrough	(void);
227 	static inline const std::string		getMissPassthrough			(void);
228 	static inline const std::string		getHitPassthrough			(void);
229 
230 	CaseDef					m_data;
231 };
232 
RayTracingTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)233 RayTracingTestCase::RayTracingTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
234 	: vkt::TestCase	(context, name, desc)
235 	, m_data		(data)
236 {
237 	DE_ASSERT((m_data.width * m_data.height) == (m_data.squaresGroupCount * m_data.geometriesGroupCount * m_data.instancesGroupCount));
238 }
239 
~RayTracingTestCase(void)240 RayTracingTestCase::~RayTracingTestCase	(void)
241 {
242 }
243 
checkSupport(Context & context) const244 void RayTracingTestCase::checkSupport(Context& context) const
245 {
246 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
247 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
248 
249 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
250 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
251 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
252 
253 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
254 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
255 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
256 }
257 
258 
getIntersectionPassthrough(void)259 const std::string RayTracingTestCase::getIntersectionPassthrough (void)
260 {
261 	const std::string intersectionPassthrough =
262 		"#version 460 core\n"
263 		"#extension GL_EXT_ray_tracing : require\n"
264 		"hitAttributeEXT vec3 hitAttribute;\n"
265 		"\n"
266 		"void main()\n"
267 		"{\n"
268 		"  reportIntersectionEXT(0.95f, 0x7Eu);\n"
269 		"}\n";
270 
271 	return intersectionPassthrough;
272 }
273 
getMissPassthrough(void)274 const std::string RayTracingTestCase::getMissPassthrough (void)
275 {
276 	const std::string missPassthrough =
277 		"#version 460 core\n"
278 		"#extension GL_EXT_ray_tracing : require\n"
279 		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
280 		"\n"
281 		"void main()\n"
282 		"{\n"
283 		"}\n";
284 
285 	return missPassthrough;
286 }
287 
getHitPassthrough(void)288 const std::string RayTracingTestCase::getHitPassthrough (void)
289 {
290 	const std::string hitPassthrough =
291 		"#version 460 core\n"
292 		"#extension GL_EXT_ray_tracing : require\n"
293 		"hitAttributeEXT vec3 attribs;\n"
294 		"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
295 		"\n"
296 		"void main()\n"
297 		"{\n"
298 		"}\n";
299 
300 	return hitPassthrough;
301 }
302 
initPrograms(SourceCollections & programCollection) const303 void RayTracingTestCase::initPrograms (SourceCollections& programCollection) const
304 {
305 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
306 
307 	const std::string	imageQualifiers		= (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? " shadercallcoherent " : "");
308 	const std::string	glslExtensions		= (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? "#extension GL_KHR_memory_scope_semantics : require\n" : "");
309 	const bool			calleeIsAnyHit		= (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
310 	const std::string	repackInstruction	= calleeIsAnyHit
311 											? "reportIntersectionEXT(0.95f, 0u)"
312 											: "executeCallableEXT(0, 0)";
313 	const std::string	updateBarrierCaller	= (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? "  memoryBarrier(gl_ScopeShaderCallEXT, gl_StorageSemanticsImage, gl_SemanticsRelease);\n" : "");
314 	const std::string	updateBarrierCallee	= (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? "  memoryBarrier(gl_ScopeShaderCallEXT, gl_StorageSemanticsImage, gl_SemanticsAcquire);\n" : "");
315 	const std::string	updateImage0		=
316 		"  uint  r = uint(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * gl_LaunchIDEXT.y);\n"
317 		"  uvec4 c = uvec4(r, 0, 0, 1);\n"
318 		"  imageStore(result, ivec2(gl_LaunchIDEXT), c);\n"
319 		"\n"
320 		+ updateBarrierCaller +
321 		"\n"
322 		"  " + repackInstruction + ";\n";
323 	const std::string	updateImage1		=
324 		"  uint  d = imageLoad(result, ivec2(gl_LaunchIDEXT)).x;\n"
325 		"  imageStore(result, ivec2(gl_LaunchIDEXT), uvec4(d + 1, 0, 0, 1));\n";
326 	const std::string	updateImageCaller	= updateImage0 + (m_data.testType == TEST_TYPE_INSIDE_STAGE ? updateImage1 : "");
327 	const std::string	updateImageCallee	= (m_data.testType == TEST_TYPE_BETWEEN_STAGES ? updateImage1 : "");
328 	const std::string	calleeShaderParam	= calleeIsAnyHit ? "" : "layout(location = 0) callableDataInEXT float dummy;\n";
329 	const std::string	calleeShader		=
330 		"#version 460 core\n"
331 		"#extension GL_EXT_ray_tracing : require\n"
332 		+ glslExtensions
333 		+ calleeShaderParam +
334 		"layout(set = 0, binding = 0, r32ui) uniform uimage2D result;\n"
335 		"\n"
336 		"void main()\n"
337 		"{\n"
338 		+ updateBarrierCallee
339 		+ updateImageCallee +
340 		"}\n";
341 
342 	switch (m_data.stage)
343 	{
344 		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
345 		{
346 			std::stringstream css;
347 			css <<
348 				"#version 460 core\n"
349 				"#extension GL_EXT_ray_tracing : require\n"
350 				+ glslExtensions +
351 				"layout(set = 0, binding = 0, r32ui)" + imageQualifiers + "uniform uimage2D result;\n"
352 				"layout(location = 0) callableDataEXT float dummy;\n"
353 				"\n"
354 				"void main()\n"
355 				"{\n"
356 				<< updateImageCaller <<
357 				"}\n";
358 
359 			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
360 			programCollection.glslSources.add("cal0") << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
361 
362 			break;
363 		}
364 
365 		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
366 		{
367 			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
368 
369 			std::stringstream css;
370 			css <<
371 				"#version 460 core\n"
372 				"#extension GL_EXT_ray_tracing : require\n"
373 				+ glslExtensions +
374 				"layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
375 				"hitAttributeEXT vec3 attribs;\n"
376 				"layout(r32ui, set = 0, binding = 0)" + imageQualifiers + "uniform uimage2D result;\n"
377 				"layout(location = 0) callableDataEXT float dummy;\n"
378 				"\n"
379 				"void main()\n"
380 				"{\n"
381 				<< updateImageCaller <<
382 				"}\n";
383 
384 			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
385 			programCollection.glslSources.add("cal0") << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
386 
387 			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
388 			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
389 			programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
390 
391 			break;
392 		}
393 
394 		case VK_SHADER_STAGE_MISS_BIT_KHR:
395 		{
396 			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
397 
398 			std::stringstream css;
399 			css <<
400 				"#version 460 core\n"
401 				"#extension GL_EXT_ray_tracing : require\n"
402 				+ glslExtensions +
403 				"layout(r32ui, set = 0, binding = 0)" + imageQualifiers + "uniform uimage2D result;\n"
404 				"layout(location = 0) callableDataEXT float dummy;\n"
405 				"\n"
406 				"void main()\n"
407 				"{\n"
408 				<< updateImageCaller <<
409 				"}\n";
410 
411 			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
412 			programCollection.glslSources.add("cal0") << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
413 
414 			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
415 			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
416 			programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
417 
418 			break;
419 		}
420 
421 		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
422 		{
423 			programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
424 
425 			std::stringstream css;
426 			css <<
427 				"#version 460 core\n"
428 				"#extension GL_EXT_ray_tracing : require\n"
429 				+ glslExtensions +
430 				"layout(r32ui, set = 0, binding = 0)" + imageQualifiers + "uniform uimage2D result;\n"
431 				"\n"
432 				"void main()\n"
433 				"{\n"
434 				<< updateImageCaller <<
435 				"}\n";
436 
437 			programCollection.glslSources.add("sect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
438 			programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
439 
440 			programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
441 			programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
442 
443 			break;
444 		}
445 
446 		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
447 		{
448 			{
449 				std::stringstream css;
450 				css <<
451 					"#version 460 core\n"
452 					"#extension GL_EXT_ray_tracing : require\n"
453 					+ glslExtensions +
454 					"layout(location = 0) callableDataEXT float dummy;\n"
455 					"layout(set = 0, binding = 0, r32ui)" + imageQualifiers + "uniform uimage2D result;\n"
456 					"\n"
457 					"void main()\n"
458 					"{\n"
459 					"  executeCallableEXT(1, 0);\n"
460 					"}\n";
461 
462 				programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
463 			}
464 
465 			{
466 				std::stringstream css;
467 				css <<
468 					"#version 460 core\n"
469 					"#extension GL_EXT_ray_tracing : require\n"
470 					+ glslExtensions +
471 					"layout(location = 1) callableDataInEXT float dummyIn;\n"
472 					"layout(location = 0) callableDataEXT float dummyOut;\n"
473 					"layout(set = 0, binding = 0, r32ui)" + imageQualifiers + "uniform uimage2D result;\n"
474 					"\n"
475 					"void main()\n"
476 					"{\n"
477 					<< updateImageCaller <<
478 					"}\n";
479 
480 				programCollection.glslSources.add("call") << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
481 			}
482 
483 			programCollection.glslSources.add("cal0") << glu::CallableSource(updateRayTracingGLSL(calleeShader)) << buildOptions;
484 
485 			break;
486 		}
487 
488 		default:
489 			TCU_THROW(InternalError, "Unknown stage");
490 	}
491 }
492 
createInstance(Context & context) const493 TestInstance* RayTracingTestCase::createInstance (Context& context) const
494 {
495 	return new RayTracingBuildTestInstance(context, m_data);
496 }
497 
makePipeline(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,VkPipelineLayout pipelineLayout)498 Move<VkPipeline> RayTracingBuildTestInstance::makePipeline (de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
499 															VkPipelineLayout					pipelineLayout)
500 {
501 	const DeviceInterface&	vkd			= m_context.getDeviceInterface();
502 	const VkDevice			device		= m_context.getDevice();
503 	vk::BinaryCollection&	collection	= m_context.getBinaryCollection();
504 
505 	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);
506 	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);
507 	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);
508 	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);
509 	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);
510 	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 + 1);
511 	if (m_extraCallShaders)											rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR		, createShaderModule(vkd, device, collection.get("cal0"), 0), m_callableShaderGroup);
512 
513 	Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
514 
515 	return pipeline;
516 }
517 
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,const deUint32 groupCount)518 de::MovePtr<BufferWithMemory> RayTracingBuildTestInstance::createShaderBindingTable (const InstanceInterface&			vki,
519 																					 const DeviceInterface&				vkd,
520 																					 const VkDevice						device,
521 																					 const VkPhysicalDevice				physicalDevice,
522 																					 const VkPipeline					pipeline,
523 																					 Allocator&							allocator,
524 																					 de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
525 																					 const deUint32						group,
526 																					 const deUint32						groupCount)
527 {
528 	de::MovePtr<BufferWithMemory>	shaderBindingTable;
529 
530 	if (group < m_shaderGroupCount)
531 	{
532 		const deUint32	shaderGroupHandleSize		= getShaderGroupSize(vki, physicalDevice);
533 		const deUint32	shaderGroupBaseAlignment	= getShaderGroupBaseAlignment(vki, physicalDevice);
534 
535 		shaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, groupCount);
536 	}
537 
538 	return shaderBindingTable;
539 }
540 
541 
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)542 de::MovePtr<TopLevelAccelerationStructure> RayTracingBuildTestInstance::initTopAccelerationStructure (VkCommandBuffer											cmdBuffer,
543 																									  vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures)
544 {
545 	const DeviceInterface&						vkd			= m_context.getDeviceInterface();
546 	const VkDevice								device		= m_context.getDevice();
547 	Allocator&									allocator	= m_context.getDefaultAllocator();
548 	de::MovePtr<TopLevelAccelerationStructure>	result		= makeTopLevelAccelerationStructure();
549 
550 	result->setInstanceCount(bottomLevelAccelerationStructures.size());
551 
552 	for (size_t structNdx = 0; structNdx < bottomLevelAccelerationStructures.size(); ++structNdx)
553 		result->addInstance(bottomLevelAccelerationStructures[structNdx]);
554 
555 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
556 
557 	return result;
558 }
559 
initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,tcu::UVec2 & startPos)560 de::MovePtr<BottomLevelAccelerationStructure> RayTracingBuildTestInstance::initBottomAccelerationStructure (VkCommandBuffer	cmdBuffer,
561 																											tcu::UVec2&		startPos)
562 {
563 	const DeviceInterface&							vkd			= m_context.getDeviceInterface();
564 	const VkDevice									device		= m_context.getDevice();
565 	Allocator&										allocator	= m_context.getDefaultAllocator();
566 	de::MovePtr<BottomLevelAccelerationStructure>	result		= makeBottomLevelAccelerationStructure();
567 
568 	result->setGeometryCount(m_data.geometriesGroupCount);
569 
570 	for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
571 	{
572 		const float				z				= (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR) ? +1.0f : -1.0f;
573 		std::vector<tcu::Vec3>	geometryData;
574 
575 		geometryData.reserve(2u * m_data.squaresGroupCount);
576 
577 		for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
578 		{
579 			const deUint32	n	= m_data.width * startPos.y() + startPos.x();
580 			const float		x0	= float(startPos.x() + 0) / float(m_data.width);
581 			const float		y0	= float(startPos.y() + 0) / float(m_data.height);
582 			const float		x1	= float(startPos.x() + 1) / float(m_data.width);
583 			const float		y1	= float(startPos.y() + 1) / float(m_data.height);
584 			const deUint32	m	= (73 * (n + 1)) % (m_data.width * m_data.height);
585 
586 			geometryData.push_back(tcu::Vec3(x0, y0, z));
587 			geometryData.push_back(tcu::Vec3(x1, y1, z));
588 
589 			startPos.y() = m / m_data.width;
590 			startPos.x() = m % m_data.width;
591 		}
592 
593 		result->addGeometry(geometryData, false);
594 	}
595 
596 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
597 
598 	return result;
599 }
600 
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)601 vector<de::SharedPtr<BottomLevelAccelerationStructure> > RayTracingBuildTestInstance::initBottomAccelerationStructures (VkCommandBuffer	cmdBuffer)
602 {
603 	tcu::UVec2													startPos;
604 	vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
605 
606 	for (size_t instanceNdx = 0; instanceNdx < m_data.instancesGroupCount; ++instanceNdx)
607 	{
608 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure	= initBottomAccelerationStructure(cmdBuffer, startPos);
609 
610 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
611 	}
612 
613 	return result;
614 }
615 
runTest(void)616 de::MovePtr<BufferWithMemory> RayTracingBuildTestInstance::runTest (void)
617 {
618 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
619 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
620 	const VkDevice						device								= m_context.getDevice();
621 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
622 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
623 	const VkQueue						queue								= m_context.getUniversalQueue();
624 	Allocator&							allocator							= m_context.getDefaultAllocator();
625 	const VkFormat						format								= VK_FORMAT_R32_UINT;
626 	const deUint32						pixelCount							= m_data.width * m_data.height;
627 	const deUint32						shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
628 
629 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
630 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
631 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
632 																					.build(vkd, device);
633 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
634 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
635 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
636 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
637 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
638 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
639 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
640 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
641 
642 	const deUint32						callableGroups						= m_extraCallShaders + ((m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR) != 0 ? 1 : 0);
643 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
644 	const Move<VkPipeline>				pipeline							= makePipeline(rayTracingPipeline, *pipelineLayout);
645 	const de::MovePtr<BufferWithMemory>	raygenShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_raygenShaderGroup);
646 	const de::MovePtr<BufferWithMemory>	missShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_missShaderGroup);
647 	const de::MovePtr<BufferWithMemory>	hitShaderBindingTable				= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_hitShaderGroup);
648 	const de::MovePtr<BufferWithMemory>	callableShaderBindingTable			= createShaderBindingTable(vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_callableShaderGroup, callableGroups);
649 
650 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion		= raygenShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
651 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion		= missShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
652 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion			= hitShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
653 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion	= callableShaderBindingTable.get() != NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize * callableGroups) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
654 
655 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, format);
656 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
657 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
658 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
659 
660 	const VkBufferCreateInfo			bufferCreateInfo					= makeBufferCreateInfo(pixelCount*sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
661 	const VkImageSubresourceLayers		bufferImageSubresourceLayers		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
662 	const VkBufferImageCopy				bufferImageRegion					= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1u), bufferImageSubresourceLayers);
663 	de::MovePtr<BufferWithMemory>		buffer								= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
664 
665 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
666 
667 	const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
668 																				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
669 																				**image, imageSubresourceRange);
670 	const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
671 																				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
672 																				**image, imageSubresourceRange);
673 	const VkMemoryBarrier				postTraceMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
674 	const VkMemoryBarrier				postCopyMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
675 	const VkClearValue					clearValue							= makeClearValueColorU32(1000000u, 0u, 0u, 255u);
676 
677 	vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
678 	de::MovePtr<TopLevelAccelerationStructure>					topLevelAccelerationStructure;
679 
680 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
681 	{
682 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
683 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
684 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
685 
686 		bottomLevelAccelerationStructures = initBottomAccelerationStructures(*cmdBuffer);
687 		topLevelAccelerationStructure = initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
688 
689 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
690 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
691 		{
692 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
693 			DE_NULL,															//  const void*							pNext;
694 			1u,																	//  deUint32							accelerationStructureCount;
695 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
696 		};
697 
698 		DescriptorSetUpdateBuilder()
699 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
700 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
701 			.update(vkd, device);
702 
703 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
704 
705 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
706 
707 		cmdTraceRays(vkd,
708 			*cmdBuffer,
709 			&raygenShaderBindingTableRegion,
710 			&missShaderBindingTableRegion,
711 			&hitShaderBindingTableRegion,
712 			&callableShaderBindingTableRegion,
713 			m_data.width, m_data.height, 1);
714 
715 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
716 
717 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
718 
719 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
720 	}
721 	endCommandBuffer(vkd, *cmdBuffer);
722 
723 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
724 
725 	invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), pixelCount * sizeof(deUint32));
726 
727 	return buffer;
728 }
729 
checkSupportInInstance(void) const730 void RayTracingBuildTestInstance::checkSupportInInstance (void) const
731 {
732 	const InstanceInterface&				vki						= m_context.getInstanceInterface();
733 	const VkPhysicalDevice					physicalDevice			= m_context.getPhysicalDevice();
734 	const vk::VkPhysicalDeviceProperties&	properties				= m_context.getDeviceProperties();
735 	const deUint32							requiredAllocations		= 8u
736 																	+ TopLevelAccelerationStructure::getRequiredAllocationCount()
737 																	+ m_data.instancesGroupCount * BottomLevelAccelerationStructure::getRequiredAllocationCount();
738 	de::MovePtr<RayTracingProperties>		rayTracingProperties	= makeRayTracingProperties(vki, physicalDevice);
739 
740 	if (rayTracingProperties->getMaxPrimitiveCount() < m_data.squaresGroupCount)
741 		TCU_THROW(NotSupportedError, "Triangles required more than supported");
742 
743 	if (rayTracingProperties->getMaxGeometryCount() < m_data.geometriesGroupCount)
744 		TCU_THROW(NotSupportedError, "Geometries required more than supported");
745 
746 	if (rayTracingProperties->getMaxInstanceCount() < m_data.instancesGroupCount)
747 		TCU_THROW(NotSupportedError, "Instances required more than supported");
748 
749 	if (properties.limits.maxMemoryAllocationCount < requiredAllocations)
750 		TCU_THROW(NotSupportedError, "Test requires more allocations allowed");
751 }
752 
iterate(void)753 tcu::TestStatus RayTracingBuildTestInstance::iterate (void)
754 {
755 	checkSupportInInstance();
756 
757 	const de::MovePtr<BufferWithMemory>	buffer		= runTest();
758 	const deUint32*						bufferPtr	= (deUint32*)buffer->getAllocation().getHostPtr();
759 	deUint32							failures	= 0;
760 	deUint32							pos			= 0;
761 
762 	for (deUint32 y = 0; y < m_data.height; ++y)
763 	{
764 		for (deUint32 x = 0; x < m_data.width; ++x)
765 		{
766 			const deUint32	expectedValue	= pos + 1;
767 
768 			if (bufferPtr[pos] != expectedValue)
769 				failures++;
770 
771 			++pos;
772 		}
773 	}
774 
775 	if (failures == 0)
776 		return tcu::TestStatus::pass("Pass");
777 	else
778 		return tcu::TestStatus::fail("failures=" + de::toString(failures));
779 }
780 
781 }	// anonymous
createMemGuaranteeTests(tcu::TestContext & testCtx)782 tcu::TestCaseGroup*	createMemGuaranteeTests (tcu::TestContext& testCtx)
783 {
784 	static const struct
785 	{
786 		const char*				name;
787 		VkShaderStageFlagBits	stage;
788 	}
789 	stages[]
790 	{
791 		{ "rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR		},
792 		{ "chit", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR	},
793 		{ "sect", VK_SHADER_STAGE_INTERSECTION_BIT_KHR	},
794 		{ "miss", VK_SHADER_STAGE_MISS_BIT_KHR			},
795 		{ "call", VK_SHADER_STAGE_CALLABLE_BIT_KHR		},
796 	};
797 
798 	static const struct
799 	{
800 		const char*	name;
801 		TestType	testType;
802 	}
803 	testTypes[]
804 	{
805 		{ "inside",		TEST_TYPE_INSIDE_STAGE		},
806 		{ "between",	TEST_TYPE_BETWEEN_STAGES	},
807 	};
808 
809 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "memguarantee", "Ray tracing memory guarantee tests"));
810 
811 	for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
812 	{
813 		de::MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(testCtx, testTypes[testTypeNdx].name, ""));
814 
815 		for (size_t stagesNdx = 0; stagesNdx < DE_LENGTH_OF_ARRAY(stages); ++stagesNdx)
816 		{
817 			const deUint32	width					= 16u;
818 			const deUint32	height					= 16u;
819 			const deUint32	geometriesGroupCount	= 4;
820 			const deUint32	instancesGroupCount		= 8;
821 			const deUint32	squaresGroupCount		= width * height / geometriesGroupCount / instancesGroupCount;
822 			const CaseDef	caseDef					=
823 			{
824 				testTypes[testTypeNdx].testType,	//  TestType				testType;
825 				stages[stagesNdx].stage,			//  VkShaderStageFlagBits	stage;
826 				width,								//  deUint32				width;
827 				height,								//  deUint32				height;
828 				squaresGroupCount,					//  deUint32				squaresGroupCount;
829 				geometriesGroupCount,				//  deUint32				geometriesGroupCount;
830 				instancesGroupCount,				//  deUint32				instancesGroupCount;
831 			};
832 			const std::string	testName	= de::toString(stages[stagesNdx].name);
833 
834 			testTypeGroup->addChild(new RayTracingTestCase(testCtx, testName.c_str(), "", caseDef));
835 		}
836 
837 		group->addChild(testTypeGroup.release());
838 	}
839 
840 	return group.release();
841 }
842 
843 }	// RayTracing
844 }	// vkt
845