• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 NVIDIA Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Ray Tracing Position Fetch Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRayTracingPositionFetchTests.hpp"
26 #include "vktTestCase.hpp"
27 
28 #include "vkRayTracingUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkBufferWithMemory.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 
36 #include "deUniquePtr.hpp"
37 
38 #include "tcuVectorUtil.hpp"
39 
40 #include <sstream>
41 #include <vector>
42 #include <iostream>
43 
44 namespace vkt
45 {
46 namespace RayTracing
47 {
48 
49 namespace
50 {
51 
52 using namespace vk;
53 
54 enum TestFlagBits
55 {
56 	TEST_FLAG_BIT_INSTANCE_TRANSFORM				= 1U << 0,
57 	TEST_FLAG_BIT_LAST								= 1U << 1
58 };
59 
60 std::vector<std::string> testFlagBitNames =
61 {
62 	"instance_transform",
63 };
64 
65 struct TestParams
66 {
67 	vk::VkAccelerationStructureBuildTypeKHR	buildType;		// are we making AS on CPU or GPU
68 	VkFormat								vertexFormat;
69 	deUint32								testFlagMask;
70 };
71 
72 class PositionFetchCase : public TestCase
73 {
74 public:
75 	PositionFetchCase(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
~PositionFetchCase(void)76 	virtual					~PositionFetchCase(void) {}
77 
78 	virtual void			checkSupport(Context& context) const;
79 	virtual void			initPrograms(vk::SourceCollections& programCollection) const;
80 	virtual TestInstance* createInstance(Context& context) const;
81 
82 protected:
83 	TestParams				m_params;
84 };
85 
86 class PositionFetchInstance : public TestInstance
87 {
88 public:
89 	PositionFetchInstance(Context& context, const TestParams& params);
~PositionFetchInstance(void)90 	virtual						~PositionFetchInstance(void) {}
91 
92 	virtual tcu::TestStatus		iterate(void);
93 
94 protected:
95 	TestParams					m_params;
96 };
97 
PositionFetchCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)98 PositionFetchCase::PositionFetchCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
99 	: TestCase	(testCtx, name)
100 	, m_params	(params)
101 {}
102 
checkSupport(Context & context) const103 void PositionFetchCase::checkSupport (Context& context) const
104 {
105 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
106 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
107 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_position_fetch");
108 
109 	const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
110 	if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
111 		TCU_THROW(TestError, "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
112 
113 	if (m_params.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
114 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
115 
116 	const VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR& rayTracingPositionFetchFeaturesKHR = context.getRayTracingPositionFetchFeatures();
117 	if (rayTracingPositionFetchFeaturesKHR.rayTracingPositionFetch == DE_FALSE)
118 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDevicePositionFetchFeaturesKHR.rayTracingPositionFetch");
119 
120 	// Check supported vertex format.
121 	checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.vertexFormat);
122 }
123 
initPrograms(vk::SourceCollections & programCollection) const124 void PositionFetchCase::initPrograms (vk::SourceCollections& programCollection) const
125 {
126 	const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
127 
128 	deUint32 numRays = 1; // XXX
129 
130 	std::ostringstream layoutDecls;
131 	layoutDecls
132 		<< "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
133 		<< "layout(set=0, binding=1, std430) buffer RayOrigins {\n"
134 		<< "  vec4 values[" << numRays << "];\n"
135 		<< "} origins;\n"
136 		<< "layout(set=0, binding=2, std430) buffer OutputPositions {\n"
137 		<< "  vec4 values[" << 6*numRays << "];\n"
138 		<< "} modes;\n"
139 		;
140 	const auto layoutDeclsStr = layoutDecls.str();
141 
142 	std::ostringstream rgen;
143 	rgen
144 		<< "#version 460 core\n"
145 		<< "#extension GL_EXT_ray_tracing : require\n"
146 		<< "#extension GL_EXT_ray_tracing_position_fetch : require\n"
147 		<< "\n"
148 		<< "layout(location=0) rayPayloadEXT int value;\n"
149 		<< "\n"
150 		<< layoutDeclsStr
151 		<< "\n"
152 		<< "void main()\n"
153 		<< "{\n"
154 		<< "  const uint  cullMask  = 0xFF;\n"
155 		<< "  const vec3  origin    = origins.values[gl_LaunchIDEXT.x].xyz;\n"
156 		<< "  const vec3  direction = vec3(0.0, 0.0, -1.0);\n"
157 		<< "  const float tMin      = 0.0;\n"
158 		<< "  const float tMax      = 2.0;\n"
159 		<< "  value                 = 0xFFFFFFFF;\n"
160 		<< "  traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, cullMask, 0, 0, 0, origin, tMin, direction, tMax, 0);\n"
161 		<< "}\n"
162 		;
163 
164 	std::ostringstream ah;
165 	ah
166 		<< "#version 460 core\n"
167 		<< "#extension GL_EXT_ray_tracing : require\n"
168 		<< "#extension GL_EXT_ray_tracing_position_fetch : require\n"
169 		<< "\n"
170 		<< layoutDeclsStr
171 		<< "\n"
172 		<< "layout(location=0) rayPayloadEXT int value;\n"
173 		<< "\n"
174 		<< "void main()\n"
175 		<< "{\n"
176 		<< "  for (int i=0; i<3; i++) {\n"
177 		<< "    modes.values[6*gl_LaunchIDEXT.x+2*i] = vec4(gl_HitTriangleVertexPositionsEXT[i], 0.0);\n"
178 		<< "  }\n"
179 		<< "  terminateRayEXT;\n"
180 		<< "}\n"
181 		;
182 
183 	std::ostringstream ch;
184 	ch
185 		<< "#version 460 core\n"
186 		<< "#extension GL_EXT_ray_tracing : require\n"
187 		<< "#extension GL_EXT_ray_tracing_position_fetch : require\n"
188 		<< "\n"
189 		<< layoutDeclsStr
190 		<< "\n"
191 		<< "layout(location=0) rayPayloadEXT int value;\n"
192 		<< "\n"
193 		<< "void main()\n"
194 		<< "{\n"
195 		<< "  for (int i=0; i<3; i++) {\n"
196 		<< "    modes.values[6*gl_LaunchIDEXT.x+2*i+1] = vec4(gl_HitTriangleVertexPositionsEXT[i], 0);\n"
197 		<< "  }\n"
198 		<< "}\n"
199 		;
200 
201 	// Should never miss to fill in with sentinel values to cause a failure
202 	std::ostringstream miss;
203 	miss
204 		<< "#version 460 core\n"
205 		<< "#extension GL_EXT_ray_tracing : require\n"
206 		<< layoutDeclsStr
207 		<< "\n"
208 		<< "layout(location=0) rayPayloadEXT int value;\n"
209 		<< "\n"
210 		<< "void main()\n"
211 		<< "{\n"
212 		<< "  for (int i=0; i<6; i++) {\n"
213 		<< "    modes.values[6*gl_LaunchIDEXT.x+i] = vec4(123.0f, 456.0f, 789.0f, 0.0f);\n"
214 		<< "  }\n"
215 		<< "}\n";
216 
217 	programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
218 	programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(miss.str())) << buildOptions;
219 	programCollection.glslSources.add("ah") << glu::AnyHitSource(updateRayTracingGLSL(ah.str())) << buildOptions;
220 	programCollection.glslSources.add("ch") << glu::ClosestHitSource(updateRayTracingGLSL(ch.str())) << buildOptions;
221 }
222 
createInstance(Context & context) const223 TestInstance* PositionFetchCase::createInstance (Context& context) const
224 {
225 	return new PositionFetchInstance(context, m_params);
226 }
227 
PositionFetchInstance(Context & context,const TestParams & params)228 PositionFetchInstance::PositionFetchInstance (Context& context, const TestParams& params)
229 	: TestInstance	(context)
230 	, m_params		(params)
231 {}
232 
iterate(void)233 tcu::TestStatus PositionFetchInstance::iterate (void)
234 {
235 	const auto&	vki		= m_context.getInstanceInterface();
236 	const auto	physDev	= m_context.getPhysicalDevice();
237 	const auto&	vkd		= m_context.getDeviceInterface();
238 	const auto	device	= m_context.getDevice();
239 	auto&		alloc	= m_context.getDefaultAllocator();
240 	const auto	qIndex	= m_context.getUniversalQueueFamilyIndex();
241 	const auto	queue	= m_context.getUniversalQueue();
242 	const auto	stages	= VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
243 
244 	// Command pool and buffer.
245 	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
246 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
247 	const auto cmdBuffer	= cmdBufferPtr.get();
248 
249 	beginCommandBuffer(vkd, cmdBuffer);
250 
251 	// If we add anything to the command buffer here that the AS builds depend on make sure
252 	// to submit and wait when in CPU build mode
253 
254 	// Build acceleration structures.
255 	auto topLevelAS		= makeTopLevelAccelerationStructure();
256 	auto bottomLevelAS	= makeBottomLevelAccelerationStructure();
257 
258 	const std::vector<tcu::Vec3> triangle =
259 	{
260 		tcu::Vec3(0.0f, 0.0f, 0.0f),
261 		tcu::Vec3(1.0f, 0.0f, 0.0f),
262 		tcu::Vec3(0.0f, 1.0f, 0.0f),
263 	};
264 
265 	const VkTransformMatrixKHR notQuiteIdentityMatrix3x4 = { { { 0.98f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.97f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.99f, 0.0f } } };
266 
267 	de::SharedPtr<RaytracedGeometryBase> geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, m_params.vertexFormat, VK_INDEX_TYPE_NONE_KHR);
268 
269 	for (auto & v : triangle) {
270 		geometry->addVertex(v);
271 	}
272 
273 	bottomLevelAS->addGeometry(geometry);
274 	bottomLevelAS->setBuildFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR);
275 	bottomLevelAS->setBuildType(m_params.buildType);
276 	bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
277 	de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr (bottomLevelAS.release());
278 
279 	topLevelAS->setInstanceCount(1);
280 	topLevelAS->setBuildType(m_params.buildType);
281 	topLevelAS->addInstance(blasSharedPtr, (m_params.testFlagMask & TEST_FLAG_BIT_INSTANCE_TRANSFORM) ? notQuiteIdentityMatrix3x4 : identityMatrix3x4);
282 	topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
283 
284 	// One ray for this test
285 	// XXX Should it be multiple triangles and one ray per triangle for more coverage?
286 	// XXX If it's really one ray, the origin buffer is complete overkill
287 	deUint32 numRays = 1; // XXX
288 
289 	// SSBO buffer for origins.
290 	const auto originsBufferSize		= static_cast<VkDeviceSize>(sizeof(tcu::Vec4) * numRays);
291 	const auto originsBufferInfo		= makeBufferCreateInfo(originsBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
292 	BufferWithMemory originsBuffer	(vkd, device, alloc, originsBufferInfo, MemoryRequirement::HostVisible);
293 	auto& originsBufferAlloc			= originsBuffer.getAllocation();
294 	void* originsBufferData				= originsBufferAlloc.getHostPtr();
295 
296 	std::vector<tcu::Vec4> origins;
297 	std::vector<tcu::Vec3> expectedOutputPositions;
298 	origins.reserve(numRays);
299 	expectedOutputPositions.reserve(6*numRays);
300 
301 	// Fill in vector of expected outputs
302 	for (deUint32 index = 0; index < numRays; index++) {
303 		for (deUint32 vert = 0; vert < 3; vert++) {
304 			tcu::Vec3 pos = triangle[vert];
305 
306 			// One from CH, one from AH
307 			expectedOutputPositions.push_back(pos);
308 			expectedOutputPositions.push_back(pos);
309 		}
310 	}
311 
312 	// XXX Arbitrary location and see above
313 	for (deUint32 index = 0; index < numRays; index++) {
314 		origins.push_back(tcu::Vec4(0.25, 0.25, 1.0, 0.0));
315 	}
316 
317 	const auto				originsBufferSizeSz = static_cast<size_t>(originsBufferSize);
318 	deMemcpy(originsBufferData, origins.data(), originsBufferSizeSz);
319 	flushAlloc(vkd, device, originsBufferAlloc);
320 
321 	// Storage buffer for output modes
322 	const auto outputPositionsBufferSize = static_cast<VkDeviceSize>(6 * 4 * sizeof(float) * numRays);
323 	const auto outputPositionsBufferInfo = makeBufferCreateInfo(outputPositionsBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
324 	BufferWithMemory outputPositionsBuffer(vkd, device, alloc, outputPositionsBufferInfo, MemoryRequirement::HostVisible);
325 	auto& outputPositionsBufferAlloc = outputPositionsBuffer.getAllocation();
326 	void* outputPositionsBufferData = outputPositionsBufferAlloc.getHostPtr();
327 	deMemset(outputPositionsBufferData, 0xFF, static_cast<size_t>(outputPositionsBufferSize));
328 	flushAlloc(vkd, device, outputPositionsBufferAlloc);
329 
330 	// Descriptor set layout.
331 	DescriptorSetLayoutBuilder dsLayoutBuilder;
332 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
333 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
334 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
335 	const auto setLayout = dsLayoutBuilder.build(vkd, device);
336 
337 	// Pipeline layout.
338 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
339 
340 	// Descriptor pool and set.
341 	DescriptorPoolBuilder poolBuilder;
342 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
343 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
344 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
345 	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
346 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
347 
348 	// Update descriptor set.
349 	{
350 		const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
351 		{
352 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
353 			nullptr,
354 			1u,
355 			topLevelAS.get()->getPtr(),
356 		};
357 		const auto inStorageBufferInfo = makeDescriptorBufferInfo(originsBuffer.get(), 0ull, VK_WHOLE_SIZE);
358 		const auto storageBufferInfo = makeDescriptorBufferInfo(outputPositionsBuffer.get(), 0ull, VK_WHOLE_SIZE);
359 
360 		DescriptorSetUpdateBuilder updateBuilder;
361 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
362 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inStorageBufferInfo);
363 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
364 		updateBuilder.update(vkd, device);
365 	}
366 
367 	// Shader modules.
368 	auto rgenModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0);
369 	auto missModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0);
370 	auto ahModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("ah"), 0);
371 	auto chModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("ch"), 0);
372 
373 	// Get some ray tracing properties.
374 	deUint32 shaderGroupHandleSize		= 0u;
375 	deUint32 shaderGroupBaseAlignment	= 1u;
376 	{
377 		const auto rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physDev);
378 		shaderGroupHandleSize				= rayTracingPropertiesKHR->getShaderGroupHandleSize();
379 		shaderGroupBaseAlignment			= rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
380 	}
381 
382 	// Create raytracing pipeline and shader binding tables.
383 	Move<VkPipeline>				pipeline;
384 	de::MovePtr<BufferWithMemory>	raygenSBT;
385 	de::MovePtr<BufferWithMemory>	missSBT;
386 	de::MovePtr<BufferWithMemory>	hitSBT;
387 	de::MovePtr<BufferWithMemory>	callableSBT;
388 
389 	auto raygenSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
390 	auto missSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
391 	auto hitSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
392 	auto callableSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
393 
394 	{
395 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
396 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,      rgenModule, 0);
397 		rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,        missModule, 1);
398 		rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,     ahModule, 2);
399 		rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chModule, 2);
400 
401 		pipeline		= rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
402 
403 		raygenSBT		= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
404 		raygenSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
405 
406 		missSBT			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
407 		missSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
408 
409 		hitSBT			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
410 		hitSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
411 	}
412 
413 	// Trace rays.
414 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
415 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
416 	vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, numRays, 1u, 1u);
417 
418 	// Barrier for the output buffer.
419 	const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
420 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &bufferBarrier, 0u, nullptr, 0u, nullptr);
421 
422 	endCommandBuffer(vkd, cmdBuffer);
423 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
424 
425 	// Verify results.
426 	std::vector<tcu::Vec4>	outputData(expectedOutputPositions.size());
427 	const auto				outputPositionsBufferSizeSz = static_cast<size_t>(outputPositionsBufferSize);
428 
429 	invalidateAlloc(vkd, device, outputPositionsBufferAlloc);
430 	DE_ASSERT(de::dataSize(outputData) == outputPositionsBufferSizeSz);
431 	deMemcpy(outputData.data(), outputPositionsBufferData, outputPositionsBufferSizeSz);
432 
433 	for (size_t i = 0; i < outputData.size(); ++i)
434 	{
435 		/*const */ auto& outVal = outputData[i]; // Should be const but .xyz() isn't
436 		tcu::Vec3 outVec3 = outVal.xyz();
437 		const auto& expectedVal = expectedOutputPositions[i];
438 		const auto& diff = expectedOutputPositions[i] - outVec3;
439 		float len = dot(diff, diff);
440 
441 		// XXX Find a better epsilon
442 		if (!(len < 1e-5))
443 		{
444 			std::ostringstream msg;
445 			msg << "Unexpected value found for element " << i << ": expected " << expectedVal << " and found " << outVal << ";";
446 			TCU_FAIL(msg.str());
447 		}
448 #if 0
449 		else
450 		{
451 			std::ostringstream msg;
452 			msg << "Expected value found for element " << i << ": expected " << expectedVal << " and found " << outVal << ";\n";
453 			std::cout << msg.str();
454 		}
455 #endif
456 	}
457 
458 
459 	return tcu::TestStatus::pass("Pass");
460 }
461 
462 } // anonymous
463 
createPositionFetchTests(tcu::TestContext & testCtx)464 tcu::TestCaseGroup*	createPositionFetchTests (tcu::TestContext& testCtx)
465 {
466 	// Test ray pipeline shaders using position fetch
467 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "position_fetch"));
468 
469 	struct
470 	{
471 		vk::VkAccelerationStructureBuildTypeKHR				buildType;
472 		const char* name;
473 	} buildTypes[] =
474 	{
475 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,	"cpu_built"	},
476 		{ VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,	"gpu_built"	},
477 	};
478 
479 	const VkFormat vertexFormats[] =
480 	{
481 		// Mandatory formats.
482 		VK_FORMAT_R32G32_SFLOAT,
483 		VK_FORMAT_R32G32B32_SFLOAT,
484 		VK_FORMAT_R16G16_SFLOAT,
485 		VK_FORMAT_R16G16B16A16_SFLOAT,
486 		VK_FORMAT_R16G16_SNORM,
487 		VK_FORMAT_R16G16B16A16_SNORM,
488 
489 		// Additional formats.
490 		VK_FORMAT_R8G8_SNORM,
491 		VK_FORMAT_R8G8B8_SNORM,
492 		VK_FORMAT_R8G8B8A8_SNORM,
493 		VK_FORMAT_R16G16B16_SNORM,
494 		VK_FORMAT_R16G16B16_SFLOAT,
495 		VK_FORMAT_R32G32B32A32_SFLOAT,
496 		VK_FORMAT_R64G64_SFLOAT,
497 		VK_FORMAT_R64G64B64_SFLOAT,
498 		VK_FORMAT_R64G64B64A64_SFLOAT,
499 	};
500 
501 	for (size_t buildTypeNdx = 0; buildTypeNdx < DE_LENGTH_OF_ARRAY(buildTypes); ++buildTypeNdx)
502 	{
503 		de::MovePtr<tcu::TestCaseGroup> buildGroup(new tcu::TestCaseGroup(group->getTestContext(), buildTypes[buildTypeNdx].name));
504 
505 		for (size_t vertexFormatNdx = 0; vertexFormatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); ++vertexFormatNdx)
506 		{
507 			const auto format = vertexFormats[vertexFormatNdx];
508 			const auto formatName = getFormatSimpleName(format);
509 
510 			de::MovePtr<tcu::TestCaseGroup> vertexFormatGroup(new tcu::TestCaseGroup(group->getTestContext(), formatName.c_str()));
511 
512 			for (deUint32 testFlagMask = 0; testFlagMask < TEST_FLAG_BIT_LAST; testFlagMask++)
513 			{
514 				std::string maskName = "";
515 
516 				for (deUint32 bit = 0; bit < testFlagBitNames.size(); bit++)
517 				{
518 					if (testFlagMask & (1 << bit))
519 					{
520 						if (maskName != "")
521 							maskName += "_";
522 						maskName += testFlagBitNames[bit];
523 					}
524 				}
525 				if (maskName == "")
526 					maskName = "NoFlags";
527 
528 				de::MovePtr<tcu::TestCaseGroup> testFlagGroup(new tcu::TestCaseGroup(group->getTestContext(), maskName.c_str()));
529 
530 				TestParams testParams
531 				{
532 					buildTypes[buildTypeNdx].buildType,
533 					format,
534 					testFlagMask,
535 				};
536 
537 				vertexFormatGroup->addChild(new PositionFetchCase(testCtx, maskName, testParams));
538 			}
539 			buildGroup->addChild(vertexFormatGroup.release());
540 		}
541 		group->addChild(buildGroup.release());
542 	}
543 
544 
545 	return group.release();
546 }
547 
548 } // RayTracing
549 } // vkt
550