• 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 Test procedural geometry with complex bouding box sets
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRayTracingProceduralGeometryTests.hpp"
25 #include "vkDefs.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vkCmdUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkImageWithMemory.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkRayTracingUtil.hpp"
37 #include "tcuVectorUtil.hpp"
38 #include "tcuTexture.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuFloat.hpp"
42 
43 namespace vkt
44 {
45 namespace RayTracing
46 {
47 namespace
48 {
49 using namespace vk;
50 using namespace vkt;
51 
52 static const VkFlags	ALL_RAY_TRACING_STAGES	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
53 												| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
54 												| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
55 												| VK_SHADER_STAGE_MISS_BIT_KHR
56 												| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
57 												| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
58 
59 enum class TestType
60 {
61 	OBJECT_BEHIND_BOUNDING_BOX = 0,
62 	TRIANGLE_IN_BETWEEN
63 };
64 
65 class RayTracingProceduralGeometryTestBase : public TestInstance
66 {
67 public:
68 
69 	RayTracingProceduralGeometryTestBase	(Context& context);
70 	~RayTracingProceduralGeometryTestBase	(void) = default;
71 
72 	tcu::TestStatus iterate					(void) override;
73 
74 protected:
75 
76 	virtual void setupRayTracingPipeline() = 0;
77 	virtual void setupAccelerationStructures() = 0;
78 
79 private:
80 
81 	VkWriteDescriptorSetAccelerationStructureKHR	makeASWriteDescriptorSet	(const VkAccelerationStructureKHR* pAccelerationStructure);
82 	void											clearBuffer					(de::SharedPtr<BufferWithMemory> buffer, VkDeviceSize bufferSize);
83 
84 protected:
85 
86 	de::MovePtr<RayTracingPipeline>									m_rayTracingPipeline;
87 	Move<VkPipelineLayout>											m_pipelineLayout;
88 	Move<VkPipeline>												m_pipeline;
89 	de::MovePtr<BufferWithMemory>									m_rgenShaderBT;
90 	de::MovePtr<BufferWithMemory>									m_chitShaderBT;
91 	de::MovePtr<BufferWithMemory>									m_missShaderBT;
92 
93 	Move<VkDescriptorSetLayout>										m_descriptorSetLayout;
94 	Move<VkCommandPool>												m_cmdPool;
95 	Move<VkCommandBuffer>											m_cmdBuffer;
96 
97 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	m_blasVect;
98 	de::SharedPtr<TopLevelAccelerationStructure>					m_referenceTLAS;
99 	de::SharedPtr<TopLevelAccelerationStructure>					m_resultTLAS;
100 };
101 
RayTracingProceduralGeometryTestBase(Context & context)102 RayTracingProceduralGeometryTestBase::RayTracingProceduralGeometryTestBase(Context& context)
103 	: vkt::TestInstance	(context)
104 	, m_referenceTLAS	(makeTopLevelAccelerationStructure().release())
105 	, m_resultTLAS		(makeTopLevelAccelerationStructure().release())
106 {
107 }
108 
iterate(void)109 tcu::TestStatus RayTracingProceduralGeometryTestBase::iterate(void)
110 {
111 	const DeviceInterface&	vkd					= m_context.getDeviceInterface();
112 	const VkDevice			device				= m_context.getDevice();
113 	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
114 	const VkQueue			queue				= m_context.getUniversalQueue();
115 	Allocator&				allocator			= m_context.getDefaultAllocator();
116 	const deUint32			sgHandleSize		= m_context.getRayTracingPipelineProperties().shaderGroupHandleSize;
117 	const deUint32			imageSize			= 64u;
118 
119 	const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
120 		.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 2u)
121 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
122 		.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
123 
124 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
125 		.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)	// as with single/four aabb's
126 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES)				// ssbo with result/reference values
127 		.build(vkd, device);
128 
129 	const Move<VkDescriptorSet>			referenceDescriptorSet	= makeDescriptorSet(vkd, device, *descriptorPool, *m_descriptorSetLayout);
130 	const Move<VkDescriptorSet>			resultDescriptorSet		= makeDescriptorSet(vkd, device, *descriptorPool, *m_descriptorSetLayout);
131 
132 	const VkDeviceSize					resultBufferSize		= imageSize * imageSize * sizeof(int);
133 	const VkBufferCreateInfo			resultBufferCreateInfo	= makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
134 	de::SharedPtr<BufferWithMemory>		referenceBuffer			= de::SharedPtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
135 	de::SharedPtr<BufferWithMemory>		resultBuffer			= de::SharedPtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
136 
137 	m_rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
138 
139 	setupRayTracingPipeline();
140 
141 	const VkStridedDeviceAddressRegionKHR	rgenSBTR		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, m_rgenShaderBT->get(), 0), sgHandleSize, sgHandleSize);
142 	const VkStridedDeviceAddressRegionKHR	chitSBTR		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, m_chitShaderBT->get(), 0), sgHandleSize, sgHandleSize);
143 	const VkStridedDeviceAddressRegionKHR	missSBTR		= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, m_missShaderBT->get(), 0), sgHandleSize, sgHandleSize);
144 	const VkStridedDeviceAddressRegionKHR	callableSBTR	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
145 
146 	m_cmdPool	= createCommandPool(vkd, device, 0, queueFamilyIndex);
147 	m_cmdBuffer	= allocateCommandBuffer(vkd, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
148 
149 	// clear result and reference buffers
150 	clearBuffer(resultBuffer, resultBufferSize);
151 	clearBuffer(referenceBuffer, resultBufferSize);
152 
153 	beginCommandBuffer(vkd, *m_cmdBuffer, 0u);
154 	{
155 		setupAccelerationStructures();
156 
157 		// update descriptor sets
158 		{
159 			typedef DescriptorSetUpdateBuilder::Location DSL;
160 
161 			const VkWriteDescriptorSetAccelerationStructureKHR	referenceAS		= makeASWriteDescriptorSet(m_referenceTLAS->getPtr());
162 			const VkDescriptorBufferInfo						referenceSSBO	= makeDescriptorBufferInfo(**referenceBuffer, 0u, VK_WHOLE_SIZE);
163 			DescriptorSetUpdateBuilder()
164 				.writeSingle(*referenceDescriptorSet, DSL::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &referenceAS)
165 				.writeSingle(*referenceDescriptorSet, DSL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &referenceSSBO)
166 				.update(vkd, device);
167 
168 			const VkWriteDescriptorSetAccelerationStructureKHR	resultAS	= makeASWriteDescriptorSet(m_resultTLAS->getPtr());
169 			const VkDescriptorBufferInfo						resultSSBO	= makeDescriptorBufferInfo(**resultBuffer, 0u, VK_WHOLE_SIZE);
170 			DescriptorSetUpdateBuilder()
171 				.writeSingle(*resultDescriptorSet, DSL::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &resultAS)
172 				.writeSingle(*resultDescriptorSet, DSL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultSSBO)
173 				.update(vkd, device);
174 		}
175 
176 		// wait for data transfers
177 		const VkMemoryBarrier bufferUploadBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
178 		cmdPipelineMemoryBarrier(vkd, *m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &bufferUploadBarrier, 1u);
179 
180 		// wait for as build
181 		const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
182 		cmdPipelineMemoryBarrier(vkd, *m_cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, &asBuildBarrier, 1u);
183 
184 		vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *m_pipeline);
185 
186 		// generate reference
187 		vkd.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *m_pipelineLayout, 0, 1, &referenceDescriptorSet.get(), 0, DE_NULL);
188 		cmdTraceRays(vkd, *m_cmdBuffer, &rgenSBTR, &missSBTR, &chitSBTR, &callableSBTR, imageSize, imageSize, 1);
189 
190 		// generate result
191 		vkd.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *m_pipelineLayout, 0, 1, &resultDescriptorSet.get(), 0, DE_NULL);
192 		cmdTraceRays(vkd, *m_cmdBuffer, &rgenSBTR, &missSBTR, &chitSBTR, &callableSBTR, imageSize, imageSize, 1);
193 
194 		const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
195 		cmdPipelineMemoryBarrier(vkd, *m_cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
196 	}
197 	endCommandBuffer(vkd, *m_cmdBuffer);
198 
199 	submitCommandsAndWait(vkd, device, queue, m_cmdBuffer.get());
200 
201 	// verify result buffer
202 	auto referenceAllocation = referenceBuffer->getAllocation();
203 	invalidateMappedMemoryRange(vkd, device, referenceAllocation.getMemory(), referenceAllocation.getOffset(), resultBufferSize);
204 
205 	auto resultAllocation = resultBuffer->getAllocation();
206 	invalidateMappedMemoryRange(vkd, device, resultAllocation.getMemory(), resultAllocation.getOffset(), resultBufferSize);
207 
208 	tcu::TextureFormat		imageFormat		(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
209 	tcu::PixelBufferAccess	referenceAccess	(imageFormat, imageSize, imageSize, 1, referenceAllocation.getHostPtr());
210 	tcu::PixelBufferAccess	resultAccess	(imageFormat, imageSize, imageSize, 1, resultAllocation.getHostPtr());
211 
212 	if (tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_EVERYTHING))
213 		return tcu::TestStatus::pass("Pass");
214 	return tcu::TestStatus::fail("Fail");
215 }
216 
makeASWriteDescriptorSet(const VkAccelerationStructureKHR * pAccelerationStructure)217 VkWriteDescriptorSetAccelerationStructureKHR RayTracingProceduralGeometryTestBase::makeASWriteDescriptorSet(const VkAccelerationStructureKHR* pAccelerationStructure)
218 {
219 	return
220 	{
221 		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,	// VkStructureType						sType
222 		DE_NULL,															// const void*							pNext
223 		1u,																	// deUint32								accelerationStructureCount
224 		pAccelerationStructure												// const VkAccelerationStructureKHR*	pAccelerationStructures
225 	};
226 }
227 
clearBuffer(de::SharedPtr<BufferWithMemory> buffer,VkDeviceSize bufferSize)228 void RayTracingProceduralGeometryTestBase::clearBuffer(de::SharedPtr<BufferWithMemory> buffer, VkDeviceSize bufferSize)
229 {
230 	const DeviceInterface&	vkd				= m_context.getDeviceInterface();
231 	const VkDevice			device			= m_context.getDevice();
232 	auto&					bufferAlloc		= buffer->getAllocation();
233 	void*					bufferPtr		= bufferAlloc.getHostPtr();
234 
235 	deMemset(bufferPtr, 1, static_cast<size_t>(bufferSize));
236 	vk::flushAlloc(vkd, device, bufferAlloc);
237 }
238 
239 class ObjectBehindBoundingBoxInstance : public RayTracingProceduralGeometryTestBase
240 {
241 public:
242 
243 	ObjectBehindBoundingBoxInstance(Context& context);
244 
245 	void setupRayTracingPipeline() override;
246 	void setupAccelerationStructures() override;
247 };
248 
ObjectBehindBoundingBoxInstance(Context & context)249 ObjectBehindBoundingBoxInstance::ObjectBehindBoundingBoxInstance(Context& context)
250 	: RayTracingProceduralGeometryTestBase(context)
251 {
252 }
253 
setupRayTracingPipeline()254 void ObjectBehindBoundingBoxInstance::setupRayTracingPipeline()
255 {
256 	const DeviceInterface&	vkd				= m_context.getDeviceInterface();
257 	const VkDevice			device			= m_context.getDevice();
258 	Allocator&				allocator		= m_context.getDefaultAllocator();
259 	vk::BinaryCollection&	bc				= m_context.getBinaryCollection();
260 	const deUint32			sgHandleSize	= m_context.getRayTracingPipelineProperties().shaderGroupHandleSize;
261 	const deUint32			sgBaseAlignment	= m_context.getRayTracingPipelineProperties().shaderGroupBaseAlignment;
262 
263 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,			createShaderModule(vkd, device, bc.get("rgen"), 0), 0);
264 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vkd, device, bc.get("isec"), 0), 1);
265 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, bc.get("chit"), 0), 1);
266 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, bc.get("miss"), 0), 2);
267 
268 	m_pipelineLayout	= makePipelineLayout(vkd, device, m_descriptorSetLayout.get());
269 	m_pipeline			= m_rayTracingPipeline->createPipeline(vkd, device, *m_pipelineLayout);
270 	m_rgenShaderBT		= m_rayTracingPipeline->createShaderBindingTable(vkd, device, *m_pipeline, allocator, sgHandleSize, sgBaseAlignment, 0, 1);
271 	m_chitShaderBT		= m_rayTracingPipeline->createShaderBindingTable(vkd, device, *m_pipeline, allocator, sgHandleSize, sgBaseAlignment, 1, 1);
272 	m_missShaderBT		= m_rayTracingPipeline->createShaderBindingTable(vkd, device, *m_pipeline, allocator, sgHandleSize, sgBaseAlignment, 2, 1);
273 }
274 
setupAccelerationStructures()275 void ObjectBehindBoundingBoxInstance::setupAccelerationStructures()
276 {
277 	const DeviceInterface&	vkd			= m_context.getDeviceInterface();
278 	const VkDevice			device		= m_context.getDevice();
279 	Allocator&				allocator	= m_context.getDefaultAllocator();
280 
281 	// build reference acceleration structure - single aabb big enough to fit whole procedural geometry
282 	de::SharedPtr<BottomLevelAccelerationStructure> referenceBLAS(makeBottomLevelAccelerationStructure().release());
283 	referenceBLAS->setGeometryData(
284 		{
285 			{  0.0,  0.0, -64.0 },
286 			{ 64.0, 64.0, -16.0 },
287 		},
288 		false,
289 		0
290 		);
291 	referenceBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
292 	m_blasVect.push_back(referenceBLAS);
293 
294 	m_referenceTLAS->setInstanceCount(1);
295 	m_referenceTLAS->addInstance(m_blasVect.back());
296 	m_referenceTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
297 
298 	// build result acceleration structure - wall of 4 aabb's and generated object is actualy behind it (as it is just 1.0 unit thick)
299 	de::SharedPtr<BottomLevelAccelerationStructure> resultBLAS(makeBottomLevelAccelerationStructure().release());
300 	resultBLAS->setGeometryData(
301 		{
302 			{  0.0,  0.0, 0.0 },	// |  |
303 			{ 32.0, 32.0, 1.0 },	// |* |
304 			{ 32.0,  0.0, 0.0 },	//    |  |
305 			{ 64.0, 32.0, 1.0 },	//    | *|
306 			{  0.0, 32.0, 0.0 },	// |* |
307 			{ 32.0, 64.0, 1.0 },	// |  |
308 			{ 32.0, 32.0, 0.0 },	//    | *|
309 			{ 64.0, 64.0, 1.0 },	//    |  |
310 		},
311 		false,
312 		0
313 		);
314 	resultBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
315 	m_blasVect.push_back(resultBLAS);
316 
317 	m_resultTLAS->setInstanceCount(1);
318 	m_resultTLAS->addInstance(m_blasVect.back());
319 	m_resultTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
320 }
321 
322 class TriangleInBeteenInstance : public RayTracingProceduralGeometryTestBase
323 {
324 public:
325 
326 	TriangleInBeteenInstance(Context& context);
327 
328 	void setupRayTracingPipeline() override;
329 	void setupAccelerationStructures() override;
330 };
331 
TriangleInBeteenInstance(Context & context)332 TriangleInBeteenInstance::TriangleInBeteenInstance(Context& context)
333 	: RayTracingProceduralGeometryTestBase(context)
334 {
335 }
336 
setupRayTracingPipeline()337 void TriangleInBeteenInstance::setupRayTracingPipeline()
338 {
339 	const DeviceInterface&	vkd				= m_context.getDeviceInterface();
340 	const VkDevice			device			= m_context.getDevice();
341 	Allocator&				allocator		= m_context.getDefaultAllocator();
342 	vk::BinaryCollection&	bc				= m_context.getBinaryCollection();
343 	const deUint32			sgHandleSize	= m_context.getRayTracingPipelineProperties().shaderGroupHandleSize;
344 	const deUint32			sgBaseAlignment = m_context.getRayTracingPipelineProperties().shaderGroupBaseAlignment;
345 
346 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,			createShaderModule(vkd, device, bc.get("rgen"), 0), 0);
347 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,	createShaderModule(vkd, device, bc.get("isec"), 0), 1);
348 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, bc.get("chit"), 0), 1);
349 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,	createShaderModule(vkd, device, bc.get("chit_triangle"), 0), 2);
350 	m_rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,			createShaderModule(vkd, device, bc.get("miss"), 0), 3);
351 
352 	m_pipelineLayout	= makePipelineLayout(vkd, device, m_descriptorSetLayout.get());
353 	m_pipeline			= m_rayTracingPipeline->createPipeline(vkd, device, *m_pipelineLayout);
354 	m_rgenShaderBT		= m_rayTracingPipeline->createShaderBindingTable(vkd, device, *m_pipeline, allocator, sgHandleSize, sgBaseAlignment, 0, 1);
355 	m_chitShaderBT		= m_rayTracingPipeline->createShaderBindingTable(vkd, device, *m_pipeline, allocator, sgHandleSize, sgBaseAlignment, 1, 2);
356 	m_missShaderBT		= m_rayTracingPipeline->createShaderBindingTable(vkd, device, *m_pipeline, allocator, sgHandleSize, sgBaseAlignment, 3, 1);
357 }
358 
setupAccelerationStructures()359 void TriangleInBeteenInstance::setupAccelerationStructures()
360 {
361 	const DeviceInterface&	vkd			= m_context.getDeviceInterface();
362 	const VkDevice			device		= m_context.getDevice();
363 	Allocator&				allocator	= m_context.getDefaultAllocator();
364 
365 	de::SharedPtr<BottomLevelAccelerationStructure> triangleBLAS(makeBottomLevelAccelerationStructure().release());
366 	triangleBLAS->setGeometryData(
367 		{
368 			{ 16.0, 16.0, -8.0 },
369 			{ 56.0, 32.0, -8.0 },
370 			{ 32.0, 48.0, -8.0 },
371 		},
372 		true,
373 		VK_GEOMETRY_OPAQUE_BIT_KHR
374 		);
375 	triangleBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
376 	m_blasVect.push_back(triangleBLAS);
377 
378 	de::SharedPtr<BottomLevelAccelerationStructure> fullElipsoidBLAS(makeBottomLevelAccelerationStructure().release());
379 	fullElipsoidBLAS->setGeometryData(
380 		{
381 			{  0.0,  0.0, -64.0 },
382 			{ 64.0, 64.0, -16.0 },
383 		},
384 		false,
385 		0
386 		);
387 	fullElipsoidBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
388 	m_blasVect.push_back(fullElipsoidBLAS);
389 
390 	// build reference acceleration structure - triangle and a single aabb big enough to fit whole procedural geometry
391 	m_referenceTLAS->setInstanceCount(2);
392 	m_referenceTLAS->addInstance(fullElipsoidBLAS);
393 	m_referenceTLAS->addInstance(triangleBLAS);
394 	m_referenceTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
395 
396 	de::SharedPtr<BottomLevelAccelerationStructure> elipsoidWallBLAS(makeBottomLevelAccelerationStructure().release());
397 	elipsoidWallBLAS->setGeometryData(
398 		{
399 			{  0.0,  0.0, 0.0 },	// |*  |
400 			{ 20.0, 64.0, 1.0 },
401 			{ 20.0,  0.0, 0.0 },	// | * |
402 			{ 44.0, 64.0, 1.0 },
403 			{ 44.0,  0.0, 0.0 },	// |  *|
404 			{ 64.0, 64.0, 1.0 },
405 		},
406 		false,
407 		0
408 		);
409 	elipsoidWallBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
410 	m_blasVect.push_back(elipsoidWallBLAS);
411 
412 	// build result acceleration structure - triangle and a three aabb's (they are in front of triangle but generate intersections behind it)
413 	m_resultTLAS->setInstanceCount(2);
414 	m_resultTLAS->addInstance(elipsoidWallBLAS);
415 	m_resultTLAS->addInstance(triangleBLAS);
416 	m_resultTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator);
417 }
418 
419 class RayTracingProceduralGeometryTestCase : public TestCase
420 {
421 public:
422 	RayTracingProceduralGeometryTestCase		(tcu::TestContext& context, const char* name, TestType testType);
423 	~RayTracingProceduralGeometryTestCase		(void) = default;
424 
425 	void				checkSupport			(Context& context) const override;
426 	void				initPrograms			(SourceCollections& programCollection) const override;
427 	TestInstance*		createInstance			(Context& context) const override;
428 
429 protected:
430 	TestType m_testType;
431 };
432 
RayTracingProceduralGeometryTestCase(tcu::TestContext & context,const char * name,TestType testType)433 RayTracingProceduralGeometryTestCase::RayTracingProceduralGeometryTestCase(tcu::TestContext& context, const char* name, TestType testType)
434 	: TestCase		(context, name, "")
435 	, m_testType	(testType)
436 {
437 }
438 
checkSupport(Context & context) const439 void RayTracingProceduralGeometryTestCase::checkSupport(Context& context) const
440 {
441 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
442 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
443 
444 	if (!context.getRayTracingPipelineFeatures().rayTracingPipeline)
445 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
446 
447 	if (!context.getAccelerationStructureFeatures().accelerationStructure)
448 		TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
449 }
450 
initPrograms(SourceCollections & programCollection) const451 void RayTracingProceduralGeometryTestCase::initPrograms(SourceCollections& programCollection) const
452 {
453 	const vk::ShaderBuildOptions glslBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
454 
455 	std::string rgenSource =
456 		"#version 460 core\n"
457 		"#extension GL_EXT_ray_tracing : require\n"
458 		"layout(location = 0) rayPayloadEXT int payload;\n"
459 
460 		"layout(set = 0, binding = 0) uniform accelerationStructureEXT tlas;\n"
461 		"layout(set = 0, binding = 1, std430) writeonly buffer Result {\n"
462 		"    int value[];\n"
463 		"} result;\n"
464 
465 		"void main()\n"
466 		"{\n"
467 		"  float tmin        = 0.0;\n"
468 		"  float tmax        = 50.0;\n"
469 		"  vec3  origin      = vec3(float(gl_LaunchIDEXT.x) + 0.5f, float(gl_LaunchIDEXT.y) + 0.5f, 2.0);\n"
470 		"  vec3  direction   = vec3(0.0,0.0,-1.0);\n"
471 		"  uint  resultIndex = gl_LaunchIDEXT.x + gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x;\n"
472 
473 		"  traceRayEXT(tlas, gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, 0, 0, 0, origin, tmin, direction, tmax, 0);\n"
474 		// to be able to display result in cherry this is interpreated as r8g8b8a8 during verification
475 		// we are using only red but we need to add alpha (note: r and a may be swapped depending on endianness)
476 		"  result.value[resultIndex] = payload + 0xFF000000;\n"
477 		"};\n";
478 	programCollection.glslSources.add("rgen") << glu::RaygenSource(rgenSource) << glslBuildOptions;
479 
480 	std::string isecSource =
481 		"#version 460 core\n"
482 		"#extension GL_EXT_ray_tracing : require\n"
483 
484 		"void main()\n"
485 		"{\n"
486 		// note: same elipsoid center and radii are also defined in chit shader
487 		"  vec3 center = vec3(32.0, 32.0, -30.0);\n"
488 		"  vec3 radii  = vec3(30.0, 15.0, 5.0);\n"
489 
490 		// simplify to ray sphere intersection
491 		"  vec3  eliDir = gl_WorldRayOriginEXT - center;\n"
492 		"  vec3  eliS   = eliDir / radii;\n"
493 		"  vec3  rayS   = gl_WorldRayDirectionEXT / radii;\n"
494 
495 		"  float a = dot(rayS, rayS);\n"
496 		"  float b = dot(eliS, rayS);\n"
497 		"  float c = dot(eliS, eliS);\n"
498 		"  float h = b * b - a * (c - 1.0);\n"
499 		"  if (h < 0.0)\n"
500 		"    return;\n"
501 		"  reportIntersectionEXT((-b - sqrt(h)) / a, 0);\n"
502 		"}\n";
503 	programCollection.glslSources.add("isec") << glu::IntersectionSource(isecSource) << glslBuildOptions;
504 
505 	std::string chitSource =
506 		"#version 460 core\n"
507 		"#extension GL_EXT_ray_tracing : require\n"
508 		"layout(location = 0) rayPayloadInEXT int payload;\n"
509 		"\n"
510 		"void main()\n"
511 		"{\n"
512 		// note: same elipsoid center and radii are also defined in chit shader
513 		"  vec3 center    = vec3(32.0, 32.0, -30.0);\n"
514 		"  vec3 radii     = vec3(30.0, 15.0, 5.0);\n"
515 		"  vec3 lightDir  = normalize(vec3(0.0, 0.0, 1.0));\n"
516 		"  vec3 hitPos    = gl_WorldRayOriginEXT + gl_HitTEXT * gl_WorldRayDirectionEXT;\n"
517 		"  vec3 hitNormal = normalize((hitPos - center) / radii);\n"
518 
519 		"  payload = 50 + int(200.0 * clamp(dot(hitNormal, lightDir), 0.0, 1.0));\n"
520 		"}\n";
521 	programCollection.glslSources.add("chit") << glu::ClosestHitSource(chitSource) << glslBuildOptions;
522 
523 	if (m_testType == TestType::TRIANGLE_IN_BETWEEN)
524 	{
525 		std::string chitTriangleSource =
526 			"#version 460 core\n"
527 			"#extension GL_EXT_ray_tracing : require\n"
528 			"layout(location = 0) rayPayloadInEXT int payload;\n"
529 			"\n"
530 			"void main()\n"
531 			"{\n"
532 			"  payload = 250;\n"
533 			"}\n";
534 		programCollection.glslSources.add("chit_triangle") << glu::ClosestHitSource(chitTriangleSource) << glslBuildOptions;
535 	}
536 
537 	std::string missSource =
538 		"#version 460 core\n"
539 		"#extension GL_EXT_ray_tracing : require\n"
540 		"layout(location = 0) rayPayloadInEXT int payload;\n"
541 		"void main()\n"
542 		"{\n"
543 		"  payload = 30;\n"
544 		"}\n";
545 	programCollection.glslSources.add("miss") << glu::MissSource(missSource) << glslBuildOptions;
546 }
547 
createInstance(Context & context) const548 TestInstance* RayTracingProceduralGeometryTestCase::createInstance(Context& context) const
549 {
550 	if (m_testType == TestType::TRIANGLE_IN_BETWEEN)
551 		return new TriangleInBeteenInstance(context);
552 
553 	// TestType::OBJECT_BEHIND_BOUNDING_BOX
554 	return new ObjectBehindBoundingBoxInstance(context);
555 }
556 
557 }	// anonymous
558 
createProceduralGeometryTests(tcu::TestContext & testCtx)559 tcu::TestCaseGroup*	createProceduralGeometryTests(tcu::TestContext& testCtx)
560 {
561 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "procedural_geometry", "Test procedural geometry with complex bouding box sets"));
562 
563 	group->addChild(new RayTracingProceduralGeometryTestCase(testCtx, "object_behind_bounding_boxes",	TestType::OBJECT_BEHIND_BOUNDING_BOX));
564 	group->addChild(new RayTracingProceduralGeometryTestCase(testCtx, "triangle_in_between",			TestType::TRIANGLE_IN_BETWEEN));
565 
566 	return group.release();
567 }
568 
569 }	// RayTracing
570 
571 }	// vkt
572