• 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 Testing traversal control in ray tracing shaders
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingTraversalControlTests.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 #include "vkImageUtil.hpp"
38 #include "deRandom.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuImageCompare.hpp"
43 
44 #include "vkRayTracingUtil.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 enum HitShaderTestType
63 {
64 	HSTT_ISECT_REPORT_INTERSECTION		= 0,
65 	HSTT_ISECT_DONT_REPORT_INTERSECTION	= 1,
66 	HSTT_AHIT_PASS_THROUGH				= 2,
67 	HSTT_AHIT_IGNORE_INTERSECTION		= 3,
68 	HSTT_AHIT_TERMINATE_RAY				= 4,
69 	HSTT_COUNT
70 };
71 
72 enum BottomTestType
73 {
74 	BTT_TRIANGLES,
75 	BTT_AABBS
76 };
77 
78 const deUint32			TEST_WIDTH			= 8;
79 const deUint32			TEST_HEIGHT			= 8;
80 
81 struct TestParams;
82 
83 class TestConfiguration
84 {
85 public:
86 	virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
87 																												 TestParams&						testParams) = 0;
88 	virtual de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
89 																												 TestParams&						testParams,
90 																												 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) = 0;
91 	virtual void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
92 																												 Context&							context,
93 																												TestParams&							testParams) = 0;
94 	virtual void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
95 																												 Context&							context,
96 																												 TestParams&						testParams,
97 																												 VkPipeline							pipeline,
98 																												 deUint32							shaderGroupHandleSize,
99 																												 deUint32							shaderGroupBaseAlignment,
100 																												 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
101 																												 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
102 																												 de::MovePtr<BufferWithMemory>&		missShaderBindingTable,
103 																												 de::MovePtr<BufferWithMemory>&		callableShaderBindingTable,
104 																												 VkStridedDeviceAddressRegionKHR&	raygenShaderBindingTableRegion,
105 																												 VkStridedDeviceAddressRegionKHR&	hitShaderBindingTableRegion,
106 																												 VkStridedDeviceAddressRegionKHR&	missShaderBindingTableRegion,
107 																												 VkStridedDeviceAddressRegionKHR&	callableShaderBindingTableRegion) = 0;
108 	virtual bool															verifyImage							(BufferWithMemory*					resultBuffer,
109 																												 Context&							context,
110 																												 TestParams&						testParams) = 0;
111 	virtual VkFormat														getResultImageFormat				() = 0;
112 	virtual size_t															getResultImageFormatSize			() = 0;
113 	virtual VkClearValue													getClearValue						() = 0;
114 };
115 
116 struct TestParams
117 {
118 	deUint32							width;
119 	deUint32							height;
120 	HitShaderTestType					hitShaderTestType;
121 	BottomTestType						bottomType;
122 	de::SharedPtr<TestConfiguration>	testConfiguration;
123 
124 };
125 
getShaderGroupHandleSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)126 deUint32 getShaderGroupHandleSize (const InstanceInterface&	vki,
127 								   const VkPhysicalDevice	physicalDevice)
128 {
129 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
130 
131 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
132 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
133 }
134 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)135 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
136 									  const VkPhysicalDevice	physicalDevice)
137 {
138 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
139 
140 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
141 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
142 }
143 
makeImageCreateInfo(deUint32 width,deUint32 height,deUint32 depth,VkFormat format)144 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
145 {
146 	const VkImageCreateInfo			imageCreateInfo			=
147 	{
148 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
149 		DE_NULL,																							// const void*				pNext;
150 		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
151 		VK_IMAGE_TYPE_3D,																					// VkImageType				imageType;
152 		format,																								// VkFormat					format;
153 		makeExtent3D(width, height, depth),																	// VkExtent3D				extent;
154 		1u,																									// deUint32					mipLevels;
155 		1u,																									// deUint32					arrayLayers;
156 		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
157 		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
158 		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
159 		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
160 		0u,																									// deUint32					queueFamilyIndexCount;
161 		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
162 		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
163 	};
164 
165 	return imageCreateInfo;
166 }
167 
168 class SingleSquareConfiguration : public TestConfiguration
169 {
170 public:
171 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
172 																										 TestParams&						testParams) override;
173 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
174 																										 TestParams&						testParams,
175 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
176 	void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
177 																										 Context&							context,
178 																										 TestParams&						testParams) override;
179 	void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
180 																										 Context&							context,
181 																										 TestParams&						testParams,
182 																										 VkPipeline							pipeline,
183 																										 deUint32							shaderGroupHandleSize,
184 																										 deUint32							shaderGroupBaseAlignment,
185 																										 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
186 																										 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
187 																										 de::MovePtr<BufferWithMemory>&		missShaderBindingTable,
188 																										 de::MovePtr<BufferWithMemory>&		callableShaderBindingTable,
189 																										 VkStridedDeviceAddressRegionKHR&	raygenShaderBindingTableRegion,
190 																										 VkStridedDeviceAddressRegionKHR&	hitShaderBindingTableRegion,
191 																										 VkStridedDeviceAddressRegionKHR&	missShaderBindingTableRegion,
192 																										 VkStridedDeviceAddressRegionKHR&	callableShaderBindingTableRegion) override;
193 	bool															verifyImage							(BufferWithMemory*					resultBuffer,
194 																										 Context&							context,
195 																										 TestParams&						testParams) override;
196 	VkFormat														getResultImageFormat				() override;
197 	size_t															getResultImageFormatSize			() override;
198 	VkClearValue													getClearValue						() override;
199 };
200 
initBottomAccelerationStructures(Context & context,TestParams & testParams)201 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > SingleSquareConfiguration::initBottomAccelerationStructures (Context&			context,
202 																														   TestParams&		testParams)
203 {
204 	DE_UNREF(context);
205 
206 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
207 	de::MovePtr<BottomLevelAccelerationStructure>					bottomLevelAccelerationStructure	= makeBottomLevelAccelerationStructure();
208 	bottomLevelAccelerationStructure->setGeometryCount(1);
209 
210 	de::SharedPtr<RaytracedGeometryBase> geometry;
211 	if (testParams.bottomType == BTT_TRIANGLES)
212 	{
213 		tcu::Vec3 v0(1.0f, float(testParams.height) - 1.0f, 0.0f);
214 		tcu::Vec3 v1(1.0f, 1.0f, 0.0f);
215 		tcu::Vec3 v2(float(testParams.width) - 1.0f, float(testParams.height) - 1.0f, 0.0f);
216 		tcu::Vec3 v3(float(testParams.width) - 1.0f, 1.0f, 0.0f);
217 
218 		geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
219 		geometry->addVertex(v0);
220 		geometry->addVertex(v1);
221 		geometry->addVertex(v2);
222 		geometry->addVertex(v2);
223 		geometry->addVertex(v1);
224 		geometry->addVertex(v3);
225 	}
226 	else // testParams.bottomType != BTT_TRIANGLES
227 	{
228 		tcu::Vec3 v0(1.0f, 1.0f, -0.1f);
229 		tcu::Vec3 v1(float(testParams.width) - 1.0f, float(testParams.height) - 1.0f, 0.1f);
230 
231 		geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
232 		geometry->addVertex(v0);
233 		geometry->addVertex(v1);
234 	}
235 	bottomLevelAccelerationStructure->addGeometry(geometry);
236 
237 	result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
238 
239 	return result;
240 }
241 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)242 de::MovePtr<TopLevelAccelerationStructure> SingleSquareConfiguration::initTopAccelerationStructure (Context&		context,
243 																									TestParams&		testParams,
244 																									std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
245 {
246 	DE_UNREF(context);
247 	DE_UNREF(testParams);
248 
249 	de::MovePtr<TopLevelAccelerationStructure>	result	= makeTopLevelAccelerationStructure();
250 	result->setInstanceCount(1);
251 	result->addInstance(bottomLevelAccelerationStructures[0]);
252 
253 	return result;
254 }
255 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)256 void SingleSquareConfiguration::initRayTracingShaders (de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
257 													   Context&								context,
258 													   TestParams&							testParams)
259 {
260 	const DeviceInterface&						vkd						= context.getDeviceInterface();
261 	const VkDevice								device					= context.getDevice();
262 
263 	const std::vector<std::vector<std::string>> shaderNames =
264 	{
265 		{	"rgen",	"isect_report",			"ahit",					"chit",	"miss" },
266 		{	"rgen",	"isect_pass_through",	"ahit",					"chit",	"miss" },
267 		{	"rgen",	"isect_report",			"ahit_pass_through",	"chit",	"miss" },
268 		{	"rgen",	"isect_report",			"ahit_ignore",			"chit",	"miss" },
269 		{	"rgen",	"isect_report",			"ahit_terminate",		"chit",	"miss" },
270 	};
271 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(shaderNames[testParams.hitShaderTestType][0]), 0), 0);
272 	if(testParams.bottomType == BTT_AABBS)
273 		rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(shaderNames[testParams.hitShaderTestType][1]), 0), 1);
274 	rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get(shaderNames[testParams.hitShaderTestType][2]), 0), 1);
275 	rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get(shaderNames[testParams.hitShaderTestType][3]), 0), 1);
276 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, context.getBinaryCollection().get(shaderNames[testParams.hitShaderTestType][4]), 0), 2);
277 }
278 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams,VkPipeline pipeline,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,de::MovePtr<BufferWithMemory> & raygenShaderBindingTable,de::MovePtr<BufferWithMemory> & hitShaderBindingTable,de::MovePtr<BufferWithMemory> & missShaderBindingTable,de::MovePtr<BufferWithMemory> & callableShaderBindingTable,VkStridedDeviceAddressRegionKHR & raygenShaderBindingTableRegion,VkStridedDeviceAddressRegionKHR & hitShaderBindingTableRegion,VkStridedDeviceAddressRegionKHR & missShaderBindingTableRegion,VkStridedDeviceAddressRegionKHR & callableShaderBindingTableRegion)279 void SingleSquareConfiguration::initShaderBindingTables (de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
280 														 Context&							context,
281 														 TestParams&						testParams,
282 														 VkPipeline							pipeline,
283 														 deUint32							shaderGroupHandleSize,
284 														 deUint32							shaderGroupBaseAlignment,
285 														 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
286 														 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
287 														 de::MovePtr<BufferWithMemory>&		missShaderBindingTable,
288 														 de::MovePtr<BufferWithMemory>&		callableShaderBindingTable,
289 														 VkStridedDeviceAddressRegionKHR&	raygenShaderBindingTableRegion,
290 														 VkStridedDeviceAddressRegionKHR&	hitShaderBindingTableRegion,
291 														 VkStridedDeviceAddressRegionKHR&	missShaderBindingTableRegion,
292 														 VkStridedDeviceAddressRegionKHR&	callableShaderBindingTableRegion)
293 {
294 	DE_UNREF(testParams);
295 	DE_UNREF(callableShaderBindingTable);
296 
297 	const DeviceInterface&	vkd			= context.getDeviceInterface();
298 	const VkDevice			device		= context.getDevice();
299 	Allocator&				allocator	= context.getDefaultAllocator();
300 
301 	raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
302 	hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
303 	missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
304 
305 	raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
306 	hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
307 	missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
308 	callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
309 }
310 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)311 bool SingleSquareConfiguration::verifyImage (BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
312 {
313 	// create result image
314 	tcu::TextureFormat			imageFormat						= vk::mapVkFormat(getResultImageFormat());
315 	tcu::ConstPixelBufferAccess	resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
316 
317 	// create reference image
318 	std::vector<deUint32>		reference(testParams.width * testParams.height * 2);
319 	tcu::PixelBufferAccess		referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
320 
321 	// clear reference image with hit and miss values
322 	// Reference image has two layers:
323 	//   - ahit shader writes results to layer 0
324 	//   - chit shader writes results to layer 1
325 	//   - miss shader writes results to layer 0
326 	//   - rays that missed on layer 0 - should have value 0 on layer 1
327 	tcu::UVec4 missValue0 = tcu::UVec4(4, 0, 0, 0);
328 	tcu::UVec4 missValue1 = tcu::UVec4(0, 0, 0, 0);
329 	tcu::UVec4 hitValue0, hitValue1;
330 	switch (testParams.hitShaderTestType)
331 	{
332 		case HSTT_ISECT_REPORT_INTERSECTION:
333 			hitValue0	= tcu::UVec4(1, 0, 0, 0);	// ahit returns 1
334 			hitValue1	= tcu::UVec4(3, 0, 0, 0);	// chit returns 3
335 			break;
336 		case HSTT_ISECT_DONT_REPORT_INTERSECTION:
337 			hitValue0	= missValue0;				// no ahit - results should report miss value
338 			hitValue1	= missValue1;				// no chit - results should report miss value
339 			break;
340 		case HSTT_AHIT_PASS_THROUGH:
341 			hitValue0	= tcu::UVec4(0, 0, 0, 0);	// empty ahit shader. Initial value from rgen written to result
342 			hitValue1	= tcu::UVec4(3, 0, 0, 0);	// chit returns 3
343 			break;
344 		case HSTT_AHIT_IGNORE_INTERSECTION:
345 			hitValue0	= missValue0;				// ahit ignores intersection - results should report miss value
346 			hitValue1	= missValue1;				// no chit - results should report miss value
347 			break;
348 		case HSTT_AHIT_TERMINATE_RAY:
349 			hitValue0	= tcu::UVec4(1, 0, 0, 0);	// ahit should return 1. If it returned 2, then terminateRayEXT did not terminate ahit shader
350 			hitValue1	= tcu::UVec4(3, 0, 0, 0);	// chit returns 3
351 			break;
352 		default:
353 			TCU_THROW(InternalError, "Wrong shader test type");
354 	}
355 
356 	tcu::clear(referenceAccess, missValue0);
357 	for (deUint32 y = 0; y < testParams.width; ++y)
358 	for (deUint32 x = 0; x < testParams.height; ++x)
359 		referenceAccess.setPixel(missValue1, x, y, 1);
360 
361 	for (deUint32 y = 1; y < testParams.width - 1; ++y)
362 	for (deUint32 x = 1; x < testParams.height - 1; ++x)
363 	{
364 		referenceAccess.setPixel(hitValue0, x, y, 0);
365 		referenceAccess.setPixel(hitValue1, x, y, 1);
366 	}
367 
368 	// compare result and reference
369 	return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
370 }
371 
getResultImageFormat()372 VkFormat SingleSquareConfiguration::getResultImageFormat ()
373 {
374 	return VK_FORMAT_R32_UINT;
375 }
376 
getResultImageFormatSize()377 size_t SingleSquareConfiguration::getResultImageFormatSize ()
378 {
379 	return sizeof(deUint32);
380 }
381 
getClearValue()382 VkClearValue SingleSquareConfiguration::getClearValue ()
383 {
384 	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
385 }
386 
387 class TraversalControlTestCase : public TestCase
388 {
389 	public:
390 							TraversalControlTestCase					(tcu::TestContext& context, const char* name, const char* desc, const TestParams data);
391 							~TraversalControlTestCase					(void);
392 
393 	virtual void			checkSupport								(Context& context) const;
394 	virtual	void			initPrograms								(SourceCollections& programCollection) const;
395 	virtual TestInstance*	createInstance								(Context& context) const;
396 private:
397 	TestParams				m_data;
398 };
399 
400 class TraversalControlTestInstance : public TestInstance
401 {
402 public:
403 																	TraversalControlTestInstance	(Context& context, const TestParams& data);
404 																	~TraversalControlTestInstance	(void);
405 	tcu::TestStatus													iterate									(void);
406 
407 protected:
408 	de::MovePtr<BufferWithMemory>									runTest									();
409 private:
410 	TestParams														m_data;
411 };
412 
TraversalControlTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams data)413 TraversalControlTestCase::TraversalControlTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data)
414 	: vkt::TestCase	(context, name, desc)
415 	, m_data		(data)
416 {
417 }
418 
~TraversalControlTestCase(void)419 TraversalControlTestCase::~TraversalControlTestCase (void)
420 {
421 }
422 
checkSupport(Context & context) const423 void TraversalControlTestCase::checkSupport (Context& context) const
424 {
425 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
426 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
427 
428 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
429 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
430 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
431 
432 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
433 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
434 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
435 }
436 
initPrograms(SourceCollections & programCollection) const437 void TraversalControlTestCase::initPrograms (SourceCollections& programCollection) const
438 {
439 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
440 	{
441 		std::stringstream css;
442 		css <<
443 			"#version 460 core\n"
444 			"#extension GL_EXT_ray_tracing : require\n"
445 			"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
446 			"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
447 			"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
448 			"\n"
449 			"void main()\n"
450 			"{\n"
451 			"  float tmin     = 0.0;\n"
452 			"  float tmax     = 1.0;\n"
453 			"  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5f);\n"
454 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
455 			"  hitValue       = uvec4(0,0,0,0);\n"
456 			"  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
457 			"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
458 			"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
459 			"}\n";
460 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
461 	}
462 
463 	{
464 		std::stringstream css;
465 		css <<
466 			"#version 460 core\n"
467 			"#extension GL_EXT_ray_tracing : require\n"
468 			"hitAttributeEXT uvec4 hitAttribute;\n"
469 			"void main()\n"
470 			"{\n"
471 			"  hitAttribute = uvec4(0,0,0,0);\n"
472 			"  reportIntersectionEXT(0.5f, 0);\n"
473 			"}\n";
474 
475 		programCollection.glslSources.add("isect_report") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
476 	}
477 
478 	{
479 		std::stringstream css;
480 		css <<
481 			"#version 460 core\n"
482 			"#extension GL_EXT_ray_tracing : require\n"
483 			"void main()\n"
484 			"{\n"
485 			"}\n";
486 
487 		programCollection.glslSources.add("isect_pass_through") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
488 	}
489 
490 	{
491 		std::stringstream css;
492 		css <<
493 			"#version 460 core\n"
494 			"#extension GL_EXT_ray_tracing : require\n"
495 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
496 			"void main()\n"
497 			"{\n"
498 			"  hitValue.x = 1;\n"
499 			"}\n";
500 
501 		programCollection.glslSources.add("ahit") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
502 	}
503 
504 	{
505 		std::stringstream css;
506 		css <<
507 			"#version 460 core\n"
508 			"#extension GL_EXT_ray_tracing : require\n"
509 			"void main()\n"
510 			"{\n"
511 			"}\n";
512 
513 		programCollection.glslSources.add("ahit_pass_through") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
514 	}
515 
516 	{
517 		std::stringstream css;
518 		css <<
519 			"#version 460 core\n"
520 			"#extension GL_EXT_ray_tracing : require\n"
521 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
522 			"void main()\n"
523 			"{\n"
524 			"  hitValue.x = 1;\n"
525 			"  ignoreIntersectionEXT;\n"
526 			"  hitValue.x = 2;\n"
527 			"}\n";
528 
529 		programCollection.glslSources.add("ahit_ignore") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
530 	}
531 
532 	{
533 		std::stringstream css;
534 		css <<
535 			"#version 460 core\n"
536 			"#extension GL_EXT_ray_tracing : require\n"
537 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
538 			"void main()\n"
539 			"{\n"
540 			"  hitValue.x = 1;\n"
541 			"  terminateRayEXT;\n"
542 			"  hitValue.x = 2;\n"
543 			"}\n";
544 
545 		programCollection.glslSources.add("ahit_terminate") << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
546 	}
547 
548 	{
549 		std::stringstream css;
550 		css <<
551 			"#version 460 core\n"
552 			"#extension GL_EXT_ray_tracing : require\n"
553 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
554 			"void main()\n"
555 			"{\n"
556 			"  hitValue.y = 3;\n"
557 			"}\n";
558 
559 		programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
560 	}
561 
562 	{
563 		std::stringstream css;
564 		css <<
565 			"#version 460 core\n"
566 			"#extension GL_EXT_ray_tracing : require\n"
567 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
568 			"void main()\n"
569 			"{\n"
570 			"  hitValue.x = 4;\n"
571 			"}\n";
572 
573 		programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
574 	}
575 }
576 
createInstance(Context & context) const577 TestInstance* TraversalControlTestCase::createInstance (Context& context) const
578 {
579 	return new TraversalControlTestInstance(context, m_data);
580 }
581 
TraversalControlTestInstance(Context & context,const TestParams & data)582 TraversalControlTestInstance::TraversalControlTestInstance (Context& context, const TestParams& data)
583 	: vkt::TestInstance		(context)
584 	, m_data				(data)
585 {
586 }
587 
~TraversalControlTestInstance(void)588 TraversalControlTestInstance::~TraversalControlTestInstance (void)
589 {
590 }
591 
runTest()592 de::MovePtr<BufferWithMemory> TraversalControlTestInstance::runTest ()
593 {
594 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
595 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
596 	const VkDevice						device								= m_context.getDevice();
597 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
598 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
599 	const VkQueue						queue								= m_context.getUniversalQueue();
600 	Allocator&							allocator							= m_context.getDefaultAllocator();
601 
602 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
603 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
604 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
605 																					.build(vkd, device);
606 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
607 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
608 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
609 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
610 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
611 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
612 
613 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
614 	m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
615 	Move<VkPipeline>					pipeline							= rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
616 
617 	de::MovePtr<BufferWithMemory>		raygenShaderBindingTable;
618 	de::MovePtr<BufferWithMemory>		hitShaderBindingTable;
619 	de::MovePtr<BufferWithMemory>		missShaderBindingTable;
620 	de::MovePtr<BufferWithMemory>		callableShaderBindingTable;
621 	VkStridedDeviceAddressRegionKHR		raygenShaderBindingTableRegion;
622 	VkStridedDeviceAddressRegionKHR		hitShaderBindingTableRegion;
623 	VkStridedDeviceAddressRegionKHR		missShaderBindingTableRegion;
624 	VkStridedDeviceAddressRegionKHR		callableShaderBindingTableRegion;
625 	m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, m_data, *pipeline, getShaderGroupHandleSize(vki, physicalDevice), getShaderGroupBaseAlignment(vki, physicalDevice), raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable, callableShaderBindingTable, raygenShaderBindingTableRegion, hitShaderBindingTableRegion, missShaderBindingTableRegion, callableShaderBindingTableRegion);
626 
627 	const VkFormat						imageFormat							= m_data.testConfiguration->getResultImageFormat();
628 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, 2, imageFormat);
629 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
630 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
631 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
632 
633 	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(m_data.width * m_data.height * 2 * m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
634 	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
635 	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 2), resultBufferImageSubresourceLayers);
636 	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
637 
638 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
639 
640 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
641 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
642 
643 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
644 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
645 
646 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
647 	{
648 		const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
649 																					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
650 																					**image, imageSubresourceRange);
651 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
652 
653 		const VkClearValue					clearValue							= m_data.testConfiguration->getClearValue();
654 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
655 
656 		const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
657 																					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
658 																					**image, imageSubresourceRange);
659 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
660 
661 		bottomLevelAccelerationStructures										= m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
662 		for (auto& blas : bottomLevelAccelerationStructures)
663 			blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
664 		topLevelAccelerationStructure											= m_data.testConfiguration->initTopAccelerationStructure(m_context, m_data, bottomLevelAccelerationStructures);
665 		topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
666 
667 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
668 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
669 		{
670 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
671 			DE_NULL,															//  const void*							pNext;
672 			1u,																	//  deUint32							accelerationStructureCount;
673 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
674 		};
675 
676 		DescriptorSetUpdateBuilder()
677 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
678 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
679 			.update(vkd, device);
680 
681 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
682 
683 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
684 
685 		cmdTraceRays(vkd,
686 			*cmdBuffer,
687 			&raygenShaderBindingTableRegion,
688 			&missShaderBindingTableRegion,
689 			&hitShaderBindingTableRegion,
690 			&callableShaderBindingTableRegion,
691 			m_data.width, m_data.height, 1);
692 
693 		const VkMemoryBarrier							postTraceMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
694 		const VkMemoryBarrier							postCopyMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
695 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
696 
697 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
698 
699 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
700 	}
701 	endCommandBuffer(vkd, *cmdBuffer);
702 
703 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
704 
705 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
706 
707 	return resultBuffer;
708 }
709 
iterate(void)710 tcu::TestStatus TraversalControlTestInstance::iterate (void)
711 {
712 	// run test using arrays of pointers
713 	const de::MovePtr<BufferWithMemory>	buffer		= runTest();
714 
715 	if (!m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data))
716 		return tcu::TestStatus::fail("Fail");
717 	return tcu::TestStatus::pass("Pass");
718 }
719 
720 }	// anonymous
721 
createTraversalControlTests(tcu::TestContext & testCtx)722 tcu::TestCaseGroup*	createTraversalControlTests(tcu::TestContext& testCtx)
723 {
724 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "traversal_control", "Tests verifying traversal control in RT hit shaders"));
725 
726 	struct HitShaderTestTypeData
727 	{
728 		HitShaderTestType						shaderTestType;
729 		bool									onlyAabbTest;
730 		const char*								name;
731 	} hitShaderTestTypes[] =
732 	{
733 		{ HSTT_ISECT_REPORT_INTERSECTION,		true,	"isect_report_intersection"			},
734 		{ HSTT_ISECT_DONT_REPORT_INTERSECTION,	true,	"isect_dont_report_intersection"	},
735 		{ HSTT_AHIT_PASS_THROUGH,				false,	"ahit_pass_through"					},
736 		{ HSTT_AHIT_IGNORE_INTERSECTION,		false,	"ahit_ignore_intersection"			},
737 		{ HSTT_AHIT_TERMINATE_RAY,				false,	"ahit_terminate_ray"				},
738 	};
739 
740 	struct
741 	{
742 		BottomTestType										testType;
743 		const char*											name;
744 	} bottomTestTypes[] =
745 	{
746 		{ BTT_TRIANGLES,									"triangles" },
747 		{ BTT_AABBS,										"aabbs" },
748 	};
749 
750 
751 	for (size_t shaderTestNdx = 0; shaderTestNdx < DE_LENGTH_OF_ARRAY(hitShaderTestTypes); ++shaderTestNdx)
752 	{
753 		de::MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), hitShaderTestTypes[shaderTestNdx].name, ""));
754 
755 		for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
756 		{
757 			if (hitShaderTestTypes[shaderTestNdx].onlyAabbTest && bottomTestTypes[testTypeNdx].testType != BTT_AABBS)
758 				continue;
759 
760 			TestParams testParams
761 			{
762 				TEST_WIDTH,
763 				TEST_HEIGHT,
764 				hitShaderTestTypes[shaderTestNdx].shaderTestType,
765 				bottomTestTypes[testTypeNdx].testType,
766 				de::SharedPtr<TestConfiguration>(new SingleSquareConfiguration())
767 			};
768 			testTypeGroup->addChild(new TraversalControlTestCase(group->getTestContext(), bottomTestTypes[testTypeNdx].name, "", testParams));
769 		}
770 		group->addChild(testTypeGroup.release());
771 
772 	}
773 
774 	return group.release();
775 }
776 
777 }	// RayTracing
778 
779 }	// vkt
780