• 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 Shader Binding Table tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingShaderBindingTableTests.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 ShaderTestType
63 {
64 	STT_HIT		= 0,
65 	STT_MISS	= 1,
66 	STT_CALL	= 2,
67 	STT_COUNT	= 3
68 };
69 
70 const deUint32			CHECKERBOARD_WIDTH			= 8;
71 const deUint32			CHECKERBOARD_HEIGHT			= 8;
72 const deUint32			HIT_GEOMETRY_COUNT			= 3;
73 const deUint32			HIT_INSTANCE_COUNT			= 1 + CHECKERBOARD_WIDTH * CHECKERBOARD_HEIGHT / ( 2 * HIT_GEOMETRY_COUNT );
74 
75 const deUint32			MAX_SBT_RECORD_OFFSET		= 3;
76 const deUint32			MAX_HIT_SBT_RECORD_STRIDE	= HIT_GEOMETRY_COUNT + 1;
77 const deUint32			SBT_RANDOM_SEED				= 1410;
78 
79 struct TestParams;
80 
81 class TestConfiguration
82 {
83 public:
84 	virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
85 																												 TestParams&						testParams) = 0;
86 	virtual de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
87 																												 TestParams&						testParams,
88 																												 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) = 0;
89 	virtual de::MovePtr<BufferWithMemory>									initUniformBuffer					(Context&							context,
90 																												 TestParams&						testParams) = 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 	ShaderTestType						shaderTestType;
121 	deUint32							sbtOffset;
122 	bool								shaderRecordPresent;
123 	deUint32							sbtRecordOffset;
124 	deUint32							sbtRecordOffsetPassedToTraceRay;
125 	deUint32							sbtRecordStride;
126 	deUint32							sbtRecordStridePassedToTraceRay;
127 	de::SharedPtr<TestConfiguration>	testConfiguration;
128 
129 };
130 
getShaderCounts()131 std::vector<deUint32> getShaderCounts ()
132 {
133 	std::vector<deUint32> shaderCount(STT_COUNT);
134 	shaderCount[STT_HIT]	= HIT_INSTANCE_COUNT + HIT_GEOMETRY_COUNT * MAX_HIT_SBT_RECORD_STRIDE + MAX_SBT_RECORD_OFFSET + 1;
135 	shaderCount[STT_MISS]	= MAX_SBT_RECORD_OFFSET + HIT_INSTANCE_COUNT + 1;
136 	shaderCount[STT_CALL]	= MAX_SBT_RECORD_OFFSET + HIT_INSTANCE_COUNT + 1;
137 	return shaderCount;
138 }
139 
getShaderGroupHandleSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)140 deUint32 getShaderGroupHandleSize (const InstanceInterface&	vki,
141 								   const VkPhysicalDevice	physicalDevice)
142 {
143 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
144 
145 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
146 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
147 }
148 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)149 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
150 									  const VkPhysicalDevice	physicalDevice)
151 {
152 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
153 
154 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
155 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
156 }
157 
makeImageCreateInfo(deUint32 width,deUint32 height,VkFormat format)158 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, VkFormat format)
159 {
160 	const VkImageCreateInfo			imageCreateInfo			=
161 	{
162 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
163 		DE_NULL,																							// const void*				pNext;
164 		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
165 		VK_IMAGE_TYPE_2D,																					// VkImageType				imageType;
166 		format,																								// VkFormat					format;
167 		makeExtent3D(width, height, 1),																		// VkExtent3D				extent;
168 		1u,																									// deUint32					mipLevels;
169 		1u,																									// deUint32					arrayLayers;
170 		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
171 		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
172 		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
173 		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
174 		0u,																									// deUint32					queueFamilyIndexCount;
175 		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
176 		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
177 	};
178 
179 	return imageCreateInfo;
180 }
181 
182 class CheckerboardConfiguration : public TestConfiguration
183 {
184 public:
185 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
186 																										 TestParams&						testParams) override;
187 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
188 																										 TestParams&						testParams,
189 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
190 	de::MovePtr<BufferWithMemory>									initUniformBuffer					(Context&							context,
191 																										 TestParams&						testParams) override;
192 	void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
193 																										 Context&							context,
194 																										 TestParams&						testParams) override;
195 	void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
196 																										 Context&							context,
197 																										 TestParams&						testParams,
198 																										 VkPipeline							pipeline,
199 																										 deUint32							shaderGroupHandleSize,
200 																										 deUint32							shaderGroupBaseAlignment,
201 																										 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
202 																										 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
203 																										 de::MovePtr<BufferWithMemory>&		missShaderBindingTable,
204 																										 de::MovePtr<BufferWithMemory>&		callableShaderBindingTable,
205 																										 VkStridedDeviceAddressRegionKHR&	raygenShaderBindingTableRegion,
206 																										 VkStridedDeviceAddressRegionKHR&	hitShaderBindingTableRegion,
207 																										 VkStridedDeviceAddressRegionKHR&	missShaderBindingTableRegion,
208 																										 VkStridedDeviceAddressRegionKHR&	callableShaderBindingTableRegion) override;
209 	bool															verifyImage							(BufferWithMemory*					resultBuffer,
210 																										 Context&							context,
211 																										 TestParams&						testParams) override;
212 	VkFormat														getResultImageFormat				() override;
213 	size_t															getResultImageFormatSize			() override;
214 	VkClearValue													getClearValue						() override;
215 };
216 
initBottomAccelerationStructures(Context & context,TestParams & testParams)217 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > CheckerboardConfiguration::initBottomAccelerationStructures (Context&			context,
218 																														   TestParams&		testParams)
219 {
220 	DE_UNREF(context);
221 
222 	std::vector<tcu::Vec3> corners;
223 	for (deUint32 y = 0; y < testParams.height; ++y)
224 	for (deUint32 x = 0; x < testParams.width; ++x)
225 	{
226 		if (((x + y) % 2) == 0)
227 			continue;
228 		corners.push_back(tcu::Vec3((float)x, (float)y, 0.0f));
229 	}
230 
231 	de::Random	rnd(SBT_RANDOM_SEED);
232 	rnd.shuffle(begin(corners), end(corners));
233 
234 	tcu::Vec3 v0(0.0, 1.0, 0.0);
235 	tcu::Vec3 v1(0.0, 0.0, 0.0);
236 	tcu::Vec3 v2(1.0, 1.0, 0.0);
237 	tcu::Vec3 v3(1.0, 0.0, 0.0);
238 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
239 
240 	for (size_t cornerNdx = 0; cornerNdx < corners.size(); cornerNdx += HIT_GEOMETRY_COUNT)
241 	{
242 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure	= makeBottomLevelAccelerationStructure();
243 		size_t											geometryCount						= std::min(corners.size() - cornerNdx, size_t(HIT_GEOMETRY_COUNT));
244 		bottomLevelAccelerationStructure->setGeometryCount(geometryCount);
245 		for (size_t idx = cornerNdx; idx < cornerNdx + geometryCount; ++idx)
246 		{
247 			de::SharedPtr<RaytracedGeometryBase> geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
248 			geometry->addVertex(corners[idx] + v0);
249 			geometry->addVertex(corners[idx] + v1);
250 			geometry->addVertex(corners[idx] + v2);
251 			geometry->addVertex(corners[idx] + v2);
252 			geometry->addVertex(corners[idx] + v1);
253 			geometry->addVertex(corners[idx] + v3);
254 			bottomLevelAccelerationStructure->addGeometry(geometry);
255 		}
256 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
257 	}
258 	return result;
259 }
260 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)261 de::MovePtr<TopLevelAccelerationStructure> CheckerboardConfiguration::initTopAccelerationStructure (Context&		context,
262 																									TestParams&		testParams,
263 																									std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
264 {
265 	DE_UNREF(context);
266 	DE_UNREF(testParams);
267 
268 	de::MovePtr<TopLevelAccelerationStructure>	result						= makeTopLevelAccelerationStructure();
269 	deUint32									instanceCount				= deUint32(bottomLevelAccelerationStructures.size());
270 	result->setInstanceCount(instanceCount);
271 
272 	VkTransformMatrixKHR						identityMatrix				= { { { 1.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f } } };
273 	for (deUint32 i = 0; i < instanceCount; ++i)
274 		result->addInstance(bottomLevelAccelerationStructures[i], identityMatrix, 0u, 0xFF, (testParams.shaderTestType == STT_MISS) ? 0 : i);
275 
276 	return result;
277 }
278 
initUniformBuffer(Context & context,TestParams & testParams)279 de::MovePtr<BufferWithMemory> CheckerboardConfiguration::initUniformBuffer (Context&		context,
280 																			TestParams&		testParams)
281 {
282 	const DeviceInterface&						vkd			= context.getDeviceInterface();
283 	const VkDevice								device		= context.getDevice();
284 	Allocator&									allocator	= context.getDefaultAllocator();
285 
286 	const VkBufferCreateInfo		uniformBufferCreateInfo	= makeBufferCreateInfo(sizeof(tcu::UVec4), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
287 	de::MovePtr<BufferWithMemory>	uniformBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
288 	tcu::UVec4						uniformValue;			// x = sbtRecordOffset, y = sbtRecordStride, z = missIndex
289 	switch (testParams.shaderTestType)
290 	{
291 		case STT_HIT:
292 		{
293 			uniformValue = tcu::UVec4(testParams.sbtRecordOffsetPassedToTraceRay, testParams.sbtRecordStride, 0, 0);
294 			break;
295 		}
296 		case STT_MISS:
297 		{
298 			uniformValue = tcu::UVec4(0, 0, testParams.sbtRecordOffsetPassedToTraceRay, 0);
299 			break;
300 		}
301 		case STT_CALL:
302 		{
303 			uniformValue = tcu::UVec4(testParams.sbtRecordOffsetPassedToTraceRay, testParams.sbtRecordStride, 0, 0);
304 			break;
305 		}
306 		default:
307 			TCU_THROW(InternalError, "Wrong shader test type");
308 	}
309 	deMemcpy(uniformBuffer->getAllocation().getHostPtr(), &uniformValue, sizeof(tcu::UVec4));
310 	flushMappedMemoryRange(vkd, device, uniformBuffer->getAllocation().getMemory(), uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
311 
312 	return uniformBuffer;
313 }
314 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,TestParams & testParams)315 void CheckerboardConfiguration::initRayTracingShaders (de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
316 													   Context&								context,
317 													   TestParams&							testParams)
318 {
319 	const DeviceInterface&						vkd						= context.getDeviceInterface();
320 	const VkDevice								device					= context.getDevice();
321 
322 	std::vector<deUint32>						shaderCount				= getShaderCounts();
323 
324 	switch (testParams.shaderTestType)
325 	{
326 		case STT_HIT:
327 		{
328 			if (testParams.shaderRecordPresent)
329 			{
330 				// shaders: rgen, chit_shaderRecord (N times), miss_0
331 				rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
332 				for (deUint32 idx = 0; idx < shaderCount[STT_HIT]; ++idx)
333 					rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_shaderRecord"), 0), 1+idx);
334 				rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_HIT]);
335 			}
336 			else
337 			{
338 				// shaders: rgen, chit_0 .. chit_N, miss_0
339 				rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
340 				for (deUint32 idx = 0; idx < shaderCount[STT_HIT]; ++idx)
341 				{
342 					std::stringstream csname;
343 					csname << "chit_" << idx;
344 					rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 1 + idx);
345 				}
346 				rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_HIT]);
347 			}
348 			rayTracingPipeline->setMaxPayloadSize(16u);
349 			break;
350 		}
351 		case STT_MISS:
352 		{
353 			if (testParams.shaderRecordPresent)
354 			{
355 				// shaders: rgen, chit_0, miss_shaderRecord ( N times )
356 				rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
357 				rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_0"), 0), 1);
358 				for (deUint32 idx = 0; idx < shaderCount[STT_MISS]; ++idx)
359 					rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_shaderRecord"), 0), 2 + idx);
360 			}
361 			else
362 			{
363 				// shaders: rgen, chit_0, miss_0 .. miss_N
364 				rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
365 				rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("chit_0"), 0), 1);
366 				for (deUint32 idx = 0; idx < shaderCount[STT_MISS]; ++idx)
367 				{
368 					std::stringstream csname;
369 					csname << "miss_" << idx;
370 					rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 2 + idx);
371 				}
372 			}
373 			rayTracingPipeline->setMaxPayloadSize(16u);
374 			break;
375 		}
376 		case STT_CALL:
377 		{
378 			if (testParams.shaderRecordPresent)
379 			{
380 				// shaders: rgen, chit_call_0 .. chit_call_N, miss_0, call_shaderRecord ( N times )
381 				rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
382 				for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
383 				{
384 					std::stringstream csname;
385 					csname << "chit_call_" << idx;
386 					rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 1 + idx);
387 				}
388 				rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_CALL]);
389 				for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
390 					rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("call_shaderRecord"), 0), 2 + shaderCount[STT_CALL] + idx);
391 			}
392 			else
393 			{
394 				// shaders: rgen, chit_call_0 .. chit_call_N, miss_0, call_0 .. call_N
395 				rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
396 				for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
397 				{
398 					std::stringstream csname;
399 					csname << "chit_call_" << idx;
400 					rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 1 + idx);
401 				}
402 				rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss_0"), 0), 1 + shaderCount[STT_CALL]);
403 				for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
404 				{
405 					std::stringstream csname;
406 					csname << "call_" << idx;
407 					rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(csname.str()), 0), 2 + shaderCount[STT_CALL] + idx);
408 				}
409 			}
410 			rayTracingPipeline->setMaxPayloadSize(16u);
411 			break;
412 		}
413 		default:
414 			TCU_THROW(InternalError, "Wrong shader test type");
415 	}
416 }
417 
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)418 void CheckerboardConfiguration::initShaderBindingTables (de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
419 														 Context&							context,
420 														 TestParams&						testParams,
421 														 VkPipeline							pipeline,
422 														 deUint32							shaderGroupHandleSize,
423 														 deUint32							shaderGroupBaseAlignment,
424 														 de::MovePtr<BufferWithMemory>&		raygenShaderBindingTable,
425 														 de::MovePtr<BufferWithMemory>&		hitShaderBindingTable,
426 														 de::MovePtr<BufferWithMemory>&		missShaderBindingTable,
427 														 de::MovePtr<BufferWithMemory>&		callableShaderBindingTable,
428 														 VkStridedDeviceAddressRegionKHR&	raygenShaderBindingTableRegion,
429 														 VkStridedDeviceAddressRegionKHR&	hitShaderBindingTableRegion,
430 														 VkStridedDeviceAddressRegionKHR&	missShaderBindingTableRegion,
431 														 VkStridedDeviceAddressRegionKHR&	callableShaderBindingTableRegion)
432 {
433 	const DeviceInterface&						vkd							= context.getDeviceInterface();
434 	const VkDevice								device						= context.getDevice();
435 	Allocator&									allocator					= context.getDefaultAllocator();
436 
437 	std::vector<deUint32>						shaderCount					= getShaderCounts();
438 
439 	// shaderBindingTableOffset must be multiple of shaderGroupBaseAlignment
440 	deUint32									shaderBindingTableOffset	= testParams.sbtOffset * shaderGroupBaseAlignment;
441 
442 	// ShaderRecordKHR size must be multiple of shaderGroupHandleSize
443 	deUint32									shaderRecordAlignedSize		= deAlign32(shaderGroupHandleSize + deUint32(sizeof(tcu::UVec4)), shaderGroupHandleSize);
444 	switch (testParams.shaderTestType)
445 	{
446 		case STT_HIT:
447 		{
448 			raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
449 			if(testParams.shaderRecordPresent)
450 				hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, shaderCount[STT_HIT], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset, sizeof(tcu::UVec4));
451 			else
452 				hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, shaderCount[STT_HIT], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset);
453 			missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1 + shaderCount[STT_HIT], 1 );
454 
455 			raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
456 			if (testParams.shaderRecordPresent)
457 				hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), shaderBindingTableOffset), shaderRecordAlignedSize, shaderCount[STT_HIT] * shaderRecordAlignedSize);
458 			else
459 				hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), shaderBindingTableOffset), shaderGroupHandleSize, shaderCount[STT_HIT] * shaderGroupHandleSize);
460 			missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
461 			callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
462 
463 			// fill ShaderRecordKHR data
464 			if (testParams.shaderRecordPresent)
465 			{
466 				deUint8* hitAddressBegin = (deUint8*)hitShaderBindingTable->getAllocation().getHostPtr() + shaderBindingTableOffset;
467 
468 				for (size_t idx = 0; idx < shaderCount[STT_HIT]; ++idx)
469 				{
470 					deUint8* shaderRecordAddress = hitAddressBegin + idx * shaderRecordAlignedSize + size_t(shaderGroupHandleSize);
471 					tcu::UVec4 shaderRecord(deUint32(idx), 0, 0, 0);
472 					deMemcpy(shaderRecordAddress, &shaderRecord, sizeof(tcu::UVec4));
473 				}
474 
475 				flushMappedMemoryRange(vkd, device, hitShaderBindingTable->getAllocation().getMemory(), hitShaderBindingTable->getAllocation().getOffset(), VK_WHOLE_SIZE);
476 			}
477 			break;
478 		}
479 		case STT_MISS:
480 		{
481 			raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
482 			hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
483 			if (testParams.shaderRecordPresent)
484 				missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, shaderCount[STT_MISS], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset, sizeof(tcu::UVec4));
485 			else
486 				missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, shaderCount[STT_MISS], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset);
487 
488 			raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
489 			hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), 0, shaderGroupHandleSize);
490 			if (testParams.shaderRecordPresent)
491 				missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), shaderBindingTableOffset), shaderRecordAlignedSize, shaderCount[STT_MISS] * shaderRecordAlignedSize);
492 			else
493 				missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), shaderBindingTableOffset), shaderGroupHandleSize, shaderCount[STT_MISS] * shaderGroupHandleSize);
494 			callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
495 
496 			if (testParams.shaderRecordPresent)
497 			{
498 				deUint8* missAddressBegin = (deUint8*)missShaderBindingTable->getAllocation().getHostPtr() + shaderBindingTableOffset;
499 
500 				for (size_t idx = 0; idx < shaderCount[STT_MISS]; ++idx)
501 				{
502 					deUint8* shaderRecordAddress = missAddressBegin + idx * shaderRecordAlignedSize + size_t(shaderGroupHandleSize);
503 					tcu::UVec4 shaderRecord(deUint32(idx), 0, 0, 0);
504 					deMemcpy(shaderRecordAddress, &shaderRecord, sizeof(tcu::UVec4));
505 				}
506 
507 				flushMappedMemoryRange(vkd, device, missShaderBindingTable->getAllocation().getMemory(), missShaderBindingTable->getAllocation().getOffset(), VK_WHOLE_SIZE);
508 			}
509 			break;
510 		}
511 		case STT_CALL:
512 		{
513 			raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
514 			hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, shaderCount[STT_CALL]);
515 			missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1 + shaderCount[STT_CALL], 1 );
516 			if (testParams.shaderRecordPresent)
517 				callableShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2 + shaderCount[STT_CALL], shaderCount[STT_CALL], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset, sizeof(tcu::UVec4));
518 			else
519 				callableShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2 + shaderCount[STT_CALL], shaderCount[STT_CALL], 0u, 0u, MemoryRequirement::Any, 0u, shaderBindingTableOffset);
520 
521 			raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
522 			hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderCount[STT_CALL] * shaderGroupHandleSize);
523 			missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
524 			if (testParams.shaderRecordPresent)
525 				callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), shaderBindingTableOffset), shaderRecordAlignedSize, shaderCount[STT_CALL] * shaderRecordAlignedSize);
526 			else
527 				callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), shaderBindingTableOffset), shaderGroupHandleSize, shaderCount[STT_CALL] * shaderGroupHandleSize);
528 
529 			if (testParams.shaderRecordPresent)
530 			{
531 				deUint8* callAddressBegin	= (deUint8*)callableShaderBindingTable->getAllocation().getHostPtr() + shaderBindingTableOffset;
532 
533 				for (size_t idx = 0; idx < shaderCount[STT_CALL]; ++idx)
534 				{
535 					deUint8* shaderRecordAddress = callAddressBegin + idx * shaderRecordAlignedSize + size_t(shaderGroupHandleSize);
536 					tcu::UVec4 shaderRecord(deUint32(idx), 0, 0, 0);
537 					deMemcpy(shaderRecordAddress, &shaderRecord, sizeof(tcu::UVec4));
538 				}
539 				flushMappedMemoryRange(vkd, device, callableShaderBindingTable->getAllocation().getMemory(), callableShaderBindingTable->getAllocation().getOffset(), VK_WHOLE_SIZE);
540 			}
541 			break;
542 		}
543 		default:
544 			TCU_THROW(InternalError, "Wrong shader test type");
545 	}
546 }
547 
verifyImage(BufferWithMemory * resultBuffer,Context & context,TestParams & testParams)548 bool CheckerboardConfiguration::verifyImage (BufferWithMemory* resultBuffer, Context& context, TestParams& testParams)
549 {
550 	// create result image
551 	tcu::TextureFormat			imageFormat						= vk::mapVkFormat(getResultImageFormat());
552 	tcu::ConstPixelBufferAccess	resultAccess(imageFormat, testParams.width, testParams.height, 1, resultBuffer->getAllocation().getHostPtr());
553 
554 	// recreate geometry indices and instance offsets
555 	std::vector<tcu::UVec4> corners;
556 	for (deUint32 y = 0; y < testParams.height; ++y)
557 	for (deUint32 x = 0; x < testParams.width; ++x)
558 	{
559 		if (((x + y) % 2) == 0)
560 			continue;
561 		corners.push_back(tcu::UVec4(x, y, 0, 0));
562 	}
563 	de::Random					rnd(SBT_RANDOM_SEED);
564 	rnd.shuffle(begin(corners), end(corners));
565 
566 	deUint32					instanceOffset	= 0;
567 	for (size_t cornerNdx = 0; cornerNdx < corners.size(); cornerNdx += HIT_GEOMETRY_COUNT, ++instanceOffset)
568 	{
569 		size_t											geometryCount = std::min(corners.size() - cornerNdx, size_t(HIT_GEOMETRY_COUNT));
570 		deUint32 geometryIndex = 0;
571 		for (size_t idx = cornerNdx; idx < cornerNdx + geometryCount; ++idx, ++geometryIndex)
572 		{
573 			corners[idx].z() = instanceOffset;
574 			corners[idx].w() = geometryIndex;
575 		}
576 	}
577 
578 	std::vector<deUint32>		reference(testParams.width * testParams.height);
579 	tcu::PixelBufferAccess		referenceAccess(imageFormat, testParams.width, testParams.height, 1, reference.data());
580 	// clear image with miss values
581 	tcu::UVec4 missValue((testParams.shaderTestType == STT_MISS) ? testParams.sbtRecordOffset : 0, 0, 0, 0);
582 	tcu::clear(referenceAccess, missValue);
583 
584 	// for each pixel - set its color to proper value
585 	for (const auto& pixel : corners)
586 	{
587 		deUint32 shaderIndex;
588 		switch (testParams.shaderTestType)
589 		{
590 		case STT_HIT:
591 		{
592 			shaderIndex = testParams.sbtRecordOffset + pixel.z() + pixel.w() * testParams.sbtRecordStride;
593 			break;
594 		}
595 		case STT_MISS:
596 		{
597 			shaderIndex = 0;// pixel.z();
598 			break;
599 		}
600 		case STT_CALL:
601 		{
602 			shaderIndex = testParams.sbtRecordOffset + pixel.z() + pixel.w() * testParams.sbtRecordStride;
603 			break;
604 		}
605 		default:
606 			TCU_THROW(InternalError, "Wrong shader test type");
607 		}
608 
609 		referenceAccess.setPixel(tcu::UVec4(shaderIndex, 0, 0, 0), pixel.x(), pixel.y());
610 	}
611 
612 	// compare result and reference
613 	return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
614 }
615 
getResultImageFormat()616 VkFormat CheckerboardConfiguration::getResultImageFormat ()
617 {
618 	return VK_FORMAT_R32_UINT;
619 }
620 
getResultImageFormatSize()621 size_t CheckerboardConfiguration::getResultImageFormatSize ()
622 {
623 	return sizeof(deUint32);
624 }
625 
getClearValue()626 VkClearValue CheckerboardConfiguration::getClearValue ()
627 {
628 	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
629 }
630 
631 class ShaderBindingTableIndexingTestCase : public TestCase
632 {
633 	public:
634 							ShaderBindingTableIndexingTestCase			(tcu::TestContext& context, const char* name, const char* desc, const TestParams data);
635 							~ShaderBindingTableIndexingTestCase			(void);
636 
637 	virtual void			checkSupport								(Context& context) const;
638 	virtual	void			initPrograms								(SourceCollections& programCollection) const;
639 	virtual TestInstance*	createInstance								(Context& context) const;
640 private:
641 	TestParams				m_data;
642 };
643 
644 class ShaderBindingTableIndexingTestInstance : public TestInstance
645 {
646 public:
647 																	ShaderBindingTableIndexingTestInstance	(Context& context, const TestParams& data);
648 																	~ShaderBindingTableIndexingTestInstance	(void);
649 	tcu::TestStatus													iterate									(void);
650 
651 protected:
652 	de::MovePtr<BufferWithMemory>									runTest									();
653 private:
654 	TestParams														m_data;
655 };
656 
ShaderBindingTableIndexingTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams data)657 ShaderBindingTableIndexingTestCase::ShaderBindingTableIndexingTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams data)
658 	: vkt::TestCase	(context, name, desc)
659 	, m_data		(data)
660 {
661 }
662 
~ShaderBindingTableIndexingTestCase(void)663 ShaderBindingTableIndexingTestCase::~ShaderBindingTableIndexingTestCase (void)
664 {
665 }
666 
checkSupport(Context & context) const667 void ShaderBindingTableIndexingTestCase::checkSupport (Context& context) const
668 {
669 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
670 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
671 
672 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
673 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
674 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
675 
676 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
677 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
678 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
679 }
680 
initPrograms(SourceCollections & programCollection) const681 void ShaderBindingTableIndexingTestCase::initPrograms (SourceCollections& programCollection) const
682 {
683 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
684 
685 	std::vector<deUint32>	shaderCount	= getShaderCounts();
686 
687 	{
688 		std::stringstream css;
689 		css <<
690 			"#version 460 core\n"
691 			"#extension GL_EXT_ray_tracing : require\n"
692 			"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
693 			"layout(r32ui, set = 0, binding = 0) uniform uimage2D result;\n"
694 			"layout(set = 0, binding = 1) uniform TraceRaysParamsUBO\n"
695 			"{\n"
696 			"	uvec4 trParams; // x = sbtRecordOffset, y = sbtRecordStride, z = missIndex\n"
697 			"};\n"
698 			"layout(set = 0, binding = 2) uniform accelerationStructureEXT topLevelAS;\n"
699 			"\n"
700 			"void main()\n"
701 			"{\n"
702 			"  float tmin     = 0.0;\n"
703 			"  float tmax     = 1.0;\n"
704 			"  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5f);\n"
705 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
706 			"  hitValue       = uvec4(0,0,0,0);\n"
707 			"  traceRayEXT(topLevelAS, 0, 0xFF, trParams.x, trParams.y, trParams.z, origin, tmin, direct, tmax, 0);\n"
708 			"  imageStore(result, ivec2(gl_LaunchIDEXT.xy), hitValue);\n"
709 			"}\n";
710 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
711 	}
712 
713 	for(deUint32 idx = 0; idx < shaderCount[STT_HIT]; ++idx)
714 	{
715 		std::stringstream css;
716 		css <<
717 			"#version 460 core\n"
718 			"#extension GL_EXT_ray_tracing : require\n"
719 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
720 			"void main()\n"
721 			"{\n"
722 			"  hitValue = uvec4("<< idx << ",0,0,1);\n"
723 			"}\n";
724 		std::stringstream csname;
725 		csname << "chit_" << idx;
726 
727 		programCollection.glslSources.add(csname.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
728 	}
729 
730 	{
731 		std::stringstream css;
732 		css <<
733 			"#version 460 core\n"
734 			"#extension GL_EXT_ray_tracing : require\n"
735 			"layout(shaderRecordEXT) buffer block\n"
736 			"{\n"
737 			"  uvec4 info;\n"
738 			"};\n"
739 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
740 			"void main()\n"
741 			"{\n"
742 			"  hitValue = info;\n"
743 			"}\n";
744 		programCollection.glslSources.add("chit_shaderRecord") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
745 	}
746 
747 	for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
748 	{
749 		std::stringstream css;
750 		css <<
751 			"#version 460 core\n"
752 			"#extension GL_EXT_ray_tracing : require\n"
753 			"layout(location = 0) callableDataEXT uvec4 value;\n"
754 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
755 			"void main()\n"
756 			"{\n"
757 			"  executeCallableEXT(" << idx << ", 0);\n"
758 			"  hitValue = value;\n"
759 			"}\n";
760 		std::stringstream csname;
761 		csname << "chit_call_" << idx;
762 
763 		programCollection.glslSources.add(csname.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
764 	}
765 
766 	for (deUint32 idx = 0; idx < shaderCount[STT_MISS]; ++idx)
767 	{
768 		std::stringstream css;
769 		css <<
770 			"#version 460 core\n"
771 			"#extension GL_EXT_ray_tracing : require\n"
772 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
773 			"void main()\n"
774 			"{\n"
775 			"  hitValue = uvec4(" << idx <<",0,0,1);\n"
776 			"}\n";
777 		std::stringstream csname;
778 		csname << "miss_" << idx;
779 
780 		programCollection.glslSources.add(csname.str()) << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
781 	}
782 
783 	{
784 		std::stringstream css;
785 		css <<
786 			"#version 460 core\n"
787 			"#extension GL_EXT_ray_tracing : require\n"
788 			"layout(shaderRecordEXT) buffer block\n"
789 			"{\n"
790 			"  uvec4 info;\n"
791 			"};\n"
792 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
793 			"void main()\n"
794 			"{\n"
795 			"  hitValue = info;\n"
796 			"}\n";
797 
798 		programCollection.glslSources.add("miss_shaderRecord") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
799 	}
800 
801 	for (deUint32 idx = 0; idx < shaderCount[STT_CALL]; ++idx)
802 	{
803 		std::stringstream css;
804 		css <<
805 			"#version 460 core\n"
806 			"#extension GL_EXT_ray_tracing : require\n"
807 			"layout(location = 0) callableDataInEXT uvec4 result;\n"
808 			"void main()\n"
809 			"{\n"
810 			"  result = uvec4(" << idx << ",0,0,1);\n"
811 			"}\n";
812 		std::stringstream csname;
813 		csname << "call_" << idx;
814 
815 		programCollection.glslSources.add(csname.str()) << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
816 	}
817 
818 	{
819 		std::stringstream css;
820 		css <<
821 			"#version 460 core\n"
822 			"#extension GL_EXT_ray_tracing : require\n"
823 			"layout(shaderRecordEXT) buffer block\n"
824 			"{\n"
825 			"  uvec4 info;\n"
826 			"};\n"
827 			"layout(location = 0) callableDataInEXT uvec4 result;\n"
828 			"void main()\n"
829 			"{\n"
830 			"  result = info;\n"
831 			"}\n";
832 
833 		programCollection.glslSources.add("call_shaderRecord") << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
834 	}
835 }
836 
createInstance(Context & context) const837 TestInstance* ShaderBindingTableIndexingTestCase::createInstance (Context& context) const
838 {
839 	return new ShaderBindingTableIndexingTestInstance(context, m_data);
840 }
841 
ShaderBindingTableIndexingTestInstance(Context & context,const TestParams & data)842 ShaderBindingTableIndexingTestInstance::ShaderBindingTableIndexingTestInstance (Context& context, const TestParams& data)
843 	: vkt::TestInstance		(context)
844 	, m_data				(data)
845 {
846 }
847 
~ShaderBindingTableIndexingTestInstance(void)848 ShaderBindingTableIndexingTestInstance::~ShaderBindingTableIndexingTestInstance (void)
849 {
850 }
851 
runTest()852 de::MovePtr<BufferWithMemory> ShaderBindingTableIndexingTestInstance::runTest ()
853 {
854 	const InstanceInterface&			vki									= m_context.getInstanceInterface();
855 	const DeviceInterface&				vkd									= m_context.getDeviceInterface();
856 	const VkDevice						device								= m_context.getDevice();
857 	const VkPhysicalDevice				physicalDevice						= m_context.getPhysicalDevice();
858 	const deUint32						queueFamilyIndex					= m_context.getUniversalQueueFamilyIndex();
859 	const VkQueue						queue								= m_context.getUniversalQueue();
860 	Allocator&							allocator							= m_context.getDefaultAllocator();
861 	const deUint32						pixelCount							= m_data.width * m_data.height * 1;
862 
863 	const Move<VkDescriptorSetLayout>	descriptorSetLayout					= DescriptorSetLayoutBuilder()
864 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
865 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ALL_RAY_TRACING_STAGES)
866 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
867 																					.build(vkd, device);
868 	const Move<VkDescriptorPool>		descriptorPool						= DescriptorPoolBuilder()
869 																					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
870 																					.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
871 																					.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
872 																					.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
873 	const Move<VkDescriptorSet>			descriptorSet						= makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
874 	const Move<VkPipelineLayout>		pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
875 
876 	de::MovePtr<RayTracingPipeline>		rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
877 	m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, m_data);
878 	Move<VkPipeline>					pipeline							= rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
879 
880 	de::MovePtr<BufferWithMemory>		raygenShaderBindingTable;
881 	de::MovePtr<BufferWithMemory>		hitShaderBindingTable;
882 	de::MovePtr<BufferWithMemory>		missShaderBindingTable;
883 	de::MovePtr<BufferWithMemory>		callableShaderBindingTable;
884 	VkStridedDeviceAddressRegionKHR		raygenShaderBindingTableRegion;
885 	VkStridedDeviceAddressRegionKHR		hitShaderBindingTableRegion;
886 	VkStridedDeviceAddressRegionKHR		missShaderBindingTableRegion;
887 	VkStridedDeviceAddressRegionKHR		callableShaderBindingTableRegion;
888 	m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, m_data, *pipeline, getShaderGroupHandleSize(vki, physicalDevice), getShaderGroupBaseAlignment(vki, physicalDevice), raygenShaderBindingTable, hitShaderBindingTable, missShaderBindingTable, callableShaderBindingTable, raygenShaderBindingTableRegion, hitShaderBindingTableRegion, missShaderBindingTableRegion, callableShaderBindingTableRegion);
889 
890 	const VkFormat						imageFormat							= m_data.testConfiguration->getResultImageFormat();
891 	const VkImageCreateInfo				imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, imageFormat);
892 	const VkImageSubresourceRange		imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
893 	const de::MovePtr<ImageWithMemory>	image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
894 	const Move<VkImageView>				imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, imageFormat, imageSubresourceRange);
895 
896 	const VkBufferCreateInfo			resultBufferCreateInfo				= makeBufferCreateInfo(pixelCount*m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
897 	const VkImageSubresourceLayers		resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
898 	const VkBufferImageCopy				resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 1), resultBufferImageSubresourceLayers);
899 	de::MovePtr<BufferWithMemory>		resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
900 
901 	const VkDescriptorImageInfo			descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
902 
903 	const Move<VkCommandPool>			cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
904 	const Move<VkCommandBuffer>			cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
905 
906 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelAccelerationStructures;
907 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
908 	de::MovePtr<BufferWithMemory>									uniformBuffer;
909 
910 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
911 	{
912 		const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
913 																					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
914 																					**image, imageSubresourceRange);
915 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
916 
917 		const VkClearValue					clearValue							= m_data.testConfiguration->getClearValue();
918 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
919 
920 		const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
921 																					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
922 																					**image, imageSubresourceRange);
923 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
924 
925 		bottomLevelAccelerationStructures										= m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
926 		for (auto& blas : bottomLevelAccelerationStructures)
927 			blas->createAndBuild(vkd, device, *cmdBuffer, allocator);
928 		topLevelAccelerationStructure											= m_data.testConfiguration->initTopAccelerationStructure(m_context, m_data, bottomLevelAccelerationStructures);
929 		topLevelAccelerationStructure->createAndBuild(vkd, device, *cmdBuffer, allocator);
930 
931 		uniformBuffer															= m_data.testConfiguration->initUniformBuffer(m_context, m_data);
932 		VkDescriptorBufferInfo							uniformBufferInfo		= makeDescriptorBufferInfo(uniformBuffer->get(), 0ull, sizeof(tcu::UVec4));
933 
934 		const TopLevelAccelerationStructure*			topLevelAccelerationStructurePtr		= topLevelAccelerationStructure.get();
935 		VkWriteDescriptorSetAccelerationStructureKHR	accelerationStructureWriteDescriptorSet	=
936 		{
937 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
938 			DE_NULL,															//  const void*							pNext;
939 			1u,																	//  deUint32							accelerationStructureCount;
940 			topLevelAccelerationStructurePtr->getPtr(),							//  const VkAccelerationStructureKHR*	pAccelerationStructures;
941 		};
942 
943 		DescriptorSetUpdateBuilder()
944 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
945 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo)
946 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
947 			.update(vkd, device);
948 
949 		vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
950 
951 		vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
952 
953 		cmdTraceRays(vkd,
954 			*cmdBuffer,
955 			&raygenShaderBindingTableRegion,
956 			&missShaderBindingTableRegion,
957 			&hitShaderBindingTableRegion,
958 			&callableShaderBindingTableRegion,
959 			m_data.width, m_data.height, 1);
960 
961 		const VkMemoryBarrier							postTraceMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
962 		const VkMemoryBarrier							postCopyMemoryBarrier					= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
963 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
964 
965 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
966 
967 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
968 	}
969 	endCommandBuffer(vkd, *cmdBuffer);
970 
971 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
972 
973 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
974 
975 	return resultBuffer;
976 }
977 
iterate(void)978 tcu::TestStatus ShaderBindingTableIndexingTestInstance::iterate (void)
979 {
980 	// run test using arrays of pointers
981 	const de::MovePtr<BufferWithMemory>	buffer		= runTest();
982 
983 	if (!m_data.testConfiguration->verifyImage(buffer.get(), m_context, m_data))
984 		return tcu::TestStatus::fail("Fail");
985 	return tcu::TestStatus::pass("Pass");
986 }
987 
988 }	// anonymous
989 
createShaderBindingTableTests(tcu::TestContext & testCtx)990 tcu::TestCaseGroup*	createShaderBindingTableTests (tcu::TestContext& testCtx)
991 {
992 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_binding_table", "Tests veryfying shader binding tables"));
993 
994 	struct ShaderTestTypeData
995 	{
996 		ShaderTestType							shaderTestType;
997 		const char*								name;
998 	} shaderTestTypes[] =
999 	{
1000 		{ STT_HIT,		"indexing_hit"	},
1001 		{ STT_MISS,		"indexing_miss"	},
1002 		{ STT_CALL,		"indexing_call"	},
1003 	};
1004 
1005 	struct ShaderBufferOffsetData
1006 	{
1007 		deUint32								sbtOffset;
1008 		const char*								name;
1009 	} shaderBufferOffsets[] =
1010 	{
1011 		{ 0u,	"sbt_offset_0"	},
1012 		{ 4u,	"sbt_offset_4"	},
1013 		{ 7u,	"sbt_offset_7"	},
1014 		{ 16u,	"sbt_offset_16"	},
1015 	};
1016 
1017 	struct ShaderRecordData
1018 	{
1019 		bool									present;
1020 		const char*								name;
1021 	} shaderRecords[] =
1022 	{
1023 		{ false,	"no_shaderrecord"	},
1024 		{ true,		"shaderrecord"		},
1025 	};
1026 
1027 	for (size_t shaderTestNdx = 0; shaderTestNdx < DE_LENGTH_OF_ARRAY(shaderTestTypes); ++shaderTestNdx)
1028 	{
1029 		de::MovePtr<tcu::TestCaseGroup> shaderTestGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderTestTypes[shaderTestNdx].name, ""));
1030 
1031 		for (size_t sbtOffsetNdx = 0; sbtOffsetNdx < DE_LENGTH_OF_ARRAY(shaderBufferOffsets); ++sbtOffsetNdx)
1032 		{
1033 			de::MovePtr<tcu::TestCaseGroup> sbtOffsetGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderBufferOffsets[sbtOffsetNdx].name, ""));
1034 
1035 			for (size_t shaderRecordNdx = 0; shaderRecordNdx < DE_LENGTH_OF_ARRAY(shaderRecords); ++shaderRecordNdx)
1036 			{
1037 				de::MovePtr<tcu::TestCaseGroup> shaderRecordGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderRecords[shaderRecordNdx].name, ""));
1038 
1039 				deUint32		maxSbtRecordStride				= (shaderTestTypes[shaderTestNdx].shaderTestType == STT_HIT) ? MAX_HIT_SBT_RECORD_STRIDE + 1 : 1;
1040 				deUint32		maxSbtRecordOffset				= MAX_SBT_RECORD_OFFSET;
1041 				const deUint32	maxSbtRecordOffsetWithExtraBits = (shaderTestTypes[shaderTestNdx].shaderTestType == STT_MISS)	? MAX_SBT_RECORD_OFFSET | (~((1u << 16) - 1))  //< Only 16 least significant bits matter for miss indices
1042 																																: MAX_SBT_RECORD_OFFSET | (~((1u << 4)  - 1)); //< Only 4 least significant bits matter for SBT record offsets
1043 
1044 				for (deUint32 sbtRecordOffset = 0; sbtRecordOffset <= maxSbtRecordOffset; ++sbtRecordOffset)
1045 				for (deUint32 sbtRecordStride = 0; sbtRecordStride <= maxSbtRecordStride; ++sbtRecordStride)
1046 				{
1047 					if ((shaderTestTypes[shaderTestNdx].shaderTestType	!= STT_HIT)				&&
1048 						(sbtRecordStride								== maxSbtRecordStride))
1049 					{
1050 						continue;
1051 					}
1052 
1053 					TestParams testParams
1054 					{
1055 						CHECKERBOARD_WIDTH,
1056 						CHECKERBOARD_HEIGHT,
1057 						shaderTestTypes[shaderTestNdx].shaderTestType,
1058 						shaderBufferOffsets[sbtOffsetNdx].sbtOffset,
1059 						shaderRecords[shaderRecordNdx].present,
1060 						sbtRecordOffset,
1061 						(sbtRecordOffset == maxSbtRecordOffset)	? maxSbtRecordOffsetWithExtraBits
1062 																: sbtRecordOffset,
1063 						//< Only first 4 least significant bits matter for SBT record stride
1064 						sbtRecordStride,
1065 						(sbtRecordStride == maxSbtRecordStride)	? maxSbtRecordStride | (~((1u << 4) - 1))
1066 																: sbtRecordStride,
1067 						de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration())
1068 					};
1069 
1070 					std::stringstream str;
1071 					str << sbtRecordOffset << "_" << sbtRecordStride;
1072 
1073 					if (testParams.sbtRecordStride != testParams.sbtRecordStridePassedToTraceRay)
1074 					{
1075 						str << "_extraSBTRecordStrideBits";
1076 					}
1077 
1078 					if (testParams.sbtRecordOffset != testParams.sbtRecordOffsetPassedToTraceRay)
1079 					{
1080 						str << "_extrabits";
1081 					}
1082 
1083 					shaderRecordGroup->addChild(new ShaderBindingTableIndexingTestCase(group->getTestContext(), str.str().c_str(), "", testParams));
1084 				}
1085 
1086 				sbtOffsetGroup->addChild(shaderRecordGroup.release());
1087 			}
1088 
1089 			shaderTestGroup->addChild(sbtOffsetGroup.release());
1090 		}
1091 
1092 		group->addChild(shaderTestGroup.release());
1093 	}
1094 
1095 	return group.release();
1096 }
1097 
1098 }	// RayTracing
1099 
1100 }	// vkt
1101