• 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 Capture/Replay tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingCaptureReplayTests.hpp"
25 
26 #include <set>
27 #include "vkDefs.hpp"
28 
29 #include "vktTestCase.hpp"
30 #include "vktTestGroupUtil.hpp"
31 #include "vktCustomInstancesDevices.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBufferWithMemory.hpp"
37 #include "vkImageWithMemory.hpp"
38 #include "vkTypeUtil.hpp"
39 
40 #include "vkRayTracingUtil.hpp"
41 
42 #include "tcuCommandLine.hpp"
43 
44 namespace vkt
45 {
46 namespace RayTracing
47 {
48 namespace
49 {
50 using namespace vk;
51 using namespace vkt;
52 
53 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
54 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
55 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
56 												| VK_SHADER_STAGE_MISS_BIT_KHR
57 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
58 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
59 
60 static const deUint32	RTCR_DEFAULT_SIZE = 8u;
61 static const deUint32	RTCR_SHADER_COUNT = 4u;
62 
63 enum SBTReplayTestType
64 {
65 	TEST_ACCELERATION_STRUCTURES,
66 	TEST_PIPELINE_SINGLE,
67 	TEST_PIPELINE_AFTER,
68 	TEST_PIPELINE_BEFORE
69 };
70 
71 enum ASOperationTarget
72 {
73 	OT_NONE,
74 	OT_TOP_ACCELERATION,
75 	OT_BOTTOM_ACCELERATION
76 };
77 
78 enum ASOperationType
79 {
80 	OP_NONE,
81 	OP_COPY,
82 	OP_COMPACT,
83 	OP_SERIALIZE
84 };
85 
86 enum ASBottomTestType
87 {
88 	BTT_TRIANGLES,
89 	BTT_AABBS
90 };
91 
92 enum ASTopTestType
93 {
94 	TTT_IDENTICAL_INSTANCES,
95 	TTT_DIFFERENT_INSTANCES
96 };
97 
98 struct TestParams;
99 
100 struct PipelineOutput
101 {
102 	Move<VkPipeline>				pipeline;
103 	de::MovePtr<BufferWithMemory>	raygenShaderBindingTable;
104 	de::MovePtr<BufferWithMemory>	missShaderBindingTable;
105 	de::MovePtr<BufferWithMemory>	hitShaderBindingTable;
106 	Move<VkDescriptorSet>			descriptorSet;
107 	de::MovePtr<BufferWithMemory>	uniformBuffer;
108 
109 	VkStridedDeviceAddressRegionKHR	raygenShaderBindingTableRegion;
110 	VkStridedDeviceAddressRegionKHR	missShaderBindingTableRegion;
111 	VkStridedDeviceAddressRegionKHR	hitShaderBindingTableRegion;
112 	VkStridedDeviceAddressRegionKHR	callableShaderBindingTableRegion;
113 };
114 
115 struct PipelineData
116 {
PipelineDatavkt::RayTracing::__anoncb767d2a0111::PipelineData117 	PipelineData(Allocator& alloc)
118 		: allocator(alloc)
119 	{}
120 	VkDescriptorSetLayout			descriptorSetLayout;
121 	VkDescriptorPool				descriptorPool;
122 	VkPipelineLayout				pipelineLayout;
123 	Allocator&						allocator;
124 	PipelineOutput					pipelines[2];
125 };
126 
127 class TestConfiguration
128 {
129 public:
130 	virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
131 																												 TestParams&						testParams) = 0;
132 	virtual de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
133 																												 TestParams&						testParams,
134 																												 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) = 0;
135 	virtual void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
136 																												 Context&							context,
137 																												 const DeviceInterface&				vkd,
138 																												 const VkDevice						device,
139 																												 TestParams&						testParams,
140 																												 bool								replay) = 0;
141 	virtual void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
142 																												 Context&							context,
143 																												 const DeviceInterface&				vkd,
144 																												 const VkDevice						device,
145 																												 TestParams&						testParams,
146 																												 deUint32							shaderGroupHandleSize,
147 																												 deUint32							shaderGroupBaseAlignment,
148 																												 PipelineData&						pipelineData,
149 																												 bool								replay) = 0;
150 	virtual bool															verifyImage							(const std::vector<deUint32>&		captureResults,
151 																												 const std::vector<deUint32>&		replayResults,
152 																												 Context&							context,
153 																												 TestParams&						testParams) = 0;
154 	virtual VkFormat														getResultImageFormat				() = 0;
155 	virtual size_t															getResultImageFormatSize			() = 0;
156 	virtual VkClearValue													getClearValue						() = 0;
157 };
158 
159 struct TestParams
160 {
161 	SBTReplayTestType							testType;			// SBT
162 	ASOperationTarget							operationTarget;	// AS
163 	ASOperationType								operationType;		// AS
164 	vk::VkAccelerationStructureBuildTypeKHR		buildType;			// AS
165 	ASBottomTestType							bottomType;			// AS
166 	ASTopTestType								topType;			// AS
167 	deUint32									width;
168 	deUint32									height;
169 	de::SharedPtr<TestConfiguration>			testConfiguration;
170 };
171 
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)172 deUint32 getShaderGroupSize (const InstanceInterface&	vki,
173 							 const VkPhysicalDevice		physicalDevice)
174 {
175 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
176 
177 	rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physicalDevice);
178 	return rayTracingPropertiesKHR->getShaderGroupHandleSize();
179 }
180 
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)181 deUint32 getShaderGroupBaseAlignment (const InstanceInterface&	vki,
182 									  const VkPhysicalDevice	physicalDevice)
183 {
184 	de::MovePtr<RayTracingProperties>	rayTracingPropertiesKHR;
185 
186 	rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
187 	return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
188 }
189 
makeImageCreateInfo(deUint32 width,deUint32 height,deUint32 depth,VkFormat format)190 VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
191 {
192 	const VkImageCreateInfo			imageCreateInfo			=
193 	{
194 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
195 		DE_NULL,																							// const void*				pNext;
196 		(VkImageCreateFlags)0u,																				// VkImageCreateFlags		flags;
197 		VK_IMAGE_TYPE_3D,																					// VkImageType				imageType;
198 		format,																								// VkFormat					format;
199 		makeExtent3D(width, height, depth),																	// VkExtent3D				extent;
200 		1u,																									// deUint32					mipLevels;
201 		1u,																									// deUint32					arrayLayers;
202 		VK_SAMPLE_COUNT_1_BIT,																				// VkSampleCountFlagBits	samples;
203 		VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
204 		VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,		// VkImageUsageFlags		usage;
205 		VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
206 		0u,																									// deUint32					queueFamilyIndexCount;
207 		DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
208 		VK_IMAGE_LAYOUT_UNDEFINED																			// VkImageLayout			initialLayout;
209 	};
210 
211 	return imageCreateInfo;
212 }
213 
makeQueryPool(const DeviceInterface & vk,const VkDevice device,const VkQueryType queryType,deUint32 queryCount)214 Move<VkQueryPool> makeQueryPool(const DeviceInterface&		vk,
215 								const VkDevice				device,
216 								const VkQueryType			queryType,
217 								deUint32					queryCount)
218 {
219 	const VkQueryPoolCreateInfo				queryPoolCreateInfo =
220 	{
221 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// sType
222 		DE_NULL,										// pNext
223 		(VkQueryPoolCreateFlags)0,						// flags
224 		queryType,										// queryType
225 		queryCount,										// queryCount
226 		0u,												// pipelineStatistics
227 	};
228 	return createQueryPool(vk, device, &queryPoolCreateInfo);
229 }
230 
getAccelerationStructureDeviceAddress(const DeviceInterface & vk,const VkDevice device,VkAccelerationStructureKHR accelerationStructure)231 VkDeviceAddress getAccelerationStructureDeviceAddress (const DeviceInterface&						vk,
232 													   const VkDevice								device,
233 													   VkAccelerationStructureKHR					accelerationStructure)
234 {
235 	const VkAccelerationStructureDeviceAddressInfoKHR addressInfo =
236 	{
237 		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType               sType;
238 		DE_NULL,															// const void*                   pNext;
239 		accelerationStructure												// VkAccelerationStructureKHR    accelerationStructure
240 	};
241 	return vk.getAccelerationStructureDeviceAddressKHR(device, &addressInfo);
242 }
243 
244 class TestShaderBindingTablesConfiguration : public TestConfiguration
245 {
246 public:
247 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
248 																										 TestParams&						testParams) override;
249 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
250 																										 TestParams&						testParams,
251 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
252 	void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
253 																										 Context&							context,
254 																										 const DeviceInterface&				vkd,
255 																										 const VkDevice						device,
256 																										 TestParams&						testParams,
257 																										 bool								replay) override;
258 	void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
259 																										 Context&							context,
260 																										 const DeviceInterface&				vkd,
261 																										 const VkDevice						device,
262 																										 TestParams&						testParams,
263 																										 deUint32							shaderGroupHandleSize,
264 																										 deUint32							shaderGroupBaseAlignment,
265 																										 PipelineData&						pipelineData,
266 																										 bool								replay) override;
267 	bool															verifyImage							(const std::vector<deUint32>&		captureResults,
268 																										 const std::vector<deUint32>&		replayResults,
269 																										 Context&							context,
270 																										 TestParams&						testParams) override;
271 	VkFormat														getResultImageFormat				() override;
272 	size_t															getResultImageFormatSize			() override;
273 	VkClearValue													getClearValue						() override;
274 protected:
275 	VkDeviceAddress													sbtSavedRaygenAddress	= 0u;
276 	VkDeviceAddress													sbtSavedMissAddress		= 0u;
277 	VkDeviceAddress													sbtSavedHitAddress		= 0u;
278 };
279 
initBottomAccelerationStructures(Context & context,TestParams & testParams)280 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > TestShaderBindingTablesConfiguration::initBottomAccelerationStructures (Context&					context,
281 																																	  TestParams&				testParams)
282 {
283 	DE_UNREF(context);
284 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
285 
286 	tcu::Vec3 v0(0.0, 1.0, 0.0);
287 	tcu::Vec3 v1(0.0, 0.0, 0.0);
288 	tcu::Vec3 v2(1.0, 1.0, 0.0);
289 	tcu::Vec3 v3(1.0, 0.0, 0.0);
290 
291 	for (deUint32 y = 0; y < testParams.height; ++y)
292 	for (deUint32 x = 0; x < testParams.width; ++x)
293 	{
294 		// let's build a chessboard of geometries
295 		if (((x + y) % 2) == 0)
296 			continue;
297 		tcu::Vec3 xyz((float)x, (float)y, 0.0f);
298 		std::vector<tcu::Vec3>	geometryData;
299 
300 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
301 		bottomLevelAccelerationStructure->setGeometryCount(1u);
302 
303 		geometryData.push_back(xyz + v0);
304 		geometryData.push_back(xyz + v1);
305 		geometryData.push_back(xyz + v2);
306 		geometryData.push_back(xyz + v2);
307 		geometryData.push_back(xyz + v1);
308 		geometryData.push_back(xyz + v3);
309 
310 		bottomLevelAccelerationStructure->addGeometry(geometryData, true);
311 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
312 	}
313 
314 	return result;
315 }
316 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)317 de::MovePtr<TopLevelAccelerationStructure> TestShaderBindingTablesConfiguration::initTopAccelerationStructure (Context&					context,
318 																											   TestParams&				testParams,
319 																											   std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures)
320 {
321 	DE_UNREF(context);
322 	deUint32 instanceCount = testParams.width * testParams.height / 2;
323 
324 	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
325 	result->setInstanceCount(instanceCount);
326 
327 	deUint32				currentInstanceIndex = 0;
328 	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 } } };
329 
330 	for (deUint32 y = 0; y < testParams.height; ++y)
331 	{
332 		deUint32 shaderOffset = y % RTCR_SHADER_COUNT;
333 		for (deUint32 x = 0; x < testParams.width; ++x)
334 		{
335 			if (((x + y) % 2) == 0)
336 				continue;
337 			result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], identityMatrix, 0, 0xFF, shaderOffset);
338 		}
339 	}
340 
341 	return result;
342 }
343 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,bool replay)344 void TestShaderBindingTablesConfiguration::initRayTracingShaders (de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
345 																  Context&								context,
346 																  const DeviceInterface&				vkd,
347 																  const VkDevice						device,
348 																  TestParams&							testParams,
349 																  bool									replay)
350 {
351 	DE_UNREF(testParams);
352 	DE_UNREF(replay);
353 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"), 0), 0);
354 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get("miss"), 0), 1);
355 	for (deUint32 shaderNdx = 0; shaderNdx < RTCR_SHADER_COUNT; ++shaderNdx)
356 	{
357 		std::stringstream shaderName;
358 		shaderName << "chit" << shaderNdx;
359 		rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, createShaderModule(vkd, device, context.getBinaryCollection().get(shaderName.str()), 0), 2 + shaderNdx);
360 	}
361 }
362 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,PipelineData & pipelineData,bool replay)363 void TestShaderBindingTablesConfiguration::initShaderBindingTables (de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
364 																	Context&							context,
365 																	const DeviceInterface&				vkd,
366 																	const VkDevice						device,
367 																	TestParams&							testParams,
368 																	deUint32							shaderGroupHandleSize,
369 																	deUint32							shaderGroupBaseAlignment,
370 																	PipelineData&						pipelineData,
371 																	bool								replay)
372 {
373 	DE_UNREF(context);
374 	const VkBufferCreateInfo				uniformBufferCreateInfo		= makeBufferCreateInfo(sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
375 
376 	if (!replay) // capture phase
377 	{
378 		pipelineData.pipelines[0].pipeline								= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
379 		pipelineData.pipelines[0].raygenShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u);
380 		pipelineData.pipelines[0].missShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u);
381 		pipelineData.pipelines[0].hitShaderBindingTable					= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, MemoryRequirement::DeviceAddress, 0u);
382 		pipelineData.pipelines[0].descriptorSet							= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
383 		pipelineData.pipelines[0].uniformBuffer							= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
384 		pipelineData.pipelines[0].raygenShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
385 		pipelineData.pipelines[0].missShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
386 		pipelineData.pipelines[0].hitShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
387 		pipelineData.pipelines[0].callableShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
388 
389 		// capture SBT addresses
390 		VkBufferDeviceAddressInfo	deviceAddressInfo	=
391 		{
392 			VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,	//VkStructureType    sType;
393 			DE_NULL,										//const void*        pNext;
394 			DE_NULL											//VkBuffer           buffer;
395 		};
396 		deviceAddressInfo.buffer										= pipelineData.pipelines[0].raygenShaderBindingTable->get();
397 		sbtSavedRaygenAddress											= vkd.getBufferOpaqueCaptureAddress( device, &deviceAddressInfo);
398 		deviceAddressInfo.buffer										= pipelineData.pipelines[0].missShaderBindingTable->get();
399 		sbtSavedMissAddress												= vkd.getBufferOpaqueCaptureAddress( device, &deviceAddressInfo);
400 		deviceAddressInfo.buffer										= pipelineData.pipelines[0].hitShaderBindingTable->get();
401 		sbtSavedHitAddress												= vkd.getBufferOpaqueCaptureAddress( device, &deviceAddressInfo);
402 	}
403 	else // replay phase
404 	{
405 		switch (testParams.testType)
406 		{
407 		case TEST_PIPELINE_SINGLE:
408 			pipelineData.pipelines[0].pipeline							= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
409 			pipelineData.pipelines[0].raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress);
410 			pipelineData.pipelines[0].missShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress);
411 			pipelineData.pipelines[0].hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress);
412 			pipelineData.pipelines[0].descriptorSet						= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
413 			pipelineData.pipelines[0].uniformBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
414 			pipelineData.pipelines[0].raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
415 			pipelineData.pipelines[0].missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
416 			pipelineData.pipelines[0].hitShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
417 			pipelineData.pipelines[0].callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
418 
419 			break;
420 		case TEST_PIPELINE_AFTER:
421 			pipelineData.pipelines[0].pipeline							= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
422 			pipelineData.pipelines[0].raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress);
423 			pipelineData.pipelines[0].missShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress);
424 			pipelineData.pipelines[0].hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress);
425 			pipelineData.pipelines[0].descriptorSet						= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
426 			pipelineData.pipelines[0].uniformBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
427 			pipelineData.pipelines[0].raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
428 			pipelineData.pipelines[0].missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
429 			pipelineData.pipelines[0].hitShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
430 			pipelineData.pipelines[0].callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
431 
432 			pipelineData.pipelines[1].pipeline							= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
433 			pipelineData.pipelines[1].raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, 0u);
434 			pipelineData.pipelines[1].missShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, 0u);
435 			pipelineData.pipelines[1].hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, 0u);
436 			pipelineData.pipelines[1].descriptorSet						= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
437 			pipelineData.pipelines[1].uniformBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
438 			pipelineData.pipelines[1].raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
439 			pipelineData.pipelines[1].missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
440 			pipelineData.pipelines[1].hitShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
441 			pipelineData.pipelines[1].callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
442 
443 			break;
444 		case TEST_PIPELINE_BEFORE:
445 			pipelineData.pipelines[0].pipeline							= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
446 			pipelineData.pipelines[0].raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, 0u);
447 			pipelineData.pipelines[0].missShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, 0u);
448 			pipelineData.pipelines[0].hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, 0u);
449 			pipelineData.pipelines[0].descriptorSet						= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
450 			pipelineData.pipelines[0].uniformBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
451 			pipelineData.pipelines[0].raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
452 			pipelineData.pipelines[0].missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
453 			pipelineData.pipelines[0].hitShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
454 			pipelineData.pipelines[0].callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
455 
456 			pipelineData.pipelines[1].pipeline							= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
457 			pipelineData.pipelines[1].raygenShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedRaygenAddress);
458 			pipelineData.pipelines[1].missShaderBindingTable			= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1, 0u, 0u, MemoryRequirement::Any, sbtSavedMissAddress);
459 			pipelineData.pipelines[1].hitShaderBindingTable				= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[1].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, RTCR_SHADER_COUNT, 0u, 0u, MemoryRequirement::Any, sbtSavedHitAddress);
460 			pipelineData.pipelines[1].descriptorSet						= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
461 			pipelineData.pipelines[1].uniformBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
462 			pipelineData.pipelines[1].raygenShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
463 			pipelineData.pipelines[1].missShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
464 			pipelineData.pipelines[1].hitShaderBindingTableRegion		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[1].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, RTCR_SHADER_COUNT * shaderGroupHandleSize);
465 			pipelineData.pipelines[1].callableShaderBindingTableRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
466 			break;
467 		default:
468 			TCU_THROW(InternalError, "Wrong test type");
469 		}
470 	}
471 }
472 
verifyImage(const std::vector<deUint32> & captureResults,const std::vector<deUint32> & replayResults,Context & context,TestParams & testParams)473 bool TestShaderBindingTablesConfiguration::verifyImage (const std::vector<deUint32>&		captureResults,
474 														const std::vector<deUint32>&		replayResults,
475 														Context&							context,
476 														TestParams&							testParams)
477 {
478 	DE_UNREF(context);
479 
480 	deUint32							pipelineCount	= (testParams.testType == TEST_PIPELINE_SINGLE) ? 1u : 2u;
481 	deUint32							imageSize		= testParams.height * testParams.width;
482 	deUint32							failures		= 0;
483 
484 	// verify results - each test case should generate checkerboard pattern
485 	for (deUint32 pipelineNdx = 0; pipelineNdx < pipelineCount; ++pipelineNdx)
486 	for (deUint32 pos = 0; pos < imageSize; ++pos)
487 	{
488 		if (captureResults[pos] != replayResults[pipelineNdx*imageSize + pos])
489 			failures++;
490 	}
491 	return failures == 0;
492 }
493 
getResultImageFormat()494 VkFormat TestShaderBindingTablesConfiguration::getResultImageFormat ()
495 {
496 	return VK_FORMAT_R32_UINT;
497 }
498 
getResultImageFormatSize()499 size_t TestShaderBindingTablesConfiguration::getResultImageFormatSize ()
500 {
501 	return sizeof(deUint32);
502 }
503 
getClearValue()504 VkClearValue TestShaderBindingTablesConfiguration::getClearValue ()
505 {
506 	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
507 }
508 
509 class TestAccelerationStructuresConfiguration : public TestConfiguration
510 {
511 public:
512 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	initBottomAccelerationStructures	(Context&							context,
513 																										 TestParams&						testParams) override;
514 	de::MovePtr<TopLevelAccelerationStructure>						initTopAccelerationStructure		(Context&							context,
515 																										 TestParams&						testParams,
516 																										 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures) override;
517 	void															initRayTracingShaders				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
518 																										 Context&							context,
519 																										 const DeviceInterface&				vkd,
520 																										 const VkDevice						device,
521 																										 TestParams&						testParams,
522 																										 bool								replay) override;
523 	void															initShaderBindingTables				(de::MovePtr<RayTracingPipeline>&	rayTracingPipeline,
524 																										 Context&							context,
525 																										 const DeviceInterface&				vkd,
526 																										 const VkDevice						device,
527 																										 TestParams&						testParams,
528 																										 deUint32							shaderGroupHandleSize,
529 																										 deUint32							shaderGroupBaseAlignment,
530 																										 PipelineData&						pipelineData,
531 																										 bool								replay) override;
532 	bool															verifyImage							(const std::vector<deUint32>&		captureResults,
533 																										 const std::vector<deUint32>&		replayResults,
534 																										 Context&							context,
535 																										 TestParams&						testParams) override;
536 	VkFormat														getResultImageFormat				() override;
537 	size_t															getResultImageFormatSize			() override;
538 	VkClearValue													getClearValue						() override;
539 protected:
540 	VkDeviceAddress													sbtSavedRaygenAddress	= 0u;
541 	VkDeviceAddress													sbtSavedMissAddress		= 0u;
542 	VkDeviceAddress													sbtSavedHitAddress		= 0u;
543 };
544 
initBottomAccelerationStructures(Context & context,TestParams & testParams)545 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> TestAccelerationStructuresConfiguration::initBottomAccelerationStructures (Context&				context,
546 																																		 TestParams&			testParams)
547 {
548 	DE_UNREF(context);
549 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	result;
550 
551 	tcu::Vec3 v0(0.0, 1.0, 0.0);
552 	tcu::Vec3 v1(0.0, 0.0, 0.0);
553 	tcu::Vec3 v2(1.0, 1.0, 0.0);
554 	tcu::Vec3 v3(1.0, 0.0, 0.0);
555 
556 	if (testParams.topType == TTT_DIFFERENT_INSTANCES)
557 	{
558 		de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
559 		bottomLevelAccelerationStructure->setGeometryCount(1u);
560 		de::SharedPtr<RaytracedGeometryBase> geometry;
561 		if (testParams.bottomType == BTT_TRIANGLES)
562 		{
563 			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
564 			geometry->addVertex(v0);
565 			geometry->addVertex(v1);
566 			geometry->addVertex(v2);
567 			geometry->addVertex(v2);
568 			geometry->addVertex(v1);
569 			geometry->addVertex(v3);
570 		}
571 		else // m_data.bottomType == BTT_AABBS
572 		{
573 			geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
574 			geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
575 			geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
576 		}
577 
578 		bottomLevelAccelerationStructure->addGeometry(geometry);
579 		result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
580 	}
581 	else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
582 	{
583 		// triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
584 		for (deUint32 y = 0; y < testParams.height; ++y)
585 			for (deUint32 x = 0; x < testParams.width; ++x)
586 			{
587 				// let's build a chessboard of geometries
588 				if (((x + y) % 2) == 0)
589 					continue;
590 				tcu::Vec3 xyz((float)x, (float)y, 0.0f);
591 
592 				de::MovePtr<BottomLevelAccelerationStructure>	bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
593 				bottomLevelAccelerationStructure->setGeometryCount(1u);
594 
595 				de::SharedPtr<RaytracedGeometryBase> geometry;
596 				if (testParams.bottomType == BTT_TRIANGLES)
597 				{
598 					geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
599 					geometry->addVertex(xyz + v0);
600 					geometry->addVertex(xyz + v1);
601 					geometry->addVertex(xyz + v2);
602 					geometry->addVertex(xyz + v2);
603 					geometry->addVertex(xyz + v1);
604 					geometry->addVertex(xyz + v3);
605 				}
606 				else // testParams.bottomTestType == BTT_AABBS
607 				{
608 					geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
609 					geometry->addVertex(xyz + tcu::Vec3(0.0f, 0.0f, -0.1f));
610 					geometry->addVertex(xyz + tcu::Vec3(1.0f, 1.0f, 0.1f));
611 				}
612 
613 				bottomLevelAccelerationStructure->addGeometry(geometry);
614 				result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
615 			}
616 	}
617 
618 	return result;
619 }
620 
initTopAccelerationStructure(Context & context,TestParams & testParams,std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)621 de::MovePtr<TopLevelAccelerationStructure> TestAccelerationStructuresConfiguration::initTopAccelerationStructure (Context&					context,
622 																												  TestParams&				testParams,
623 																												  std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >&	bottomLevelAccelerationStructures)
624 {
625 	DE_UNREF(context);
626 
627 	deUint32 instanceCount = testParams.width * testParams.height / 2;
628 
629 	de::MovePtr<TopLevelAccelerationStructure>	result = makeTopLevelAccelerationStructure();
630 	result->setInstanceCount(instanceCount);
631 
632 	if (testParams.topType == TTT_DIFFERENT_INSTANCES)
633 	{
634 
635 		for (deUint32 y = 0; y < testParams.height; ++y)
636 		for (deUint32 x = 0; x < testParams.width; ++x)
637 		{
638 			if (((x + y) % 2) == 0)
639 				continue;
640 			const VkTransformMatrixKHR			transformMatrixKHR =
641 			{
642 				{								//  float	matrix[3][4];
643 					{ 1.0f, 0.0f, 0.0f, (float)x },
644 					{ 0.0f, 1.0f, 0.0f, (float)y },
645 					{ 0.0f, 0.0f, 1.0f, 0.0f },
646 				}
647 			};
648 			result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR);
649 		}
650 	}
651 	else // testParams.topType == TTT_IDENTICAL_INSTANCES
652 	{
653 		deUint32 currentInstanceIndex = 0;
654 
655 		for (deUint32 y = 0; y < testParams.height; ++y)
656 		for (deUint32 x = 0; x < testParams.width; ++x)
657 		{
658 			if (((x + y) % 2) == 0)
659 				continue;
660 			result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++]);
661 		}
662 	}
663 
664 	return result;
665 }
666 
initRayTracingShaders(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,bool replay)667 void TestAccelerationStructuresConfiguration::initRayTracingShaders (de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
668 																	 Context&								context,
669 																	 const DeviceInterface&					vkd,
670 																	 const VkDevice							device,
671 																	 TestParams&							testParams,
672 																	 bool									replay)
673 {
674 	DE_UNREF(testParams);
675 	DE_UNREF(replay);
676 	rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,		createShaderModule(vkd, device, context.getBinaryCollection().get("rgen"),  0), 0);
677 	rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get("chit1"),  0), 1);
678 	rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get("chit1"),  0), 2);
679 	rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vkd, device, context.getBinaryCollection().get("isect"), 0), 2);
680 	rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, context.getBinaryCollection().get("miss"),  0), 3);
681 
682 }
683 
initShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,Context & context,const DeviceInterface & vkd,const VkDevice device,TestParams & testParams,deUint32 shaderGroupHandleSize,deUint32 shaderGroupBaseAlignment,PipelineData & pipelineData,bool replay)684 void TestAccelerationStructuresConfiguration::initShaderBindingTables (de::MovePtr<RayTracingPipeline>&		rayTracingPipeline,
685 																	   Context&								context,
686 																	   const DeviceInterface&				vkd,
687 																	   const VkDevice						device,
688 																	   TestParams&							testParams,
689 																	   deUint32								shaderGroupHandleSize,
690 																	   deUint32								shaderGroupBaseAlignment,
691 																	   PipelineData&						pipelineData,
692 																	   bool									replay)
693 {
694 	DE_UNREF(context);
695 	DE_UNREF(replay);
696 	const VkBufferCreateInfo				uniformBufferCreateInfo		= makeBufferCreateInfo(sizeof(deUint32), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
697 
698 	pipelineData.pipelines[0].pipeline									= rayTracingPipeline->createPipeline(vkd, device, pipelineData.pipelineLayout);
699 	pipelineData.pipelines[0].raygenShaderBindingTable					= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1 );
700 	if(testParams.bottomType == BTT_AABBS)
701 		pipelineData.pipelines[0].hitShaderBindingTable					= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1 );
702 	else // testParams.bottomType == BTT_TRIANGLES
703 		pipelineData.pipelines[0].hitShaderBindingTable					= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1 );
704 	pipelineData.pipelines[0].missShaderBindingTable					= rayTracingPipeline->createShaderBindingTable(vkd, device, *(pipelineData.pipelines[0].pipeline), pipelineData.allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1 );
705 	pipelineData.pipelines[0].descriptorSet								= makeDescriptorSet(vkd, device, pipelineData.descriptorPool, pipelineData.descriptorSetLayout);
706 	pipelineData.pipelines[0].uniformBuffer								= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, pipelineData.allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
707 	pipelineData.pipelines[0].raygenShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
708 	pipelineData.pipelines[0].missShaderBindingTableRegion				= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
709 	pipelineData.pipelines[0].hitShaderBindingTableRegion				= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, pipelineData.pipelines[0].hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
710 	pipelineData.pipelines[0].callableShaderBindingTableRegion			= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
711 
712 }
713 
verifyImage(const std::vector<deUint32> & captureResults,const std::vector<deUint32> & replayResults,Context & context,TestParams & testParams)714 bool TestAccelerationStructuresConfiguration::verifyImage (const std::vector<deUint32>&		captureResults,
715 														   const std::vector<deUint32>&		replayResults,
716 														   Context&							context,
717 														   TestParams&						testParams)
718 {
719 	DE_UNREF(context);
720 
721 	deUint32							imageSize		= testParams.height * testParams.width;
722 	deUint32							failures		= 0;
723 
724 	// verify results - each test case should generate checkerboard pattern
725 	for (deUint32 pos = 0; pos < imageSize; ++pos)
726 	{
727 		if (captureResults[pos] != replayResults[pos])
728 			failures++;
729 	}
730 	return failures == 0;
731 }
732 
getResultImageFormat()733 VkFormat TestAccelerationStructuresConfiguration::getResultImageFormat ()
734 {
735 	return VK_FORMAT_R32_UINT;
736 }
737 
getResultImageFormatSize()738 size_t TestAccelerationStructuresConfiguration::getResultImageFormatSize ()
739 {
740 	return sizeof(deUint32);
741 }
742 
getClearValue()743 VkClearValue TestAccelerationStructuresConfiguration::getClearValue ()
744 {
745 	return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
746 }
747 
748 class RayTracingCaptureReplayTestCase : public TestCase
749 {
750 	public:
751 							RayTracingCaptureReplayTestCase				(tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
752 							~RayTracingCaptureReplayTestCase			(void);
753 
754 	virtual void			checkSupport								(Context& context) const;
755 	virtual	void			initPrograms								(SourceCollections& programCollection) const;
756 	virtual TestInstance*	createInstance								(Context& context) const;
757 private:
758 	TestParams				m_data;
759 };
760 
761 class RayTracingCaptureReplayTestInstance : public TestInstance
762 {
763 public:
764 																	RayTracingCaptureReplayTestInstance		(Context& context, const TestParams& data);
765 																	~RayTracingCaptureReplayTestInstance	(void);
766 	tcu::TestStatus													iterate									(void);
767 
768 protected:
769 	std::vector<deUint32>											runTest									(bool replay);
770 private:
771 	TestParams														m_data;
772 	std::vector<VkDeviceAddress>									buildBLASAddresses;
773 	std::vector<VkDeviceAddress>									copyBLASAddresses;
774 	VkDeviceAddress													buildTLASAddress;
775 	VkDeviceAddress													copyTLASAddress;
776 };
777 
RayTracingCaptureReplayTestCase(tcu::TestContext & context,const char * name,const char * desc,const TestParams & data)778 RayTracingCaptureReplayTestCase::RayTracingCaptureReplayTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
779 	: vkt::TestCase	(context, name, desc)
780 	, m_data		(data)
781 {
782 }
783 
~RayTracingCaptureReplayTestCase(void)784 RayTracingCaptureReplayTestCase::~RayTracingCaptureReplayTestCase	(void)
785 {
786 }
787 
checkSupport(Context & context) const788 void RayTracingCaptureReplayTestCase::checkSupport(Context& context) const
789 {
790 	context.requireDeviceFunctionality("VK_KHR_buffer_device_address");
791 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
792 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
793 
794 	const VkPhysicalDeviceRayTracingPipelineFeaturesKHR&	rayTracingPipelineFeaturesKHR		= context.getRayTracingPipelineFeatures();
795 	if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
796 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
797 
798 	if (m_data.testType == TEST_PIPELINE_BEFORE && rayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplayMixed == DE_FALSE)
799 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplayMixed");
800 
801 	if (m_data.testType != TEST_ACCELERATION_STRUCTURES && rayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplay == DE_FALSE)
802 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipelineShaderGroupHandleCaptureReplay");
803 
804 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR&	accelerationStructureFeaturesKHR	= context.getAccelerationStructureFeatures();
805 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
806 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
807 
808 	if (m_data.testType == TEST_ACCELERATION_STRUCTURES && accelerationStructureFeaturesKHR.accelerationStructureCaptureReplay == DE_FALSE)
809 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureCaptureReplay");
810 
811 	if (m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
812 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
813 
814 	const VkPhysicalDeviceBufferDeviceAddressFeatures&		bufferDeviceAddressFeatures = context.getBufferDeviceAddressFeatures();
815 
816 	if (bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay == DE_FALSE)
817 		TCU_THROW(NotSupportedError, "Requires bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay");
818 }
819 
initPrograms(SourceCollections & programCollection) const820 void RayTracingCaptureReplayTestCase::initPrograms (SourceCollections& programCollection) const
821 {
822 	const vk::ShaderBuildOptions	buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
823 	{
824 		std::stringstream css;
825 		css <<
826 			"#version 460 core\n"
827 			"#extension GL_EXT_ray_tracing : require\n"
828 			"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
829 			"layout(set = 0, binding = 0) uniform UniformParams\n"
830 			"{\n"
831 			"  uint targetLayer;\n"
832 			"} uniformParams;\n"
833 			"layout(r32ui, set = 0, binding = 1) uniform uimage3D result;\n"
834 			"layout(set = 0, binding = 2) uniform accelerationStructureEXT topLevelAS;\n"
835 			"\n"
836 			"void main()\n"
837 			"{\n"
838 			"  float tmin     = 0.0;\n"
839 			"  float tmax     = 1.0;\n"
840 			"  vec3  origin   = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 0.5);\n"
841 			"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
842 			"  hitValue       = uvec4(0,0,0,0);\n"
843 			"  traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
844 			"  imageStore(result, ivec3(gl_LaunchIDEXT.xy, uniformParams.targetLayer), hitValue);\n"
845 			"}\n";
846 		programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
847 	}
848 
849 	for (deUint32 shaderNdx = 0; shaderNdx < RTCR_SHADER_COUNT; ++shaderNdx)
850 	{
851 		deUint32 colorValue = 2 * (shaderNdx + 1);
852 		std::stringstream css;
853 		css <<
854 			"#version 460 core\n"
855 			"#extension GL_EXT_ray_tracing : require\n"
856 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
857 			"void main()\n"
858 			"{\n"
859 			"  hitValue = uvec4(" << colorValue << ",0,0,1);\n"
860 			"}\n";
861 		std::stringstream shaderName;
862 		shaderName << "chit" << shaderNdx;
863 
864 		programCollection.glslSources.add(shaderName.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
865 	}
866 
867 	{
868 		std::stringstream css;
869 		css <<
870 			"#version 460 core\n"
871 			"#extension GL_EXT_ray_tracing : require\n"
872 			"hitAttributeEXT uvec4 hitAttribute;\n"
873 			"void main()\n"
874 			"{\n"
875 			"  hitAttribute = uvec4(0,0,0,0);\n"
876 			"  reportIntersectionEXT(0.5f, 0);\n"
877 			"}\n";
878 
879 		programCollection.glslSources.add("isect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
880 	}
881 
882 	{
883 		std::stringstream css;
884 		css <<
885 			"#version 460 core\n"
886 			"#extension GL_EXT_ray_tracing : require\n"
887 			"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
888 			"void main()\n"
889 			"{\n"
890 			"  hitValue = uvec4(1,0,0,1);\n"
891 			"}\n";
892 
893 		programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
894 	}
895 }
896 
removeExtensions(const std::vector<std::string> & a,const std::vector<const char * > & b)897 std::vector<std::string> removeExtensions (const std::vector<std::string>& a, const std::vector<const char*>& b)
898 {
899 	std::vector<std::string>	res;
900 	std::set<std::string>		removeExts	(b.begin(), b.end());
901 
902 	for (std::vector<std::string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter)
903 	{
904 		if (!de::contains(removeExts, *aIter))
905 			res.push_back(*aIter);
906 	}
907 	return res;
908 }
909 
createInstance(Context & context) const910 TestInstance* RayTracingCaptureReplayTestCase::createInstance (Context& context) const
911 {
912 	return new RayTracingCaptureReplayTestInstance(context, m_data);
913 }
914 
RayTracingCaptureReplayTestInstance(Context & context,const TestParams & data)915 RayTracingCaptureReplayTestInstance::RayTracingCaptureReplayTestInstance (Context& context, const TestParams& data)
916 	: vkt::TestInstance		(context)
917 	, m_data				(data)
918 {
919 }
920 
~RayTracingCaptureReplayTestInstance(void)921 RayTracingCaptureReplayTestInstance::~RayTracingCaptureReplayTestInstance (void)
922 {
923 }
924 
runTest(bool replay)925 std::vector<deUint32> RayTracingCaptureReplayTestInstance::runTest(bool replay)
926 {
927 	const deUint32 NO_MATCH_FOUND = ~((deUint32)0);
928 
929 	// For this test we need to create separate device with ray tracing features and buffer device address features enabled
930 	const PlatformInterface&				vkp									= m_context.getPlatformInterface();
931 	const InstanceInterface&				vki									= m_context.getInstanceInterface();
932 	const VkInstance						instance							= m_context.getInstance();
933 	const VkPhysicalDevice					physicalDevice						= m_context.getPhysicalDevice();
934 	const auto								validationEnabled					= m_context.getTestContext().getCommandLine().isValidationEnabled();
935 
936 	VkQueue									queue								= DE_NULL;
937 	deUint32								queueFamilyIndex					= NO_MATCH_FOUND;
938 
939 	std::vector<VkQueueFamilyProperties>	queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
940 	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
941 	{
942 		if (queueFamilyProperties[queueNdx].queueFlags & ( VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT ))
943 		{
944 			if (queueFamilyIndex == NO_MATCH_FOUND)
945 				queueFamilyIndex = queueNdx;
946 		}
947 	}
948 	if (queueFamilyIndex == NO_MATCH_FOUND)
949 		TCU_THROW(NotSupportedError, "Could not create queue");
950 
951 	const float								queuePriority						= 1.0f;
952 	VkDeviceQueueCreateInfo					queueInfo;
953 	deMemset(&queueInfo, 0, sizeof(queueInfo));
954 	queueInfo.sType																= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
955 	queueInfo.pNext																= DE_NULL;
956 	queueInfo.flags																= (VkDeviceQueueCreateFlags)0u;
957 	queueInfo.queueFamilyIndex													= queueFamilyIndex;
958 	queueInfo.queueCount														= 1;
959 	queueInfo.pQueuePriorities													= &queuePriority;
960 
961 	VkPhysicalDeviceRayTracingPipelineFeaturesKHR		rayTracingFeaturesKHR;
962 	rayTracingFeaturesKHR.sType													= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
963 	rayTracingFeaturesKHR.pNext													= DE_NULL;
964 
965 	VkPhysicalDeviceAccelerationStructureFeaturesKHR	accelerationStructureFeaturesKHR;
966 	accelerationStructureFeaturesKHR.sType										= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
967 	accelerationStructureFeaturesKHR.pNext										= &rayTracingFeaturesKHR;
968 
969 	VkPhysicalDeviceBufferDeviceAddressFeatures			bufferDeviceAddressFeatures;
970 	bufferDeviceAddressFeatures.sType											= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
971 	bufferDeviceAddressFeatures.pNext											= &accelerationStructureFeaturesKHR;
972 
973 	VkPhysicalDeviceFeatures2				deviceFeatures2;
974 	deviceFeatures2.sType														= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
975 	deviceFeatures2.pNext														= &bufferDeviceAddressFeatures;
976 	vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2);
977 
978 	// skip core device extensions according to API version
979 	std::vector<const char*>				coreExtensions;
980 	getCoreDeviceExtensions(m_context.getUsedApiVersion(), coreExtensions);
981 	std::vector<std::string>				nonCoreDeviceExtensions				(removeExtensions(m_context.getDeviceExtensions(), coreExtensions));
982 	std::vector<const char*>				nonCoreDeviceExtensionsC;
983 
984 	// ppEnabledExtensionNames must not contain both VK_KHR_buffer_device_address and VK_EXT_buffer_device_address
985 	if ( ( de::contains(begin(coreExtensions), end(coreExtensions), "VK_KHR_buffer_device_address") ||
986 		   de::contains(begin(nonCoreDeviceExtensions), end(nonCoreDeviceExtensions), "VK_KHR_buffer_device_address") ) &&
987 		 de::contains(begin(nonCoreDeviceExtensions), end(nonCoreDeviceExtensions), "VK_EXT_buffer_device_address") )
988 		std::for_each(begin(nonCoreDeviceExtensions), end(nonCoreDeviceExtensions), [&nonCoreDeviceExtensionsC](const std::string& text) { if (text != "VK_EXT_buffer_device_address") nonCoreDeviceExtensionsC.push_back(text.c_str()); });
989 	else
990 		std::for_each(begin(nonCoreDeviceExtensions), end(nonCoreDeviceExtensions), [&nonCoreDeviceExtensionsC](const std::string& text) { nonCoreDeviceExtensionsC.push_back(text.c_str()); });
991 
992 	VkDeviceCreateInfo						deviceInfo;
993 	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
994 	deviceInfo.sType															= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
995 	deviceInfo.pNext															= &deviceFeatures2;
996 	deviceInfo.enabledExtensionCount											= deUint32(nonCoreDeviceExtensionsC.size());
997 	deviceInfo.ppEnabledExtensionNames											= nonCoreDeviceExtensionsC.data();
998 	deviceInfo.enabledLayerCount												= 0u;
999 	deviceInfo.ppEnabledLayerNames												= DE_NULL;
1000 	deviceInfo.pEnabledFeatures													= DE_NULL;
1001 	deviceInfo.queueCreateInfoCount												= 1;
1002 	deviceInfo.pQueueCreateInfos												= &queueInfo;
1003 	Move<VkDevice>							testDevice							= createCustomDevice(validationEnabled, vkp, m_context.getInstance(), vki, physicalDevice, &deviceInfo);
1004 	VkDevice								device								= *testDevice;
1005 	DeviceDriver							vkd									(vkp, instance, device);
1006 
1007 	vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
1008 
1009 	// create memory allocator for new VkDevice
1010 	VkPhysicalDeviceMemoryProperties		memoryProperties					= getPhysicalDeviceMemoryProperties(vki, physicalDevice);
1011 	de::UniquePtr<vk::Allocator>			allocator							(new SimpleAllocator(vkd, device, memoryProperties));
1012 
1013 	// Create common pipeline layout for all raytracing pipelines
1014 	const Move<VkDescriptorSetLayout>		descriptorSetLayout					= DescriptorSetLayoutBuilder()
1015 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ALL_RAY_TRACING_STAGES)
1016 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1017 																					.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1018 																					.build(vkd, device);
1019 	deUint32								pipelineCount						= (!replay || ( m_data.testType == TEST_PIPELINE_SINGLE) || (m_data.testType == TEST_ACCELERATION_STRUCTURES)) ? 1u : 2u;
1020 	const Move<VkDescriptorPool>			descriptorPool						= DescriptorPoolBuilder()
1021 																						.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pipelineCount)
1022 																						.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, pipelineCount)
1023 																						.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, pipelineCount)
1024 																						.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, pipelineCount);
1025 	const Move<VkPipelineLayout>			pipelineLayout						= makePipelineLayout(vkd, device, descriptorSetLayout.get());
1026 
1027 	// All pipelines will be using the same set of shaders and shader groups.
1028 	// Single RayTracingPipeline object will be enough to define it
1029 	de::MovePtr<RayTracingPipeline>			rayTracingPipeline					= de::newMovePtr<RayTracingPipeline>();
1030 	m_data.testConfiguration->initRayTracingShaders(rayTracingPipeline, m_context, vkd, device, m_data, replay);
1031 
1032 	// Capture phase ( replay==false ):
1033 	// - TEST_ACCELERATION_STRUCTURES:
1034 	//   - build/copy/compact/serialize structure, record addresses
1035 	// - TEST_PIPELINE_SINGLE:
1036 	// - TEST_PIPELINE_AFTER:
1037 	// - TEST_PIPELINE_BEFORE:
1038 	//   - single pipeline records addresses and fills test data
1039 	// Replay phase ( replay==true ):
1040 	// - TEST_ACCELERATION_STRUCTURES:
1041 	//   - build/copy/compact/serialize structure with addresses captured previously
1042 	// - TEST_PIPELINE_SINGLE:
1043 	//   - single pipeline with addresses captured previously - writes into first image layer
1044 	// - TEST_PIPELINE_AFTER:
1045 	//   - first pipeline with addresses captured previously - writes into first image layer
1046 	//   - second pipeline created without captured addresses - writes into second image layer
1047 	// - TEST_PIPELINE_BEFORE:
1048 	//   - first pipeline created without captured addresses - writes into first image layer
1049 	//   - second pipeline with addresses captured previously - writes into second image layer
1050 	//
1051 	// Comparing results in all tests: all layers must be identical to the layer from capture phase
1052 
1053 	PipelineData							pipelineData(*allocator);
1054 	pipelineData.pipelineLayout													= *pipelineLayout;
1055 	pipelineData.descriptorSetLayout											= *descriptorSetLayout;
1056 	pipelineData.descriptorPool													= *descriptorPool;
1057 	const deUint32							shaderGroupHandleSize				= getShaderGroupSize(vki, physicalDevice);
1058 	const deUint32							shaderGroupBaseAlignment			= getShaderGroupBaseAlignment(vki, physicalDevice);
1059 	m_data.testConfiguration->initShaderBindingTables(rayTracingPipeline, m_context, vkd, device, m_data, shaderGroupHandleSize, shaderGroupBaseAlignment, pipelineData, replay);
1060 
1061 	const VkFormat							imageFormat							= m_data.testConfiguration->getResultImageFormat();
1062 	const VkImageCreateInfo					imageCreateInfo						= makeImageCreateInfo(m_data.width, m_data.height, pipelineCount, imageFormat);
1063 	const VkImageSubresourceRange			imageSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1064 	const de::MovePtr<ImageWithMemory>		image								= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
1065 	const Move<VkImageView>					imageView							= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
1066 	const VkDescriptorImageInfo				descriptorImageInfo					= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1067 
1068 	const deUint32							pixelCount							= m_data.width * m_data.height * pipelineCount;
1069 	const VkBufferCreateInfo				resultBufferCreateInfo				= makeBufferCreateInfo(pixelCount*m_data.testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1070 	const VkImageSubresourceLayers			resultBufferImageSubresourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1071 	const VkBufferImageCopy					resultBufferImageRegion				= makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, pipelineCount), resultBufferImageSubresourceLayers);
1072 	de::MovePtr<BufferWithMemory>			resultBuffer						= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, *allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
1073 
1074 	const Move<VkCommandPool>				cmdPool								= createCommandPool(vkd, device, 0, queueFamilyIndex);
1075 	const Move<VkCommandBuffer>				cmdBuffer							= allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1076 
1077 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	bottomLevelAccelerationStructures;
1078 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructure;
1079 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>	bottomLevelAccelerationStructureCopies;
1080 	de::MovePtr<TopLevelAccelerationStructure>						topLevelAccelerationStructureCopy;
1081 	std::vector<de::SharedPtr<SerialStorage>>						bottomSerialized;
1082 	std::vector<de::SharedPtr<SerialStorage>>						topSerialized;
1083 	Move<VkQueryPool>												m_queryPoolCompact;
1084 	Move<VkQueryPool>												m_queryPoolSerial;
1085 
1086 	beginCommandBuffer(vkd, *cmdBuffer, 0u);
1087 	{
1088 		const VkImageMemoryBarrier			preImageBarrier						= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1089 																				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1090 																				**image, imageSubresourceRange);
1091 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1092 		const VkClearValue					clearValue							= m_data.testConfiguration->getClearValue();
1093 		vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
1094 		const VkImageMemoryBarrier			postImageBarrier					= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1095 																				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1096 																				**image, imageSubresourceRange);
1097 		cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1098 
1099 		// build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
1100 		bool									bottomCompact		= m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1101 		bool									bottomSerial		= m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
1102 		bottomLevelAccelerationStructures							= m_data.testConfiguration->initBottomAccelerationStructures(m_context, m_data);
1103 		VkBuildAccelerationStructureFlagsKHR	allowCompactionFlag	= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
1104 		VkBuildAccelerationStructureFlagsKHR	emptyCompactionFlag	= VkBuildAccelerationStructureFlagsKHR(0);
1105 		VkBuildAccelerationStructureFlagsKHR	bottomBuildFlags	= (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
1106 		std::vector<VkAccelerationStructureKHR>	accelerationStructureHandles;
1107 		std::vector<VkDeviceSize>				bottomBlasCompactSize;
1108 		std::vector<VkDeviceSize>				bottomBlasSerialSize;
1109 
1110 		for (size_t idx=0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1111 		{
1112 			bottomLevelAccelerationStructures[idx]->setBuildFlags	(bottomBuildFlags);
1113 			bottomLevelAccelerationStructures[idx]->setBuildType	(m_data.buildType);
1114 			VkDeviceAddress	deviceAddress							= ( m_data.testType == TEST_ACCELERATION_STRUCTURES && replay ) ? buildBLASAddresses[idx] : 0u;
1115 			if ( m_data.testType == TEST_ACCELERATION_STRUCTURES && replay )
1116 				bottomLevelAccelerationStructures[idx]->setCreateFlags	( VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1117 			bottomLevelAccelerationStructures[idx]->createAndBuild	(vkd, device, *cmdBuffer, *allocator, deviceAddress);
1118 			accelerationStructureHandles.push_back					(*(bottomLevelAccelerationStructures[idx]->getPtr()));
1119 			if (m_data.testType == TEST_ACCELERATION_STRUCTURES && !replay)
1120 				buildBLASAddresses.push_back(getAccelerationStructureDeviceAddress(vkd, device, *(bottomLevelAccelerationStructures[idx]->getPtr())));
1121 		}
1122 
1123 		if (m_data.operationType == OP_COMPACT)
1124 		{
1125 			deUint32 queryCount	= (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
1126 			if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1127 				m_queryPoolCompact	= makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
1128 			if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1129 				queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
1130 		}
1131 		if (m_data.operationType == OP_SERIALIZE)
1132 		{
1133 			deUint32 queryCount	= (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
1134 			if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1135 				m_queryPoolSerial	= makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
1136 			if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1137 				queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
1138 		}
1139 
1140 		// if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1141 		if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
1142 		{
1143 			endCommandBuffer(vkd, *cmdBuffer);
1144 
1145 			submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1146 
1147 			if (bottomCompact)
1148 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(bottomBlasCompactSize.size()), sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1149 			if (bottomSerial)
1150 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(bottomBlasSerialSize.size()), sizeof(VkDeviceSize) * bottomBlasSerialSize.size(), bottomBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1151 
1152 			vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1153 			beginCommandBuffer(vkd, *cmdBuffer, 0u);
1154 		}
1155 
1156 		auto bottomLevelAccelerationStructuresPtr								= &bottomLevelAccelerationStructures;
1157 		if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
1158 		{
1159 			switch (m_data.operationType)
1160 			{
1161 			case OP_COPY:
1162 			{
1163 				for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1164 				{
1165 					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1166 					asCopy->setBuildType(m_data.buildType);
1167 					VkDeviceAddress	deviceAddress = replay ? copyBLASAddresses[idx] : 0u;
1168 					if (replay)
1169 						asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1170 					asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, bottomLevelAccelerationStructures[idx].get(), 0u, deviceAddress);
1171 					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1172 					if (!replay)
1173 						copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress(vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr())));
1174 				}
1175 				break;
1176 			}
1177 			case OP_COMPACT:
1178 			{
1179 				for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1180 				{
1181 					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1182 					asCopy->setBuildType(m_data.buildType);
1183 					VkDeviceAddress	deviceAddress = replay ? copyBLASAddresses[idx] : 0u;
1184 					if (replay)
1185 						asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1186 					asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, bottomLevelAccelerationStructures[idx].get(), bottomBlasCompactSize[idx], deviceAddress);
1187 					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1188 					if (!replay)
1189 						copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress(vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr())));
1190 				}
1191 				break;
1192 			}
1193 			case OP_SERIALIZE:
1194 			{
1195 				for (size_t idx = 0; idx < bottomLevelAccelerationStructures.size(); ++idx)
1196 				{
1197 					de::SharedPtr<SerialStorage> storage(new SerialStorage(vkd, device, *allocator, m_data.buildType, bottomBlasSerialSize[idx]));
1198 					bottomLevelAccelerationStructures[idx]->serialize(vkd, device, *cmdBuffer, storage.get());
1199 					bottomSerialized.push_back(storage);
1200 
1201 					if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1202 					{
1203 						endCommandBuffer(vkd, *cmdBuffer);
1204 
1205 						submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1206 
1207 						vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1208 						beginCommandBuffer(vkd, *cmdBuffer, 0u);
1209 					}
1210 
1211 					de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
1212 					asCopy->setBuildType(m_data.buildType);
1213 					VkDeviceAddress	deviceAddress = replay ? copyBLASAddresses[idx] : 0u;
1214 					if (replay)
1215 						asCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1216 					asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, *allocator, storage.get(), deviceAddress);
1217 					bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
1218 					if (!replay)
1219 						copyBLASAddresses.push_back(getAccelerationStructureDeviceAddress(vkd, device, *(bottomLevelAccelerationStructureCopies[idx]->getPtr())));
1220 				}
1221 				break;
1222 			}
1223 			default:
1224 				DE_ASSERT(DE_FALSE);
1225 			}
1226 			bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
1227 		}
1228 
1229 		// build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
1230 		bool									topCompact			= m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
1231 		bool									topSerial			= m_data.testType == TEST_ACCELERATION_STRUCTURES && m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
1232 		VkBuildAccelerationStructureFlagsKHR	topBuildFlags		= (topCompact ? allowCompactionFlag : emptyCompactionFlag);
1233 		std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
1234 		std::vector<VkDeviceSize>				topBlasCompactSize;
1235 		std::vector<VkDeviceSize>				topBlasSerialSize;
1236 
1237 		topLevelAccelerationStructure								= m_data.testConfiguration->initTopAccelerationStructure(m_context, m_data, *bottomLevelAccelerationStructuresPtr);
1238 		topLevelAccelerationStructure->setBuildFlags				(topBuildFlags);
1239 		topLevelAccelerationStructure->setBuildType					(m_data.buildType);
1240 		VkDeviceAddress							deviceAddressBuild	= ( m_data.testType == TEST_ACCELERATION_STRUCTURES && replay ) ? buildTLASAddress : 0u;
1241 		if (m_data.testType == TEST_ACCELERATION_STRUCTURES && replay)
1242 			topLevelAccelerationStructure->setCreateFlags			(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1243 		topLevelAccelerationStructure->createAndBuild				(vkd, device, *cmdBuffer, *allocator, deviceAddressBuild);
1244 		topLevelStructureHandles.push_back							(*(topLevelAccelerationStructure->getPtr()));
1245 		if (m_data.testType == TEST_ACCELERATION_STRUCTURES && !replay)
1246 			buildTLASAddress = getAccelerationStructureDeviceAddress(vkd, device, *(topLevelAccelerationStructure->getPtr()));
1247 
1248 		if (topCompact)
1249 			queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
1250 		if (topSerial)
1251 			queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
1252 
1253 		// if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
1254 		if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
1255 		{
1256 			endCommandBuffer(vkd, *cmdBuffer);
1257 
1258 			submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1259 
1260 			if (topCompact)
1261 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(topBlasCompactSize.size()), sizeof(VkDeviceSize) * topBlasCompactSize.size(), topBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1262 			if (topSerial)
1263 				VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(topBlasSerialSize.size()), sizeof(VkDeviceSize) * topBlasSerialSize.size(), topBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
1264 
1265 			vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1266 			beginCommandBuffer(vkd, *cmdBuffer, 0u);
1267 		}
1268 
1269 		const TopLevelAccelerationStructure*			topLevelRayTracedPtr	= topLevelAccelerationStructure.get();
1270 		if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
1271 		{
1272 			switch (m_data.operationType)
1273 			{
1274 				case OP_COPY:
1275 				{
1276 					topLevelAccelerationStructureCopy				= makeTopLevelAccelerationStructure();
1277 					topLevelAccelerationStructureCopy->setBuildType	(m_data.buildType);
1278 					VkDeviceAddress			deviceAddress			= replay ? copyTLASAddress : 0u;
1279 					if(replay)
1280 						topLevelAccelerationStructureCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1281 					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, topLevelAccelerationStructure.get(), 0u, deviceAddress);
1282 					if (!replay)
1283 						copyTLASAddress = getAccelerationStructureDeviceAddress(vkd, device, *(topLevelAccelerationStructureCopy->getPtr()));
1284 					break;
1285 				}
1286 				case OP_COMPACT:
1287 				{
1288 					topLevelAccelerationStructureCopy				= makeTopLevelAccelerationStructure();
1289 					topLevelAccelerationStructureCopy->setBuildType	(m_data.buildType);
1290 					VkDeviceAddress			deviceAddress			= replay ? copyTLASAddress : 0u;
1291 					if(replay)
1292 						topLevelAccelerationStructureCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1293 					topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, *allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], deviceAddress);
1294 					if (!replay)
1295 						copyTLASAddress = getAccelerationStructureDeviceAddress(vkd, device, *(topLevelAccelerationStructureCopy->getPtr()));
1296 					break;
1297 				}
1298 				case OP_SERIALIZE:
1299 				{
1300 					de::SharedPtr<SerialStorage> storage( new SerialStorage(vkd, device, *allocator, m_data.buildType, topBlasSerialSize[0]));
1301 					topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
1302 					topSerialized.push_back(storage);
1303 
1304 					if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1305 					{
1306 						endCommandBuffer(vkd, *cmdBuffer);
1307 
1308 						submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1309 
1310 						vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1311 						beginCommandBuffer(vkd, *cmdBuffer, 0u);
1312 					}
1313 
1314 					topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
1315 					topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
1316 					VkDeviceAddress			deviceAddress			= replay ? copyTLASAddress : 0u;
1317 					if(replay)
1318 						topLevelAccelerationStructureCopy->setCreateFlags(VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR);
1319 					topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, *allocator, storage.get(), deviceAddress);
1320 					if (!replay)
1321 						copyTLASAddress = getAccelerationStructureDeviceAddress(vkd, device, *(topLevelAccelerationStructureCopy->getPtr()));
1322 					break;
1323 				}
1324 				default:
1325 					DE_ASSERT(DE_FALSE);
1326 			}
1327 			topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
1328 		}
1329 
1330 		// copy layer index into uniform buffer
1331 		for (deUint32 i = 0; i < pipelineCount; ++i)
1332 		{
1333 			deMemcpy(pipelineData.pipelines[i].uniformBuffer->getAllocation().getHostPtr(), &i, sizeof(deUint32));
1334 			flushMappedMemoryRange(vkd, device, pipelineData.pipelines[i].uniformBuffer->getAllocation().getMemory(), pipelineData.pipelines[i].uniformBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1335 		}
1336 
1337 		const VkMemoryBarrier				preTraceMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
1338 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &preTraceMemoryBarrier);
1339 
1340 		VkWriteDescriptorSetAccelerationStructureKHR							accelerationStructureWriteDescriptorSet	=
1341 		{
1342 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	//  VkStructureType						sType;
1343 			DE_NULL,															//  const void*							pNext;
1344 			1u,																	//  deUint32							accelerationStructureCount;
1345 			topLevelRayTracedPtr->getPtr()										//  const VkAccelerationStructureKHR*	pAccelerationStructures;
1346 		};
1347 
1348 		for( deUint32 i=0; i<pipelineCount; ++i )
1349 		{
1350 			VkDescriptorBufferInfo	uniformBufferInfo = makeDescriptorBufferInfo(pipelineData.pipelines[i].uniformBuffer->get(), 0ull, sizeof(deUint32));
1351 
1352 			DescriptorSetUpdateBuilder()
1353 				.writeSingle(*(pipelineData.pipelines[i].descriptorSet), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo)
1354 				.writeSingle(*(pipelineData.pipelines[i].descriptorSet), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1355 				.writeSingle(*(pipelineData.pipelines[i].descriptorSet), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1356 				.update(vkd, device);
1357 
1358 			vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &(pipelineData.pipelines[i].descriptorSet.get()), 0, DE_NULL);
1359 
1360 			vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *(pipelineData.pipelines[i].pipeline));
1361 
1362 			cmdTraceRays(vkd,
1363 				*cmdBuffer,
1364 				&(pipelineData.pipelines[i].raygenShaderBindingTableRegion),
1365 				&(pipelineData.pipelines[i].missShaderBindingTableRegion),
1366 				&(pipelineData.pipelines[i].hitShaderBindingTableRegion),
1367 				&(pipelineData.pipelines[i].callableShaderBindingTableRegion),
1368 				m_data.width, m_data.height, 1);
1369 		}
1370 
1371 		const VkMemoryBarrier													postTraceMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1372 		const VkMemoryBarrier													postCopyMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1373 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1374 
1375 		vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
1376 
1377 		cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
1378 	}
1379 	endCommandBuffer(vkd, *cmdBuffer);
1380 
1381 	submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1382 
1383 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), pixelCount * sizeof(deUint32));
1384 
1385 	std::vector<deUint32> result(pixelCount);
1386 	deMemcpy(result.data(), resultBuffer->getAllocation().getHostPtr(), pixelCount * sizeof(deUint32));
1387 	return result;
1388 }
1389 
iterate(void)1390 tcu::TestStatus RayTracingCaptureReplayTestInstance::iterate (void)
1391 {
1392 	// run test capturing different elements
1393 	const std::vector<deUint32>	captureResults		= runTest(false);
1394 
1395 	// run test that replays different elements
1396 	const std::vector<deUint32>	replayResults		= runTest(true);
1397 
1398 	if (!m_data.testConfiguration->verifyImage(captureResults, replayResults, m_context, m_data))
1399 		return tcu::TestStatus::fail("Fail");
1400 	return tcu::TestStatus::pass("Pass");
1401 }
1402 
1403 }	// anonymous
1404 
addReplayShaderBindingTablesTests(tcu::TestCaseGroup * group)1405 void addReplayShaderBindingTablesTests(tcu::TestCaseGroup* group)
1406 {
1407 	struct
1408 	{
1409 		SBTReplayTestType	testType;
1410 		const char*			name;
1411 		const char*			description;
1412 	} testTypes[] =
1413 	{
1414 		{ TEST_PIPELINE_SINGLE,		"pipeline_single",			"Capture-replay scenario with single captured pipeline" },
1415 		{ TEST_PIPELINE_AFTER	,	"pipeline_after_captured",	"Not captured pipeline created after captured one" },
1416 		{ TEST_PIPELINE_BEFORE,		"pipeline_before_captured",	"Not captured pipeline created before captured one" },
1417 	};
1418 
1419 	for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1420 	{
1421 		TestParams testParams
1422 		{
1423 			testTypes[testTypeNdx].testType,
1424 			OT_NONE,
1425 			OP_NONE,
1426 			VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
1427 			BTT_TRIANGLES,
1428 			TTT_IDENTICAL_INSTANCES,
1429 			RTCR_DEFAULT_SIZE,
1430 			RTCR_DEFAULT_SIZE,
1431 			de::SharedPtr<TestConfiguration>(new TestShaderBindingTablesConfiguration())
1432 		};
1433 		group->addChild(new RayTracingCaptureReplayTestCase(group->getTestContext(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, testParams));
1434 	}
1435 }
1436 
addReplayAccelerationStruturesTests(tcu::TestCaseGroup * group)1437 void addReplayAccelerationStruturesTests(tcu::TestCaseGroup* group)
1438 {
1439 	struct
1440 	{
1441 		ASOperationType										operationType;
1442 		const char*											name;
1443 	} operationTypes[] =
1444 	{
1445 		{ OP_NONE,											"building"		},
1446 		{ OP_COPY,											"copy"			},
1447 		{ OP_COMPACT,										"compaction"	},
1448 		{ OP_SERIALIZE,										"serialization"	},
1449 	};
1450 
1451 	struct
1452 	{
1453 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
1454 		const char*											name;
1455 	} buildTypes[] =
1456 	{
1457 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
1458 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
1459 	};
1460 
1461 	struct
1462 	{
1463 		ASOperationTarget									operationTarget;
1464 		const char*											name;
1465 	} operationTargets[] =
1466 	{
1467 		{ OT_TOP_ACCELERATION,								"top_acceleration_structure"		},
1468 		{ OT_BOTTOM_ACCELERATION,							"bottom_acceleration_structure"	},
1469 	};
1470 
1471 	struct
1472 	{
1473 		ASBottomTestType									testType;
1474 		const char*											name;
1475 	} bottomTestTypes[] =
1476 	{
1477 		{ BTT_TRIANGLES,									"triangles" },
1478 		{ BTT_AABBS,										"aabbs" },
1479 	};
1480 
1481 	for (size_t operationTypeNdx = 0; operationTypeNdx < DE_LENGTH_OF_ARRAY(operationTypes); ++operationTypeNdx)
1482 	{
1483 		de::MovePtr<tcu::TestCaseGroup> operationTypeGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTypes[operationTypeNdx].name, ""));
1484 
1485 		for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
1486 		{
1487 			de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name, ""));
1488 
1489 			for (size_t operationTargetNdx = 0; operationTargetNdx < DE_LENGTH_OF_ARRAY(operationTargets); ++operationTargetNdx)
1490 			{
1491 				de::MovePtr<tcu::TestCaseGroup> operationTargetGroup(new tcu::TestCaseGroup(group->getTestContext(), operationTargets[operationTargetNdx].name, ""));
1492 
1493 				for (size_t testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(bottomTestTypes); ++testTypeNdx)
1494 				{
1495 					ASTopTestType topTest = (operationTargets[operationTargetNdx].operationTarget == OT_TOP_ACCELERATION) ? TTT_DIFFERENT_INSTANCES : TTT_IDENTICAL_INSTANCES;
1496 
1497 					TestParams testParams
1498 					{
1499 						TEST_ACCELERATION_STRUCTURES,
1500 						operationTargets[operationTargetNdx].operationTarget,
1501 						operationTypes[operationTypeNdx].operationType,
1502 						buildTypes[buildTypeNdx].buildType,
1503 						bottomTestTypes[testTypeNdx].testType,
1504 						topTest,
1505 						RTCR_DEFAULT_SIZE,
1506 						RTCR_DEFAULT_SIZE,
1507 						de::SharedPtr<TestConfiguration>(new TestAccelerationStructuresConfiguration())
1508 					};
1509 					operationTargetGroup->addChild(new RayTracingCaptureReplayTestCase(group->getTestContext(), bottomTestTypes[testTypeNdx].name, "", testParams));
1510 				}
1511 				buildGroup->addChild(operationTargetGroup.release());
1512 			}
1513 			operationTypeGroup->addChild(buildGroup.release());
1514 		}
1515 		group->addChild(operationTypeGroup.release());
1516 	}
1517 }
1518 
createCaptureReplayTests(tcu::TestContext & testCtx)1519 tcu::TestCaseGroup*	createCaptureReplayTests(tcu::TestContext& testCtx)
1520 {
1521 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "capture_replay", "Capture-replay capabilities"));
1522 
1523 	addTestGroup(group.get(), "shader_binding_tables", "Test replaying shader binding tables", addReplayShaderBindingTablesTests);
1524 	addTestGroup(group.get(), "acceleration_structures", "Test replaying acceleration structure", addReplayAccelerationStruturesTests);
1525 
1526 	return group.release();
1527 }
1528 
1529 }	// RayTracing
1530 
1531 }	// vkt
1532