• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Valve 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 Barycentric Coordinates Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRayTracingBarycentricCoordinatesTests.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 #include "deRandom.hpp"
38 
39 #include <sstream>
40 #include <vector>
41 
42 namespace vkt
43 {
44 namespace RayTracing
45 {
46 
47 namespace
48 {
49 
50 using namespace vk;
51 
52 enum class TestCaseRT
53 {
54 	CLOSEST_HIT,
55 	ANY_HIT,
56 	CLOSEST_AND_ANY_HIT_TERMINATE
57 };
58 
59 struct TestParams
60 {
61 	TestCaseRT				testCase;
62 	deUint32				seed;
63 };
64 
getUsedStages(const TestParams & params)65 VkShaderStageFlags getUsedStages (const TestParams& params)
66 {
67 	VkShaderStageFlags stageFlags{VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR};
68 	if (params.testCase == TestCaseRT::CLOSEST_HIT)
69 		stageFlags |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
70 	else if (params.testCase == TestCaseRT::ANY_HIT)
71 		stageFlags |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
72 	else if (params.testCase == TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE)
73 		stageFlags |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
74 
75 	return stageFlags;
76 }
77 
78 constexpr float		kZCoord		= 5.0f;
79 constexpr float		kXYCoordAbs	= 1.0f;
80 
81 constexpr float		kThreshold	= 0.001f;				// For the resulting coordinates.
82 constexpr float		kTMin		= 1.0f - kThreshold;	// Require the same precision in T.
83 constexpr float		kTMax		= 1.0f + kThreshold;	// Ditto.
84 constexpr deUint32	kNumRays	= 20u;
85 
86 class BarycentricCoordinatesCase : public TestCase
87 {
88 public:
89 							BarycentricCoordinatesCase	(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
~BarycentricCoordinatesCase(void)90 	virtual					~BarycentricCoordinatesCase	(void) {}
91 
92 	virtual void			checkSupport				(Context& context) const;
93 	virtual void			initPrograms				(vk::SourceCollections& programCollection) const;
94 	virtual TestInstance*	createInstance				(Context& context) const;
95 
96 protected:
97 	TestParams				m_params;
98 };
99 
100 class BarycentricCoordinatesInstance : public TestInstance
101 {
102 public:
103 								BarycentricCoordinatesInstance	(Context& context, const TestParams& params);
~BarycentricCoordinatesInstance(void)104 	virtual						~BarycentricCoordinatesInstance	(void) {}
105 
106 	virtual tcu::TestStatus		iterate							(void);
107 
108 protected:
109 	TestParams					m_params;
110 };
111 
BarycentricCoordinatesCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)112 BarycentricCoordinatesCase::BarycentricCoordinatesCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
113 	: TestCase	(testCtx, name)
114 	, m_params	(params)
115 {}
116 
checkSupport(Context & context) const117 void BarycentricCoordinatesCase::checkSupport (Context& context) const
118 {
119 	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
120 	context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
121 }
122 
initPrograms(vk::SourceCollections & programCollection) const123 void BarycentricCoordinatesCase::initPrograms (vk::SourceCollections& programCollection) const
124 {
125 	const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
126 
127 	std::ostringstream layoutDecls;
128 	layoutDecls
129 		<< "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
130 		<< "layout(set=0, binding=1) uniform RayDirections {\n"
131 		<< "  vec4 values[" << kNumRays << "];\n"
132 		<< "} directions;\n"
133 		<< "layout(set=0, binding=2, std430) buffer OutputBarycentrics {\n"
134 		<< "  vec4 values[" << kNumRays << "];\n"
135 		<< "} coordinates;\n"
136 		;
137 	const auto layoutDeclsStr = layoutDecls.str();
138 
139 	std::ostringstream rgen;
140 	rgen
141 		<< "#version 460 core\n"
142 		<< "#extension GL_EXT_ray_tracing : require\n"
143 		<< "\n"
144 		<< "layout(location=0) rayPayloadEXT vec3 hitValue;\n"
145 		<< "\n"
146 		<< layoutDeclsStr
147 		<< "\n"
148 		<< "void main()\n"
149 		<< "{\n"
150 		<< "  const uint  cullMask  = 0xFF;\n"
151 		<< "  const vec3  origin    = vec3(0.0, 0.0, 0.0);\n"
152 		<< "  const vec3  direction = directions.values[gl_LaunchIDEXT.x].xyz;\n"
153 		<< "  const float tMin      = " << kTMin << ";\n"
154 		<< "  const float tMax      = " << kTMax << ";\n"
155 		<< "  traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, cullMask, 0, 0, 0, origin, tMin, direction, tMax, 0);\n"
156 		<< "}\n"
157 		;
158 
159 	std::ostringstream chit;
160 	chit
161 		<< "#version 460 core\n"
162 		<< "#extension GL_EXT_ray_tracing : require\n"
163 		<< "\n"
164 		<< "hitAttributeEXT vec2 baryCoord;\n"
165 		<< "\n"
166 		<< layoutDeclsStr
167 		<< "\n"
168 		<< "void main()\n"
169 		<< "{\n"
170 		<< "  coordinates.values[gl_LaunchIDEXT.x].xy = baryCoord;\n"
171 		<< "}\n"
172 		;
173 
174 	std::ostringstream ahitTerminate;
175 	ahitTerminate
176 		<< "#version 460 core\n"
177 		<< "#extension GL_EXT_ray_tracing : require\n"
178 		<< "\n"
179 		<< "hitAttributeEXT vec2 baryCoord;\n"
180 		<< "\n"
181 		<< layoutDeclsStr
182 		<< "\n"
183 		<< "void main()\n"
184 		<< "{\n"
185 		<< "  coordinates.values[gl_LaunchIDEXT.x].z = 0.999;\n"
186 		<< "  if(baryCoord.x < 0.7){\n"
187 		<< "	terminateRayEXT;\n"
188 		<< "    coordinates.values[gl_LaunchIDEXT.x].z = 0.5;\n"
189 		<< "  }\n"
190 		<< "}\n"
191 		;
192 
193 	std::ostringstream miss;
194 	miss
195 		<< "#version 460 core\n"
196 		<< "#extension GL_EXT_ray_tracing : require\n"
197 		<< "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
198 		<< layoutDeclsStr
199 		<< "\n"
200 		<< "void main()\n"
201 		<< "{\n"
202 		<< "  coordinates.values[gl_LaunchIDEXT.x] = vec4(-1.0, -1.0, -1.0, -1.0);\n"
203 		<< "}\n";
204 
205 	programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
206 	programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(miss.str())) << buildOptions;
207 
208 	if (m_params.testCase == TestCaseRT::CLOSEST_HIT)
209 		programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(chit.str())) << buildOptions;
210 	else if(m_params.testCase == TestCaseRT::ANY_HIT)
211 		programCollection.glslSources.add("chit") << glu::AnyHitSource(updateRayTracingGLSL(chit.str())) << buildOptions;
212 	else if (m_params.testCase == TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE)
213 	{
214 		programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(chit.str())) << buildOptions;
215 		programCollection.glslSources.add("ahitTerminate") << glu::AnyHitSource(updateRayTracingGLSL(ahitTerminate.str())) << buildOptions;
216 	}
217 	else
218 		DE_ASSERT(false);
219 }
220 
createInstance(Context & context) const221 TestInstance* BarycentricCoordinatesCase::createInstance (Context& context) const
222 {
223 	return new BarycentricCoordinatesInstance(context, m_params);
224 }
225 
BarycentricCoordinatesInstance(Context & context,const TestParams & params)226 BarycentricCoordinatesInstance::BarycentricCoordinatesInstance (Context& context, const TestParams& params)
227 	: TestInstance	(context)
228 	, m_params		(params)
229 {}
230 
231 // Calculates coordinates in a triangle given barycentric coordinates b and c.
calcCoordinates(const std::vector<tcu::Vec3> & triangle,float b,float c)232 tcu::Vec3 calcCoordinates (const std::vector<tcu::Vec3>& triangle, float b, float c)
233 {
234 	DE_ASSERT(triangle.size() == 3u);
235 	DE_ASSERT(b > 0.0f);
236 	DE_ASSERT(c > 0.0f);
237 	DE_ASSERT(b + c < 1.0f);
238 
239 	const float a = 1.0f - b - c;
240 	DE_ASSERT(a > 0.0f);
241 
242 	return triangle[0] * a + triangle[1] * b + triangle[2] * c;
243 }
244 
245 // Return a, b, c with a close to 1.0f and (b, c) close to 0.0f.
getBarycentricVertex(void)246 tcu::Vec3 getBarycentricVertex (void)
247 {
248 	const float a = 0.999f;
249 	const float aux = 1.0f - a;
250 	const float b = aux / 2.0f;
251 	const float c = b;
252 
253 	return tcu::Vec3(a, b, c);
254 }
255 
extendToV4(const tcu::Vec3 & vec3)256 tcu::Vec4 extendToV4 (const tcu::Vec3& vec3)
257 {
258 	return tcu::Vec4(vec3.x(), vec3.y(), vec3.z(), 0.0f);
259 }
260 
iterate(void)261 tcu::TestStatus BarycentricCoordinatesInstance::iterate (void)
262 {
263 	const auto&	vki		= m_context.getInstanceInterface();
264 	const auto	physDev	= m_context.getPhysicalDevice();
265 	const auto&	vkd		= m_context.getDeviceInterface();
266 	const auto	device	= m_context.getDevice();
267 	auto&		alloc	= m_context.getDefaultAllocator();
268 	const auto	qIndex	= m_context.getUniversalQueueFamilyIndex();
269 	const auto	queue	= m_context.getUniversalQueue();
270 	const auto	stages	= getUsedStages(m_params);
271 
272 	// Command pool and buffer.
273 	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
274 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
275 	const auto cmdBuffer	= cmdBufferPtr.get();
276 
277 	beginCommandBuffer(vkd, cmdBuffer);
278 
279 	// Build acceleration structures.
280 	auto topLevelAS		= makeTopLevelAccelerationStructure();
281 	auto bottomLevelAS	= makeBottomLevelAccelerationStructure();
282 
283 	const std::vector<tcu::Vec3> triangle =
284 	{
285 		tcu::Vec3(        0.0f, -kXYCoordAbs, kZCoord),
286 		tcu::Vec3(-kXYCoordAbs,  kXYCoordAbs, kZCoord),
287 		tcu::Vec3( kXYCoordAbs,  kXYCoordAbs, kZCoord),
288 	};
289 
290 	bottomLevelAS->addGeometry(triangle, true/*is triangles*/, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
291 	bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
292 	de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr (bottomLevelAS.release());
293 
294 	topLevelAS->setInstanceCount(1);
295 	topLevelAS->addInstance(blasSharedPtr, identityMatrix3x4, 0, 0xFFu, 0u, VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR);
296 	topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
297 
298 	// Uniform buffer for directions.
299 	const auto directionsBufferSize		= static_cast<VkDeviceSize>(sizeof(tcu::Vec4) * kNumRays);
300 	const auto directionsBufferInfo		= makeBufferCreateInfo(directionsBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
301 	BufferWithMemory directionsBuffer	(vkd, device, alloc, directionsBufferInfo, MemoryRequirement::HostVisible);
302 	auto& directionsBufferAlloc			= directionsBuffer.getAllocation();
303 	void* directionsBufferData			= directionsBufferAlloc.getHostPtr();
304 
305 	// Generate rays towards the 3 triangle coordinates (avoiding exact vertices) and additional coordinates.
306 	std::vector<tcu::Vec4> directions;
307 	std::vector<tcu::Vec4> expectedOutputCoordinates;
308 	directions.reserve(kNumRays);
309 	expectedOutputCoordinates.reserve(kNumRays);
310 
311 	const auto barycentricABC = getBarycentricVertex();
312 
313 	directions.push_back(extendToV4(calcCoordinates(triangle, barycentricABC.x(), barycentricABC.y())));
314 	directions.push_back(extendToV4(calcCoordinates(triangle, barycentricABC.y(), barycentricABC.x())));
315 	directions.push_back(extendToV4(calcCoordinates(triangle, barycentricABC.y(), barycentricABC.z())));
316 
317 	float expectedZ = 0.0f;
318 	// Set expectedZ to the same value as the AnyHit shader sets
319 	if (m_params.testCase == TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE)
320 		expectedZ = 0.999f;
321 
322 	expectedOutputCoordinates.push_back(tcu::Vec4(barycentricABC.x(), barycentricABC.y(), expectedZ, 0.0f));
323 	expectedOutputCoordinates.push_back(tcu::Vec4(barycentricABC.y(), barycentricABC.x(), expectedZ, 0.0f));
324 	expectedOutputCoordinates.push_back(tcu::Vec4(barycentricABC.y(), barycentricABC.z(), expectedZ, 0.0f));
325 
326 	de::Random rnd(m_params.seed);
327 	while (directions.size() < kNumRays)
328 	{
329 		// Avoid 0.0 when choosing b and c.
330 		float b;
331 		while ((b = rnd.getFloat()) == 0.0f)
332 			;
333 		float c;
334 		while ((c = rnd.getFloat(0.0f, 1.0f - b)) == 0.0f)
335 			;
336 		directions.push_back(extendToV4(calcCoordinates(triangle, b, c)));
337 		if (m_params.testCase == TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE)
338 			expectedOutputCoordinates.push_back(tcu::Vec4(b, c, expectedZ, 0.0f));
339 		else
340 			expectedOutputCoordinates.push_back(tcu::Vec4(b, c, 0.0f, 0.0f));
341 	}
342 
343 	deMemcpy(directionsBufferData, directions.data(), directionsBufferSize);
344 	flushAlloc(vkd, device, directionsBufferAlloc);
345 
346 	// Storage buffer for output barycentric coordinates.
347 	const auto barycoordsBufferSize		= static_cast<VkDeviceSize>(sizeof(tcu::Vec4) * kNumRays);
348 	const auto barycoordsBufferInfo		= makeBufferCreateInfo(barycoordsBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
349 	BufferWithMemory barycoordsBuffer	(vkd, device, alloc, barycoordsBufferInfo, MemoryRequirement::HostVisible);
350 	auto& barycoordsBufferAlloc			= barycoordsBuffer.getAllocation();
351 	void* barycoordsBufferData			= barycoordsBufferAlloc.getHostPtr();
352 	deMemset(barycoordsBufferData, 0, static_cast<size_t>(barycoordsBufferSize));
353 	flushAlloc(vkd, device, barycoordsBufferAlloc);
354 
355 	// Descriptor set layout.
356 	DescriptorSetLayoutBuilder dsLayoutBuilder;
357 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
358 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stages);
359 	dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
360 	const auto setLayout = dsLayoutBuilder.build(vkd, device);
361 
362 	// Pipeline layout.
363 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
364 
365 	// Descriptor pool and set.
366 	DescriptorPoolBuilder poolBuilder;
367 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
368 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
369 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
370 	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
371 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
372 
373 	// Update descriptor set.
374 	{
375 		const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
376 		{
377 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
378 			nullptr,
379 			1u,
380 			topLevelAS.get()->getPtr(),
381 		};
382 		const auto uniformBufferInfo = makeDescriptorBufferInfo(directionsBuffer.get(), 0ull, VK_WHOLE_SIZE);
383 		const auto storageBufferInfo = makeDescriptorBufferInfo(barycoordsBuffer.get(), 0ull, VK_WHOLE_SIZE);
384 
385 		DescriptorSetUpdateBuilder updateBuilder;
386 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
387 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo);
388 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
389 		updateBuilder.update(vkd, device);
390 	}
391 
392 	// Shader modules.
393 	auto rgenModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("rgen"), 0);
394 	auto missModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("miss"), 0);
395 	auto chitModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("chit"), 0);
396 	Move<VkShaderModule> ahitTerminateModule;
397 	if(m_params.testCase == TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE)
398 		ahitTerminateModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("ahitTerminate"), 0);
399 
400 	// Get some ray tracing properties.
401 	deUint32 shaderGroupHandleSize		= 0u;
402 	deUint32 shaderGroupBaseAlignment	= 1u;
403 	{
404 		const auto rayTracingPropertiesKHR	= makeRayTracingProperties(vki, physDev);
405 		shaderGroupHandleSize				= rayTracingPropertiesKHR->getShaderGroupHandleSize();
406 		shaderGroupBaseAlignment			= rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
407 	}
408 
409 	// Create raytracing pipeline and shader binding tables.
410 	Move<VkPipeline>				pipeline;
411 	de::MovePtr<BufferWithMemory>	raygenSBT;
412 	de::MovePtr<BufferWithMemory>	missSBT;
413 	de::MovePtr<BufferWithMemory>	hitSBT;
414 	de::MovePtr<BufferWithMemory>	callableSBT;
415 
416 	auto raygenSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
417 	auto missSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
418 	auto hitSBTRegion		= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
419 	auto callableSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
420 
421 	{
422 		const auto rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
423 		rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenModule, 0);
424 		rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR, missModule, 1);
425 		if(m_params.testCase == TestCaseRT::CLOSEST_HIT)
426 			rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, 2);
427 		if (m_params.testCase == TestCaseRT::ANY_HIT)
428 			rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR, chitModule, 2);
429 		else if (m_params.testCase == TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE)
430 		{
431 			rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, chitModule, 2);
432 			rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR, ahitTerminateModule, 2);
433 		}
434 
435 		pipeline		= rayTracingPipeline->createPipeline(vkd, device, pipelineLayout.get());
436 
437 		raygenSBT		= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
438 		raygenSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
439 
440 		missSBT			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
441 		missSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
442 
443 		hitSBT			= rayTracingPipeline->createShaderBindingTable(vkd, device, pipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
444 		hitSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
445 	}
446 
447 	// Trace rays.
448 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
449 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
450 	vkd.cmdTraceRaysKHR(cmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, kNumRays, 1u, 1u);
451 
452 	// Barrier for the output buffer.
453 	const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
454 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &bufferBarrier, 0u, nullptr, 0u, nullptr);
455 
456 	endCommandBuffer(vkd, cmdBuffer);
457 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
458 
459 	// Verify results.
460 	std::vector<tcu::Vec4>	outputData				(expectedOutputCoordinates.size());
461 	const auto				barycoordsBufferSizeSz	= static_cast<size_t>(barycoordsBufferSize);
462 
463 	invalidateAlloc(vkd, device, barycoordsBufferAlloc);
464 	DE_ASSERT(de::dataSize(outputData) == barycoordsBufferSizeSz);
465 	deMemcpy(outputData.data(), barycoordsBufferData, barycoordsBufferSizeSz);
466 
467 	for (size_t i = 0; i < outputData.size(); ++i)
468 	{
469 		const auto& outVal		= outputData[i];
470 		const auto& expectedVal	= expectedOutputCoordinates[i];
471 
472 		if (outVal.z() != expectedVal.z() || outVal.w() != 0.0f || de::abs(outVal.x() - expectedVal.x()) > kThreshold || de::abs(outVal.y() - expectedVal.y()) > kThreshold)
473 		{
474 			std::ostringstream msg;
475 			msg << "Unexpected value found for ray " << i << ": expected " << expectedVal << " and found " << outVal << ";";
476 			TCU_FAIL(msg.str());
477 		}
478 	}
479 	return tcu::TestStatus::pass("Pass");
480 }
481 
482 } // anonymous
483 
createBarycentricCoordinatesTests(tcu::TestContext & testCtx)484 tcu::TestCaseGroup*	createBarycentricCoordinatesTests (tcu::TestContext& testCtx)
485 {
486 	using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
487 
488 	// Test barycentric coordinates reported in hit attributes
489 	GroupPtr mainGroup(new tcu::TestCaseGroup(testCtx, "barycentric_coordinates"));
490 
491 	deUint32 seed = 1614343620u;
492 	mainGroup->addChild(new BarycentricCoordinatesCase(testCtx, "chit", TestParams{TestCaseRT::CLOSEST_HIT,						seed++}));
493 	mainGroup->addChild(new BarycentricCoordinatesCase(testCtx, "ahit", TestParams{TestCaseRT::ANY_HIT,							seed++}));
494 	mainGroup->addChild(new BarycentricCoordinatesCase(testCtx, "ahitTerminate", TestParams{TestCaseRT::CLOSEST_AND_ANY_HIT_TERMINATE,		seed++}));
495 
496 	return mainGroup.release();
497 }
498 
499 } // RayTracing
500 } // vkt
501