• 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 Basic cmdTraceRays* tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingTraceRaysTests.hpp"
25 
26 #include "vkDefs.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 
38 #include "vkRayTracingUtil.hpp"
39 
40 namespace vkt
41 {
42 namespace RayTracing
43 {
44 namespace
45 {
46 using namespace vk;
47 using namespace vkt;
48 
49 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
50 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
51 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
52 												| VK_SHADER_STAGE_MISS_BIT_KHR
53 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
54 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
55 
56 constexpr deUint32		kClearColorValue	= 0xFFu;
57 constexpr deUint32		kHitColorValue		= 2u;
58 constexpr deUint32		kMissColorValue		= 1u;
59 
60 enum class TraceType
61 {
62 	DIRECT			= 0,
63 	INDIRECT_CPU	= 1,
64 	INDIRECT_GPU	= 2,
65 };
66 
67 struct TestParams
68 {
69 	TraceType						traceType;
70 	VkTraceRaysIndirectCommandKHR	traceDimensions;	// Note: to be used for both direct and indirect variants.
71 };
72 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)73 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
74 							 const VkPhysicalDevice		physicalDevice)
75 {
76 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
77 
78 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
79 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
80 }
81 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)82 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
83 									  const VkPhysicalDevice	physicalDevice)
84 {
85 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
86 
87 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
88 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
89 }
90 
isNullTrace(const VkTraceRaysIndirectCommandKHR & cmd)91 bool isNullTrace (const VkTraceRaysIndirectCommandKHR& cmd)
92 {
93 	return (cmd.width == 0u || cmd.height == 0u || cmd.depth == 0u);
94 }
95 
getImageExtent(const VkTraceRaysIndirectCommandKHR & cmd)96 VkExtent3D getImageExtent (const VkTraceRaysIndirectCommandKHR& cmd)
97 {
98 	return (isNullTrace(cmd) ? makeExtent3D(8u, 8u, 1u) : makeExtent3D(cmd.width, cmd.height, cmd.depth));
99 }
100 
makeImageCreateInfo(deUint32 width,deUint32 height,deUint32 depth,VkFormat format)101 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
102 {
103 	const VkImageCreateInfo			imageCreateInfo			=
104 	{
105 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
106 		DE_NULL,																							// const void*				pNext;
107 		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
108 		VK_IMAGE_TYPE_3D,																					// VkImageType				imageType;
109 		format,																								// VkFormat					format;
110 		makeExtent3D(width, height, depth),																	// VkExtent3D				extent;
111 		1u,																									// deUint32					mipLevels;
112 		1u,																									// deUint32					arrayLayers;
113 		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
114 		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
115 		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
116 		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
117 		0u,																									// deUint32					queueFamilyIndexCount;
118 		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
119 		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
120 	};
121 
122 	return imageCreateInfo;
123 }
124 
125 class RayTracingTraceRaysIndirectTestCase : public TestCase
126 {
127 	public:
128 							RayTracingTraceRaysIndirectTestCase		(tcu::TestContext& context, const char* name, const char* desc, const TestParams data);
129 							~RayTracingTraceRaysIndirectTestCase	(void);
130 
131 	virtual void			checkSupport								(Context& context) const;
132 	virtual	void			initPrograms								(SourceCollections& programCollection) const;
133 	virtual TestInstance*	createInstance								(Context& context) const;
134 private:
135 	TestParams				m_data;
136 };
137 
138 class RayTracingTraceRaysIndirectTestInstance : public TestInstance
139 {
140 public:
141 																	RayTracingTraceRaysIndirectTestInstance			(Context& context, const TestParams& data);
142 																	~RayTracingTraceRaysIndirectTestInstance		(void);
143 	tcu::TestStatus													iterate								(void);
144 
145 protected:
146 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(VkCommandBuffer												cmdBuffer);
147 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(VkCommandBuffer												cmdBuffer,
148 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures);
149 	de::MovePtr<BufferWithMemory>									runTest								();
150 private:
151 	TestParams														m_data;
152 	const VkExtent3D												m_imageExtent;
153 };
154 
155 
RayTracingTraceRaysIndirectTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams data)156 RayTracingTraceRaysIndirectTestCase::RayTracingTraceRaysIndirectTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data)
157 	: vkt::TestCase	(context, name, desc)
158 	, m_data		(data)
159 {
160 }
161 
~RayTracingTraceRaysIndirectTestCase(void)162 RayTracingTraceRaysIndirectTestCase::~RayTracingTraceRaysIndirectTestCase	(void)
163 {
164 }
165 
checkSupport(Context & context) const166 void RayTracingTraceRaysIndirectTestCase::checkSupport(Context& context) const
167 {
168 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
169 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
170 
171 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
172 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
173 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
174 
175 	if (rayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect == DE_FALSE)
176 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineTraceRaysIndirect");
177 
178 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
179 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
180 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
181 }
182 
initPrograms(SourceCollections & programCollection) const183 void RayTracingTraceRaysIndirectTestCase::initPrograms (SourceCollections& programCollection) const
184 {
185 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
186 	{
187 		std::stringstream css;
188 		css <<
189 			"#version 460 core\n"
190 			"struct TraceRaysIndirectCommand\n"
191 			"{\n"
192 			"	uint width;\n"
193 			"	uint height;\n"
194 			"	uint depth;\n"
195 			"};\n"
196 			"layout(binding = 0) uniform IndirectCommandsUBO\n"
197 			"{\n"
198 			"	TraceRaysIndirectCommand indirectCommands;\n"
199 			"} ubo;\n"
200 			"layout(binding = 1) buffer IndirectCommandsSBO\n"
201 			"{\n"
202 			"	TraceRaysIndirectCommand indirectCommands;\n"
203 			"};\n"
204 			"void main()\n"
205 			"{\n"
206 			"  indirectCommands.width  = ubo.indirectCommands.width;\n"
207 			"  indirectCommands.height = ubo.indirectCommands.height;\n"
208 			"  indirectCommands.depth  = ubo.indirectCommands.depth;\n"
209 			"}\n";
210 
211 		programCollection.glslSources.add("compute_indirect_command") << glu::ComputeSource(css.str()) << buildOptions;
212 	}
213 
214 	{
215 		std::stringstream css;
216 		css <<
217 			"#version 460 core\n"
218 			"#extension GL_EXT_ray_tracing : require\n"
219 			"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
220 			"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
221 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
222 			"\n"
223 			"void main()\n"
224 			"{\n"
225 			"  float tmin     = 0.0;\n"
226 			"  float tmax     = 1.0;\n"
227 			"  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, float(gl_LaunchIDEXT.z + 0.5f));\n"
228 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
229 			"  hitValue       = uvec4(0,0,0,0);\n"
230 			"  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
231 			"  imageStore(result, ivec3(gl_LaunchIDEXT), hitValue);\n"
232 			"}\n";
233 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
234 	}
235 
236 	{
237 		std::stringstream css;
238 		css <<
239 			"#version 460 core\n"
240 			"#extension GL_EXT_ray_tracing : require\n"
241 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
242 			"void main()\n"
243 			"{\n"
244 			"  hitValue = uvec4(" << kHitColorValue << ",0,0,1);\n"
245 			"}\n";
246 		programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
247 	}
248 
249 	{
250 		std::stringstream css;
251 		css <<
252 			"#version 460 core\n"
253 			"#extension GL_EXT_ray_tracing : require\n"
254 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
255 			"void main()\n"
256 			"{\n"
257 			"  hitValue = uvec4(" << kMissColorValue << ",0,0,1);\n"
258 			"}\n";
259 
260 		programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
261 	}
262 }
263 
createInstance(Context & context) const264 TestInstance* RayTracingTraceRaysIndirectTestCase::createInstance (Context& context) const
265 {
266 	return new RayTracingTraceRaysIndirectTestInstance(context, m_data);
267 }
268 
RayTracingTraceRaysIndirectTestInstance(Context & context,const TestParams & data)269 RayTracingTraceRaysIndirectTestInstance::RayTracingTraceRaysIndirectTestInstance (Context& context, const TestParams& data)
270 	: vkt::TestInstance		(context)
271 	, m_data				(data)
272 	, m_imageExtent			(getImageExtent(data.traceDimensions))
273 {
274 }
275 
~RayTracingTraceRaysIndirectTestInstance(void)276 RayTracingTraceRaysIndirectTestInstance::~RayTracingTraceRaysIndirectTestInstance (void)
277 {
278 }
279 
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)280 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > RayTracingTraceRaysIndirectTestInstance::initBottomAccelerationStructures (VkCommandBuffer cmdBuffer)
281 {
282 	const DeviceInterface&											vkd			= m_context.getDeviceInterface();
283 	const VkDevice													device		= m_context.getDevice();
284 	Allocator&														allocator	= m_context.getDefaultAllocator();
285 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
286 
287 	tcu::Vec3 v0(0.0, 1.0, 0.0);
288 	tcu::Vec3 v1(0.0, 0.0, 0.0);
289 	tcu::Vec3 v2(1.0, 1.0, 0.0);
290 	tcu::Vec3 v3(1.0, 0.0, 0.0);
291 
292 	for (deUint32 z = 0; z < m_imageExtent.depth; ++z)
293 	for (deUint32 y = 0; y < m_imageExtent.height; ++y)
294 	for (deUint32 x = 0; x < m_imageExtent.width; ++x)
295 	{
296 		// let's build a 3D chessboard of geometries
297 		if (((x + y + z) % 2) == 0)
298 			continue;
299 		tcu::Vec3 xyz((float)x, (float)y, (float)z);
300 		std::vector<tcu::Vec3>	geometryData;
301 
302 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
303 		bottomLevelAccelerationStructure->setGeometryCount(1u);
304 
305 		geometryData.push_back(xyz + v0);
306 		geometryData.push_back(xyz + v1);
307 		geometryData.push_back(xyz + v2);
308 		geometryData.push_back(xyz + v2);
309 		geometryData.push_back(xyz + v1);
310 		geometryData.push_back(xyz + v3);
311 
312 		bottomLevelAccelerationStructure->addGeometry(geometryData, true);
313 		bottomLevelAccelerationStructure->createAndBuild(vkd, device, cmdBuffer, allocator);
314 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
315 	}
316 
317 	return result;
318 }
319 
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)320 de::MovePtr<TopLevelAccelerationStructure> RayTracingTraceRaysIndirectTestInstance::initTopAccelerationStructure (VkCommandBuffer													cmdBuffer,
321 																													  std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures)
322 {
323 	const DeviceInterface&						vkd				= m_context.getDeviceInterface();
324 	const VkDevice								device			= m_context.getDevice();
325 	Allocator&									allocator		= m_context.getDefaultAllocator();
326 	const deUint32								instanceCount	= m_imageExtent.depth * m_imageExtent.height * m_imageExtent.width / 2;
327 
328 	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
329 	result->setInstanceCount(instanceCount);
330 
331 	deUint32 currentInstanceIndex = 0;
332 
333 	for (deUint32 z = 0; z < m_imageExtent.depth; ++z)
334 	for (deUint32 y = 0; y < m_imageExtent.height; ++y)
335 	for (deUint32 x = 0; x < m_imageExtent.width; ++x)
336 	{
337 		if (((x + y + z) % 2) == 0)
338 			continue;
339 		result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]);
340 	}
341 	result->createAndBuild(vkd, device, cmdBuffer, allocator);
342 
343 	return result;
344 }
345 
runTest()346 de::MovePtr<BufferWithMemory> RayTracingTraceRaysIndirectTestInstance::runTest()
347 {
348 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
349 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
350 	const VkDevice						device								= m_context.getDevice();
351 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
352 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
353 	const VkQueue						queue								= m_context.getUniversalQueue();
354 	Allocator&							allocator							= m_context.getDefaultAllocator();
355 	const deUint32						pixelCount							= m_imageExtent.depth * m_imageExtent.height * m_imageExtent.width;
356 	const deUint32						shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
357 	const deUint32						shaderGroupBaseAlignment			= getShaderGroupBaseAlignment(vki, physicalDevice);
358 
359 	Move<VkDescriptorSetLayout>			computeDescriptorSetLayout;
360 	Move<VkDescriptorPool>				computeDescriptorPool;
361 	Move<VkDescriptorSet>				computeDescriptorSet;
362 	Move<VkPipelineLayout>				computePipelineLayout;
363 	Move<VkShaderModule>				computeShader;
364 	Move<VkPipeline>					computePipeline;
365 
366 	if (m_data.traceType == TraceType::INDIRECT_GPU)
367 	{
368 		computeDescriptorSetLayout			= DescriptorSetLayoutBuilder()
369 													.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
370 													.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
371 													.build(vkd, device);
372 		computeDescriptorPool				= DescriptorPoolBuilder()
373 													.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
374 													.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
375 													.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
376 		computeDescriptorSet				= makeDescriptorSet(vkd, device, *computeDescriptorPool, *computeDescriptorSetLayout);
377 		computePipelineLayout				= makePipelineLayout(vkd, device, computeDescriptorSetLayout.get());
378 
379 		computeShader						= createShaderModule(vkd, device, m_context.getBinaryCollection().get("compute_indirect_command"), 0);
380 		const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
381 		{
382 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
383 			DE_NULL,												// const void*							pNext;
384 			VkPipelineShaderStageCreateFlags(0u),					// VkPipelineShaderStageCreateFlags		flags;
385 			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
386 			*computeShader,											// VkShaderModule						module;
387 			"main",													// const char*							pName;
388 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
389 		};
390 		const VkComputePipelineCreateInfo pipelineCreateInfo =
391 		{
392 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
393 			DE_NULL,											// const void*						pNext;
394 			VkPipelineCreateFlags(0u),							// VkPipelineCreateFlags			flags;
395 			pipelineShaderStageParams,							// VkPipelineShaderStageCreateInfo	stage;
396 			*computePipelineLayout,								// VkPipelineLayout					layout;
397 			DE_NULL,											// VkPipeline						basePipelineHandle;
398 			0,													// deInt32							basePipelineIndex;
399 		};
400 
401 		computePipeline = vk::createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo);
402 	}
403 
404 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
405 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
406 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
407 																					.build(vkd, device);
408 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
409 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
410 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
411 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
412 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
413 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
414 
415 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
416 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0), 0);
417 	rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0), 1);
418 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0), 2);
419 	Move<VkPipeline>					pipeline							= rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
420 
421 	const de::MovePtr<BufferWithMemory>	raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
422 	const de::MovePtr<BufferWithMemory>	hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
423 	const de::MovePtr<BufferWithMemory>	missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
424 
425 	const VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
426 	const VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
427 	const VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
428 	const VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
429 
430 	const VkFormat						imageFormat							= VK_FORMAT_R32_UINT;
431 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, imageFormat);
432 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
433 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
434 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
435 
436 	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(pixelCount*sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
437 	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
438 	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(m_imageExtent, resultBufferImageSubresourceLayers);
439 	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
440 
441 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
442 
443 	// create indirect command buffer and fill it with parameter values
444 	de::MovePtr<BufferWithMemory>		indirectBuffer;
445 	de::MovePtr<BufferWithMemory>		uniformBuffer;
446 
447 	if (m_data.traceType != TraceType::DIRECT)
448 	{
449 		const bool							indirectGpu							= (m_data.traceType == TraceType::INDIRECT_GPU);
450 		VkBufferUsageFlags					indirectBufferUsageFlags			= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | ( indirectGpu ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT );
451 		const VkBufferCreateInfo			indirectBufferCreateInfo			= makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommandKHR), indirectBufferUsageFlags);
452 		vk::MemoryRequirement				indirectBufferMemoryRequirement		= MemoryRequirement::DeviceAddress | ( indirectGpu ? MemoryRequirement::Any : MemoryRequirement::HostVisible );
453 		indirectBuffer															= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, indirectBufferCreateInfo, indirectBufferMemoryRequirement));
454 	}
455 
456 	if (m_data.traceType == TraceType::INDIRECT_GPU)
457 	{
458 		const VkBufferCreateInfo			uniformBufferCreateInfo			= makeBufferCreateInfo(sizeof(VkTraceRaysIndirectCommandKHR), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
459 		uniformBuffer														= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
460 		deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions, sizeof(VkTraceRaysIndirectCommandKHR));
461 		flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(), uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
462 	}
463 	else if (m_data.traceType == TraceType::INDIRECT_CPU)
464 	{
465 		deMemcpy(indirectBuffer->getAllocation().getHostPtr(), &m_data.traceDimensions, sizeof(VkTraceRaysIndirectCommandKHR));
466 		flushMappedMemoryRange(vkd, device, indirectBuffer->getAllocation().getMemory(), indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
467 	}
468 
469 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
470 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
471 
472 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
473 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
474 
475 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
476 	{
477 		const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
478 																					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
479 																					**image, imageSubresourceRange);
480 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
481 
482 		const VkClearValue					clearValue							= makeClearValueColorU32(kClearColorValue, 0u, 0u, 0u);
483 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
484 
485 		const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
486 																					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
487 																					**image, imageSubresourceRange);
488 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
489 
490 		bottomLevelAccelerationStructures	= initBottomAccelerationStructures(*cmdBuffer);
491 		topLevelAccelerationStructure		= initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
492 
493 		if (m_data.traceType == TraceType::INDIRECT_GPU)
494 		{
495 			const VkDescriptorBufferInfo	uniformBufferDescriptorInfo		= makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
496 			const VkDescriptorBufferInfo	indirectBufferDescriptorInfo	= makeDescriptorBufferInfo(indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
497 			DescriptorSetUpdateBuilder()
498 				.writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferDescriptorInfo)
499 				.writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectBufferDescriptorInfo)
500 				.update(vkd, device);
501 
502 			vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
503 			vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &computeDescriptorSet.get(), 0u, DE_NULL);
504 			vkd.cmdDispatch(*cmdBuffer, 1, 1, 1);
505 
506 			const VkBufferMemoryBarrier		fillIndirectBufferMemoryBarrier	= makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
507 																				indirectBuffer->get(), 0ull, sizeof(VkTraceRaysIndirectCommandKHR));
508 			cmdPipelineBufferMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, &fillIndirectBufferMemoryBarrier);
509 		}
510 
511 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
512 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
513 		{
514 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
515 			DE_NULL,															//  const void*							pNext;
516 			1u,																	//  deUint32							accelerationStructureCount;
517 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
518 		};
519 
520 		DescriptorSetUpdateBuilder()
521 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
522 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
523 			.update(vkd, device);
524 
525 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
526 
527 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
528 
529 		// Both calls should give the same results.
530 		if (m_data.traceType == TraceType::DIRECT)
531 		{
532 			cmdTraceRays(vkd,
533 				*cmdBuffer,
534 				&raygenShaderBindingTableRegion,
535 				&missShaderBindingTableRegion,
536 				&hitShaderBindingTableRegion,
537 				&callableShaderBindingTableRegion,
538 				m_data.traceDimensions.width, m_data.traceDimensions.height, m_data.traceDimensions.depth);
539 		}
540 		else
541 		{
542 			cmdTraceRaysIndirect(vkd,
543 				*cmdBuffer,
544 				&raygenShaderBindingTableRegion,
545 				&missShaderBindingTableRegion,
546 				&hitShaderBindingTableRegion,
547 				&callableShaderBindingTableRegion,
548 				getBufferDeviceAddress(vkd, device, indirectBuffer->get(), 0));
549 		}
550 
551 		const VkMemoryBarrier							postTraceMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
552 		const VkMemoryBarrier							postCopyMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
553 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
554 
555 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
556 
557 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
558 	}
559 	endCommandBuffer(vkd, *cmdBuffer);
560 
561 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
562 
563 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
564 
565 	return resultBuffer;
566 }
567 
iterate(void)568 tcu::TestStatus RayTracingTraceRaysIndirectTestInstance::iterate (void)
569 {
570 	// run test using arrays of pointers
571 	const de::MovePtr<BufferWithMemory>	buffer		= runTest();
572 	const deUint32*						bufferPtr	= (deUint32*)buffer->getAllocation().getHostPtr();
573 	const bool							noWrites	= isNullTrace(m_data.traceDimensions);
574 
575 	deUint32							failures		= 0;
576 	deUint32							pos				= 0;
577 
578 	// verify results
579 	for (deUint32 z = 0; z < m_imageExtent.depth; ++z)
580 	for (deUint32 y = 0; y < m_imageExtent.height; ++y)
581 	for (deUint32 x = 0; x < m_imageExtent.width; ++x)
582 	{
583 		const deUint32 expectedResult = (noWrites ? kClearColorValue : (((x + y + z) % 2) ? kHitColorValue : kMissColorValue));
584 		if (bufferPtr[pos] != expectedResult)
585 			failures++;
586 		++pos;
587 	}
588 
589 	if (failures == 0)
590 		return tcu::TestStatus::pass("Pass");
591 	else
592 		return tcu::TestStatus::fail("Fail (failures=" + de::toString(failures) + ")");
593 }
594 
makeDimensionsName(const VkTraceRaysIndirectCommandKHR & cmd)595 std::string makeDimensionsName (const VkTraceRaysIndirectCommandKHR& cmd)
596 {
597 	std::ostringstream name;
598 	name << cmd.width << "_" << cmd.height << "_" << cmd.depth;
599 	return name.str();
600 }
601 
602 }	// anonymous
603 
createTraceRaysTests(tcu::TestContext & testCtx)604 tcu::TestCaseGroup*	createTraceRaysTests(tcu::TestContext& testCtx)
605 {
606 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "trace_rays_cmds", "Tests veryfying vkCmdTraceRays* commands"));
607 
608 	struct BufferSourceTypeData
609 	{
610 		TraceType								traceType;
611 		const char*								name;
612 	} bufferSourceTypes[] =
613 	{
614 		{ TraceType::DIRECT,		"direct"			},
615 		{ TraceType::INDIRECT_CPU,	"indirect_cpu"		},
616 		{ TraceType::INDIRECT_GPU,	"indirect_gpu"		},
617 	};
618 
619 	const VkTraceRaysIndirectCommandKHR traceDimensions[] =
620 	{
621 		{  0,  0, 0 },
622 		{  0,  1, 1 },
623 		{  1,  0, 1 },
624 		{  1,  1, 0 },
625 		{  8,  1, 1 },
626 		{  8,  8, 1 },
627 		{  8,  8, 8 },
628 		{ 11,  1, 1 },
629 		{ 11, 13, 1 },
630 		{ 11, 13, 5 },
631 	};
632 
633 	for (size_t bufferSourceNdx = 0; bufferSourceNdx < DE_LENGTH_OF_ARRAY(bufferSourceTypes); ++bufferSourceNdx)
634 	{
635 		de::MovePtr<tcu::TestCaseGroup> bufferSourceGroup(new tcu::TestCaseGroup(group->getTestContext(), bufferSourceTypes[bufferSourceNdx].name, ""));
636 
637 		for (size_t traceDimensionsIdx = 0; traceDimensionsIdx < DE_LENGTH_OF_ARRAY(traceDimensions); ++traceDimensionsIdx)
638 		{
639 			TestParams testParams
640 			{
641 				bufferSourceTypes[bufferSourceNdx].traceType,
642 				traceDimensions[traceDimensionsIdx],
643 			};
644 			const auto testName = makeDimensionsName(traceDimensions[traceDimensionsIdx]);
645 			bufferSourceGroup->addChild(new RayTracingTraceRaysIndirectTestCase(group->getTestContext(), testName.c_str(), "", testParams));
646 		}
647 
648 		group->addChild(bufferSourceGroup.release());
649 	}
650 
651 	return group.release();
652 }
653 
654 }	// RayTracing
655 
656 }	// vkt
657