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