• 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 Pipeline Library Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingPipelineLibraryTests.hpp"
25 
26 #include <list>
27 #include <vector>
28 
29 #include "vkDefs.hpp"
30 
31 #include "vktTestCase.hpp"
32 #include "vktTestGroupUtil.hpp"
33 #include "vktCustomInstancesDevices.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBufferWithMemory.hpp"
39 #include "vkImageWithMemory.hpp"
40 #include "vkTypeUtil.hpp"
41 
42 #include "vkRayTracingUtil.hpp"
43 
44 #include "tcuCommandLine.hpp"
45 
46 namespace vkt
47 {
48 namespace RayTracing
49 {
50 namespace
51 {
52 using namespace vk;
53 using namespace vkt;
54 
55 static const VkFlags	ALL_RAY_TRACING_STAGES		= VK_SHADER_STAGE_RAYGEN_BIT_KHR
56 													| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
57 													| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
58 													| VK_SHADER_STAGE_MISS_BIT_KHR
59 													| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
60 													| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
61 
62 static const deUint32	RTPL_DEFAULT_SIZE			= 8u;
63 static const deUint32	RTPL_MAX_CHIT_SHADER_COUNT	= 16;
64 
65 struct LibraryConfiguration
66 {
67 	deInt32								pipelineShaders;
68 	std::vector<tcu::IVec2>				pipelineLibraries; // IVec2 = ( parentID, shaderCount )
69 };
70 
71 struct TestParams
72 {
73 	LibraryConfiguration				libraryConfiguration;
74 	bool								multithreadedCompilation;
75 	bool								pipelinesCreatedUsingDHO;
76 	deUint32							width;
77 	deUint32							height;
78 };
79 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)80 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
81 							 const VkPhysicalDevice		physicalDevice)
82 {
83 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
84 
85 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
86 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
87 }
88 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)89 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
90 									  const VkPhysicalDevice	physicalDevice)
91 {
92 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
93 
94 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
95 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
96 }
97 
makeImageCreateInfo(deUint32 width,deUint32 height,VkFormat format)98 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, VkFormat format)
99 {
100 	const VkImageCreateInfo			imageCreateInfo			=
101 	{
102 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
103 		DE_NULL,																							// const void*				pNext;
104 		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
105 		VK_IMAGE_TYPE_2D,																					// VkImageType				imageType;
106 		format,																								// VkFormat					format;
107 		makeExtent3D(width, height, 1),																		// VkExtent3D				extent;
108 		1u,																									// deUint32					mipLevels;
109 		1u,																									// deUint32					arrayLayers;
110 		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
111 		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
112 		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
113 		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
114 		0u,																									// deUint32					queueFamilyIndexCount;
115 		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
116 		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
117 	};
118 
119 	return imageCreateInfo;
120 }
121 
122 class RayTracingPipelineLibraryTestCase : public TestCase
123 {
124 	public:
125 							RayTracingPipelineLibraryTestCase	(tcu::TestContext& context, const char* name, const char* desc, const TestParams data);
126 							~RayTracingPipelineLibraryTestCase	(void);
127 
128 	virtual void			checkSupport								(Context& context) const;
129 	virtual	void			initPrograms								(SourceCollections& programCollection) const;
130 	virtual TestInstance*	createInstance								(Context& context) const;
131 private:
132 	TestParams				m_data;
133 };
134 
135 struct DeviceTestFeatures
136 {
137 	VkPhysicalDeviceRayTracingPipelineFeaturesKHR		rayTracingPipelineFeatures;
138 	VkPhysicalDeviceAccelerationStructureFeaturesKHR	accelerationStructureFeatures;
139 	VkPhysicalDeviceBufferDeviceAddressFeaturesKHR		deviceAddressFeatures;
140 	VkPhysicalDeviceFeatures2							deviceFeatures;
141 
linkStructuresvkt::RayTracing::__anonc13c59a90111::DeviceTestFeatures142 	void linkStructures ()
143 	{
144 		rayTracingPipelineFeatures.pNext	= nullptr;
145 		accelerationStructureFeatures.pNext	= &rayTracingPipelineFeatures;
146 		deviceAddressFeatures.pNext			= &accelerationStructureFeatures;
147 		deviceFeatures.pNext				= &deviceAddressFeatures;
148 	}
149 
DeviceTestFeaturesvkt::RayTracing::__anonc13c59a90111::DeviceTestFeatures150 	DeviceTestFeatures (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
151 	{
152 		rayTracingPipelineFeatures.sType	= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
153 		accelerationStructureFeatures.sType	= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
154 		deviceAddressFeatures.sType			= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
155 		deviceFeatures.sType				= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
156 
157 		linkStructures();
158 		vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
159 	}
160 };
161 
162 struct DeviceHelper
163 {
164 	Move<VkDevice>					device;
165 	de::MovePtr<DeviceDriver>		vkd;
166 	deUint32						queueFamilyIndex;
167 	VkQueue							queue;
168 	de::MovePtr<SimpleAllocator>	allocator;
169 
DeviceHelpervkt::RayTracing::__anonc13c59a90111::DeviceHelper170 	DeviceHelper (Context& context)
171 	{
172 		const auto&	vkp				= context.getPlatformInterface();
173 		const auto&	vki				= context.getInstanceInterface();
174 		const auto	instance		= context.getInstance();
175 		const auto	physicalDevice	= context.getPhysicalDevice();
176 		const auto	queuePriority	= 1.0f;
177 
178 		// Queue index first.
179 		queueFamilyIndex = context.getUniversalQueueFamilyIndex();
180 
181 		// Get device features (these have already been checked in the test case).
182 		DeviceTestFeatures features(vki, physicalDevice);
183 		features.linkStructures();
184 
185 		// Make sure robust buffer access is disabled as in the default device.
186 		features.deviceFeatures.features.robustBufferAccess = VK_FALSE;
187 
188 		const VkDeviceQueueCreateInfo queueInfo =
189 		{
190 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	//	VkStructureType				sType;
191 			nullptr,									//	const void*					pNext;
192 			0u,											//	VkDeviceQueueCreateFlags	flags;
193 			queueFamilyIndex,							//	deUint32					queueFamilyIndex;
194 			1u,											//	deUint32					queueCount;
195 			&queuePriority,								//	const float*				pQueuePriorities;
196 		};
197 
198 		// Required extensions.
199 		std::vector<const char*> requiredExtensions;
200 		requiredExtensions.push_back("VK_KHR_ray_tracing_pipeline");
201 		requiredExtensions.push_back("VK_KHR_pipeline_library");
202 		requiredExtensions.push_back("VK_KHR_acceleration_structure");
203 		requiredExtensions.push_back("VK_KHR_deferred_host_operations");
204 		requiredExtensions.push_back("VK_KHR_buffer_device_address");
205 		requiredExtensions.push_back("VK_EXT_descriptor_indexing");
206 		requiredExtensions.push_back("VK_KHR_spirv_1_4");
207 		requiredExtensions.push_back("VK_KHR_shader_float_controls");
208 
209 		const VkDeviceCreateInfo createInfo =
210 		{
211 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,				//	VkStructureType					sType;
212 			features.deviceFeatures.pNext,						//	const void*						pNext;
213 			0u,													//	VkDeviceCreateFlags				flags;
214 			1u,													//	deUint32						queueCreateInfoCount;
215 			&queueInfo,											//	const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
216 			0u,													//	deUint32						enabledLayerCount;
217 			nullptr,											//	const char* const*				ppEnabledLayerNames;
218 			static_cast<deUint32>(requiredExtensions.size()),	//	deUint32						enabledExtensionCount;
219 			requiredExtensions.data(),							//	const char* const*				ppEnabledExtensionNames;
220 			&features.deviceFeatures.features,					//	const VkPhysicalDeviceFeatures*	pEnabledFeatures;
221 		};
222 
223 		// Create custom device and related objects.
224 		device		= createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &createInfo);
225 		vkd			= de::MovePtr<DeviceDriver>(new DeviceDriver(vkp, instance, device.get()));
226 		queue		= getDeviceQueue(*vkd, *device, queueFamilyIndex, 0u);
227 		allocator	= de::MovePtr<SimpleAllocator>(new SimpleAllocator(*vkd, device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
228 	}
229 };
230 
231 class RayTracingPipelineLibraryTestInstance : public TestInstance
232 {
233 public:
234 																	RayTracingPipelineLibraryTestInstance	(Context& context, const TestParams& data);
235 																	~RayTracingPipelineLibraryTestInstance	(void);
236 	tcu::TestStatus													iterate									(void);
237 
238 protected:
239 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures		(DeviceHelper& deviceHelper, VkCommandBuffer cmdBuffer);
240 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure			(DeviceHelper& deviceHelper, VkCommandBuffer cmdBuffer,
241 																											 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures);
242 	de::MovePtr<BufferWithMemory>									runTest									(DeviceHelper& deviceHelper);
243 private:
244 	TestParams														m_data;
245 };
246 
247 
RayTracingPipelineLibraryTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams data)248 RayTracingPipelineLibraryTestCase::RayTracingPipelineLibraryTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data)
249 	: vkt::TestCase	(context, name, desc)
250 	, m_data		(data)
251 {
252 }
253 
~RayTracingPipelineLibraryTestCase(void)254 RayTracingPipelineLibraryTestCase::~RayTracingPipelineLibraryTestCase	(void)
255 {
256 }
257 
checkSupport(Context & context) const258 void RayTracingPipelineLibraryTestCase::checkSupport(Context& context) const
259 {
260 	const auto&	vki					= context.getInstanceInterface();
261 	const auto	physicalDevice		= context.getPhysicalDevice();
262 	const auto	supportedExtensions	= enumerateDeviceExtensionProperties(vki, physicalDevice, nullptr);
263 
264 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_ray_tracing_pipeline")))
265 		TCU_THROW(NotSupportedError, "VK_KHR_ray_tracing_pipeline not supported");
266 
267 	// VK_KHR_pipeline_library must be supported if the ray tracing pipeline extension is supported, which it should be at this point.
268 	// If it's not supported, this is considered a failure.
269 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_pipeline_library")))
270 		TCU_FAIL("VK_KHR_pipeline_library not supported but VK_KHR_ray_tracing_pipeline supported");
271 
272 	// VK_KHR_acceleration_structure is required by VK_KHR_ray_tracing_pipeline.
273 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_acceleration_structure")))
274 		TCU_FAIL("VK_KHR_acceleration_structure not supported but VK_KHR_ray_tracing_pipeline supported");
275 
276 	// VK_KHR_deferred_host_operations is required by VK_KHR_acceleration_structure.
277 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_deferred_host_operations")))
278 		TCU_FAIL("VK_KHR_deferred_host_operations not supported but VK_KHR_acceleration_structure supported");
279 
280 	// The same for VK_KHR_buffer_device_address.
281 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_buffer_device_address")))
282 		TCU_FAIL("VK_KHR_buffer_device_address not supported but VK_KHR_acceleration_structure supported");
283 
284 	// Get and check needed features.
285 	DeviceTestFeatures testFeatures (vki, physicalDevice);
286 
287 	if (!testFeatures.rayTracingPipelineFeatures.rayTracingPipeline)
288 		TCU_THROW(NotSupportedError, "Ray tracing pipelines not supported");
289 
290 	if (!testFeatures.accelerationStructureFeatures.accelerationStructure)
291 		TCU_THROW(NotSupportedError, "Acceleration structures not supported");
292 
293 	if (!testFeatures.deviceAddressFeatures.bufferDeviceAddress)
294 		TCU_FAIL("Acceleration structures supported but bufferDeviceAddress not supported");
295 }
296 
initPrograms(SourceCollections & programCollection) const297 void RayTracingPipelineLibraryTestCase::initPrograms (SourceCollections& programCollection) const
298 {
299 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
300 
301 	{
302 		std::stringstream css;
303 		css <<
304 			"#version 460 core\n"
305 			"#extension GL_EXT_ray_tracing : require\n"
306 			"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
307 			"layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
308 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
309 			"\n"
310 			"void main()\n"
311 			"{\n"
312 			"  float tmin     = 0.0;\n"
313 			"  float tmax     = 1.0;\n"
314 			"  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, float(gl_LaunchIDEXT.z + 0.5f));\n"
315 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
316 			"  hitValue       = uvec4(" << RTPL_MAX_CHIT_SHADER_COUNT+1 << ",0,0,0);\n"
317 			"  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
318 			"  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
319 			"}\n";
320 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
321 	}
322 
323 	{
324 		std::stringstream css;
325 		css <<
326 			"#version 460 core\n"
327 			"#extension GL_EXT_ray_tracing : require\n"
328 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
329 			"void main()\n"
330 			"{\n"
331 			"  hitValue = uvec4("<< RTPL_MAX_CHIT_SHADER_COUNT <<",0,0,1);\n"
332 			"}\n";
333 
334 		programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
335 	}
336 
337 	for(deUint32 i=0; i<RTPL_MAX_CHIT_SHADER_COUNT; ++i)
338 	{
339 		std::stringstream css;
340 		css <<
341 			"#version 460 core\n"
342 			"#extension GL_EXT_ray_tracing : require\n"
343 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
344 			"void main()\n"
345 			"{\n"
346 			"  hitValue = uvec4(" << i << ",0,0,1);\n"
347 			"}\n";
348 		std::stringstream csname;
349 		csname << "chit" << i;
350 		programCollection.glslSources.add(csname.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
351 	}
352 }
353 
createInstance(Context & context) const354 TestInstance* RayTracingPipelineLibraryTestCase::createInstance (Context& context) const
355 {
356 	return new RayTracingPipelineLibraryTestInstance(context, m_data);
357 }
358 
RayTracingPipelineLibraryTestInstance(Context & context,const TestParams & data)359 RayTracingPipelineLibraryTestInstance::RayTracingPipelineLibraryTestInstance (Context& context, const TestParams& data)
360 	: vkt::TestInstance		(context)
361 	, m_data				(data)
362 {
363 }
364 
~RayTracingPipelineLibraryTestInstance(void)365 RayTracingPipelineLibraryTestInstance::~RayTracingPipelineLibraryTestInstance (void)
366 {
367 }
368 
initBottomAccelerationStructures(DeviceHelper & deviceHelper,VkCommandBuffer cmdBuffer)369 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > RayTracingPipelineLibraryTestInstance::initBottomAccelerationStructures (DeviceHelper& deviceHelper, VkCommandBuffer cmdBuffer)
370 {
371 	const auto&														vkd			= *deviceHelper.vkd;
372 	const auto														device		= deviceHelper.device.get();
373 	auto&															allocator	= *deviceHelper.allocator;
374 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
375 
376 	tcu::Vec3 v0(0.0, 1.0, 0.0);
377 	tcu::Vec3 v1(0.0, 0.0, 0.0);
378 	tcu::Vec3 v2(1.0, 1.0, 0.0);
379 	tcu::Vec3 v3(1.0, 0.0, 0.0);
380 
381 	for (deUint32 y = 0; y < m_data.height; ++y)
382 	for (deUint32 x = 0; x < m_data.width; ++x)
383 	{
384 		// let's build a 3D chessboard of geometries
385 		if (((x + y) % 2) == 0)
386 			continue;
387 		tcu::Vec3 xyz((float)x, (float)y, 0.0f);
388 		std::vector<tcu::Vec3>	geometryData;
389 
390 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
391 		bottomLevelAccelerationStructure->setGeometryCount(1u);
392 
393 		geometryData.push_back(xyz + v0);
394 		geometryData.push_back(xyz + v1);
395 		geometryData.push_back(xyz + v2);
396 		geometryData.push_back(xyz + v2);
397 		geometryData.push_back(xyz + v1);
398 		geometryData.push_back(xyz + v3);
399 
400 		bottomLevelAccelerationStructure->addGeometry(geometryData, true);
401 		bottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
402 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
403 	}
404 
405 	return result;
406 }
407 
initTopAccelerationStructure(DeviceHelper & deviceHelper,VkCommandBuffer cmdBuffer,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)408 de::MovePtr<TopLevelAccelerationStructure> RayTracingPipelineLibraryTestInstance::initTopAccelerationStructure (DeviceHelper& deviceHelper, VkCommandBuffer cmdBuffer,
409 																												std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
410 {
411 	const auto&									vkd			= *deviceHelper.vkd;
412 	const auto									device		= deviceHelper.device.get();
413 	auto&										allocator	= *deviceHelper.allocator;
414 
415 	deUint32 instanceCount = m_data.width * m_data.height / 2;
416 
417 	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
418 	result->setInstanceCount(instanceCount);
419 
420 	deUint32 currentInstanceIndex	= 0;
421 	deUint32 numShadersUsed			= m_data.libraryConfiguration.pipelineShaders;
422 	for (auto it = begin(m_data.libraryConfiguration.pipelineLibraries), eit = end(m_data.libraryConfiguration.pipelineLibraries); it != eit; ++it)
423 		numShadersUsed += it->y();
424 
425 	for (deUint32 y = 0; y < m_data.height; ++y)
426 	for (deUint32 x = 0; x < m_data.width; ++x)
427 	{
428 		if (((x + y) % 2) == 0)
429 			continue;
430 		const VkTransformMatrixKHR			identityMatrix =
431 		{
432 			{								//  float	matrix[3][4];
433 				{ 1.0f, 0.0f, 0.0f, 0.0f },
434 				{ 0.0f, 1.0f, 0.0f, 0.0f },
435 				{ 0.0f, 0.0f, 1.0f, 0.0f },
436 			}
437 		};
438 
439 		result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex], identityMatrix, 0, 0xFF, currentInstanceIndex % numShadersUsed, 0U);
440 		currentInstanceIndex++;
441 	}
442 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
443 
444 	return result;
445 }
446 
compileShaders(DeviceHelper & deviceHelper,Context & context,de::SharedPtr<de::MovePtr<RayTracingPipeline>> & pipeline,const std::vector<std::tuple<std::string,VkShaderStageFlagBits>> & shaderData)447 void compileShaders (DeviceHelper& deviceHelper, Context& context, de::SharedPtr<de::MovePtr<RayTracingPipeline>>& pipeline, const std::vector<std::tuple<std::string, VkShaderStageFlagBits>>& shaderData)
448 {
449 	const auto&	vkd		= *deviceHelper.vkd;
450 	const auto	device	= deviceHelper.device.get();
451 
452 	for (deUint32 i=0; i< shaderData.size(); ++i)
453 	{
454 		std::string				shaderName;
455 		VkShaderStageFlagBits	shaderStage;
456 		std::tie(shaderName, shaderStage) = shaderData[i];
457 		pipeline->get()->addShader(shaderStage, createShaderModule(vkd, device, context.getBinaryCollection().get(shaderName), 0), i);
458 	}
459 }
460 
461 struct CompileShadersMultithreadData
462 {
463 	DeviceHelper&														deviceHelper;
464 	Context&															context;
465 	de::SharedPtr<de::MovePtr<RayTracingPipeline>>&						pipeline;
466 	const std::vector<std::tuple<std::string, VkShaderStageFlagBits>>&	shaderData;
467 };
468 
compileShadersThread(void * param)469 void compileShadersThread (void* param)
470 {
471 	CompileShadersMultithreadData* csmd = (CompileShadersMultithreadData*)param;
472 	compileShaders(csmd->deviceHelper, csmd->context, csmd->pipeline, csmd->shaderData);
473 }
474 
runTest(DeviceHelper & deviceHelper)475 de::MovePtr<BufferWithMemory> RayTracingPipelineLibraryTestInstance::runTest (DeviceHelper& deviceHelper)
476 {
477 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
478 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
479 	const auto&							vkd									= *deviceHelper.vkd;
480 	const auto							device								= deviceHelper.device.get();
481 	const auto							queueFamilyIndex					= deviceHelper.queueFamilyIndex;
482 	const auto							queue								= deviceHelper.queue;
483 	auto&								allocator							= *deviceHelper.allocator;
484 	const deUint32						pixelCount							= m_data.height * m_data.width;
485 	const deUint32						shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
486 	const deUint32						shaderGroupBaseAlignment			= getShaderGroupBaseAlignment(vki, physicalDevice);
487 
488 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
489 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
490 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
491 																					.build(vkd, device);
492 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
493 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
494 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
495 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
496 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
497 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
498 
499 	// sort pipeline library configurations ( including main pipeline )
500 	std::vector<std::tuple<int, deUint32, deUint32>> libraryList;
501 	{
502 		// push main pipeline on the list
503 		deUint32 shaderOffset	= 0U;
504 		libraryList.push_back(std::make_tuple(-1, shaderOffset, m_data.libraryConfiguration.pipelineShaders));
505 		shaderOffset			+= m_data.libraryConfiguration.pipelineShaders;
506 
507 		for (size_t i = 0; i < m_data.libraryConfiguration.pipelineLibraries.size(); ++i)
508 		{
509 			int parentIndex			= m_data.libraryConfiguration.pipelineLibraries[i].x();
510 			deUint32 shaderCount	= deUint32(m_data.libraryConfiguration.pipelineLibraries[i].y());
511 			if (parentIndex < 0 || parentIndex >= int(libraryList.size()) )
512 				TCU_THROW(InternalError, "Wrong library tree definition");
513 			libraryList.push_back(std::make_tuple(parentIndex, shaderOffset, shaderCount));
514 			shaderOffset			+= shaderCount;
515 		}
516 	}
517 
518 	// create pipeline libraries
519 	std::vector<de::SharedPtr<de::MovePtr<RayTracingPipeline>>>					pipelineLibraries(libraryList.size());
520 	std::vector<std::vector<std::tuple<std::string, VkShaderStageFlagBits>>>	pipelineShaders(libraryList.size());
521 	for (size_t idx=0; idx < libraryList.size(); ++idx)
522 	{
523 		int			parentIndex;
524 		deUint32	shaderCount, shaderOffset;
525 		std::tie(parentIndex, shaderOffset, shaderCount) = libraryList[idx];
526 
527 		// create pipeline objects
528 		de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipeline = makeVkSharedPtr(de::MovePtr<RayTracingPipeline>(new RayTracingPipeline));
529 
530 		(*pipeline)->setDeferredOperation(m_data.pipelinesCreatedUsingDHO);
531 
532 		// all pipelines are pipeline libraries, except for the main pipeline
533 		if(idx>0)
534 			pipeline->get()->setCreateFlags(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
535 		pipeline->get()->setMaxPayloadSize(16U); // because rayPayloadInEXT is uvec4 ( = 16 bytes ) for all chit shaders
536 		pipelineLibraries[idx] = pipeline;
537 
538 		// prepare all shader names for all pipelines
539 		if (idx == 0)
540 		{
541 			pipelineShaders[0].push_back(std::make_tuple( "rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR ));
542 			pipelineShaders[0].push_back(std::make_tuple( "miss", VK_SHADER_STAGE_MISS_BIT_KHR ));
543 		}
544 		for ( deUint32 i=0; i < shaderCount; ++i)
545 		{
546 			std::stringstream csname;
547 			csname << "chit" << shaderOffset + i;
548 			pipelineShaders[idx].push_back(std::make_tuple( csname.str(), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ));
549 		}
550 	}
551 	// singlethreaded / multithreaded compilation of all shaders
552 	if (m_data.multithreadedCompilation)
553 	{
554 		std::vector<CompileShadersMultithreadData> csmds;
555 		for (deUint32 i = 0; i < pipelineLibraries.size(); ++i)
556 			csmds.push_back(CompileShadersMultithreadData{ deviceHelper, m_context, pipelineLibraries[i], pipelineShaders[i] });
557 
558 		std::vector<deThread>	threads;
559 		for (deUint32 i = 0; i < csmds.size(); ++i)
560 			threads.push_back(deThread_create(compileShadersThread, (void*)&csmds[i], DE_NULL));
561 
562 		for (deUint32 i = 0; i < threads.size(); ++i)
563 		{
564 			deThread_join(threads[i]);
565 			deThread_destroy(threads[i]);
566 		}
567 	}
568 	else // m_data.multithreadedCompilation == false
569 	{
570 		for (deUint32 i = 0; i < pipelineLibraries.size(); ++i)
571 			compileShaders(deviceHelper, m_context, pipelineLibraries[i], pipelineShaders[i]);
572 	}
573 
574 	// connect libraries into a tree structure
575 	for (size_t idx = 0; idx < libraryList.size(); ++idx)
576 	{
577 		int			parentIndex;
578 		deUint32 shaderCount, shaderOffset;
579 		std::tie(parentIndex, shaderCount, shaderOffset) = libraryList[idx];
580 		if (parentIndex != -1)
581 			pipelineLibraries[parentIndex]->get()->addLibrary(pipelineLibraries[idx]);
582 	}
583 
584 	// build main pipeline and all pipeline libraries that it depends on
585 	std::vector<de::SharedPtr<Move<VkPipeline>>>	pipelines				= pipelineLibraries[0]->get()->createPipelineWithLibraries(vkd, device, *pipelineLayout);
586 	DE_ASSERT(pipelines.size() > 0);
587 	VkPipeline pipeline = pipelines[0]->get();
588 
589 	deUint32							numShadersUsed						= m_data.libraryConfiguration.pipelineShaders;
590 	for (auto it = begin(m_data.libraryConfiguration.pipelineLibraries), eit = end(m_data.libraryConfiguration.pipelineLibraries); it != eit; ++it)
591 		numShadersUsed += it->y();
592 
593 	// build shader binding tables
594 	const de::MovePtr<BufferWithMemory>	raygenShaderBindingTable			= pipelineLibraries[0]->get()->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
595 	const de::MovePtr<BufferWithMemory>	missShaderBindingTable				= pipelineLibraries[0]->get()->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
596 	const de::MovePtr<BufferWithMemory>	hitShaderBindingTable				= pipelineLibraries[0]->get()->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, numShadersUsed);
597 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
598 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
599 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, numShadersUsed * shaderGroupHandleSize);
600 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
601 
602 	const VkFormat						imageFormat							= VK_FORMAT_R32_UINT;
603 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
604 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
605 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
606 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
607 
608 	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(pixelCount*sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
609 	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
610 	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1), resultBufferImageSubresourceLayers);
611 	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
612 
613 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
614 
615 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
616 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
617 
618 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
619 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
620 
621 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
622 	{
623 		const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
624 																					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
625 																					**image, imageSubresourceRange);
626 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
627 
628 		const VkClearValue					clearValue							= makeClearValueColorU32(0xFF, 0u, 0u, 0u);
629 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
630 
631 		const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
632 																					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
633 																					**image, imageSubresourceRange);
634 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
635 
636 		bottomLevelAccelerationStructures	= initBottomAccelerationStructures(deviceHelper, *cmdBuffer);
637 		topLevelAccelerationStructure		= initTopAccelerationStructure(deviceHelper, *cmdBuffer, bottomLevelAccelerationStructures);
638 
639 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
640 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
641 		{
642 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
643 			DE_NULL,															//  const void*							pNext;
644 			1u,																	//  deUint32							accelerationStructureCount;
645 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
646 		};
647 
648 		DescriptorSetUpdateBuilder()
649 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
650 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
651 			.update(vkd, device);
652 
653 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
654 
655 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
656 
657 		cmdTraceRays(vkd,
658 			*cmdBuffer,
659 			&raygenShaderBindingTableRegion,
660 			&missShaderBindingTableRegion,
661 			&hitShaderBindingTableRegion,
662 			&callableShaderBindingTableRegion,
663 			m_data.width, m_data.height, 1);
664 
665 		const VkMemoryBarrier							postTraceMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
666 		const VkMemoryBarrier							postCopyMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
667 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
668 
669 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
670 
671 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
672 	}
673 	endCommandBuffer(vkd, *cmdBuffer);
674 
675 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
676 
677 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
678 
679 	return resultBuffer;
680 }
681 
iterate(void)682 tcu::TestStatus RayTracingPipelineLibraryTestInstance::iterate (void)
683 {
684 	// run test using arrays of pointers
685 	DeviceHelper						deviceHelper(m_context);
686 	const de::MovePtr<BufferWithMemory>	buffer		= runTest(deviceHelper);
687 	const deUint32*						bufferPtr	= (deUint32*)buffer->getAllocation().getHostPtr();
688 
689 	deUint32							failures		= 0;
690 	deUint32							pos				= 0;
691 	deUint32							shaderIdx		= 0;
692 	deUint32							numShadersUsed	= m_data.libraryConfiguration.pipelineShaders;
693 	for (auto it = begin(m_data.libraryConfiguration.pipelineLibraries), eit = end(m_data.libraryConfiguration.pipelineLibraries); it != eit; ++it)
694 		numShadersUsed += it->y();
695 
696 	// verify results
697 	for (deUint32 y = 0; y < m_data.height; ++y)
698 	for (deUint32 x = 0; x < m_data.width; ++x)
699 	{
700 		deUint32 expectedResult;
701 		if ((x + y) % 2)
702 		{
703 			expectedResult = shaderIdx % numShadersUsed;
704 			++shaderIdx;
705 		}
706 		else
707 			expectedResult = RTPL_MAX_CHIT_SHADER_COUNT;
708 
709 		if (bufferPtr[pos] != expectedResult)
710 			failures++;
711 		++pos;
712 	}
713 
714 	if (failures == 0)
715 		return tcu::TestStatus::pass("Pass");
716 	else
717 		return tcu::TestStatus::fail("Fail (failures=" + de::toString(failures) + ")");
718 }
719 
720 }	// anonymous
721 
addPipelineLibraryConfigurationsTests(tcu::TestCaseGroup * group)722 void addPipelineLibraryConfigurationsTests (tcu::TestCaseGroup* group)
723 {
724 	struct ThreadData
725 	{
726 		bool									multithreaded;
727 		bool									pipelinesCreatedUsingDHO;
728 		const char*								name;
729 	} threadData[] =
730 	{
731 		{ false,	false,	"singlethreaded_compilation"	},
732 		{ true,		false,	"multithreaded_compilation"		},
733 		{ true,		true,	"multithreaded_compilation_dho"	},
734 	};
735 
736 	struct LibraryConfigurationData
737 	{
738 		LibraryConfiguration		libraryConfiguration;
739 		const char*					name;
740 	} libraryConfigurationData[] =
741 	{
742 		{ {0, { { 0, 1 } } },								"s0_l1"			},	// 0 shaders in a main pipeline. 1 pipeline library with 1 shader
743 		{ {1, { { 0, 1 } } },								"s1_l1"			},	// 1 shader  in a main pipeline. 1 pipeline library with 1 shader
744 		{ {0, { { 0, 1 }, { 0, 1 } } },						"s0_l11"		},	// 0 shaders in a main pipeline. 2 pipeline libraries with 1 shader each
745 		{ {3, { { 0, 1 }, { 0, 1 } } },						"s3_l11"		},	// 3 shaders in a main pipeline. 2 pipeline libraries with 1 shader each
746 		{ {0, { { 0, 2 }, { 0, 3 } } },						"s0_l23"		},	// 0 shaders in a main pipeline. 2 pipeline libraries with 2 and 3 shaders respectively
747 		{ {2, { { 0, 2 }, { 0, 3 } } },						"s2_l23"		},	// 2 shaders in a main pipeline. 2 pipeline libraries with 2 and 3 shaders respectively
748 		{ {0, { { 0, 1 }, { 1, 1 } } },						"s0_l1_l1"		},	// 0 shaders in a main pipeline. 2 pipeline libraries with 1 shader each. Second library is a child of a first library
749 		{ {1, { { 0, 1 }, { 1, 1 } } },						"s1_l1_l1"		},	// 1 shader  in a main pipeline. 2 pipeline libraries with 1 shader each. Second library is a child of a first library
750 		{ {0, { { 0, 2 }, { 1, 3 } } },						"s0_l2_l3"		},	// 0 shaders in a main pipeline. 2 pipeline libraries with 2 and 3 shaders respectively. Second library is a child of a first library
751 		{ {3, { { 0, 2 }, { 1, 3 } } },						"s3_l2_l3"		},	// 3 shaders in a main pipeline. 2 pipeline libraries with 2 and 3 shaders respectively. Second library is a child of a first library
752 		{ {3, { { 0, 2 }, { 0, 3 }, { 0, 2 } } },			"s3_l232"		},	// 3 shaders in a main pipeline. 3 pipeline libraries with 2, 3 and 2 shaders respectively.
753 		{ {3, { { 0, 2 }, { 1, 2 }, { 1, 2 }, { 0, 2 } } },	"s3_l22_l22"	},	// 3 shaders in a main pipeline. 4 pipeline libraries with 2 shaders each. Second and third library is a child of a first library
754 	};
755 
756 	for (size_t threadNdx = 0; threadNdx < DE_LENGTH_OF_ARRAY(threadData); ++threadNdx)
757 	{
758 		de::MovePtr<tcu::TestCaseGroup> threadGroup(new tcu::TestCaseGroup(group->getTestContext(), threadData[threadNdx].name, ""));
759 
760 		for (size_t libConfigNdx = 0; libConfigNdx < DE_LENGTH_OF_ARRAY(libraryConfigurationData); ++libConfigNdx)
761 		{
762 			TestParams testParams
763 			{
764 				libraryConfigurationData[libConfigNdx].libraryConfiguration,
765 				threadData[threadNdx].multithreaded,
766 				threadData[threadNdx].pipelinesCreatedUsingDHO,
767 				RTPL_DEFAULT_SIZE,
768 				RTPL_DEFAULT_SIZE
769 			};
770 			threadGroup->addChild(new RayTracingPipelineLibraryTestCase(group->getTestContext(), libraryConfigurationData[libConfigNdx].name, "", testParams));
771 		}
772 		group->addChild(threadGroup.release());
773 	}
774 }
775 
createPipelineLibraryTests(tcu::TestContext & testCtx)776 tcu::TestCaseGroup*	createPipelineLibraryTests(tcu::TestContext& testCtx)
777 {
778 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pipeline_library", "Tests verifying pipeline libraries"));
779 
780 	addTestGroup(group.get(), "configurations", "Test different configurations of pipeline libraries", addPipelineLibraryConfigurationsTests);
781 
782 	return group.release();
783 }
784 
785 }	// RayTracing
786 
787 }	// vkt
788