• 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 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 TestParams data)657 ShaderBindingTableIndexingTestCase::ShaderBindingTableIndexingTestCase (tcu::TestContext& context, const char* name, const TestParams data)
658 	: vkt::TestCase	(context, name)
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 /*
989 
990 Test the advertised shader group handle alignment requirements work as expected. The tests will prepare shader binding tables using
991 shader record buffers for padding and achieving the desired alignments.
992 
993 +-------------------------------------------
994 | Shader | Shader    | Aligned |
995 | Group  | Record    | Shader  | ...
996 | Handle | Buffer    | Group   |
997 |        | (padding) | Handle  |
998 +-------------------------------------------
999 
1000 The number of geometries to try (hence the number of alignments and shader record buffers to try) is 32/align + 1, so 33 in the case
1001 of align=1, and 2 in the case of align=32. This allows us to test all possible alignment values.
1002 
1003 Geometries are triangles put alongside the X axis. The base triangle is:
1004 
1005 0,1|      x
1006    |     x x
1007    |    x  0.5,0.5
1008    |   x  x  x
1009    |  x       x
1010    | xxxxxxxxxxx
1011    +-------------
1012  0,0             1,0
1013 
1014 A triangle surrounding point (0.5, 0.5), in the [0, 1] range of both the X and Y axis.
1015 
1016 As more than one triangle is needed, each triangle is translated one more unit in the X axis, so each triangle is in the [i, i+1]
1017 range. The Y axis doesn't change, triangles are always in the [0,1] range.
1018 
1019 Triangles have Z=5, and one ray is traced per triangle, origin (i+0.5, 0.5, 0) direction (0, 0, 1), where i is gl_LaunchIDEXT.x.
1020 
1021 For each geometry, the shader record buffer contents vary depending on the geometry index and the desired alignment (padding).
1022 
1023 Alignment	Element Type	Element Count			Data
1024 1			uint8_t			1						0x80 | geometryID
1025 2			uint16_t		1						0xABC0 | geometryID
1026 4+			uint32_t		alignment/4				For each element: 0xABCDE0F0 | (element << 8) | geometryID
1027 
1028 The test will try to verify everything works properly and all shader record buffers can be read with the right values.
1029 
1030  */
1031 struct ShaderGroupHandleAlignmentParams
1032 {
1033 	const uint32_t alignment;
1034 
ShaderGroupHandleAlignmentParamsvkt::RayTracing::__anonfeb9a2770111::ShaderGroupHandleAlignmentParams1035 	ShaderGroupHandleAlignmentParams (uint32_t alignment_)
1036 		: alignment (alignment_)
1037 	{
1038 		DE_ASSERT(alignment >= 1u && alignment <= 32u);
1039 		DE_ASSERT(deIsPowerOfTwo32(static_cast<int>(alignment)));
1040 	}
1041 
geometryCountvkt::RayTracing::__anonfeb9a2770111::ShaderGroupHandleAlignmentParams1042 	uint32_t geometryCount () const
1043 	{
1044 		return (32u / alignment + 1u);
1045 	}
1046 
shaderRecordElementCountvkt::RayTracing::__anonfeb9a2770111::ShaderGroupHandleAlignmentParams1047 	uint32_t shaderRecordElementCount () const
1048 	{
1049 		return ((alignment <= 4u) ? 1u : (alignment / 4u));
1050 	}
1051 
glslElementTypevkt::RayTracing::__anonfeb9a2770111::ShaderGroupHandleAlignmentParams1052 	std::string glslElementType () const
1053 	{
1054 		if (alignment == 1u)
1055 			return "uint8_t";
1056 		if (alignment == 2u)
1057 			return "uint16_t";
1058 		return "uint32_t";
1059 	}
1060 
glslExtensionvkt::RayTracing::__anonfeb9a2770111::ShaderGroupHandleAlignmentParams1061 	std::string glslExtension () const
1062 	{
1063 		if (alignment == 1u)
1064 			return "GL_EXT_shader_explicit_arithmetic_types_int8";
1065 		if (alignment == 2u)
1066 			return "GL_EXT_shader_explicit_arithmetic_types_int16";
1067 		return "GL_EXT_shader_explicit_arithmetic_types_int32";
1068 	}
1069 
getRecordDatavkt::RayTracing::__anonfeb9a2770111::ShaderGroupHandleAlignmentParams1070 	std::vector<uint8_t> getRecordData (uint32_t geometryID) const
1071 	{
1072 		std::vector<uint8_t> recordData;
1073 		switch (alignment)
1074 		{
1075 		case 1u:
1076 			recordData.push_back(static_cast<uint8_t>(0x80u | geometryID));
1077 			break;
1078 		case 2u:
1079 			recordData.push_back(uint8_t{0xABu});
1080 			recordData.push_back(static_cast<uint8_t>(0xC0u | geometryID));
1081 			break;
1082 		default:
1083 			{
1084 				const auto elemCount = shaderRecordElementCount();
1085 				for (uint32_t i = 0u; i < elemCount; ++i)
1086 				{
1087 					recordData.push_back(uint8_t{0xABu});
1088 					recordData.push_back(uint8_t{0xCDu});
1089 					recordData.push_back(static_cast<uint8_t>(0xE0u | i));
1090 					recordData.push_back(static_cast<uint8_t>(0xF0u | geometryID));
1091 				}
1092 			}
1093 			break;
1094 		}
1095 		return recordData;
1096 	}
1097 };
1098 
1099 class ShaderGroupHandleAlignmentCase : public TestCase
1100 {
1101 public:
ShaderGroupHandleAlignmentCase(tcu::TestContext & testCtx,const std::string & name,const ShaderGroupHandleAlignmentParams & params)1102 					ShaderGroupHandleAlignmentCase		(tcu::TestContext& testCtx, const std::string& name, const ShaderGroupHandleAlignmentParams& params)
1103 						: TestCase	(testCtx, name)
1104 						, m_params	(params)
1105 						{
1106 						}
~ShaderGroupHandleAlignmentCase(void)1107 	virtual			~ShaderGroupHandleAlignmentCase		(void) {}
1108 
1109 	void			checkSupport						(Context& context) const override;
1110 	void			initPrograms						(vk::SourceCollections& programCollection) const override;
1111 	TestInstance*	createInstance						(Context& context) const override;
1112 
1113 protected:
1114 	ShaderGroupHandleAlignmentParams					m_params;
1115 };
1116 
1117 class ShaderGroupHandleAlignmentInstance : public TestInstance
1118 {
1119 public:
ShaderGroupHandleAlignmentInstance(Context & context,const ShaderGroupHandleAlignmentParams & params)1120 						ShaderGroupHandleAlignmentInstance	(Context& context, const ShaderGroupHandleAlignmentParams& params)
1121 							: TestInstance	(context)
1122 							, m_params		(params)
1123 							{}
~ShaderGroupHandleAlignmentInstance(void)1124 	virtual				~ShaderGroupHandleAlignmentInstance	(void) {}
1125 
1126 	tcu::TestStatus		iterate								(void) override;
1127 
1128 protected:
1129 	ShaderGroupHandleAlignmentParams							m_params;
1130 };
1131 
checkSupport(Context & context) const1132 void ShaderGroupHandleAlignmentCase::checkSupport (Context& context) const
1133 {
1134 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
1135 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1136 
1137 	const auto&	vki				= context.getInstanceInterface();
1138 	const auto	physicalDevice	= context.getPhysicalDevice();
1139 	const auto	rtProperties	= makeRayTracingProperties(vki, physicalDevice);
1140 
1141 	if (m_params.alignment < rtProperties->getShaderGroupHandleAlignment())
1142 		TCU_THROW(NotSupportedError, "Required shader group handle alignment not supported");
1143 
1144 	switch (m_params.alignment)
1145 	{
1146 	case 1u:
1147 		{
1148 			const auto& int8Features = context.getShaderFloat16Int8Features();
1149 			if (!int8Features.shaderInt8)
1150 				TCU_THROW(NotSupportedError, "shaderInt8 not supported");
1151 
1152 			const auto& int8StorageFeatures = context.get8BitStorageFeatures();
1153 			if (!int8StorageFeatures.storageBuffer8BitAccess)
1154 				TCU_THROW(NotSupportedError, "storageBuffer8BitAccess not supported");
1155 		}
1156 		break;
1157 
1158 	case 2u:
1159 		{
1160 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_INT16);
1161 
1162 			const auto& int16StorageFeatures = context.get16BitStorageFeatures();
1163 			if (!int16StorageFeatures.storageBuffer16BitAccess)
1164 				TCU_THROW(NotSupportedError, "storageBuffer16BitAccess not supported");
1165 		}
1166 		break;
1167 
1168 	default:
1169 		break;
1170 	}
1171 }
1172 
initPrograms(vk::SourceCollections & programCollection) const1173 void ShaderGroupHandleAlignmentCase::initPrograms (vk::SourceCollections& programCollection) const
1174 {
1175 	const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1176 
1177 	const auto elemType			= m_params.glslElementType();
1178 	const auto geometryCount	= m_params.geometryCount();
1179 	const auto elementCount		= m_params.shaderRecordElementCount();
1180 	const auto extension		= m_params.glslExtension();
1181 
1182 	std::ostringstream descriptors;
1183 	descriptors
1184 		<< "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
1185 		<< "layout(set=0, binding=1, std430) buffer SSBOBlock {\n"
1186 		<< "  " << elemType << " data[" << geometryCount << "][" << elementCount << "];\n"
1187 		<< "} ssbo;\n"
1188 		;
1189 	const auto descriptorsStr = descriptors.str();
1190 
1191 	std::ostringstream commonHeader;
1192 	commonHeader
1193 		<< "#version 460 core\n"
1194 		<< "#extension GL_EXT_ray_tracing : require\n"
1195 		<< "#extension " << extension << " : require\n"
1196 		;
1197 	const auto commontHeaderStr = commonHeader.str();
1198 
1199 	std::ostringstream rgen;
1200 	rgen
1201 		<< commontHeaderStr
1202 		<< "\n"
1203 		<< descriptorsStr
1204 		<< "layout(location=0) rayPayloadEXT vec4 unused;\n"
1205 		<< "\n"
1206 		<< "void main()\n"
1207 		<< "{\n"
1208 		<< "  const uint  rayFlags  = 0;\n"
1209 		<< "  const uint  cullMask  = 0xFF;\n"
1210 		<< "  const float tMin      = 0.0;\n"
1211 		<< "  const float tMax      = 10.0;\n"
1212 		<< "  const vec3  origin    = vec3(float(gl_LaunchIDEXT.x) + 0.5, 0.5, 0.0);\n"
1213 		<< "  const vec3  direction = vec3(0.0, 0.0, 1.0);\n"
1214 		<< "  const uint  sbtOffset = 0;\n"
1215 		<< "  const uint  sbtStride = 1;\n"
1216 		<< "  const uint  missIndex = 0;\n"
1217 		<< "  traceRayEXT(topLevelAS, rayFlags, cullMask, sbtOffset, sbtStride, missIndex, origin, tMin, direction, tMax, 0);\n"
1218 		<< "}\n"
1219 		;
1220 
1221 	std::ostringstream chit;
1222 	chit
1223 		<< commontHeaderStr
1224 		<< "\n"
1225 		<< descriptorsStr
1226 		<< "layout(location=0) rayPayloadInEXT vec4 unused;\n"
1227 		<< "layout(shaderRecordEXT, std430) buffer srbBlock {\n"
1228 		<< "  " << elemType << " data[" << elementCount << "];\n"
1229 		<< "} srb;\n"
1230 		<< "\n"
1231 		<< "void main()\n"
1232 		<< "{\n"
1233 		<< "  for (uint i = 0; i < " << elementCount << "; ++i) {\n"
1234 		<< "    ssbo.data[gl_LaunchIDEXT.x][i] = srb.data[i];\n"
1235 		<< "  }\n"
1236 		<< "}\n"
1237 		;
1238 
1239 	std::ostringstream miss;
1240 	miss
1241 		<< commontHeaderStr
1242 		<< "\n"
1243 		<< descriptorsStr
1244 		<< "layout(location=0) rayPayloadInEXT vec4 unused;\n"
1245 		<< "\n"
1246 		<< "void main()\n"
1247 		<< "{\n"
1248 		<< "}\n"
1249 		;
1250 
1251 	programCollection.glslSources.add("rgen") << glu::RaygenSource(rgen.str()) << buildOptions;
1252 	programCollection.glslSources.add("chit") << glu::ClosestHitSource(chit.str()) << buildOptions;
1253 	programCollection.glslSources.add("miss") << glu::MissSource(miss.str()) << buildOptions;
1254 }
1255 
createInstance(Context & context) const1256 TestInstance* ShaderGroupHandleAlignmentCase::createInstance (Context& context) const
1257 {
1258 	return new ShaderGroupHandleAlignmentInstance(context, m_params);
1259 }
1260 
iterate(void)1261 tcu::TestStatus ShaderGroupHandleAlignmentInstance::iterate (void)
1262 {
1263 	const auto&	vki			= m_context.getInstanceInterface();
1264 	const auto	physDev		= m_context.getPhysicalDevice();
1265 	const auto&	vkd			= m_context.getDeviceInterface();
1266 	const auto	device		= m_context.getDevice();
1267 	auto&		alloc		= m_context.getDefaultAllocator();
1268 	const auto	qIndex		= m_context.getUniversalQueueFamilyIndex();
1269 	const auto	queue		= m_context.getUniversalQueue();
1270 	const auto	stages		= (VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR);
1271 	const auto	geoCount	= m_params.geometryCount();
1272 	const auto	triangleZ	= 5.0f;
1273 
1274 	// Command pool and buffer.
1275 	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
1276 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1277 	const auto cmdBuffer	= cmdBufferPtr.get();
1278 
1279 	beginCommandBuffer(vkd, cmdBuffer);
1280 
1281 	// Build acceleration structures.
1282 	auto topLevelAS		= makeTopLevelAccelerationStructure();
1283 	auto bottomLevelAS	= makeBottomLevelAccelerationStructure();
1284 
1285 	// Create the needed amount of geometries (triangles) with the right coordinates.
1286 	const tcu::Vec3	baseLocation	(0.5f, 0.5f, triangleZ);
1287 	const float		vertexOffset	= 0.25f; // From base location, to build a triangle around it.
1288 
1289 	for (uint32_t i = 0; i < geoCount; ++i)
1290 	{
1291 		// Triangle "center" or base location.
1292 		const tcu::Vec3					triangleLocation (baseLocation.x() + static_cast<float>(i), baseLocation.y(), baseLocation.z());
1293 
1294 		// Actual triangle.
1295 		const std::vector<tcu::Vec3>	triangle
1296 		{
1297 			tcu::Vec3(triangleLocation.x() - vertexOffset, triangleLocation.y() - vertexOffset, triangleLocation.z()),
1298 			tcu::Vec3(triangleLocation.x() + vertexOffset, triangleLocation.y() - vertexOffset, triangleLocation.z()),
1299 			tcu::Vec3(triangleLocation.x(),                triangleLocation.y() + vertexOffset, triangleLocation.z()),
1300 		};
1301 
1302 		bottomLevelAS->addGeometry(triangle, true/*triangles*/);
1303 	}
1304 
1305 	bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
1306 
1307 	de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr (bottomLevelAS.release());
1308 	topLevelAS->setInstanceCount(1);
1309 	topLevelAS->addInstance(blasSharedPtr, identityMatrix3x4, 0u, 0xFF, 0u, VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR);
1310 	topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
1311 
1312 	// Get some ray tracing properties.
1313 	uint32_t shaderGroupHandleSize		= 0u;
1314 	uint32_t shaderGroupBaseAlignment	= 1u;
1315 	{
1316 		const auto rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physDev);
1317 		shaderGroupHandleSize				= rayTracingPropertiesKHR->getShaderGroupHandleSize();
1318 		shaderGroupBaseAlignment			= rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
1319 	}
1320 
1321 	// SSBO to copy results over from the shaders.
1322 	const auto			shaderRecordSize	= m_params.alignment;
1323 	const auto			hitSBTStride		= shaderGroupHandleSize + shaderRecordSize;
1324 	const auto			ssboSize			= static_cast<VkDeviceSize>(geoCount * hitSBTStride);
1325 	const auto			ssboInfo			= makeBufferCreateInfo(ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1326 	BufferWithMemory	ssbo				(vkd, device, alloc, ssboInfo, MemoryRequirement::HostVisible);
1327 	auto&				ssboAlloc			= ssbo.getAllocation();
1328 	void*				ssboData			= ssboAlloc.getHostPtr();
1329 
1330 	deMemset(ssboData, 0, static_cast<size_t>(ssboSize));
1331 
1332 	// Descriptor set layout and pipeline layout.
1333 	DescriptorSetLayoutBuilder setLayoutBuilder;
1334 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
1335 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
1336 	const auto setLayout		= setLayoutBuilder.build(vkd, device);
1337 	const auto pipelineLayout	= makePipelineLayout(vkd, device, setLayout.get());
1338 
1339 	// Descriptor pool and set.
1340 	DescriptorPoolBuilder poolBuilder;
1341 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
1342 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
1343 	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1344 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
1345 
1346 	// Update descriptor set.
1347 	{
1348 		const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
1349 		{
1350 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
1351 			nullptr,
1352 			1u,
1353 			topLevelAS.get()->getPtr(),
1354 		};
1355 
1356 		const auto ssboDescInfo = makeDescriptorBufferInfo(ssbo.get(), 0ull, ssboSize);
1357 
1358 		DescriptorSetUpdateBuilder updateBuilder;
1359 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
1360 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboDescInfo);
1361 		updateBuilder.update(vkd, device);
1362 	}
1363 
1364 	// Shader modules.
1365 	auto rgenModule = makeVkSharedPtr(createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0));
1366 	auto missModule = makeVkSharedPtr(createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0));
1367 	auto chitModule = makeVkSharedPtr(createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0));
1368 
1369 	// Create raytracing pipeline and shader binding tables.
1370 	Move<VkPipeline>				pipeline;
1371 
1372 	de::MovePtr<BufferWithMemory>	raygenSBT;
1373 	de::MovePtr<BufferWithMemory>	missSBT;
1374 	de::MovePtr<BufferWithMemory>	hitSBT;
1375 	de::MovePtr<BufferWithMemory>	callableSBT;
1376 
1377 	VkStridedDeviceAddressRegionKHR	raygenSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1378 	VkStridedDeviceAddressRegionKHR	missSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1379 	VkStridedDeviceAddressRegionKHR	hitSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1380 	VkStridedDeviceAddressRegionKHR	callableSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1381 
1382 	// Create shader record buffer data.
1383 	using DataVec = std::vector<uint8_t>;
1384 
1385 	std::vector<DataVec> srbData;
1386 	for (uint32_t i = 0; i < geoCount; ++i)
1387 	{
1388 		srbData.emplace_back(m_params.getRecordData(i));
1389 	}
1390 
1391 	std::vector<const void*> srbDataPtrs;
1392 	srbDataPtrs.reserve(srbData.size());
1393 	std::transform(begin(srbData), end(srbData), std::back_inserter(srbDataPtrs), [](const DataVec& data) { return data.data(); });
1394 
1395 	// Generate ids for the closest hit and miss shaders according to the test parameters.
1396 	{
1397 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1398 
1399 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0u);
1400 		rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, missModule, 1u);
1401 
1402 		for (uint32_t i = 0; i < geoCount; ++i)
1403 			rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, 2u + i);
1404 
1405 		pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
1406 
1407 		raygenSBT		= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0u, 1u);
1408 		raygenSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1409 
1410 		missSBT			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1u, 1u);
1411 		missSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
1412 
1413 		hitSBT			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 2u, geoCount,
1414 																	   0u, 0u, MemoryRequirement::Any, 0u, 0u, shaderRecordSize, srbDataPtrs.data(), false/*autoalign*/);
1415 		hitSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitSBT->get(), 0), hitSBTStride, hitSBTStride*geoCount);
1416 	}
1417 
1418 	// Trace rays and verify ssbo contents.
1419 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
1420 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1421 	vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, geoCount, 1u, 1u);
1422 	const auto shaderToHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1423 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_HOST_BIT, &shaderToHostBarrier);
1424 
1425 	endCommandBuffer(vkd, cmdBuffer);
1426 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1427 
1428 	invalidateAlloc(vkd, device, ssboAlloc);
1429 
1430 	// Verify SSBO.
1431 	const auto	ssboDataAsBytes	= reinterpret_cast<const uint8_t*>(ssboData);
1432 	size_t		ssboDataIdx		= 0u;
1433 	bool		fail			= false;
1434 	auto&		log				= m_context.getTestContext().getLog();
1435 
1436 	for (const auto& dataVec : srbData)
1437 		for (const uint8_t byte : dataVec)
1438 		{
1439 			const uint8_t outputByte = ssboDataAsBytes[ssboDataIdx++];
1440 			if (byte != outputByte)
1441 			{
1442 				std::ostringstream msg;
1443 				msg
1444 					<< std::hex << std::setfill('0')
1445 					<< "Unexpectd output data: "
1446 					<< "0x" << std::setw(2) << static_cast<int>(outputByte)
1447 					<< " vs "
1448 					<< "0x" << std::setw(2) << static_cast<int>(byte)
1449 					;
1450 				log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
1451 				fail = true;
1452 			}
1453 		}
1454 
1455 	if (fail)
1456 		return tcu::TestStatus::fail("Unexpected output data found; check log for details");
1457 	return tcu::TestStatus::pass("Pass");
1458 }
1459 
1460 }	// anonymous
1461 
createShaderBindingTableTests(tcu::TestContext & testCtx)1462 tcu::TestCaseGroup*	createShaderBindingTableTests (tcu::TestContext& testCtx)
1463 {
1464 	// Tests veryfying shader binding tables
1465 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_binding_table"));
1466 
1467 	struct ShaderTestTypeData
1468 	{
1469 		ShaderTestType							shaderTestType;
1470 		const char*								name;
1471 	} shaderTestTypes[] =
1472 	{
1473 		{ STT_HIT,		"indexing_hit"	},
1474 		{ STT_MISS,		"indexing_miss"	},
1475 		{ STT_CALL,		"indexing_call"	},
1476 	};
1477 
1478 	struct ShaderBufferOffsetData
1479 	{
1480 		deUint32								sbtOffset;
1481 		const char*								name;
1482 	} shaderBufferOffsets[] =
1483 	{
1484 		{ 0u,	"sbt_offset_0"	},
1485 		{ 4u,	"sbt_offset_4"	},
1486 		{ 7u,	"sbt_offset_7"	},
1487 		{ 16u,	"sbt_offset_16"	},
1488 	};
1489 
1490 	struct ShaderRecordData
1491 	{
1492 		bool									present;
1493 		const char*								name;
1494 	} shaderRecords[] =
1495 	{
1496 		{ false,	"no_shaderrecord"	},
1497 		{ true,		"shaderrecord"		},
1498 	};
1499 
1500 	for (size_t shaderTestNdx = 0; shaderTestNdx < DE_LENGTH_OF_ARRAY(shaderTestTypes); ++shaderTestNdx)
1501 	{
1502 		de::MovePtr<tcu::TestCaseGroup> shaderTestGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderTestTypes[shaderTestNdx].name));
1503 
1504 		for (size_t sbtOffsetNdx = 0; sbtOffsetNdx < DE_LENGTH_OF_ARRAY(shaderBufferOffsets); ++sbtOffsetNdx)
1505 		{
1506 			de::MovePtr<tcu::TestCaseGroup> sbtOffsetGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderBufferOffsets[sbtOffsetNdx].name));
1507 
1508 			for (size_t shaderRecordNdx = 0; shaderRecordNdx < DE_LENGTH_OF_ARRAY(shaderRecords); ++shaderRecordNdx)
1509 			{
1510 				de::MovePtr<tcu::TestCaseGroup> shaderRecordGroup(new tcu::TestCaseGroup(group->getTestContext(), shaderRecords[shaderRecordNdx].name));
1511 
1512 				deUint32		maxSbtRecordStride				= (shaderTestTypes[shaderTestNdx].shaderTestType == STT_HIT) ? MAX_HIT_SBT_RECORD_STRIDE + 1 : 1;
1513 				deUint32		maxSbtRecordOffset				= MAX_SBT_RECORD_OFFSET;
1514 				const deUint32	maxSbtRecordOffsetWithExtraBits = (shaderTestTypes[shaderTestNdx].shaderTestType == STT_MISS)	? MAX_SBT_RECORD_OFFSET | (~((1u << 16) - 1))  //< Only 16 least significant bits matter for miss indices
1515 																																: MAX_SBT_RECORD_OFFSET | (~((1u << 4)  - 1)); //< Only 4 least significant bits matter for SBT record offsets
1516 
1517 				for (deUint32 sbtRecordOffset = 0; sbtRecordOffset <= maxSbtRecordOffset; ++sbtRecordOffset)
1518 					for (deUint32 sbtRecordStride = 0; sbtRecordStride <= maxSbtRecordStride; ++sbtRecordStride)
1519 					{
1520 						if ((shaderTestTypes[shaderTestNdx].shaderTestType	!= STT_HIT)				&&
1521 							(sbtRecordStride								== maxSbtRecordStride))
1522 						{
1523 							continue;
1524 						}
1525 
1526 						TestParams testParams
1527 						{
1528 							CHECKERBOARD_WIDTH,
1529 							CHECKERBOARD_HEIGHT,
1530 							shaderTestTypes[shaderTestNdx].shaderTestType,
1531 							shaderBufferOffsets[sbtOffsetNdx].sbtOffset,
1532 							shaderRecords[shaderRecordNdx].present,
1533 							sbtRecordOffset,
1534 							(sbtRecordOffset == maxSbtRecordOffset)	? maxSbtRecordOffsetWithExtraBits
1535 																	: sbtRecordOffset,
1536 							//< Only first 4 least significant bits matter for SBT record stride
1537 							sbtRecordStride,
1538 							(sbtRecordStride == maxSbtRecordStride)	? maxSbtRecordStride | (~((1u << 4) - 1))
1539 																	: sbtRecordStride,
1540 							de::SharedPtr<TestConfiguration>(new CheckerboardConfiguration())
1541 						};
1542 
1543 						std::stringstream str;
1544 						str << sbtRecordOffset << "_" << sbtRecordStride;
1545 
1546 						if (testParams.sbtRecordStride != testParams.sbtRecordStridePassedToTraceRay)
1547 						{
1548 							str << "_extraSBTRecordStrideBits";
1549 						}
1550 
1551 						if (testParams.sbtRecordOffset != testParams.sbtRecordOffsetPassedToTraceRay)
1552 						{
1553 							str << "_extrabits";
1554 						}
1555 
1556 						shaderRecordGroup->addChild(new ShaderBindingTableIndexingTestCase(group->getTestContext(), str.str().c_str(), testParams));
1557 					}
1558 
1559 				sbtOffsetGroup->addChild(shaderRecordGroup.release());
1560 			}
1561 
1562 			shaderTestGroup->addChild(sbtOffsetGroup.release());
1563 		}
1564 
1565 		group->addChild(shaderTestGroup.release());
1566 	}
1567 
1568 	{
1569 		const uint32_t					kAlignments[]			= { 1u, 2u, 4u, 8u, 16u, 32u };
1570 		de::MovePtr<tcu::TestCaseGroup>	handleAlignmentGroup	(new tcu::TestCaseGroup(testCtx, "handle_alignment", "Test allowed handle alignments"));
1571 
1572 		for (const auto alignment : kAlignments)
1573 		{
1574 			const auto alignStr = std::to_string(alignment);
1575 			const auto testName = "alignment_" + alignStr;
1576 			// Check aligning shader group handles
1577 			handleAlignmentGroup->addChild(new ShaderGroupHandleAlignmentCase(testCtx, testName, ShaderGroupHandleAlignmentParams{alignment}));
1578 		}
1579 
1580 		group->addChild(handleAlignmentGroup.release());
1581 	}
1582 
1583 	return group.release();
1584 }
1585 
1586 }	// RayTracing
1587 
1588 }	// vkt
1589