1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Ray Tracing Builtin and specialization constant tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRayTracingBuiltinTests.hpp"
25
26 #include "vkDefs.hpp"
27
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkPipelineConstructionUtil.hpp"
38
39 #include "vkRayTracingUtil.hpp"
40
41 #include "tcuTestLog.hpp"
42 #include "tcuMatrix.hpp"
43
44 #include "deMath.h"
45
46 namespace vkt
47 {
48 namespace RayTracing
49 {
50 namespace
51 {
52 using namespace vk;
53 using namespace std;
54
55 static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
56 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
57 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
58
59 enum GeomType
60 {
61 GEOM_TYPE_TRIANGLES,
62 GEOM_TYPE_AABBS,
63 };
64
65 enum TestId
66 {
67 TEST_ID_LAUNCH_ID_EXT = 0,
68 TEST_ID_LAUNCH_SIZE_EXT,
69 TEST_ID_PRIMITIVE_ID,
70 TEST_ID_INSTANCE_ID,
71 TEST_ID_INSTANCE_CUSTOM_INDEX_EXT,
72 TEST_ID_GEOMETRY_INDEX_EXT,
73 TEST_ID_WORLD_RAY_ORIGIN_EXT,
74 TEST_ID_WORLD_RAY_DIRECTION_EXT,
75 TEST_ID_OBJECT_RAY_ORIGIN_EXT,
76 TEST_ID_OBJECT_RAY_DIRECTION_EXT,
77 TEST_ID_RAY_T_MIN_EXT,
78 TEST_ID_RAY_T_MAX_EXT,
79 TEST_ID_INCOMING_RAY_FLAGS_EXT,
80 TEST_ID_HIT_T_EXT,
81 TEST_ID_HIT_KIND_EXT,
82 TEST_ID_OBJECT_TO_WORLD_EXT,
83 TEST_ID_OBJECT_TO_WORLD_3X4_EXT,
84 TEST_ID_WORLD_TO_OBJECT_EXT,
85 TEST_ID_WORLD_TO_OBJECT_3X4_EXT,
86 TEST_ID_INDICES_INDIRECT,
87 TEST_ID_TRANSFORMS_INDIRECT,
88 TEST_ID_TMINMAX_INDIRECT,
89 TEST_ID_INCOMING_RAY_FLAGS_INDIRECT,
90 TEST_ID_HIT_KIND_INDIRECT,
91 TEST_ID_LAST
92 };
93
94 enum RayFlagBits
95 {
96 RAY_FLAG_BIT_OPAQUE_EXT = 0, // const uint gl_RayFlagsOpaqueEXT = 1U;
97 RAY_FLAG_BIT_NO_OPAQUE_EXT = 1, // const uint gl_RayFlagsNoOpaqueEXT = 2U;
98 RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT = 2, // const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;
99 RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT = 3, // const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;
100 RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT = 4, // const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;
101 RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT = 5, // const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;
102 RAY_FLAG_BIT_CULL_OPAQUE_EXT = 6, // const uint gl_RayFlagsCullOpaqueEXT = 64U;
103 RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT = 7, // const uint gl_RayFlagsCullNoOpaqueEXT = 128U;
104 RAY_FLAG_BIT_LAST_PER_TEST,
105 RAY_FLAG_BIT_SKIP_TRIANGLES_EXT = 8, // const uint gl_RayFlagsSkipTrianglesEXT = 256U;
106 RAY_FLAG_BIT_SKIP_AABB_EXT = 9, // const uint gl_RayFlagsSkipAABBEXT = 512U;
107 RAY_FLAG_BIT_LAST
108 };
109
110 struct CaseDef
111 {
112 TestId id;
113 const char *name;
114 uint32_t width;
115 uint32_t height;
116 uint32_t depth;
117 uint32_t raysDepth;
118 VkFormat format;
119 bool fixedPointScalarOutput;
120 bool fixedPointVectorOutput;
121 bool fixedPointMatrixOutput;
122 GeomType geomType;
123 uint32_t squaresGroupCount;
124 uint32_t geometriesGroupCount;
125 uint32_t instancesGroupCount;
126 VkShaderStageFlagBits stage;
127 bool rayFlagSkipTriangles;
128 bool rayFlagSkipAABSs;
129 bool opaque;
130 bool frontFace;
131 VkPipelineCreateFlags pipelineCreateFlags;
132 bool useSpecConstants;
133 bool skipClosestHit;
134 bool useMaintenance5;
135 };
136
137 const uint32_t DEFAULT_UINT_CLEAR_VALUE = 0x7F000000;
138 const uint32_t FIXED_POINT_DIVISOR = 1024 * 1024;
139 const uint32_t FIXED_POINT_ALLOWED_ERROR = 4;
140
isPlain(const uint32_t width,const uint32_t height,const uint32_t depth)141 bool isPlain(const uint32_t width, const uint32_t height, const uint32_t depth)
142 {
143 return (width == 1 || height == 1 || depth == 1);
144 }
145
getShaderGroupSize(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)146 uint32_t getShaderGroupSize(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
147 {
148 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
149
150 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
151 return rayTracingPropertiesKHR->getShaderGroupHandleSize();
152 }
153
getShaderGroupBaseAlignment(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)154 uint32_t getShaderGroupBaseAlignment(const InstanceInterface &vki, const VkPhysicalDevice physicalDevice)
155 {
156 de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
157
158 rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
159 return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
160 }
161
makeImageCreateInfo(uint32_t width,uint32_t height,uint32_t depth,VkFormat format)162 VkImageCreateInfo makeImageCreateInfo(uint32_t width, uint32_t height, uint32_t depth, VkFormat format)
163 {
164 const VkImageType imageType = VK_IMAGE_TYPE_3D;
165 const VkImageUsageFlags usage =
166 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
167 const VkImageCreateInfo imageCreateInfo = {
168 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
169 DE_NULL, // const void* pNext;
170 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
171 imageType, // VkImageType imageType;
172 format, // VkFormat format;
173 makeExtent3D(width, height, depth), // VkExtent3D extent;
174 1u, // uint32_t mipLevels;
175 1u, // uint32_t arrayLayers;
176 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
177 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
178 usage, // VkImageUsageFlags usage;
179 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
180 0u, // uint32_t queueFamilyIndexCount;
181 DE_NULL, // const uint32_t* pQueueFamilyIndices;
182 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
183 };
184
185 return imageCreateInfo;
186 }
187
188 class RayTracingBuiltinLaunchTestInstance : public TestInstance
189 {
190 public:
191 RayTracingBuiltinLaunchTestInstance(Context &context, const CaseDef &data);
192 ~RayTracingBuiltinLaunchTestInstance(void);
193 tcu::TestStatus iterate(void);
194
195 protected:
196 void checkSupportInInstance(void) const;
197 Move<VkPipeline> makePipeline(de::MovePtr<RayTracingPipeline> &rayTracingPipeline, VkPipelineLayout pipelineLayout,
198 const VkSpecializationInfo *specializationInfo);
199 std::vector<int32_t> expectedIntValuesBuffer(void);
200 std::vector<float> expectedFloatValuesBuffer(void);
201 std::vector<float> expectedVectorValuesBuffer(void);
202 std::vector<float> expectedMatrixValuesBuffer(void);
203 de::MovePtr<BufferWithMemory> runTest(void);
204 de::MovePtr<BufferWithMemory> createShaderBindingTable(const InstanceInterface &vki, const DeviceInterface &vkd,
205 const VkDevice device, const VkPhysicalDevice physicalDevice,
206 const VkPipeline pipeline, Allocator &allocator,
207 de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
208 const uint32_t group);
209
210 bool validateIntBuffer(de::MovePtr<BufferWithMemory> buffer);
211 bool validateFloatBuffer(de::MovePtr<BufferWithMemory> buffer);
212 bool validateVectorBuffer(de::MovePtr<BufferWithMemory> buffer);
213 bool validateMatrixBuffer(de::MovePtr<BufferWithMemory> buffer);
214
215 de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
216 VkCommandBuffer cmdBuffer,
217 vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures);
218 vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(VkCommandBuffer cmdBuffer);
219 de::MovePtr<BottomLevelAccelerationStructure> initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,
220 tcu::UVec2 &startPos);
221
222 private:
223 CaseDef m_data;
224 VkShaderStageFlags m_shaders;
225 uint32_t m_raygenShaderGroup;
226 uint32_t m_missShaderGroup;
227 uint32_t m_hitShaderGroup;
228 uint32_t m_callableShaderGroup;
229 uint32_t m_shaderGroupCount;
230 };
231
RayTracingBuiltinLaunchTestInstance(Context & context,const CaseDef & data)232 RayTracingBuiltinLaunchTestInstance::RayTracingBuiltinLaunchTestInstance(Context &context, const CaseDef &data)
233 : vkt::TestInstance(context)
234 , m_data(data)
235 , m_shaders(0)
236 , m_raygenShaderGroup(~0u)
237 , m_missShaderGroup(~0u)
238 , m_hitShaderGroup(~0u)
239 , m_callableShaderGroup(~0u)
240 , m_shaderGroupCount(0)
241 {
242 const VkShaderStageFlags hitStages =
243 VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
244 BinaryCollection &collection = m_context.getBinaryCollection();
245 uint32_t group = 0;
246 uint32_t shaderCount = 0;
247
248 if (collection.contains("rgen"))
249 m_shaders |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
250 if (collection.contains("ahit"))
251 m_shaders |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
252 if (collection.contains("chit"))
253 m_shaders |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
254 if (collection.contains("miss"))
255 m_shaders |= VK_SHADER_STAGE_MISS_BIT_KHR;
256 if (collection.contains("sect"))
257 m_shaders |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
258 if (collection.contains("call"))
259 m_shaders |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
260
261 for (BinaryCollection::Iterator it = collection.begin(); it != collection.end(); ++it)
262 shaderCount++;
263
264 if (shaderCount != (uint32_t)dePop32(m_shaders))
265 TCU_THROW(InternalError, "Unused shaders detected in the collection");
266
267 if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
268 m_raygenShaderGroup = group++;
269
270 if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
271 m_missShaderGroup = group++;
272
273 if (0 != (m_shaders & hitStages))
274 m_hitShaderGroup = group++;
275
276 if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
277 m_callableShaderGroup = group++;
278
279 m_shaderGroupCount = group;
280 }
281
~RayTracingBuiltinLaunchTestInstance(void)282 RayTracingBuiltinLaunchTestInstance::~RayTracingBuiltinLaunchTestInstance(void)
283 {
284 }
285
286 class RayTracingTestCase : public TestCase
287 {
288 public:
289 RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
290 ~RayTracingTestCase(void);
291
292 virtual void initPrograms(SourceCollections &programCollection) const;
293 virtual TestInstance *createInstance(Context &context) const;
294 virtual void checkSupport(Context &context) const;
295
296 private:
297 static inline const std::string getIntersectionPassthrough(void);
298 static inline const std::string getMissPassthrough(void);
299 static inline const std::string getHitPassthrough(void);
300
301 CaseDef m_data;
302 };
303
RayTracingTestCase(tcu::TestContext & context,const char * name,const CaseDef data)304 RayTracingTestCase::RayTracingTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
305 : vkt::TestCase(context, name)
306 , m_data(data)
307 {
308 }
309
~RayTracingTestCase(void)310 RayTracingTestCase::~RayTracingTestCase(void)
311 {
312 }
313
checkSupport(Context & context) const314 void RayTracingTestCase::checkSupport(Context &context) const
315 {
316 const bool pipelineFlagSkipTriangles =
317 ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0);
318 const bool pipelineFlagSkipAABSs =
319 ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0);
320 const bool cullingFlags =
321 m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs || pipelineFlagSkipTriangles || pipelineFlagSkipAABSs;
322
323 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
324 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
325
326 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
327 context.getRayTracingPipelineFeatures();
328 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
329 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
330
331 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
332 context.getAccelerationStructureFeatures();
333 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
334 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
335 "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
336
337 if (cullingFlags && rayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling == false)
338 TCU_THROW(NotSupportedError,
339 "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling");
340
341 if (m_data.useMaintenance5)
342 context.requireDeviceFunctionality("VK_KHR_maintenance5");
343 }
344
getIntersectionPassthrough(void)345 const std::string RayTracingTestCase::getIntersectionPassthrough(void)
346 {
347 const std::string intersectionPassthrough = "#version 460 core\n"
348 "#extension GL_EXT_ray_tracing : require\n"
349 "hitAttributeEXT vec3 hitAttribute;\n"
350 "\n"
351 "void main()\n"
352 "{\n"
353 " reportIntersectionEXT(0.95f, 0x7Eu);\n"
354 "}\n";
355
356 return intersectionPassthrough;
357 }
358
getMissPassthrough(void)359 const std::string RayTracingTestCase::getMissPassthrough(void)
360 {
361 const std::string missPassthrough = "#version 460 core\n"
362 "#extension GL_EXT_ray_tracing : require\n"
363 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
364 "\n"
365 "void main()\n"
366 "{\n"
367 "}\n";
368
369 return missPassthrough;
370 }
371
getHitPassthrough(void)372 const std::string RayTracingTestCase::getHitPassthrough(void)
373 {
374 const std::string hitPassthrough = "#version 460 core\n"
375 "#extension GL_EXT_ray_tracing : require\n"
376 "hitAttributeEXT vec3 attribs;\n"
377 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
378 "\n"
379 "void main()\n"
380 "{\n"
381 "}\n";
382
383 return hitPassthrough;
384 }
385
initPrograms(SourceCollections & programCollection) const386 void RayTracingTestCase::initPrograms(SourceCollections &programCollection) const
387 {
388 const bool useSC = m_data.useSpecConstants;
389 DE_ASSERT(!useSC || m_data.id == TEST_ID_LAUNCH_ID_EXT);
390
391 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
392
393 if (m_data.id == TEST_ID_LAUNCH_ID_EXT || m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
394 {
395 const std::string specConstants = "layout (constant_id=0) const highp int factor1 = 1;\n"
396 "layout (constant_id=1) const highp float factor2 = 2.0;\n";
397
398 const std::string updateImage = " ivec3 p = ivec3(gl_LaunchIDEXT);\n"
399 " ivec3 v = ivec3(gl_" +
400 std::string(m_data.name) +
401 ");\n"
402 " int r = v.x + " +
403 (useSC ? "factor1" : "256") + " * (v.y + " + (useSC ? "int(factor2)" : "256") +
404 " * v.z) + 1;\n"
405 " ivec4 c = ivec4(r,0,0,1);\n"
406 " imageStore(result, p, c);\n";
407
408 switch (m_data.stage)
409 {
410 case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
411 {
412 std::stringstream css;
413 css << "#version 460 core\n"
414 "#extension GL_EXT_ray_tracing : require\n"
415 << (useSC ? specConstants : "")
416 << "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
417 "\n"
418 "void main()\n"
419 "{\n"
420 << updateImage << "}\n";
421
422 programCollection.glslSources.add("rgen")
423 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
424
425 break;
426 }
427
428 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
429 {
430 programCollection.glslSources.add("rgen")
431 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
432
433 {
434 std::stringstream css;
435 css << "#version 460 core\n"
436 "#extension GL_EXT_ray_tracing : require\n"
437 << (useSC ? specConstants : "")
438 << "hitAttributeEXT vec3 attribs;\n"
439 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
440 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
441 "\n"
442 "void main()\n"
443 "{\n"
444 << updateImage << "}\n";
445
446 programCollection.glslSources.add("ahit")
447 << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
448 }
449
450 programCollection.glslSources.add("chit")
451 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
452 programCollection.glslSources.add("miss")
453 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
454
455 break;
456 }
457
458 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
459 {
460 programCollection.glslSources.add("rgen")
461 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
462
463 {
464 std::stringstream css;
465 css << "#version 460 core\n"
466 "#extension GL_EXT_ray_tracing : require\n"
467 << (useSC ? specConstants : "")
468 << "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
469 "hitAttributeEXT vec3 attribs;\n"
470 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
471 "\n"
472 "void main()\n"
473 "{\n"
474 << updateImage << "}\n";
475
476 programCollection.glslSources.add("chit")
477 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
478 }
479
480 programCollection.glslSources.add("ahit")
481 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
482 programCollection.glslSources.add("miss")
483 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
484
485 break;
486 }
487
488 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
489 {
490 programCollection.glslSources.add("rgen")
491 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
492
493 {
494 std::stringstream css;
495 css << "#version 460 core\n"
496 "#extension GL_EXT_ray_tracing : require\n"
497 << (useSC ? specConstants : "")
498 << "hitAttributeEXT vec3 hitAttribute;\n"
499 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
500 "\n"
501 "void main()\n"
502 "{\n"
503 << updateImage
504 << " hitAttribute = vec3(0.0f, 0.0f, 0.0f);\n"
505 " reportIntersectionEXT(1.0f, 0);\n"
506 "}\n";
507
508 programCollection.glslSources.add("sect")
509 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
510 }
511
512 programCollection.glslSources.add("ahit")
513 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
514 programCollection.glslSources.add("chit")
515 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
516 programCollection.glslSources.add("miss")
517 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
518
519 break;
520 }
521
522 case VK_SHADER_STAGE_MISS_BIT_KHR:
523 {
524 programCollection.glslSources.add("rgen")
525 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
526
527 {
528 std::stringstream css;
529 css << "#version 460 core\n"
530 "#extension GL_EXT_ray_tracing : require\n"
531 << (useSC ? specConstants : "")
532 << "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
533 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
534 "\n"
535 "void main()\n"
536 "{\n"
537 << updateImage << "}\n";
538
539 programCollection.glslSources.add("miss")
540 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
541 }
542
543 programCollection.glslSources.add("ahit")
544 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
545 programCollection.glslSources.add("chit")
546 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
547
548 break;
549 }
550
551 case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
552 {
553 {
554 std::stringstream css;
555 css << "#version 460 core\n"
556 "#extension GL_EXT_ray_tracing : require\n"
557 "layout(location = 0) callableDataEXT float dummy;"
558 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
559 "\n"
560 "void main()\n"
561 "{\n"
562 " executeCallableEXT(0, 0);\n"
563 "}\n";
564
565 programCollection.glslSources.add("rgen")
566 << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
567 }
568
569 {
570 std::stringstream css;
571 css << "#version 460 core\n"
572 "#extension GL_EXT_ray_tracing : require\n"
573 << (useSC ? specConstants : "")
574 << "layout(location = 0) callableDataInEXT float dummy;"
575 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
576 "\n"
577 "void main()\n"
578 "{\n"
579 << updateImage << "}\n";
580
581 programCollection.glslSources.add("call")
582 << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
583 }
584
585 programCollection.glslSources.add("ahit")
586 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
587 programCollection.glslSources.add("chit")
588 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
589 programCollection.glslSources.add("miss")
590 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
591
592 break;
593 }
594
595 default:
596 TCU_THROW(InternalError, "Unknown stage");
597 }
598 }
599 else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT || m_data.id == TEST_ID_PRIMITIVE_ID ||
600 m_data.id == TEST_ID_INSTANCE_ID || m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT ||
601 m_data.id == TEST_ID_HIT_KIND_EXT)
602 {
603 const std::string conditionGeometryIndex = " int n = int(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * "
604 "(gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z));\n"
605 " int m = (n / " +
606 de::toString(m_data.squaresGroupCount) + ") % " +
607 de::toString(m_data.geometriesGroupCount) +
608 ";\n"
609 " if (r == m)";
610 const std::string conditionPrimitiveId = " int n = int(gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * "
611 "(gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * gl_LaunchIDEXT.z));\n"
612 " int m = n % " +
613 de::toString(m_data.squaresGroupCount) +
614 ";\n"
615 " if (r == m)";
616 const std::string condition =
617 (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT) && (m_data.geomType == GEOM_TYPE_AABBS) ? conditionGeometryIndex :
618 (m_data.id == TEST_ID_PRIMITIVE_ID) && (m_data.geomType == GEOM_TYPE_AABBS) ? conditionPrimitiveId :
619 "";
620 const std::string updateImage = " ivec3 p = ivec3(gl_LaunchIDEXT);\n"
621 " int r = int(gl_" +
622 std::string(m_data.name) +
623 ");\n"
624 " ivec4 c = ivec4(r,0,0,1);\n" +
625 condition + " imageStore(result, p, c);\n";
626
627 switch (m_data.stage)
628 {
629 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
630 {
631 programCollection.glslSources.add("rgen")
632 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
633
634 {
635 std::stringstream css;
636 css << "#version 460 core\n"
637 "#extension GL_EXT_ray_tracing : require\n"
638 "hitAttributeEXT vec3 attribs;\n"
639 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
640 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
641 "\n"
642 "void main()\n"
643 "{\n"
644 << updateImage << "}\n";
645
646 programCollection.glslSources.add("ahit")
647 << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
648 }
649
650 programCollection.glslSources.add("chit")
651 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
652 programCollection.glslSources.add("miss")
653 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
654
655 if (m_data.geomType == GEOM_TYPE_AABBS)
656 programCollection.glslSources.add("sect")
657 << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
658
659 break;
660 }
661
662 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
663 {
664 programCollection.glslSources.add("rgen")
665 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
666
667 {
668 std::stringstream css;
669 css << "#version 460 core\n"
670 "#extension GL_EXT_ray_tracing : require\n"
671 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
672 "hitAttributeEXT vec3 attribs;\n"
673 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
674 "\n"
675 "void main()\n"
676 "{\n"
677 << updateImage << "}\n";
678
679 programCollection.glslSources.add("chit")
680 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
681 }
682
683 programCollection.glslSources.add("ahit")
684 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
685 programCollection.glslSources.add("miss")
686 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
687
688 if (m_data.geomType == GEOM_TYPE_AABBS)
689 {
690 const std::string intersectionShaderSingle = "#version 460 core\n"
691 "#extension GL_EXT_ray_tracing : require\n"
692 "hitAttributeEXT vec3 hitAttribute;\n"
693 "\n"
694 "void main()\n"
695 "{\n"
696 " int r = int(gl_" +
697 std::string(m_data.name) + ");\n" + condition +
698 " reportIntersectionEXT(0.95f, 0x7Eu);\n"
699 "}\n";
700 const std::string intersectionShader =
701 condition.empty() ? getIntersectionPassthrough() : intersectionShaderSingle;
702
703 programCollection.glslSources.add("sect")
704 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
705 }
706
707 break;
708 }
709
710 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
711 {
712 programCollection.glslSources.add("rgen")
713 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
714
715 {
716 std::stringstream css;
717 css << "#version 460 core\n"
718 "#extension GL_EXT_ray_tracing : require\n"
719 "hitAttributeEXT vec3 hitAttribute;\n"
720 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
721 "\n"
722 "void main()\n"
723 "{\n"
724 << updateImage
725 << " reportIntersectionEXT(0.95f, 0);\n"
726 "}\n";
727
728 programCollection.glslSources.add("sect")
729 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
730 }
731
732 programCollection.glslSources.add("ahit")
733 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
734 programCollection.glslSources.add("chit")
735 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
736 programCollection.glslSources.add("miss")
737 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
738
739 break;
740 }
741
742 default:
743 TCU_THROW(InternalError, "Unknown stage");
744 }
745 }
746 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
747 {
748 const bool cullingFlags = m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs;
749 const std::string cullingFlagsInit = (m_data.rayFlagSkipTriangles && m_data.rayFlagSkipAABSs) ?
750 "gl_RayFlagsSkipTrianglesEXT|gl_RayFlagsSkipAABBEXT" :
751 m_data.rayFlagSkipTriangles ? "gl_RayFlagsSkipTrianglesEXT" :
752 m_data.rayFlagSkipAABSs ? "gl_RayFlagsSkipAABBEXT" :
753 "gl_RayFlagsNoneEXT";
754 const std::string updateImage = " ivec3 p = ivec3(gl_LaunchIDEXT);\n"
755 " int r = int(gl_" +
756 std::string(m_data.name) +
757 ");\n"
758 " ivec4 c = ivec4(r,0,0,1);\n"
759 " imageStore(result, p, c);\n";
760 const std::string intersectionShader = "#version 460 core\n"
761 "#extension GL_EXT_ray_tracing : require\n"
762 "hitAttributeEXT vec3 hitAttribute;\n"
763 "\n"
764 "void main()\n"
765 "{\n"
766 " uint hitKind = " +
767 std::string(m_data.frontFace ? "0x7Eu" : "0x7Fu") +
768 ";\n"
769 " reportIntersectionEXT(0.95f, hitKind);\n"
770 "}\n";
771 const std::string raygenFlagsFragment = "\n"
772 " if (0 != (n & (1<<" +
773 de::toString(RAY_FLAG_BIT_OPAQUE_EXT) +
774 "))) f = f | gl_RayFlagsOpaqueEXT;\n"
775 " else if (0 != (n & (1<<" +
776 de::toString(RAY_FLAG_BIT_NO_OPAQUE_EXT) +
777 "))) f = f | gl_RayFlagsNoOpaqueEXT;\n"
778 " else if (0 != (n & (1<<" +
779 de::toString(RAY_FLAG_BIT_CULL_OPAQUE_EXT) +
780 "))) f = f | gl_RayFlagsCullOpaqueEXT;\n"
781 " else if (0 != (n & (1<<" +
782 de::toString(RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT) +
783 "))) f = f | gl_RayFlagsCullNoOpaqueEXT;\n"
784 "\n"
785 " if (0 != (n & (1<<" +
786 de::toString(RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT) +
787 "))) f = f | gl_RayFlagsCullBackFacingTrianglesEXT;\n"
788 " else if (0 != (n & (1<<" +
789 de::toString(RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT) +
790 "))) f = f | gl_RayFlagsCullFrontFacingTrianglesEXT;\n"
791 "\n"
792 " if (0 != (n & (1<<" +
793 de::toString(RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT) +
794 "))) f = f | gl_RayFlagsTerminateOnFirstHitEXT;\n"
795 " if (0 != (n & (1<<" +
796 de::toString(RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT) +
797 "))) f = f | gl_RayFlagsSkipClosestHitShaderEXT;\n"
798 "\n";
799 const std::string raygenShader =
800 "#version 460 core\n"
801 "#extension GL_EXT_ray_tracing : require\n" +
802 (cullingFlags ? std::string("#extension GL_EXT_ray_flags_primitive_culling : require\n") : "") +
803 "layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
804 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
805 "\n"
806 "void main()\n"
807 "{\n"
808 " uint n = gl_LaunchIDEXT.x + gl_LaunchSizeEXT.x * (gl_LaunchIDEXT.y + gl_LaunchSizeEXT.y * "
809 "gl_LaunchIDEXT.z);\n"
810 " uint f = " +
811 cullingFlagsInit + ";\n" + raygenFlagsFragment +
812 " uint rayFlags = f;\n"
813 " uint cullMask = 0xFF;\n"
814 " float tmin = 0.0;\n"
815 " float tmax = 9.0;\n"
816 " vec3 origin = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), "
817 "(float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n"
818 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
819 " traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
820 "}\n";
821
822 switch (m_data.stage)
823 {
824 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
825 {
826 programCollection.glslSources.add("rgen")
827 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
828
829 {
830 std::stringstream css;
831 css << "#version 460 core\n"
832 "#extension GL_EXT_ray_tracing : require\n"
833 "hitAttributeEXT vec3 hitAttribute;\n"
834 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
835 "\n"
836 "void main()\n"
837 "{\n"
838 << updateImage << "}\n";
839
840 programCollection.glslSources.add("sect")
841 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
842 }
843
844 programCollection.glslSources.add("ahit")
845 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
846 programCollection.glslSources.add("chit")
847 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
848 programCollection.glslSources.add("miss")
849 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
850
851 break;
852 }
853
854 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
855 {
856 programCollection.glslSources.add("rgen")
857 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
858
859 {
860 std::stringstream css;
861 css << "#version 460 core\n"
862 "#extension GL_EXT_ray_tracing : require\n"
863 "hitAttributeEXT vec3 attribs;\n"
864 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
865 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
866 "\n"
867 "void main()\n"
868 "{\n"
869 << updateImage << "}\n";
870
871 programCollection.glslSources.add("ahit")
872 << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
873 }
874
875 programCollection.glslSources.add("chit")
876 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
877 programCollection.glslSources.add("miss")
878 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
879
880 if (m_data.geomType == GEOM_TYPE_AABBS)
881 programCollection.glslSources.add("sect")
882 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
883
884 break;
885 }
886
887 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
888 {
889 programCollection.glslSources.add("rgen")
890 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
891
892 {
893 std::stringstream css;
894 css << "#version 460 core\n"
895 "#extension GL_EXT_ray_tracing : require\n"
896 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
897 "hitAttributeEXT vec3 attribs;\n"
898 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
899 "\n"
900 "void main()\n"
901 "{\n"
902 << updateImage << "}\n";
903
904 programCollection.glslSources.add("chit")
905 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
906 }
907
908 programCollection.glslSources.add("ahit")
909 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
910 programCollection.glslSources.add("miss")
911 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
912
913 if (m_data.geomType == GEOM_TYPE_AABBS)
914 programCollection.glslSources.add("sect")
915 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
916
917 break;
918 }
919
920 case VK_SHADER_STAGE_MISS_BIT_KHR:
921 {
922 programCollection.glslSources.add("rgen")
923 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
924
925 {
926 std::stringstream css;
927 css << "#version 460 core\n"
928 "#extension GL_EXT_ray_tracing : require\n"
929 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
930 "\n"
931 "void main()\n"
932 "{\n"
933 << updateImage << "}\n";
934
935 programCollection.glslSources.add("miss")
936 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
937 }
938
939 programCollection.glslSources.add("chit")
940 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
941 programCollection.glslSources.add("ahit")
942 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
943
944 if (m_data.geomType == GEOM_TYPE_AABBS)
945 programCollection.glslSources.add("sect")
946 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
947
948 break;
949 }
950
951 default:
952 TCU_THROW(InternalError, "Unknown stage");
953 }
954 }
955 else if (m_data.id == TEST_ID_HIT_T_EXT || m_data.id == TEST_ID_RAY_T_MIN_EXT || m_data.id == TEST_ID_RAY_T_MAX_EXT)
956 {
957 const std::string raygenShader =
958 "#version 460 core\n"
959 "#extension GL_EXT_ray_tracing : require\n"
960 "layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
961 "layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
962 "\n"
963 "void main()\n"
964 "{\n"
965 " uint cullMask = 0xFF;\n"
966 " float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
967 " float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
968 " float c = 0.25f * a / b;\n"
969 " float tmin = c;\n"
970 " float tmax = 0.75f + c;\n"
971 " vec3 origin = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), "
972 "(float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n"
973 " vec3 direct = vec3(0.0, 0.0, -1.0);\n"
974 " traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
975 "}\n";
976 const std::string intersectionShader = "#version 460 core\n"
977 "#extension GL_EXT_ray_tracing : require\n"
978 "hitAttributeEXT vec3 hitAttribute;\n"
979 "\n"
980 "void main()\n"
981 "{\n"
982 " float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
983 " float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
984 " float c = 0.25f * a / b;\n"
985 " reportIntersectionEXT(0.03125f + c, 0);\n"
986 "}\n";
987 const std::string updateImage = " ivec3 p = ivec3(gl_LaunchIDEXT);\n"
988 " int r = int(" +
989 de::toString(FIXED_POINT_DIVISOR) + ".0f * gl_" + std::string(m_data.name) +
990 ");\n"
991 " ivec4 c = ivec4(r,0,0,1);\n"
992 " imageStore(result, p, c);\n";
993
994 const std::string updateImageConcurrentlyMin = " ivec3 p = ivec3(gl_LaunchIDEXT);\n"
995 " int r = int(" +
996 de::toString(FIXED_POINT_DIVISOR) + ".0f * gl_" +
997 std::string(m_data.name) +
998 ");\n"
999 " imageAtomicMin(result, p, r);\n";
1000
1001 switch (m_data.stage)
1002 {
1003 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1004 {
1005 programCollection.glslSources.add("rgen")
1006 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
1007
1008 // The anyhit shader is launched multiple times for the same launch ID. To
1009 // avoid write-after-write hazard on result image data and because intesection shader
1010 // execution is not ordered, we need to use atomic operation to get proper (smallest)
1011 // TMa result.
1012 auto anyHitShaderUpdateImage =
1013 (m_data.id == TEST_ID_RAY_T_MAX_EXT ? updateImageConcurrentlyMin : updateImage);
1014
1015 {
1016 std::stringstream css;
1017 css << "#version 460 core\n"
1018 "#extension GL_EXT_ray_tracing : require\n"
1019 "hitAttributeEXT vec3 attribs;\n"
1020 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1021 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1022 "\n"
1023 "void main()\n"
1024 "{\n"
1025 << anyHitShaderUpdateImage << "}\n";
1026
1027 programCollection.glslSources.add("ahit")
1028 << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1029 }
1030
1031 programCollection.glslSources.add("chit")
1032 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1033 programCollection.glslSources.add("miss")
1034 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1035
1036 if (m_data.geomType == GEOM_TYPE_AABBS)
1037 programCollection.glslSources.add("sect")
1038 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
1039
1040 break;
1041 }
1042
1043 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1044 {
1045 programCollection.glslSources.add("rgen")
1046 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
1047
1048 {
1049 std::stringstream css;
1050 css << "#version 460 core\n"
1051 "#extension GL_EXT_ray_tracing : require\n"
1052 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1053 "hitAttributeEXT vec3 attribs;\n"
1054 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1055 "\n"
1056 "void main()\n"
1057 "{\n"
1058 << updateImage << "}\n";
1059
1060 programCollection.glslSources.add("chit")
1061 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1062 }
1063
1064 programCollection.glslSources.add("ahit")
1065 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1066 programCollection.glslSources.add("miss")
1067 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1068
1069 if (m_data.geomType == GEOM_TYPE_AABBS)
1070 programCollection.glslSources.add("sect")
1071 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
1072
1073 break;
1074 }
1075
1076 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1077 {
1078 programCollection.glslSources.add("rgen")
1079 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
1080
1081 {
1082 // The intersection shader is launched multiple times for the same launch ID. To
1083 // avoid write-after-write hazard on result image data and because intesection shader
1084 // execution is not ordered, we need to use atomic operation to get proper (smallest)
1085 // TMa result.
1086 auto intersectionShaderUpdateImage =
1087 (m_data.id == TEST_ID_RAY_T_MAX_EXT ? updateImageConcurrentlyMin : updateImage);
1088 std::stringstream css;
1089 css << "#version 460 core\n"
1090 "#extension GL_EXT_ray_tracing : require\n"
1091 "hitAttributeEXT vec3 hitAttribute;\n"
1092 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1093 "\n"
1094 "void main()\n"
1095 "{\n"
1096 << intersectionShaderUpdateImage
1097 << "\n"
1098 " float a = float(gl_LaunchIDEXT.x) / gl_LaunchSizeEXT.x;\n"
1099 " float b = 1.0f + float(gl_LaunchIDEXT.y) / gl_LaunchSizeEXT.y;\n"
1100 " reportIntersectionEXT(0.4375f + 0.25f * a / b, 0x7Eu);\n"
1101 "}\n";
1102
1103 programCollection.glslSources.add("sect")
1104 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1105 }
1106
1107 programCollection.glslSources.add("ahit")
1108 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1109 programCollection.glslSources.add("chit")
1110 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1111 programCollection.glslSources.add("miss")
1112 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1113
1114 break;
1115 }
1116
1117 case VK_SHADER_STAGE_MISS_BIT_KHR:
1118 {
1119 programCollection.glslSources.add("rgen")
1120 << glu::RaygenSource(updateRayTracingGLSL(raygenShader)) << buildOptions;
1121
1122 {
1123 std::stringstream css;
1124 css << "#version 460 core\n"
1125 "#extension GL_EXT_ray_tracing : require\n"
1126 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1127 "\n"
1128 "void main()\n"
1129 "{\n"
1130 << updateImage << "}\n";
1131
1132 programCollection.glslSources.add("miss")
1133 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1134 }
1135
1136 programCollection.glslSources.add("chit")
1137 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1138 programCollection.glslSources.add("ahit")
1139 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1140
1141 if (m_data.geomType == GEOM_TYPE_AABBS)
1142 programCollection.glslSources.add("sect")
1143 << glu::IntersectionSource(updateRayTracingGLSL(intersectionShader)) << buildOptions;
1144
1145 break;
1146 }
1147
1148 default:
1149 TCU_THROW(InternalError, "Unknown stage");
1150 }
1151 }
1152 else if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT || m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT ||
1153 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT || m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT ||
1154 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT ||
1155 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT)
1156 {
1157 const bool matrix4x3 = (m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT);
1158 const bool matrix3x4 =
1159 (m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT);
1160 const bool matrixOutput = matrix4x3 || matrix3x4;
1161 const std::string vectorLoop = " for (int ndx = 0; ndx < 3; ndx++)\n"
1162 " {\n";
1163 const std::string matrixLoop4x3 = " int ndx = -1;\n"
1164 " for (int row = 0; row < 3; row++)\n"
1165 " for (int col = 0; col < 4; col++)\n"
1166 " {\n"
1167 " ndx++;\n";
1168 const std::string matrixLoop3x4 = " int ndx = -1;\n"
1169 " for (int col = 0; col < 3; col++)\n"
1170 " for (int row = 0; row < 4; row++)\n"
1171 " {\n"
1172 " ndx++;\n";
1173 const std::string loop = matrix4x3 ? matrixLoop4x3 : matrix3x4 ? matrixLoop3x4 : vectorLoop;
1174 const std::string index = (matrixOutput ? "[col][row]" : "[ndx]");
1175 const std::string updateImage = " float k = " + de::toString(FIXED_POINT_DIVISOR) + ".0f;\n" + loop +
1176 " ivec3 p = ivec3(gl_LaunchIDEXT.xy, ndx);\n"
1177 " float r = k * gl_" +
1178 std::string(m_data.name) + index +
1179 ";\n"
1180 " ivec4 c = ivec4(int(r),0,0,1);\n"
1181 " imageStore(result, p, c);\n"
1182 " }\n";
1183
1184 switch (m_data.stage)
1185 {
1186 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1187 {
1188 programCollection.glslSources.add("rgen")
1189 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1190
1191 {
1192 std::stringstream css;
1193 css << "#version 460 core\n"
1194 "#extension GL_EXT_ray_tracing : require\n"
1195 "hitAttributeEXT vec3 attribs;\n"
1196 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1197 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1198 "\n"
1199 "void main()\n"
1200 "{\n"
1201 << updateImage << "}\n";
1202
1203 programCollection.glslSources.add("ahit")
1204 << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1205 }
1206
1207 programCollection.glslSources.add("chit")
1208 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1209 programCollection.glslSources.add("miss")
1210 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1211
1212 if (m_data.geomType == GEOM_TYPE_AABBS)
1213 programCollection.glslSources.add("sect")
1214 << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1215
1216 break;
1217 }
1218
1219 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1220 {
1221 programCollection.glslSources.add("rgen")
1222 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1223
1224 {
1225 std::stringstream css;
1226 css << "#version 460 core\n"
1227 "#extension GL_EXT_ray_tracing : require\n"
1228 "layout(location = 0) rayPayloadInEXT vec3 hitValue;\n"
1229 "hitAttributeEXT vec3 attribs;\n"
1230 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1231 "\n"
1232 "void main()\n"
1233 "{\n"
1234 << updateImage << "}\n";
1235
1236 programCollection.glslSources.add("chit")
1237 << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
1238 }
1239
1240 programCollection.glslSources.add("ahit")
1241 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1242 programCollection.glslSources.add("miss")
1243 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1244
1245 if (m_data.geomType == GEOM_TYPE_AABBS)
1246 programCollection.glslSources.add("sect")
1247 << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1248
1249 break;
1250 }
1251
1252 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1253 {
1254 programCollection.glslSources.add("rgen")
1255 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1256
1257 {
1258 std::stringstream css;
1259 css << "#version 460 core\n"
1260 "#extension GL_EXT_ray_tracing : require\n"
1261 "hitAttributeEXT vec3 hitAttribute;\n"
1262 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1263 "\n"
1264 "void main()\n"
1265 "{\n"
1266 << updateImage
1267 << " reportIntersectionEXT(0.95f, 0);\n"
1268 "}\n";
1269
1270 programCollection.glslSources.add("sect")
1271 << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
1272 }
1273
1274 programCollection.glslSources.add("chit")
1275 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1276 programCollection.glslSources.add("ahit")
1277 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1278 programCollection.glslSources.add("miss")
1279 << glu::MissSource(updateRayTracingGLSL(getMissPassthrough())) << buildOptions;
1280
1281 break;
1282 }
1283
1284 case VK_SHADER_STAGE_MISS_BIT_KHR:
1285 {
1286 programCollection.glslSources.add("rgen")
1287 << glu::RaygenSource(updateRayTracingGLSL(getCommonRayGenerationShader())) << buildOptions;
1288
1289 {
1290 std::stringstream css;
1291 css << "#version 460 core\n"
1292 "#extension GL_EXT_ray_tracing : require\n"
1293 "layout(set = 0, binding = 0, r32i) uniform iimage3D result;\n"
1294 "\n"
1295 "void main()\n"
1296 "{\n"
1297 << updateImage << "}\n";
1298
1299 programCollection.glslSources.add("miss")
1300 << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
1301 }
1302
1303 programCollection.glslSources.add("chit")
1304 << glu::ClosestHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1305 programCollection.glslSources.add("ahit")
1306 << glu::AnyHitSource(updateRayTracingGLSL(getHitPassthrough())) << buildOptions;
1307
1308 if (m_data.geomType == GEOM_TYPE_AABBS)
1309 programCollection.glslSources.add("sect")
1310 << glu::IntersectionSource(updateRayTracingGLSL(getIntersectionPassthrough())) << buildOptions;
1311
1312 break;
1313 }
1314
1315 default:
1316 TCU_THROW(InternalError, "Unknown stage");
1317 }
1318 }
1319 else
1320 {
1321 TCU_THROW(InternalError, "Not implemented");
1322 }
1323 }
1324
createInstance(Context & context) const1325 TestInstance *RayTracingTestCase::createInstance(Context &context) const
1326 {
1327 return new RayTracingBuiltinLaunchTestInstance(context, m_data);
1328 }
1329
initTopAccelerationStructure(VkCommandBuffer cmdBuffer,vector<de::SharedPtr<BottomLevelAccelerationStructure>> & bottomLevelAccelerationStructures)1330 de::MovePtr<TopLevelAccelerationStructure> RayTracingBuiltinLaunchTestInstance::initTopAccelerationStructure(
1331 VkCommandBuffer cmdBuffer,
1332 vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures)
1333 {
1334 const DeviceInterface &vkd = m_context.getDeviceInterface();
1335 const VkDevice device = m_context.getDevice();
1336 Allocator &allocator = m_context.getDefaultAllocator();
1337 de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
1338 const bool transformTest =
1339 m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT || m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT ||
1340 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT || m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT ||
1341 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT ||
1342 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT;
1343
1344 result->setInstanceCount(bottomLevelAccelerationStructures.size());
1345
1346 for (size_t structNdx = 0; structNdx < bottomLevelAccelerationStructures.size(); ++structNdx)
1347 {
1348 VkTransformMatrixKHR transform = identityMatrix3x4;
1349
1350 if (transformTest)
1351 {
1352 if (structNdx & 1)
1353 transform.matrix[0][3] = (1.0f / 8.0f) / float(m_data.width);
1354
1355 if (structNdx & 2)
1356 transform.matrix[1][3] = (1.0f / 16.0f) / float(m_data.height);
1357 }
1358
1359 result->addInstance(bottomLevelAccelerationStructures[structNdx], transform, uint32_t(2 * structNdx));
1360 }
1361
1362 result->createAndBuild(vkd, device, cmdBuffer, allocator);
1363
1364 return result;
1365 }
1366
initBottomAccelerationStructure(VkCommandBuffer cmdBuffer,tcu::UVec2 & startPos)1367 de::MovePtr<BottomLevelAccelerationStructure> RayTracingBuiltinLaunchTestInstance::initBottomAccelerationStructure(
1368 VkCommandBuffer cmdBuffer, tcu::UVec2 &startPos)
1369 {
1370 const DeviceInterface &vkd = m_context.getDeviceInterface();
1371 const VkDevice device = m_context.getDevice();
1372 Allocator &allocator = m_context.getDefaultAllocator();
1373 de::MovePtr<BottomLevelAccelerationStructure> result = makeBottomLevelAccelerationStructure();
1374
1375 result->setGeometryCount(m_data.geometriesGroupCount);
1376
1377 if (m_data.id == TEST_ID_LAUNCH_ID_EXT || m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
1378 {
1379 result->setDefaultGeometryData(m_data.stage);
1380 }
1381 else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT || m_data.id == TEST_ID_PRIMITIVE_ID ||
1382 m_data.id == TEST_ID_INSTANCE_ID || m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT)
1383 {
1384 const bool triangles = (m_data.geomType == GEOM_TYPE_TRIANGLES);
1385 const bool missShader = (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1386 const float z = !missShader ? -1.0f : -100.0f;
1387
1388 DE_ASSERT(m_data.squaresGroupCount != 1);
1389
1390 for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1391 {
1392 std::vector<tcu::Vec3> geometryData;
1393
1394 geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1395
1396 for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1397 {
1398 const uint32_t n = m_data.width * startPos.y() + startPos.x();
1399 const float x0 = float(startPos.x() + 0) / float(m_data.width);
1400 const float y0 = float(startPos.y() + 0) / float(m_data.height);
1401 const float x1 = float(startPos.x() + 1) / float(m_data.width);
1402 const float y1 = float(startPos.y() + 1) / float(m_data.height);
1403 const uint32_t m = n + 1;
1404
1405 if (triangles)
1406 {
1407 const float xm = (x0 + x1) / 2.0f;
1408 const float ym = (y0 + y1) / 2.0f;
1409
1410 geometryData.push_back(tcu::Vec3(x0, y0, z));
1411 geometryData.push_back(tcu::Vec3(xm, y1, z));
1412 geometryData.push_back(tcu::Vec3(x1, ym, z));
1413 }
1414 else
1415 {
1416 geometryData.push_back(tcu::Vec3(x0, y0, z));
1417 geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1418 }
1419
1420 startPos.y() = m / m_data.width;
1421 startPos.x() = m % m_data.width;
1422 }
1423
1424 result->addGeometry(geometryData, triangles);
1425 }
1426 }
1427 else if (m_data.id == TEST_ID_HIT_KIND_EXT)
1428 {
1429 const bool triangles = (m_data.geomType == GEOM_TYPE_TRIANGLES);
1430 const bool missShader = (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1431 const float z = !missShader ? -1.0f : -100.0f;
1432
1433 DE_ASSERT(m_data.squaresGroupCount != 1);
1434 DE_ASSERT(m_data.geometriesGroupCount == 4);
1435
1436 std::vector<tcu::Vec3> geometryDataOpaque;
1437 std::vector<tcu::Vec3> geometryDataNonOpaque;
1438
1439 geometryDataOpaque.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1440 geometryDataNonOpaque.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1441
1442 for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1443 {
1444 const bool cw = ((geometryNdx & 1) == 0) ? true : false;
1445 std::vector<tcu::Vec3> &geometryData =
1446 ((geometryNdx & 2) == 0) ? geometryDataOpaque : geometryDataNonOpaque;
1447
1448 for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1449 {
1450 const uint32_t n = m_data.width * startPos.y() + startPos.x();
1451 const uint32_t m = n + 1;
1452 const float x0 = float(startPos.x() + 0) / float(m_data.width);
1453 const float y0 = float(startPos.y() + 0) / float(m_data.height);
1454 const float x1 = float(startPos.x() + 1) / float(m_data.width);
1455 const float y1 = float(startPos.y() + 1) / float(m_data.height);
1456
1457 if (triangles)
1458 {
1459 const float xm = (x0 + x1) / 2.0f;
1460 const float ym = (y0 + y1) / 2.0f;
1461
1462 if (cw)
1463 {
1464 geometryData.push_back(tcu::Vec3(x0, y0, z));
1465 geometryData.push_back(tcu::Vec3(x1, ym, z));
1466 geometryData.push_back(tcu::Vec3(xm, y1, z));
1467 }
1468 else
1469 {
1470 geometryData.push_back(tcu::Vec3(x0, y0, z));
1471 geometryData.push_back(tcu::Vec3(xm, y1, z));
1472 geometryData.push_back(tcu::Vec3(x1, ym, z));
1473 }
1474 }
1475 else
1476 {
1477 geometryData.push_back(tcu::Vec3(x0, y0, z));
1478 geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1479 }
1480
1481 startPos.y() = m / m_data.width;
1482 startPos.x() = m % m_data.width;
1483 }
1484 }
1485
1486 DE_ASSERT(startPos.y() == m_data.height && startPos.x() == 0);
1487
1488 result->addGeometry(geometryDataOpaque, triangles, (VkGeometryFlagsKHR)VK_GEOMETRY_OPAQUE_BIT_KHR);
1489 result->addGeometry(geometryDataNonOpaque, triangles, (VkGeometryFlagsKHR)0);
1490 }
1491 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
1492 {
1493 const bool triangles = (m_data.geomType == GEOM_TYPE_TRIANGLES);
1494 const bool missShader = (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1495 const float z = !missShader ? -1.0f : -100.0f;
1496 const VkGeometryFlagsKHR geometryFlags = m_data.opaque ?
1497 static_cast<VkGeometryFlagsKHR>(VK_GEOMETRY_OPAQUE_BIT_KHR) :
1498 static_cast<VkGeometryFlagsKHR>(0);
1499 const bool cw = m_data.frontFace;
1500 std::vector<tcu::Vec3> geometryData;
1501
1502 DE_ASSERT(m_data.geometriesGroupCount == 1);
1503 DE_ASSERT(m_data.squaresGroupCount != 1);
1504
1505 geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1506
1507 for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1508 {
1509 const uint32_t n = m_data.width * startPos.y() + startPos.x();
1510 const uint32_t m = n + 1;
1511 const float x0 = float(startPos.x() + 0) / float(m_data.width);
1512 const float y0 = float(startPos.y() + 0) / float(m_data.height);
1513 const float x1 = float(startPos.x() + 1) / float(m_data.width);
1514 const float y1 = float(startPos.y() + 1) / float(m_data.height);
1515
1516 if (triangles)
1517 {
1518 const float xm = (x0 + x1) / 2.0f;
1519 const float ym = (y0 + y1) / 2.0f;
1520
1521 if (cw)
1522 {
1523 geometryData.push_back(tcu::Vec3(x0, y0, z));
1524 geometryData.push_back(tcu::Vec3(x1, ym, z));
1525 geometryData.push_back(tcu::Vec3(xm, y1, z));
1526 }
1527 else
1528 {
1529 geometryData.push_back(tcu::Vec3(x0, y0, z));
1530 geometryData.push_back(tcu::Vec3(xm, y1, z));
1531 geometryData.push_back(tcu::Vec3(x1, ym, z));
1532 }
1533 }
1534 else
1535 {
1536 geometryData.push_back(tcu::Vec3(x0, y0, z));
1537 geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1538 }
1539
1540 startPos.y() = m / m_data.width;
1541 startPos.x() = m % m_data.width;
1542 }
1543
1544 DE_ASSERT(startPos.y() == m_data.height && startPos.x() == 0);
1545
1546 result->addGeometry(geometryData, triangles, geometryFlags);
1547 }
1548 else if (m_data.id == TEST_ID_HIT_T_EXT || m_data.id == TEST_ID_RAY_T_MIN_EXT || m_data.id == TEST_ID_RAY_T_MAX_EXT)
1549 {
1550 const bool triangles = (m_data.geomType == GEOM_TYPE_TRIANGLES);
1551 const bool missShader = (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1552 const bool sectShader = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
1553 const bool maxTTest = (m_data.id == TEST_ID_RAY_T_MAX_EXT);
1554
1555 DE_ASSERT(m_data.squaresGroupCount != 1);
1556
1557 for (size_t geometryNdx = 0; geometryNdx < m_data.geometriesGroupCount; ++geometryNdx)
1558 {
1559 std::vector<tcu::Vec3> geometryData;
1560
1561 geometryData.reserve(m_data.squaresGroupCount * (triangles ? 3u : 2u));
1562
1563 for (size_t squareNdx = 0; squareNdx < m_data.squaresGroupCount; ++squareNdx)
1564 {
1565 const uint32_t n = m_data.width * startPos.y() + startPos.x();
1566 const uint32_t m = n + 1;
1567 const bool shiftRight =
1568 sectShader && maxTTest && (0 == (startPos.y() & 1)) && (0 == (startPos.x() & 1));
1569 const uint32_t xo = shiftRight ? 1 : 0;
1570 const float x0 = float(startPos.x() + 0 + xo) / float(m_data.width);
1571 const float y0 = float(startPos.y() + 0) / float(m_data.height);
1572 const float x1 = float(startPos.x() + 1 + xo) / float(m_data.width);
1573 const float y1 = float(startPos.y() + 1) / float(m_data.height);
1574 const float a = x0;
1575 const float b = 1.0f + y0;
1576 const float c = 0.03125f + 0.25f * a / b;
1577 const float z = !missShader ? -c : -100.0f;
1578
1579 if (triangles)
1580 {
1581 const float xm = (x0 + x1) / 2.0f;
1582 const float ym = (y0 + y1) / 2.0f;
1583
1584 geometryData.push_back(tcu::Vec3(x0, y0, z));
1585 geometryData.push_back(tcu::Vec3(xm, y1, z));
1586 geometryData.push_back(tcu::Vec3(x1, ym, z));
1587 }
1588 else
1589 {
1590 geometryData.push_back(tcu::Vec3(x0, y0, z));
1591 geometryData.push_back(tcu::Vec3(x1, y1, z * 0.9f));
1592 }
1593
1594 startPos.y() = m / m_data.width;
1595 startPos.x() = m % m_data.width;
1596 }
1597
1598 result->addGeometry(geometryData, triangles);
1599 }
1600 }
1601 else if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT || m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT ||
1602 m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT || m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT ||
1603 m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT ||
1604 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT)
1605 {
1606 const bool triangles = m_data.geomType == GEOM_TYPE_TRIANGLES;
1607 const float y0 = float(startPos.y() + 0) / float(m_data.height);
1608 const float y1 = float(startPos.y() + 1) / float(m_data.height);
1609 const bool missShader = (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR);
1610 const float z = !missShader ? -1.0f : -100.0f;
1611 std::vector<tcu::Vec3> geometryData;
1612
1613 if (triangles)
1614 {
1615 geometryData.push_back(tcu::Vec3(-1.0f, y1, z));
1616 geometryData.push_back(tcu::Vec3(-1.0f, y0, z));
1617 geometryData.push_back(tcu::Vec3(+1.0f, y0, z));
1618 geometryData.push_back(tcu::Vec3(-1.0f, y1, z));
1619 geometryData.push_back(tcu::Vec3(+1.0f, y0, z));
1620 geometryData.push_back(tcu::Vec3(+1.0f, y1, z));
1621 }
1622 else
1623 {
1624 geometryData.reserve(2);
1625
1626 geometryData.push_back(tcu::Vec3(-1.0f, y0, z));
1627 geometryData.push_back(tcu::Vec3(+1.0f, y1, z));
1628 }
1629
1630 DE_ASSERT(startPos.y() < m_data.height);
1631
1632 startPos.y()++;
1633
1634 result->addGeometry(geometryData, triangles);
1635 }
1636 else
1637 {
1638 TCU_THROW(InternalError, "Not implemented");
1639 }
1640
1641 result->createAndBuild(vkd, device, cmdBuffer, allocator);
1642
1643 return result;
1644 }
1645
1646 vector<de::SharedPtr<BottomLevelAccelerationStructure>> RayTracingBuiltinLaunchTestInstance::
initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)1647 initBottomAccelerationStructures(VkCommandBuffer cmdBuffer)
1648 {
1649 tcu::UVec2 startPos;
1650 vector<de::SharedPtr<BottomLevelAccelerationStructure>> result;
1651
1652 for (size_t instanceNdx = 0; instanceNdx < m_data.instancesGroupCount; ++instanceNdx)
1653 {
1654 de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure =
1655 initBottomAccelerationStructure(cmdBuffer, startPos);
1656
1657 result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
1658 }
1659
1660 return result;
1661 }
1662
makePipeline(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,VkPipelineLayout pipelineLayout,const VkSpecializationInfo * specializationInfo)1663 Move<VkPipeline> RayTracingBuiltinLaunchTestInstance::makePipeline(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
1664 VkPipelineLayout pipelineLayout,
1665 const VkSpecializationInfo *specializationInfo)
1666 {
1667 const DeviceInterface &vkd = m_context.getDeviceInterface();
1668 const VkDevice device = m_context.getDevice();
1669 vk::BinaryCollection &collection = m_context.getBinaryCollection();
1670
1671 if (0 != (m_shaders & VK_SHADER_STAGE_RAYGEN_BIT_KHR))
1672 rayTracingPipeline->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR,
1673 createShaderModule(vkd, device, collection.get("rgen"), 0), m_raygenShaderGroup,
1674 specializationInfo);
1675 if (0 != (m_shaders & VK_SHADER_STAGE_ANY_HIT_BIT_KHR))
1676 rayTracingPipeline->addShader(VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
1677 createShaderModule(vkd, device, collection.get("ahit"), 0), m_hitShaderGroup,
1678 specializationInfo);
1679 if (0 != (m_shaders & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))
1680 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
1681 createShaderModule(vkd, device, collection.get("chit"), 0), m_hitShaderGroup,
1682 specializationInfo);
1683 if (0 != (m_shaders & VK_SHADER_STAGE_MISS_BIT_KHR))
1684 rayTracingPipeline->addShader(VK_SHADER_STAGE_MISS_BIT_KHR,
1685 createShaderModule(vkd, device, collection.get("miss"), 0), m_missShaderGroup,
1686 specializationInfo);
1687 if (0 != (m_shaders & VK_SHADER_STAGE_INTERSECTION_BIT_KHR))
1688 rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
1689 createShaderModule(vkd, device, collection.get("sect"), 0), m_hitShaderGroup,
1690 specializationInfo);
1691 if (0 != (m_shaders & VK_SHADER_STAGE_CALLABLE_BIT_KHR))
1692 rayTracingPipeline->addShader(VK_SHADER_STAGE_CALLABLE_BIT_KHR,
1693 createShaderModule(vkd, device, collection.get("call"), 0), m_callableShaderGroup,
1694 specializationInfo);
1695
1696 if (m_data.pipelineCreateFlags != 0)
1697 {
1698 rayTracingPipeline->setCreateFlags(m_data.pipelineCreateFlags);
1699 if (m_data.useMaintenance5)
1700 rayTracingPipeline->setCreateFlags2(translateCreateFlag(m_data.pipelineCreateFlags));
1701 }
1702
1703 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vkd, device, pipelineLayout);
1704
1705 return pipeline;
1706 }
1707
createShaderBindingTable(const InstanceInterface & vki,const DeviceInterface & vkd,const VkDevice device,const VkPhysicalDevice physicalDevice,const VkPipeline pipeline,Allocator & allocator,de::MovePtr<RayTracingPipeline> & rayTracingPipeline,const uint32_t group)1708 de::MovePtr<BufferWithMemory> RayTracingBuiltinLaunchTestInstance::createShaderBindingTable(
1709 const InstanceInterface &vki, const DeviceInterface &vkd, const VkDevice device,
1710 const VkPhysicalDevice physicalDevice, const VkPipeline pipeline, Allocator &allocator,
1711 de::MovePtr<RayTracingPipeline> &rayTracingPipeline, const uint32_t group)
1712 {
1713 de::MovePtr<BufferWithMemory> shaderBindingTable;
1714
1715 if (group < m_shaderGroupCount)
1716 {
1717 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
1718 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
1719
1720 shaderBindingTable = rayTracingPipeline->createShaderBindingTable(
1721 vkd, device, pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, group, 1u);
1722 }
1723
1724 return shaderBindingTable;
1725 }
1726
1727 // Provides two spec constants, one integer and one float, both with value 256.
1728 class SpecConstantsHelper
1729 {
1730 public:
1731 SpecConstantsHelper();
1732 const VkSpecializationInfo &getSpecializationInfo(void) const;
1733
1734 private:
1735 std::vector<uint8_t> m_data;
1736 std::vector<VkSpecializationMapEntry> m_mapEntries;
1737 VkSpecializationInfo m_specInfo;
1738 };
1739
SpecConstantsHelper()1740 SpecConstantsHelper::SpecConstantsHelper() : m_data(), m_mapEntries()
1741 {
1742 // To make things interesting, make both data unaligned and add some padding.
1743 const int32_t value1 = 256;
1744 const float value2 = 256.0f;
1745
1746 const size_t offset1 = 1u; // Offset of 1 byte.
1747 const size_t offset2 = 1u + sizeof(value1) + 2u; // Offset of 3 bytes plus the size of value1.
1748
1749 m_data.resize(sizeof(value1) + sizeof(value2) + 5u); // Some extra padding at the end too.
1750 deMemcpy(&m_data[offset1], &value1, sizeof(value1));
1751 deMemcpy(&m_data[offset2], &value2, sizeof(value2));
1752
1753 // Map entries.
1754 m_mapEntries.reserve(2u);
1755 m_mapEntries.push_back({0u, static_cast<uint32_t>(offset1), static_cast<uintptr_t>(sizeof(value1))});
1756 m_mapEntries.push_back({1u, static_cast<uint32_t>(offset2), static_cast<uintptr_t>(sizeof(value2))});
1757
1758 // Specialization info.
1759 m_specInfo.mapEntryCount = static_cast<uint32_t>(m_mapEntries.size());
1760 m_specInfo.pMapEntries = m_mapEntries.data();
1761 m_specInfo.dataSize = static_cast<uintptr_t>(m_data.size());
1762 m_specInfo.pData = m_data.data();
1763 }
1764
getSpecializationInfo(void) const1765 const VkSpecializationInfo &SpecConstantsHelper::getSpecializationInfo(void) const
1766 {
1767 return m_specInfo;
1768 }
1769
runTest(void)1770 de::MovePtr<BufferWithMemory> RayTracingBuiltinLaunchTestInstance::runTest(void)
1771 {
1772 const InstanceInterface &vki = m_context.getInstanceInterface();
1773 const DeviceInterface &vkd = m_context.getDeviceInterface();
1774 const VkDevice device = m_context.getDevice();
1775 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1776 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1777 const VkQueue queue = m_context.getUniversalQueue();
1778 Allocator &allocator = m_context.getDefaultAllocator();
1779 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
1780 const VkFormat format = m_data.format;
1781 const uint32_t pixelSize = tcu::getPixelSize(mapVkFormat(format));
1782 const uint32_t pixelCount = m_data.width * m_data.height * m_data.depth;
1783
1784 const Move<VkDescriptorSetLayout> descriptorSetLayout =
1785 DescriptorSetLayoutBuilder()
1786 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
1787 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
1788 .build(vkd, device);
1789 const Move<VkDescriptorPool> descriptorPool =
1790 DescriptorPoolBuilder()
1791 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1792 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
1793 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1794 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
1795 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
1796 const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1797 const Move<VkCommandBuffer> cmdBuffer =
1798 allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1799
1800 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
1801 const SpecConstantsHelper specConstantHelper;
1802 const VkSpecializationInfo *specializationInfo =
1803 (m_data.useSpecConstants ? &specConstantHelper.getSpecializationInfo() : nullptr);
1804 const Move<VkPipeline> pipeline = makePipeline(rayTracingPipeline, *pipelineLayout, specializationInfo);
1805 const de::MovePtr<BufferWithMemory> raygenShaderBindingTable = createShaderBindingTable(
1806 vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_raygenShaderGroup);
1807 const de::MovePtr<BufferWithMemory> missShaderBindingTable = createShaderBindingTable(
1808 vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_missShaderGroup);
1809 const de::MovePtr<BufferWithMemory> hitShaderBindingTable = createShaderBindingTable(
1810 vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_hitShaderGroup);
1811 const de::MovePtr<BufferWithMemory> callableShaderBindingTable = createShaderBindingTable(
1812 vki, vkd, device, physicalDevice, *pipeline, allocator, rayTracingPipeline, m_callableShaderGroup);
1813
1814 const VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion =
1815 raygenShaderBindingTable.get() != NULL ?
1816 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0),
1817 shaderGroupHandleSize, shaderGroupHandleSize) :
1818 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1819 const VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion =
1820 missShaderBindingTable.get() != NULL ?
1821 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0),
1822 shaderGroupHandleSize, shaderGroupHandleSize) :
1823 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1824 const VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion =
1825 hitShaderBindingTable.get() != NULL ?
1826 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0),
1827 shaderGroupHandleSize, shaderGroupHandleSize) :
1828 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1829 const VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion =
1830 callableShaderBindingTable.get() != NULL ?
1831 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0),
1832 shaderGroupHandleSize, shaderGroupHandleSize) :
1833 makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
1834
1835 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, m_data.depth, format);
1836 const VkImageSubresourceRange imageSubresourceRange =
1837 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u);
1838 const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1839 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1840 const Move<VkImageView> imageView =
1841 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, format, imageSubresourceRange);
1842
1843 const VkBufferCreateInfo bufferCreateInfo =
1844 makeBufferCreateInfo(pixelCount * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1845 const VkImageSubresourceLayers bufferImageSubresourceLayers =
1846 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1847 const VkBufferImageCopy bufferImageRegion =
1848 makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, m_data.depth), bufferImageSubresourceLayers);
1849 de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
1850 new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1851
1852 const VkDescriptorImageInfo descriptorImageInfo =
1853 makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
1854
1855 const VkImageMemoryBarrier preImageBarrier =
1856 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1857 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, **image, imageSubresourceRange);
1858 const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
1859 VK_ACCESS_TRANSFER_WRITE_BIT,
1860 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
1861 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, **image, imageSubresourceRange);
1862 const VkMemoryBarrier postTraceMemoryBarrier =
1863 makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
1864 const VkMemoryBarrier postCopyMemoryBarrier =
1865 makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1866 const VkClearValue clearValue =
1867 makeClearValueColorU32(DEFAULT_UINT_CLEAR_VALUE, DEFAULT_UINT_CLEAR_VALUE, DEFAULT_UINT_CLEAR_VALUE, 255u);
1868
1869 vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
1870 de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
1871
1872 beginCommandBuffer(vkd, *cmdBuffer, 0u);
1873 {
1874 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1875 VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
1876 vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1,
1877 &imageSubresourceRange);
1878 cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1879 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
1880
1881 bottomLevelAccelerationStructures = initBottomAccelerationStructures(*cmdBuffer);
1882 topLevelAccelerationStructure = initTopAccelerationStructure(*cmdBuffer, bottomLevelAccelerationStructures);
1883
1884 const TopLevelAccelerationStructure *topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
1885 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
1886 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
1887 DE_NULL, // const void* pNext;
1888 1u, // uint32_t accelerationStructureCount;
1889 topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
1890 };
1891
1892 DescriptorSetUpdateBuilder()
1893 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1894 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1895 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1896 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
1897 .update(vkd, device);
1898
1899 vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
1900 &descriptorSet.get(), 0, DE_NULL);
1901
1902 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
1903
1904 cmdTraceRays(vkd, *cmdBuffer, &raygenShaderBindingTableRegion, &missShaderBindingTableRegion,
1905 &hitShaderBindingTableRegion, &callableShaderBindingTableRegion, m_data.width, m_data.height,
1906 m_data.raysDepth);
1907
1908 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
1909 VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier);
1910
1911 vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **buffer, 1u, &bufferImageRegion);
1912
1913 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1914 &postCopyMemoryBarrier);
1915 }
1916 endCommandBuffer(vkd, *cmdBuffer);
1917
1918 submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
1919
1920 invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(),
1921 VK_WHOLE_SIZE);
1922
1923 return buffer;
1924 }
1925
checkFormatSupported(Context & context,VkFormat format,VkImageUsageFlags usage,const VkExtent3D & extent)1926 void checkFormatSupported(Context &context, VkFormat format, VkImageUsageFlags usage, const VkExtent3D &extent)
1927 {
1928 VkResult result;
1929 VkImageFormatProperties properties;
1930
1931 result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
1932 context.getPhysicalDevice(), format, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
1933
1934 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
1935 {
1936 std::ostringstream msg;
1937
1938 msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
1939
1940 TCU_THROW(NotSupportedError, msg.str());
1941 }
1942
1943 if (properties.maxExtent.width < extent.width || properties.maxExtent.height < extent.height ||
1944 properties.maxExtent.depth < extent.depth)
1945 TCU_THROW(NotSupportedError, "Image size is too large for this format");
1946
1947 VK_CHECK(result);
1948 }
1949
checkSupportInInstance(void) const1950 void RayTracingBuiltinLaunchTestInstance::checkSupportInInstance(void) const
1951 {
1952 const InstanceInterface &vki = m_context.getInstanceInterface();
1953 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1954 const vk::VkPhysicalDeviceProperties &properties = m_context.getDeviceProperties();
1955 const uint32_t requiredAllocations =
1956 8u + TopLevelAccelerationStructure::getRequiredAllocationCount() +
1957 m_data.instancesGroupCount * BottomLevelAccelerationStructure::getRequiredAllocationCount();
1958 const de::MovePtr<RayTracingProperties> rayTracingProperties = makeRayTracingProperties(vki, physicalDevice);
1959 const VkExtent3D extent = makeExtent3D(m_data.width, m_data.height, m_data.depth);
1960
1961 checkFormatSupported(m_context, m_data.format,
1962 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1963 extent);
1964
1965 if (rayTracingProperties->getMaxPrimitiveCount() < 2 * m_data.squaresGroupCount)
1966 TCU_THROW(NotSupportedError, "Triangles required more than supported");
1967
1968 if (rayTracingProperties->getMaxGeometryCount() < m_data.geometriesGroupCount)
1969 TCU_THROW(NotSupportedError, "Geometries required more than supported");
1970
1971 if (rayTracingProperties->getMaxInstanceCount() < m_data.instancesGroupCount)
1972 TCU_THROW(NotSupportedError, "Instances required more than supported");
1973
1974 if (properties.limits.maxMemoryAllocationCount < requiredAllocations)
1975 TCU_THROW(NotSupportedError, "Test requires more allocations allowed");
1976 }
1977
expectedIntValuesBuffer(void)1978 std::vector<int32_t> RayTracingBuiltinLaunchTestInstance::expectedIntValuesBuffer(void)
1979 {
1980 uint32_t pos = 0;
1981 std::vector<int32_t> result;
1982
1983 result.reserve(m_data.depth * m_data.height * m_data.width);
1984
1985 if (m_data.id == TEST_ID_LAUNCH_ID_EXT)
1986 {
1987 for (uint32_t z = 0; z < m_data.depth; ++z)
1988 for (uint32_t y = 0; y < m_data.height; ++y)
1989 for (uint32_t x = 0; x < m_data.width; ++x)
1990 result.push_back(int32_t(x + 256 * (y + 256 * z)) + 1);
1991 }
1992 else if (m_data.id == TEST_ID_LAUNCH_SIZE_EXT)
1993 {
1994 const uint32_t expectedValue = m_data.width + 256 * (m_data.height + 256 * m_data.depth);
1995 const std::vector<int32_t> result2(m_data.depth * m_data.height * m_data.width, int32_t(expectedValue) + 1);
1996
1997 result = result2;
1998 }
1999 else if (m_data.id == TEST_ID_GEOMETRY_INDEX_EXT)
2000 {
2001 for (uint32_t z = 0; z < m_data.depth; ++z)
2002 for (uint32_t y = 0; y < m_data.height; ++y)
2003 for (uint32_t x = 0; x < m_data.width; ++x)
2004 result.push_back(int32_t((pos++ / m_data.squaresGroupCount) % m_data.geometriesGroupCount));
2005 }
2006 else if (m_data.id == TEST_ID_PRIMITIVE_ID)
2007 {
2008 for (uint32_t z = 0; z < m_data.depth; ++z)
2009 for (uint32_t y = 0; y < m_data.height; ++y)
2010 for (uint32_t x = 0; x < m_data.width; ++x)
2011 result.push_back(int32_t(pos++ % m_data.squaresGroupCount));
2012 }
2013 else if (m_data.id == TEST_ID_INSTANCE_ID)
2014 {
2015 for (uint32_t z = 0; z < m_data.depth; ++z)
2016 for (uint32_t y = 0; y < m_data.height; ++y)
2017 for (uint32_t x = 0; x < m_data.width; ++x)
2018 result.push_back(int32_t(pos++ / (m_data.squaresGroupCount * m_data.geometriesGroupCount)));
2019 }
2020 else if (m_data.id == TEST_ID_INSTANCE_CUSTOM_INDEX_EXT)
2021 {
2022 for (uint32_t z = 0; z < m_data.depth; ++z)
2023 for (uint32_t y = 0; y < m_data.height; ++y)
2024 for (uint32_t x = 0; x < m_data.width; ++x)
2025 result.push_back(int32_t(2 * (pos++ / (m_data.squaresGroupCount * m_data.geometriesGroupCount))));
2026 }
2027 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_EXT)
2028 {
2029 DE_ASSERT(m_data.squaresGroupCount == (1 << RAY_FLAG_BIT_LAST_PER_TEST));
2030 DE_ASSERT(DEFAULT_UINT_CLEAR_VALUE != (1 << RAY_FLAG_BIT_LAST_PER_TEST));
2031
2032 for (uint32_t z = 0; z < m_data.depth; ++z)
2033 for (uint32_t y = 0; y < m_data.height; ++y)
2034 for (uint32_t x = 0; x < m_data.width; ++x)
2035 {
2036 const uint32_t n = x + m_data.width * (y + m_data.height * z);
2037 const bool rayOpaque = (0 != (n & (1 << RAY_FLAG_BIT_OPAQUE_EXT)));
2038 const bool rayNoOpaque = (0 != (n & (1 << RAY_FLAG_BIT_NO_OPAQUE_EXT))) && !rayOpaque;
2039 const bool rayTerminateOnFirstHit = (0 != (n & (1 << RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT)));
2040 const bool raySkipClosestHitShader = (0 != (n & (1 << RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT)));
2041 const bool rayCullBack = (0 != (n & (1 << RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT)));
2042 const bool rayCullFront =
2043 (0 != (n & (1 << RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT))) && !rayCullBack;
2044 const bool rayCullOpaque =
2045 (0 != (n & (1 << RAY_FLAG_BIT_CULL_OPAQUE_EXT))) && !rayOpaque && !rayNoOpaque;
2046 const bool rayCullNoOpaque = (0 != (n & (1 << RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT))) && !rayOpaque &&
2047 !rayNoOpaque && !rayCullOpaque;
2048 const bool raySkipTriangles = m_data.rayFlagSkipTriangles;
2049 const bool raySkipAABBs = m_data.rayFlagSkipAABSs;
2050 const bool pipelineSkipTriangles =
2051 (m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0;
2052 const bool pipelineSkipAABBs =
2053 (m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0;
2054 const bool cullingTest = m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs ||
2055 pipelineSkipTriangles || pipelineSkipAABBs;
2056 const bool geometryFrontFace = m_data.frontFace;
2057 const bool geometryOpaque = m_data.opaque;
2058 const bool geometryTriangles = (m_data.geomType == GEOM_TYPE_TRIANGLES) ? true : false;
2059 const bool geometryAABBs = (m_data.geomType == GEOM_TYPE_AABBS) ? true : false;
2060 uint32_t v = 0 | (rayOpaque ? (1 << RAY_FLAG_BIT_OPAQUE_EXT) : 0) |
2061 (rayNoOpaque ? (1 << RAY_FLAG_BIT_NO_OPAQUE_EXT) : 0) |
2062 (rayTerminateOnFirstHit ? (1 << RAY_FLAG_BIT_TERMINATE_ON_FIRST_HIT_EXT) : 0) |
2063 (raySkipClosestHitShader ? (1 << RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT) : 0) |
2064 (rayCullBack ? (1 << RAY_FLAG_BIT_CULL_BACK_FACING_TRIANGLES_EXT) : 0) |
2065 (rayCullFront ? (1 << RAY_FLAG_BIT_CULL_FRONT_FACING_TRIANGLES_EXT) : 0) |
2066 (rayCullOpaque ? (1 << RAY_FLAG_BIT_CULL_OPAQUE_EXT) : 0) |
2067 (rayCullNoOpaque ? (1 << RAY_FLAG_BIT_CULL_NO_OPAQUE_EXT) : 0) |
2068 (raySkipTriangles ? (1 << RAY_FLAG_BIT_SKIP_TRIANGLES_EXT) : 0) |
2069 (raySkipAABBs ? (1 << RAY_FLAG_BIT_SKIP_AABB_EXT) : 0);
2070
2071 if (m_data.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR && raySkipClosestHitShader)
2072 v = DEFAULT_UINT_CLEAR_VALUE;
2073
2074 if (m_data.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR &&
2075 (rayOpaque || (geometryOpaque && !rayOpaque && !rayNoOpaque)))
2076 v = DEFAULT_UINT_CLEAR_VALUE;
2077
2078 if (geometryOpaque)
2079 {
2080 if (rayCullOpaque)
2081 if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
2082 v = DEFAULT_UINT_CLEAR_VALUE;
2083 }
2084 else
2085 {
2086 if (rayCullNoOpaque)
2087 if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
2088 v = DEFAULT_UINT_CLEAR_VALUE;
2089 }
2090
2091 if (geometryTriangles)
2092 {
2093 if (geometryFrontFace)
2094 {
2095 if (rayCullFront)
2096 if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
2097 v = DEFAULT_UINT_CLEAR_VALUE;
2098 }
2099 else
2100 {
2101 if (rayCullBack)
2102 if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
2103 v = DEFAULT_UINT_CLEAR_VALUE;
2104 }
2105 }
2106
2107 if (cullingTest)
2108 {
2109 if (m_data.stage != VK_SHADER_STAGE_MISS_BIT_KHR)
2110 {
2111 if (geometryTriangles)
2112 {
2113 if (raySkipTriangles || pipelineSkipTriangles)
2114 v = DEFAULT_UINT_CLEAR_VALUE;
2115 }
2116
2117 if (geometryAABBs)
2118 {
2119 if (raySkipAABBs || pipelineSkipAABBs)
2120 v = DEFAULT_UINT_CLEAR_VALUE;
2121 }
2122 }
2123 }
2124
2125 result.push_back(int32_t(v));
2126 }
2127 }
2128 else if (m_data.id == TEST_ID_HIT_KIND_EXT)
2129 {
2130 for (uint32_t z = 0; z < m_data.depth; ++z)
2131 for (uint32_t y = 0; y < m_data.height; ++y)
2132 for (uint32_t x = 0; x < m_data.width; ++x)
2133 {
2134 const uint32_t n = x + m_data.width * (y + m_data.height * z);
2135 const uint32_t geometryNdx = n / m_data.squaresGroupCount;
2136 const uint32_t hitKind = ((geometryNdx & 1) == 0) ? 0xFEu : 0xFFu;
2137 const bool geometryOpaque = ((geometryNdx & 2) == 0) ? true : false;
2138 uint32_t v = (m_data.geomType == GEOM_TYPE_TRIANGLES) ? hitKind : 0x7Eu;
2139
2140 if (m_data.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR && geometryOpaque)
2141 v = DEFAULT_UINT_CLEAR_VALUE;
2142
2143 result.push_back(int32_t(v));
2144 }
2145 }
2146 else
2147 {
2148 TCU_THROW(InternalError, "Not implemented");
2149 }
2150
2151 return result;
2152 }
2153
expectedFloatValuesBuffer(void)2154 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedFloatValuesBuffer(void)
2155 {
2156 std::vector<float> result;
2157
2158 result.reserve(m_data.depth * m_data.height * m_data.width);
2159
2160 if (m_data.id == TEST_ID_HIT_T_EXT)
2161 {
2162 for (uint32_t z = 0; z < m_data.depth; ++z)
2163 for (uint32_t y = 0; y < m_data.height; ++y)
2164 for (uint32_t x = 0; x < m_data.width; ++x)
2165 {
2166 const float a = float(x) / float(m_data.width);
2167 const float b = 1.0f + float(y) / float(m_data.height);
2168 const float f = 0.03125f + 0.25f * a / b;
2169
2170 result.push_back(f);
2171 }
2172 }
2173 else if (m_data.id == TEST_ID_RAY_T_MIN_EXT)
2174 {
2175 for (uint32_t z = 0; z < m_data.depth; ++z)
2176 for (uint32_t y = 0; y < m_data.height; ++y)
2177 for (uint32_t x = 0; x < m_data.width; ++x)
2178 {
2179 const float a = float(x) / float(m_data.width);
2180 const float b = 1.0f + float(y) / float(m_data.height);
2181 const float f = 0.25f * a / b;
2182
2183 result.push_back(f);
2184 }
2185 }
2186 else if (m_data.id == TEST_ID_RAY_T_MAX_EXT)
2187 {
2188 for (uint32_t z = 0; z < m_data.depth; ++z)
2189 for (uint32_t y = 0; y < m_data.height; ++y)
2190 for (uint32_t x = 0; x < m_data.width; ++x)
2191 {
2192 const float a = float(x) / float(m_data.width);
2193 const float b = 1.0f + float(y) / float(m_data.height);
2194 const float c = 0.25f * a / b;
2195 // In a miss shader, the value is identical to the parameter passed into traceRayEXT().
2196 const float m = 0.75f + c;
2197 // In the closest-hit shader, the value reflects the closest distance to the intersected primitive.
2198 // In the any-hit shader, it reflects the distance to the primitive currently being intersected.
2199 // In the intersection shader, it reflects the distance to the closest primitive intersected so far.
2200 const float n = 0.03125f + c;
2201 const bool normalRow = (y & 1) != 0;
2202 const bool doublePrimitive = (x & 1) != 0;
2203 const float s = normalRow ? m :
2204 doublePrimitive ? 0.4375f + c :
2205 float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR);
2206 const float f = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR) ? s :
2207 (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR) ? m :
2208 n;
2209
2210 result.push_back(f);
2211 }
2212 }
2213 else
2214 {
2215 TCU_THROW(InternalError, "Not implemented");
2216 }
2217
2218 return result;
2219 }
2220
expectedVectorValuesBuffer(void)2221 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedVectorValuesBuffer(void)
2222 {
2223 const uint32_t imageDepth = 4;
2224 const uint32_t expectedFloats = imageDepth * m_data.height * m_data.width;
2225 std::vector<float> result(expectedFloats, float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR));
2226
2227 if (m_data.id == TEST_ID_WORLD_RAY_ORIGIN_EXT)
2228 {
2229 uint32_t pos = 0;
2230
2231 for (uint32_t y = 0; y < m_data.height; ++y)
2232 for (uint32_t x = 0; x < m_data.width; ++x)
2233 result[pos++] = (0.5f + float(x)) / float(m_data.width);
2234
2235 for (uint32_t y = 0; y < m_data.height; ++y)
2236 for (uint32_t x = 0; x < m_data.width; ++x)
2237 result[pos++] = (0.5f + float(y)) / float(m_data.height);
2238
2239 for (uint32_t y = 0; y < m_data.height; ++y)
2240 for (uint32_t x = 0; x < m_data.width; ++x)
2241 result[pos++] = 0.0f;
2242 }
2243 else if (m_data.id == TEST_ID_WORLD_RAY_DIRECTION_EXT)
2244 {
2245 uint32_t pos = 0;
2246
2247 for (uint32_t y = 0; y < m_data.height; ++y)
2248 for (uint32_t x = 0; x < m_data.width; ++x)
2249 result[pos++] = 0.0f;
2250
2251 for (uint32_t y = 0; y < m_data.height; ++y)
2252 for (uint32_t x = 0; x < m_data.width; ++x)
2253 result[pos++] = 0.0f;
2254
2255 for (uint32_t y = 0; y < m_data.height; ++y)
2256 for (uint32_t x = 0; x < m_data.width; ++x)
2257 result[pos++] = -1.0f;
2258 }
2259 else if (m_data.id == TEST_ID_OBJECT_RAY_ORIGIN_EXT)
2260 {
2261 uint32_t pos = 0;
2262
2263 for (uint32_t y = 0; y < m_data.height; ++y)
2264 for (uint32_t x = 0; x < m_data.width; ++x)
2265 {
2266 const uint32_t instanceId = y / (m_data.height / m_data.instancesGroupCount);
2267 const float offset = (instanceId & 1) ? 1.0f / 8.0f : 0.0f;
2268
2269 result[pos++] = (0.5f + float(x) - offset) / float(m_data.width);
2270 }
2271
2272 for (uint32_t y = 0; y < m_data.height; ++y)
2273 for (uint32_t x = 0; x < m_data.width; ++x)
2274 {
2275 const uint32_t instanceId = y / (m_data.height / m_data.instancesGroupCount);
2276 const float offset = (instanceId & 2) ? 1.0f / 16.0f : 0.0f;
2277
2278 result[pos++] = (0.5f + float(y) - offset) / float(m_data.height);
2279 }
2280
2281 for (uint32_t y = 0; y < m_data.height; ++y)
2282 for (uint32_t x = 0; x < m_data.width; ++x)
2283 result[pos++] = 0.0f;
2284 }
2285 else if (m_data.id == TEST_ID_OBJECT_RAY_DIRECTION_EXT)
2286 {
2287 uint32_t pos = 0;
2288
2289 for (uint32_t y = 0; y < m_data.height; ++y)
2290 for (uint32_t x = 0; x < m_data.width; ++x)
2291 result[pos++] = 0.0f;
2292
2293 for (uint32_t y = 0; y < m_data.height; ++y)
2294 for (uint32_t x = 0; x < m_data.width; ++x)
2295 result[pos++] = 0.0f;
2296
2297 for (uint32_t y = 0; y < m_data.height; ++y)
2298 for (uint32_t x = 0; x < m_data.width; ++x)
2299 result[pos++] = -1.0f;
2300 }
2301 else
2302 {
2303 TCU_THROW(InternalError, "Not implemented");
2304 }
2305
2306 return result;
2307 }
2308
expectedMatrixValuesBuffer(void)2309 std::vector<float> RayTracingBuiltinLaunchTestInstance::expectedMatrixValuesBuffer(void)
2310 {
2311 const uint32_t colCount = 4;
2312 const uint32_t rowCount = 3;
2313 const uint32_t imageDepth = 4 * 4;
2314 const uint32_t zStride = m_data.height * m_data.width;
2315 const uint32_t expectedFloats = imageDepth * m_data.height * m_data.width;
2316 std::vector<float> result(expectedFloats, float(DEFAULT_UINT_CLEAR_VALUE) / float(FIXED_POINT_DIVISOR));
2317
2318 if (m_data.id == TEST_ID_OBJECT_TO_WORLD_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT ||
2319 m_data.id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT)
2320 {
2321 const int translateColumnNumber = 3;
2322 const float translateSign =
2323 (m_data.id == TEST_ID_WORLD_TO_OBJECT_EXT || m_data.id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT) ? -1.0f : +1.0f;
2324 const float translateX = translateSign * (1.0f / 8.0f) / float(m_data.width);
2325 const float translateY = translateSign * (1.0f / 16.0f) / float(m_data.height);
2326
2327 for (uint32_t y = 0; y < m_data.height; ++y)
2328 {
2329 const uint32_t instanceId = y / (m_data.height / m_data.instancesGroupCount);
2330
2331 for (uint32_t x = 0; x < m_data.width; ++x)
2332 {
2333 tcu::Matrix<float, rowCount, colCount> m;
2334 const uint32_t elem0Pos = x + m_data.width * y;
2335
2336 if (instanceId & 1)
2337 m[translateColumnNumber][0] = translateX;
2338
2339 if (instanceId & 2)
2340 m[translateColumnNumber][1] = translateY;
2341
2342 for (uint32_t rowNdx = 0; rowNdx < rowCount; ++rowNdx)
2343 for (uint32_t colNdx = 0; colNdx < colCount; ++colNdx)
2344 {
2345 const uint32_t z = rowNdx * colCount + colNdx;
2346 const uint32_t pos = elem0Pos + zStride * z;
2347
2348 result[pos] = m[colNdx][rowNdx];
2349 }
2350 }
2351 }
2352 }
2353 else
2354 {
2355 TCU_THROW(InternalError, "Not implemented");
2356 }
2357
2358 return result;
2359 }
2360
validateIntBuffer(de::MovePtr<BufferWithMemory> buffer)2361 bool RayTracingBuiltinLaunchTestInstance::validateIntBuffer(de::MovePtr<BufferWithMemory> buffer)
2362 {
2363 const int32_t *bufferPtr = (int32_t *)buffer->getAllocation().getHostPtr();
2364 const vector<int32_t> expectedValues = expectedIntValuesBuffer();
2365 tcu::TestLog &log = m_context.getTestContext().getLog();
2366 uint32_t failures = 0;
2367 uint32_t pos = 0;
2368
2369 for (uint32_t z = 0; z < m_data.depth; ++z)
2370 for (uint32_t y = 0; y < m_data.height; ++y)
2371 for (uint32_t x = 0; x < m_data.width; ++x)
2372 {
2373 if (bufferPtr[pos] != expectedValues[pos])
2374 failures++;
2375
2376 ++pos;
2377 }
2378
2379 if (failures != 0)
2380 {
2381 const char *names[] = {"Retrieved:", "Expected:"};
2382 for (uint32_t n = 0; n < 2; ++n)
2383 {
2384 const int32_t *loggedData = (n == 0) ? bufferPtr : expectedValues.data();
2385 std::stringstream css;
2386
2387 pos = 0;
2388
2389 for (uint32_t z = 0; z < m_data.depth; ++z)
2390 for (uint32_t y = 0; y < m_data.height; ++y)
2391 {
2392 for (uint32_t x = 0; x < m_data.width; ++x)
2393 {
2394 if (bufferPtr[pos] == expectedValues[pos])
2395 css << "____,";
2396 else
2397 css << std::hex << std::setw(4) << loggedData[pos] << ",";
2398
2399 pos++;
2400 }
2401
2402 css << std::endl;
2403 }
2404
2405 log << tcu::TestLog::Message << names[n] << tcu::TestLog::EndMessage;
2406 log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2407 }
2408 }
2409
2410 return failures == 0;
2411 }
2412
validateFloatBuffer(de::MovePtr<BufferWithMemory> buffer)2413 bool RayTracingBuiltinLaunchTestInstance::validateFloatBuffer(de::MovePtr<BufferWithMemory> buffer)
2414 {
2415 const float eps = float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2416 const int32_t *bufferPtr = (int32_t *)buffer->getAllocation().getHostPtr();
2417 const vector<float> expectedValues = expectedFloatValuesBuffer();
2418 tcu::TestLog &log = m_context.getTestContext().getLog();
2419 uint32_t failures = 0;
2420 uint32_t pos = 0;
2421
2422 for (uint32_t z = 0; z < m_data.depth; ++z)
2423 for (uint32_t y = 0; y < m_data.height; ++y)
2424 for (uint32_t x = 0; x < m_data.width; ++x)
2425 {
2426 const float retrievedValue = float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2427
2428 if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2429 failures++;
2430
2431 ++pos;
2432 }
2433
2434 if (failures != 0)
2435 {
2436 const char *names[] = {"Retrieved:", "Expected:"};
2437
2438 for (uint32_t n = 0; n < 2; ++n)
2439 {
2440 std::stringstream css;
2441
2442 pos = 0;
2443
2444 for (uint32_t z = 0; z < m_data.depth; ++z)
2445 for (uint32_t y = 0; y < m_data.height; ++y)
2446 {
2447 for (uint32_t x = 0; x < m_data.width; ++x)
2448 {
2449 const float retrievedValue = float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2450 const float expectedValue = expectedValues[pos];
2451
2452 if (deFloatAbs(retrievedValue - expectedValue) > eps)
2453 css << std::setprecision(8) << std::setw(12) << (n == 0 ? retrievedValue : expectedValue)
2454 << ",";
2455 else
2456 css << "____________,";
2457
2458 pos++;
2459 }
2460
2461 css << std::endl;
2462 }
2463
2464 log << tcu::TestLog::Message << names[n] << tcu::TestLog::EndMessage;
2465 log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2466 }
2467 }
2468
2469 return failures == 0;
2470 }
2471
validateVectorBuffer(de::MovePtr<BufferWithMemory> buffer)2472 bool RayTracingBuiltinLaunchTestInstance::validateVectorBuffer(de::MovePtr<BufferWithMemory> buffer)
2473 {
2474 const float eps = float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2475 const int32_t *bufferPtr = (int32_t *)buffer->getAllocation().getHostPtr();
2476 const vector<float> expectedValues = expectedVectorValuesBuffer();
2477 const uint32_t depth = 3u; // vec3
2478 tcu::TestLog &log = m_context.getTestContext().getLog();
2479 uint32_t failures = 0;
2480 uint32_t pos = 0;
2481
2482 DE_ASSERT(depth <= m_data.depth);
2483
2484 for (uint32_t z = 0; z < depth; ++z)
2485 for (uint32_t y = 0; y < m_data.height; ++y)
2486 for (uint32_t x = 0; x < m_data.width; ++x)
2487 {
2488 const float retrievedValue = float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2489
2490 if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2491 failures++;
2492
2493 ++pos;
2494 }
2495
2496 if (failures != 0)
2497 {
2498 const char *names[] = {"Retrieved", "Expected "};
2499 std::stringstream css;
2500
2501 for (uint32_t y = 0; y < m_data.height; ++y)
2502 {
2503 for (uint32_t x = 0; x < m_data.width; ++x)
2504 {
2505 for (uint32_t n = 0; n < 2; ++n)
2506 {
2507 css << names[n] << " at (" << x << "," << y << ") {";
2508
2509 for (uint32_t z = 0; z < depth; ++z)
2510 {
2511 pos = x + m_data.width * (y + m_data.height * z);
2512
2513 const float retrievedValue = float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2514 const float expectedValue = expectedValues[pos];
2515
2516 if (deFloatAbs(retrievedValue - expectedValue) > eps)
2517 css << std::setprecision(8) << std::setw(12) << (n == 0 ? retrievedValue : expectedValue)
2518 << ",";
2519 else
2520 css << "____________,";
2521 }
2522
2523 css << "}" << std::endl;
2524 }
2525 }
2526 }
2527
2528 log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2529 }
2530
2531 return failures == 0;
2532 }
2533
validateMatrixBuffer(de::MovePtr<BufferWithMemory> buffer)2534 bool RayTracingBuiltinLaunchTestInstance::validateMatrixBuffer(de::MovePtr<BufferWithMemory> buffer)
2535 {
2536 const float eps = float(FIXED_POINT_ALLOWED_ERROR) / float(FIXED_POINT_DIVISOR);
2537 const int32_t *bufferPtr = (int32_t *)buffer->getAllocation().getHostPtr();
2538 const vector<float> expectedValues = expectedMatrixValuesBuffer();
2539 const uint32_t depth = 12u; // mat3x4 or mat4x3
2540 tcu::TestLog &log = m_context.getTestContext().getLog();
2541 uint32_t failures = 0;
2542 uint32_t pos = 0;
2543
2544 DE_ASSERT(depth <= m_data.depth);
2545
2546 for (uint32_t z = 0; z < depth; ++z)
2547 for (uint32_t y = 0; y < m_data.height; ++y)
2548 for (uint32_t x = 0; x < m_data.width; ++x)
2549 {
2550 const float retrievedValue = float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2551
2552 if (deFloatAbs(retrievedValue - expectedValues[pos]) > eps)
2553 failures++;
2554
2555 ++pos;
2556 }
2557
2558 if (failures != 0)
2559 {
2560 const char *names[] = {"Retrieved", "Expected"};
2561 std::stringstream css;
2562
2563 for (uint32_t y = 0; y < m_data.height; ++y)
2564 {
2565 for (uint32_t x = 0; x < m_data.width; ++x)
2566 {
2567 css << "At (" << x << "," << y << ")" << std::endl;
2568 for (uint32_t n = 0; n < 2; ++n)
2569 {
2570 css << names[n] << std::endl << "{" << std::endl;
2571
2572 for (uint32_t z = 0; z < depth; ++z)
2573 {
2574 pos = x + m_data.width * (y + m_data.height * z);
2575
2576 const float retrievedValue = float(bufferPtr[pos]) / float(FIXED_POINT_DIVISOR);
2577 const float expectedValue = expectedValues[pos];
2578
2579 if (z % 4 == 0)
2580 css << " {";
2581
2582 if (deFloatAbs(retrievedValue - expectedValue) > eps)
2583 css << std::setprecision(5) << std::setw(9) << (n == 0 ? retrievedValue : expectedValue)
2584 << ",";
2585 else
2586 css << "_________,";
2587
2588 if (z % 4 == 3)
2589 css << "}" << std::endl;
2590 }
2591
2592 css << "}" << std::endl;
2593 }
2594 }
2595 }
2596
2597 log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2598 }
2599
2600 return failures == 0;
2601 }
2602
iterate(void)2603 tcu::TestStatus RayTracingBuiltinLaunchTestInstance::iterate(void)
2604 {
2605 checkSupportInInstance();
2606
2607 de::MovePtr<BufferWithMemory> buffer = runTest();
2608 const bool ok = m_data.fixedPointMatrixOutput ? validateMatrixBuffer(buffer) :
2609 m_data.fixedPointVectorOutput ? validateVectorBuffer(buffer) :
2610 m_data.fixedPointScalarOutput ? validateFloatBuffer(buffer) :
2611 validateIntBuffer(buffer);
2612
2613 if (ok)
2614 return tcu::TestStatus::pass("pass");
2615 else
2616 return tcu::TestStatus::fail("fail");
2617 }
2618
2619 enum ShaderSourceFlag
2620 {
2621 DEFINE_RAY = 0x1,
2622 DEFINE_RESULT_BUFFER = 0x2,
2623 DEFINE_SCENE = 0x4,
2624 DEFINE_RAY_BUFFER = 0x8,
2625 DEFINE_SIMPLE_BINDINGS = DEFINE_RESULT_BUFFER | DEFINE_SCENE | DEFINE_RAY_BUFFER
2626 };
2627
generateShaderSource(const char * body,const char * resultType="",uint32_t flags=0,const char * prefix="")2628 std::string generateShaderSource(const char *body, const char *resultType = "", uint32_t flags = 0,
2629 const char *prefix = "")
2630 {
2631 std::ostringstream src;
2632 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_460) << "\n";
2633
2634 src << "#extension GL_EXT_ray_tracing : enable\n";
2635
2636 src << prefix << "\n";
2637
2638 if (flags & DEFINE_SIMPLE_BINDINGS)
2639 flags |= DEFINE_RAY_BUFFER;
2640
2641 if (flags & DEFINE_RAY_BUFFER)
2642 flags |= DEFINE_RAY;
2643
2644 if (flags & DEFINE_RAY)
2645 {
2646 src << "struct Ray { vec3 pos; float tmin; vec3 dir; float tmax; };\n";
2647 }
2648
2649 if (flags & DEFINE_RESULT_BUFFER)
2650 src << "layout(std430, set = 0, binding = " << 0 << ") buffer Results { " << resultType << " results[]; };\n";
2651
2652 if (flags & DEFINE_SCENE)
2653 {
2654 src << "layout(set = 0, binding = " << 1 << ") uniform accelerationStructureEXT scene;\n";
2655 }
2656
2657 if (flags & DEFINE_RAY_BUFFER)
2658 src << "layout(std430, set = 0, binding = " << 2 << ") buffer Rays { Ray rays[]; };\n";
2659
2660 src << "uint launchIndex() { return gl_LaunchIDEXT.z*gl_LaunchSizeEXT.x*gl_LaunchSizeEXT.y + "
2661 "gl_LaunchIDEXT.y*gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x; }\n";
2662
2663 src << body;
2664
2665 return src.str();
2666 }
2667
getShaderIdentifier(const CaseDef & params,VkShaderStageFlagBits stage)2668 std::string getShaderIdentifier(const CaseDef ¶ms, VkShaderStageFlagBits stage)
2669 {
2670 std::string testStage;
2671
2672 switch (params.stage)
2673 {
2674 case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2675 testStage = "raygen";
2676 break;
2677 case VK_SHADER_STAGE_MISS_BIT_KHR:
2678 testStage = "-miss";
2679 break;
2680 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2681 testStage = "-closest-hit";
2682 break;
2683 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2684 testStage = "-any_hit";
2685 break;
2686 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2687 testStage = "-closest_hit";
2688 break;
2689 case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2690 testStage = "-callable";
2691 break;
2692 default:
2693 DE_ASSERT(false);
2694 return std::string();
2695 }
2696
2697 switch (stage)
2698 {
2699 case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2700 return testStage + "-rgen";
2701 case VK_SHADER_STAGE_MISS_BIT_KHR:
2702 return testStage + "-miss";
2703 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2704 return testStage + "-closest_hit";
2705 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2706 return testStage + "-any_hit";
2707 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2708 return testStage + "-isect";
2709 case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2710 return testStage + "-callable";
2711 default:
2712 DE_ASSERT(false);
2713 return std::string();
2714 }
2715 }
2716
replaceString(std::string text,const std::string & search,const std::string & replace)2717 std::string replaceString(std::string text, const std::string &search, const std::string &replace)
2718 {
2719 size_t found;
2720
2721 while ((found = text.find(search)) != std::string::npos)
2722 {
2723 text = text.replace(found, search.length(), replace);
2724 }
2725
2726 return text;
2727 }
2728
2729 template <typename T>
addBuiltInShaderSource(SourceCollections & programCollection,VkShaderStageFlagBits stage,const std::string & body,const CaseDef & params,std::string builtInType)2730 inline void addBuiltInShaderSource(SourceCollections &programCollection, VkShaderStageFlagBits stage,
2731 const std::string &body, const CaseDef ¶ms, std::string builtInType)
2732 {
2733 std::string identifier = getShaderIdentifier(params, stage);
2734
2735 uint32_t flags = 0;
2736
2737 if (stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR)
2738 flags |= DEFINE_RAY | DEFINE_SIMPLE_BINDINGS;
2739
2740 std::string text = generateShaderSource(body.c_str(), builtInType.c_str(), flags, "");
2741
2742 text = replaceString(text, "$builtInType$", builtInType);
2743
2744 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
2745 programCollection.glslSources.add(identifier) << T(text) << buildOptions;
2746 }
2747
2748 class RayTracingIndirectTestInstance : public TestInstance
2749 {
2750 public:
2751 RayTracingIndirectTestInstance(Context &context, const CaseDef &data);
2752 ~RayTracingIndirectTestInstance(void);
2753 tcu::TestStatus iterate(void);
2754
2755 private:
2756 void checkSupportInInstance(void) const;
2757 Move<VkPipeline> createPipelineAndShaderBindingTables(de::MovePtr<RayTracingPipeline> &rayTracingPipeline,
2758 bool aabb, VkPipelineLayout pipelineLayout);
2759
2760 void createPipelineLayoutAndSet(uint32_t setCount, vk::Move<VkDescriptorPool> &descriptorPool,
2761 vk::Move<VkDescriptorSetLayout> &descriptorSetLayout,
2762 std::vector<vk::Move<VkDescriptorSet>> &descriptorSets,
2763 vk::Move<VkPipelineLayout> &pipelineLayout);
2764
2765 de::SharedPtr<TopLevelAccelerationStructure> initTopAccelerationStructure(
2766 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &bottomLevelAccelerationStructures);
2767 vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures(void);
2768 void initializeParameters(void);
2769 bool verifyResults(void);
2770
2771 private:
2772 CaseDef m_data;
2773 std::vector<std::vector<tcu::Vec3>> m_geomData;
2774 de::MovePtr<BufferWithMemory> m_resultBuffer;
2775 de::MovePtr<BufferWithMemory> m_rayBuffer;
2776 uint32_t m_numGeoms;
2777 uint32_t m_primsPerGeometry;
2778 uint32_t m_geomsPerInstance;
2779
2780 de::MovePtr<BufferWithMemory> m_raygenShaderBindingTable;
2781 de::MovePtr<BufferWithMemory> m_missShaderBindingTable;
2782 de::MovePtr<BufferWithMemory> m_hitShaderBindingTable;
2783
2784 VkStridedDeviceAddressRegionKHR m_raygenShaderBindingTableRegion;
2785 VkStridedDeviceAddressRegionKHR m_missShaderBindingTableRegion;
2786 VkStridedDeviceAddressRegionKHR m_hitShaderBindingTableRegion;
2787 VkStridedDeviceAddressRegionKHR m_callableShaderBindingTableRegion;
2788 };
2789
RayTracingIndirectTestInstance(Context & context,const CaseDef & data)2790 RayTracingIndirectTestInstance::RayTracingIndirectTestInstance(Context &context, const CaseDef &data)
2791 : vkt::TestInstance(context)
2792 , m_data(data)
2793 , m_numGeoms(0)
2794 , m_primsPerGeometry(0)
2795 , m_geomsPerInstance(0)
2796 {
2797 }
2798
~RayTracingIndirectTestInstance(void)2799 RayTracingIndirectTestInstance::~RayTracingIndirectTestInstance(void)
2800 {
2801 }
2802
2803 class RayTracingIndirectTestCase : public TestCase
2804 {
2805 public:
2806 RayTracingIndirectTestCase(tcu::TestContext &context, const char *name, const CaseDef data);
2807 ~RayTracingIndirectTestCase(void);
2808
2809 virtual void initPrograms(SourceCollections &programCollection) const;
2810 virtual TestInstance *createInstance(Context &context) const;
2811 virtual void checkSupport(Context &context) const;
2812
2813 private:
2814 static inline const std::string getIntersectionPassthrough(void);
2815 static inline const std::string getMissPassthrough(void);
2816 static inline const std::string getHitPassthrough(void);
2817
2818 CaseDef m_data;
2819 };
2820
RayTracingIndirectTestCase(tcu::TestContext & context,const char * name,const CaseDef data)2821 RayTracingIndirectTestCase::RayTracingIndirectTestCase(tcu::TestContext &context, const char *name, const CaseDef data)
2822 : vkt::TestCase(context, name)
2823 , m_data(data)
2824 {
2825 }
2826
~RayTracingIndirectTestCase(void)2827 RayTracingIndirectTestCase::~RayTracingIndirectTestCase(void)
2828 {
2829 }
2830
checkSupport(Context & context) const2831 void RayTracingIndirectTestCase::checkSupport(Context &context) const
2832 {
2833 const bool pipelineFlagSkipTriangles =
2834 ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0);
2835 const bool pipelineFlagSkipAABSs =
2836 ((m_data.pipelineCreateFlags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0);
2837 const bool cullingFlags =
2838 m_data.rayFlagSkipTriangles || m_data.rayFlagSkipAABSs || pipelineFlagSkipTriangles || pipelineFlagSkipAABSs;
2839
2840 context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
2841 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
2842
2843 const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
2844 context.getRayTracingPipelineFeatures();
2845 if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
2846 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
2847
2848 const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
2849 context.getAccelerationStructureFeatures();
2850 if (accelerationStructureFeaturesKHR.accelerationStructure == false)
2851 TCU_THROW(TestError, "VK_KHR_ray_tracing_pipeline requires "
2852 "VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
2853
2854 if (cullingFlags && rayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling == false)
2855 TCU_THROW(NotSupportedError,
2856 "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTraversalPrimitiveCulling");
2857 }
2858
initPrograms(SourceCollections & programCollection) const2859 void RayTracingIndirectTestCase::initPrograms(SourceCollections &programCollection) const
2860 {
2861 if (m_data.id == TEST_ID_INDICES_INDIRECT)
2862 {
2863 std::ostringstream raygenSrc;
2864 raygenSrc << "struct Payload { uvec4 data; };\n"
2865 << "layout(location = 0) rayPayloadEXT Payload payload;\n"
2866 << "void main() {\n"
2867 << " uint index = launchIndex();\n"
2868 << " payload.data = uvec4(0, 0, 0, 0);\n"
2869 << " Ray ray = rays[index];\n"
2870 << " traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
2871 << " results[index] = payload.data;\n"
2872 << "}";
2873 const std::string raygen = raygenSrc.str();
2874 addBuiltInShaderSource<glu::RaygenSource>(programCollection, VK_SHADER_STAGE_RAYGEN_BIT_KHR, raygen, m_data,
2875 "uvec4");
2876
2877 std::ostringstream missSrc;
2878 missSrc << "struct Payload { uvec4 data; };\n"
2879 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2880 << "void main() {\n"
2881 << " payload.data = uvec4(111, 222, 333, 444);\n"
2882 << "}";
2883 const std::string miss = missSrc.str();
2884 addBuiltInShaderSource<glu::MissSource>(programCollection, VK_SHADER_STAGE_MISS_BIT_KHR, miss, m_data, "uvec4");
2885
2886 std::ostringstream closestHitSrc;
2887 closestHitSrc << "struct Payload { uvec4 data; };\n"
2888 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2889 << "hitAttributeEXT vec2 attribs;\n"
2890 << "void main() {\n"
2891 << " payload.data = uvec4(gl_PrimitiveID, 0, gl_InstanceID, gl_InstanceCustomIndexEXT);\n"
2892 << "}";
2893 const std::string closestHit = closestHitSrc.str();
2894 addBuiltInShaderSource<glu::ClosestHitSource>(programCollection, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
2895 closestHit, m_data, "uvec4");
2896
2897 std::ostringstream anyHitSrc;
2898 anyHitSrc << "struct Payload { uvec4 data; };\n"
2899 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2900 << "hitAttributeEXT vec2 attribs;\n"
2901 << "void main() {\n"
2902 << " payload.data = uvec4(gl_PrimitiveID, 0, gl_InstanceID, gl_InstanceCustomIndexEXT);\n"
2903 << "}";
2904 const std::string anyHit = anyHitSrc.str();
2905 addBuiltInShaderSource<glu::AnyHitSource>(programCollection, VK_SHADER_STAGE_ANY_HIT_BIT_KHR, anyHit, m_data,
2906 "uvec4");
2907
2908 std::ostringstream isectSrc;
2909 isectSrc << "hitAttributeEXT vec2 dummy;\n"
2910 << "void main() {\n"
2911 << " reportIntersectionEXT(0.0, 0u);\n"
2912 << "}";
2913 const std::string isect = isectSrc.str();
2914 addBuiltInShaderSource<glu::IntersectionSource>(programCollection, VK_SHADER_STAGE_INTERSECTION_BIT_KHR, isect,
2915 m_data, "uvec4");
2916 }
2917 else if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
2918 {
2919 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
2920
2921 std::ostringstream preambleSrc;
2922 preambleSrc << "struct ResultData { Ray ray; vec4 worldRayOrig; vec4 worldRayDir; vec4 objectRayOrig; vec4 "
2923 "objectRayDir;\n"
2924 << "vec4 objectToWorld[4]; vec4 worldToObject[4];\n"
2925 << "uint missResult; uint closestHitResult; uint anyHitResult; uint isectResult; };\n"
2926 << "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
2927 << "\n"
2928 << "#ifdef CHECKS\n"
2929 << "bool fuzzy_check(vec3 a, vec3 b) {\n"
2930 << " float eps = 0.00001;\n"
2931 << " return abs(a.x - b.x) <= eps && abs(a.y - b.y) <= eps && abs(a.z - b.z) <= eps;\n"
2932 << "}\n"
2933 << "bool check_all() {\n"
2934 << " if (fuzzy_check(results.worldRayOrig.xyz, gl_WorldRayOriginEXT) == false)\n"
2935 << " return false;\n"
2936 << " if (fuzzy_check(results.worldRayDir.xyz, gl_WorldRayDirectionEXT) == false)\n"
2937 << " return false;\n"
2938 << "#ifndef MISS_SHADER\n"
2939 << " if (fuzzy_check(results.objectRayOrig.xyz, gl_ObjectRayOriginEXT) == false)\n"
2940 << " return false;\n"
2941 << " if (fuzzy_check(results.objectRayDir.xyz, gl_WorldRayDirectionEXT) == false)\n"
2942 << " return false;\n"
2943 << " if (fuzzy_check(results.objectToWorld[0].xyz, gl_ObjectToWorldEXT[0]) == false)\n"
2944 << " return false;\n"
2945 << " if (fuzzy_check(results.objectToWorld[1].xyz, gl_ObjectToWorldEXT[1]) == false)\n"
2946 << " return false;\n"
2947 << " if (fuzzy_check(results.objectToWorld[2].xyz, gl_ObjectToWorldEXT[2]) == false)\n"
2948 << " return false;\n"
2949 << " if (fuzzy_check(results.objectToWorld[3].xyz, gl_ObjectToWorldEXT[3]) == false)\n"
2950 << " return false;\n"
2951 << " if (fuzzy_check(results.worldToObject[0].xyz, gl_WorldToObjectEXT[0]) == false)\n"
2952 << " return false;\n"
2953 << " if (fuzzy_check(results.worldToObject[1].xyz, gl_WorldToObjectEXT[1]) == false)\n"
2954 << " return false;\n"
2955 << " if (fuzzy_check(results.worldToObject[2].xyz, gl_WorldToObjectEXT[2]) == false)\n"
2956 << " return false;\n"
2957 << " if (fuzzy_check(results.worldToObject[3].xyz, gl_WorldToObjectEXT[3]) == false)\n"
2958 << " return false;\n"
2959 << "#endif\n"
2960 << " return true;\n"
2961 << "};\n"
2962 << "#endif\n";
2963 const std::string preamble = preambleSrc.str();
2964
2965 std::ostringstream raygenSrc;
2966 raygenSrc << "$preamble$\n"
2967 << "struct Payload { uint x; };\n"
2968 << "layout(location = 0) rayPayloadEXT Payload payload;\n"
2969 << "void main() {\n"
2970 << " payload.x = 0;\n"
2971 << " results.missResult = 0;\n"
2972 << " results.closestHitResult = 0;\n"
2973 << " results.anyHitResult = 0;\n"
2974 << " results.isectResult = 0;\n"
2975 << " Ray ray = results.ray;\n"
2976 << " traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
2977 << "}";
2978 std::string raygen = raygenSrc.str();
2979 raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
2980 raygen = replaceString(raygen, "$preamble$", preamble);
2981 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR))
2982 << glu::RaygenSource(raygen) << buildOptions;
2983
2984 std::ostringstream missSrc;
2985 missSrc << "#define CHECKS\n"
2986 << "#define MISS_SHADER\n"
2987 << "$preamble$\n"
2988 << "struct Payload { uint x; };\n"
2989 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
2990 << "void main() {\n"
2991 << " if (check_all())\n"
2992 << " results.missResult = 1;\n"
2993 << "}";
2994 std::string miss = missSrc.str();
2995 miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
2996 miss = replaceString(miss, "$preamble$", preamble);
2997 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR))
2998 << glu::MissSource(miss) << buildOptions;
2999
3000 std::ostringstream closestHitSrc;
3001 closestHitSrc << "#define CHECKS\n"
3002 << "$preamble$\n"
3003 << "struct Payload { uint x; };\n"
3004 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3005 << "hitAttributeEXT vec2 attribs; "
3006 << "void main() {\n"
3007 << " if (check_all())\n"
3008 << " results.closestHitResult = 1;\n"
3009 << "}";
3010 std::string closestHit = closestHitSrc.str();
3011 closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
3012 closestHit = replaceString(closestHit, "$preamble$", preamble);
3013 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))
3014 << glu::ClosestHitSource(closestHit) << buildOptions;
3015
3016 std::ostringstream anyHitSrc;
3017 anyHitSrc << "#define CHECKS\n"
3018 << "$preamble$\n"
3019 << "struct Payload { uint x; };\n"
3020 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3021 << "hitAttributeEXT vec2 attribs; "
3022 << "void main() {\n"
3023 << " if (check_all())\n"
3024 << " results.anyHitResult = 1;\n"
3025 << "}";
3026 std::string anyHit = anyHitSrc.str();
3027 anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
3028 anyHit = replaceString(anyHit, "$preamble$", preamble);
3029 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR))
3030 << glu::AnyHitSource(anyHit) << buildOptions;
3031
3032 std::ostringstream isectSrc;
3033 isectSrc << "#define CHECKS\n"
3034 << "$preamble$\n"
3035 << "hitAttributeEXT vec2 dummy;\n"
3036 << "void main() {\n"
3037 << " if (check_all())\n"
3038 << " results.isectResult = 1;\n"
3039 << " reportIntersectionEXT(0.0, 0u);\n"
3040 << "}";
3041 std::string isect = isectSrc.str();
3042 isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3043 isect = replaceString(isect, "$preamble$", preamble);
3044 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR))
3045 << glu::IntersectionSource(isect) << buildOptions;
3046 }
3047 else if (m_data.id == TEST_ID_TMINMAX_INDIRECT)
3048 {
3049 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
3050
3051 std::ostringstream preambleSrc;
3052 preambleSrc
3053 << "struct ResultData { Ray ray; float miss_maxt; float chit_maxt; float ahit_maxt; float isect_maxt;\n"
3054 << "uint missResult; uint closestHitResult; uint anyHitResult; uint isectResult; float debug; };\n"
3055 << "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
3056 << "\n"
3057 << "#ifdef CHECKS\n"
3058 << "bool fuzzy_check(float a, float b) {\n"
3059 << " float eps = 0.0001;\n"
3060 << " return abs(a - b) <= eps;\n"
3061 << "}\n"
3062 << "bool check_all() {\n"
3063 << " if (fuzzy_check(results.ray.tmin, gl_RayTminEXT) == false)\n"
3064 << " return false;\n"
3065 << "#ifdef MISS_SHADER\n"
3066 << " if (fuzzy_check(results.miss_maxt, gl_RayTmaxEXT) == false)\n"
3067 << " return false;\n"
3068 << "#endif\n"
3069 << "#ifdef CHIT_SHADER\n"
3070 << " if (fuzzy_check(results.chit_maxt, gl_RayTmaxEXT) == false)\n"
3071 << " return false;\n"
3072 << "#endif\n"
3073 << "#ifdef AHIT_SHADER\n"
3074 << " if (fuzzy_check(results.ahit_maxt, gl_RayTmaxEXT) == false)\n"
3075 << " return false;\n"
3076 << "#endif\n"
3077 << "#ifdef ISECT_SHADER\n"
3078 << " if (fuzzy_check(results.isect_maxt, gl_RayTmaxEXT) == false)\n"
3079 << " return false;\n"
3080 << "#endif\n"
3081 << " return true;\n"
3082 << "};\n"
3083 << "#endif\n";
3084 const std::string preamble = preambleSrc.str();
3085
3086 std::ostringstream raygenSrc;
3087 raygenSrc << "$preamble$\n"
3088 << "struct Payload { uint x; };\n"
3089 << "layout(location = 0) rayPayloadEXT Payload payload;\n"
3090 << "void main() {\n"
3091 << " payload.x = 0;\n"
3092 << " results.missResult = 0;\n"
3093 << " results.closestHitResult = 0;\n"
3094 << " results.anyHitResult = 0;\n"
3095 << " results.isectResult = 0;\n"
3096 << " Ray ray = results.ray;\n"
3097 << " traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
3098 << "}";
3099 std::string raygen = raygenSrc.str();
3100 raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
3101 raygen = replaceString(raygen, "$preamble$", preamble);
3102 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR))
3103 << glu::RaygenSource(raygen) << buildOptions;
3104
3105 std::ostringstream missSrc;
3106 missSrc << "#define CHECKS\n"
3107 << "#define MISS_SHADER\n"
3108 << "$preamble$\n"
3109 << "struct Payload { uint x; };\n"
3110 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3111 << "void main() {\n"
3112 << " if (check_all())\n"
3113 << " results.missResult = 1;\n"
3114 << "}";
3115 std::string miss = missSrc.str();
3116 miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
3117 miss = replaceString(miss, "$preamble$", preamble);
3118 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR))
3119 << glu::MissSource(miss) << buildOptions;
3120
3121 std::ostringstream cloesetHitSrc;
3122 cloesetHitSrc << "#define CHECKS\n"
3123 << "#define CHIT_SHADER\n"
3124 << "$preamble$\n"
3125 << "struct Payload { uint x; };\n"
3126 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3127 << "hitAttributeEXT vec2 attribs; "
3128 << "void main() {\n"
3129 << " if (check_all())\n"
3130 << " results.closestHitResult = 1;\n"
3131 << "}";
3132 std::string closestHit = cloesetHitSrc.str();
3133 closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
3134 closestHit = replaceString(closestHit, "$preamble$", preamble);
3135 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))
3136 << glu::ClosestHitSource(closestHit) << buildOptions;
3137
3138 std::ostringstream anyHitSrc;
3139 anyHitSrc << "#define CHECKS\n"
3140 << "#define AHIT_SHADER\n"
3141 << "$preamble$\n"
3142 << "struct Payload { uint x; };\n"
3143 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3144 << "hitAttributeEXT vec2 attribs; "
3145 << "void main() {\n"
3146 << " if (check_all())\n"
3147 << " results.anyHitResult = 1;\n"
3148 << "}";
3149 std::string anyHit = anyHitSrc.str();
3150 anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
3151 anyHit = replaceString(anyHit, "$preamble$", preamble);
3152 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR))
3153 << glu::AnyHitSource(anyHit) << buildOptions;
3154
3155 std::ostringstream isectSrc;
3156 isectSrc << "#define CHECKS\n"
3157 << "#define ISECT_SHADER\n"
3158 << "$preamble$\n"
3159 << "hitAttributeEXT vec2 dummy;\n"
3160 << "void main() {\n"
3161 << " results.debug = gl_RayTmaxEXT;\n"
3162 << " if (check_all())\n"
3163 << " results.isectResult = 1;\n"
3164 << " reportIntersectionEXT(results.chit_maxt, 0u);\n"
3165 << "}";
3166 std::string isect = isectSrc.str();
3167 isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3168 isect = replaceString(isect, "$preamble$", preamble);
3169 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR))
3170 << glu::IntersectionSource(isect) << buildOptions;
3171 }
3172 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT)
3173 {
3174 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
3175
3176 std::ostringstream preambleSrc;
3177 preambleSrc << "struct ResultData { Ray ray[2]; uint flags; uint miss[2]; uint chit[2]; uint ahit[2]; uint "
3178 "isect[2]; };\n"
3179 << "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
3180 << "\n"
3181 << "#ifdef CHECKS\n"
3182 << "bool check_all() {\n"
3183 << " if (gl_IncomingRayFlagsEXT != results.flags)\n"
3184 << " return false;\n"
3185 << " return true;\n"
3186 << "}\n"
3187 << "#endif\n";
3188 const std::string preamble = preambleSrc.str();
3189
3190 std::ostringstream raygenSrc;
3191 raygenSrc << "$preamble$\n"
3192 << "struct Payload { uint x; };\n"
3193 << "layout(location = 0) rayPayloadEXT Payload payload;\n"
3194 << "void main() {\n"
3195 << " payload.x = 0;\n"
3196 << " results.miss[gl_LaunchIDEXT.x] = 0;\n"
3197 << " results.chit[gl_LaunchIDEXT.x] = 0;\n"
3198 << " results.ahit[gl_LaunchIDEXT.x] = 0;\n"
3199 << " results.isect[gl_LaunchIDEXT.x] = 0;\n"
3200 << " Ray ray = results.ray[gl_LaunchIDEXT.x];\n"
3201 << " traceRayEXT(scene, results.flags, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
3202 << "}";
3203 std::string raygen = raygenSrc.str();
3204 raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
3205 raygen = replaceString(raygen, "$preamble$", preamble);
3206 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR))
3207 << glu::RaygenSource(raygen) << buildOptions;
3208
3209 std::ostringstream missSrc;
3210 missSrc << "#define CHECKS\n"
3211 << "#define MISS_SHADER\n"
3212 << "$preamble$\n"
3213 << "struct Payload { uint x; };\n"
3214 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3215 << "void main() {\n"
3216 << " if (check_all())\n"
3217 << " results.miss[gl_LaunchIDEXT.x]++;\n"
3218 << "}";
3219 std::string miss = missSrc.str();
3220 miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
3221 miss = replaceString(miss, "$preamble$", preamble);
3222 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR))
3223 << glu::MissSource(miss) << buildOptions;
3224
3225 std::ostringstream closestHitSrc;
3226 closestHitSrc << "#define CHECKS\n"
3227 << "#define CHIT_SHADER\n"
3228 << "$preamble$\n"
3229 << "struct Payload { uint x; };\n"
3230 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3231 << "hitAttributeEXT vec2 attribs; "
3232 << "void main() {\n"
3233 << " if (check_all())\n"
3234 << " results.chit[gl_LaunchIDEXT.x]++;\n"
3235 << "}";
3236 std::string closestHit = closestHitSrc.str();
3237 closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
3238 closestHit = replaceString(closestHit, "$preamble$", preamble);
3239 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))
3240 << glu::ClosestHitSource(closestHit) << buildOptions;
3241
3242 std::ostringstream anyHitSrc;
3243 anyHitSrc << "#define CHECKS\n"
3244 << "#define AHIT_SHADER\n"
3245 << "$preamble$\n"
3246 << "struct Payload { uint x; };\n"
3247 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3248 << "hitAttributeEXT vec2 attribs; "
3249 << "void main() {\n"
3250 << " if (check_all())\n"
3251 << " results.ahit[gl_LaunchIDEXT.x]++;\n"
3252 << "}";
3253 std::string anyHit = anyHitSrc.str();
3254 anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
3255 anyHit = replaceString(anyHit, "$preamble$", preamble);
3256 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR))
3257 << glu::AnyHitSource(anyHit) << buildOptions;
3258
3259 std::ostringstream isectSrc;
3260 isectSrc << "#define CHECKS\n"
3261 << "#define ISECT_SHADER\n"
3262 << "$preamble$\n"
3263 << "hitAttributeEXT vec2 dummy;\n"
3264 << "void main() {\n"
3265 << " if (check_all())\n"
3266 << " results.isect[gl_LaunchIDEXT.x]++;\n"
3267 << " reportIntersectionEXT(gl_RayTminEXT, 0u);\n"
3268 << "}";
3269 std::string isect = isectSrc.str();
3270 isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3271 isect = replaceString(isect, "$preamble$", preamble);
3272 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR))
3273 << glu::IntersectionSource(isect) << buildOptions;
3274 }
3275 else if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3276 {
3277 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
3278
3279 std::ostringstream preambleSrc;
3280 preambleSrc << "struct ResultData { Ray ray[2]; uint kind[2]; uint chit[2]; uint ahit[2]; uint debug[2]; };\n"
3281 << "layout(std430, set = 0, binding = 0) buffer Results { ResultData results; };\n"
3282 << "\n"
3283 << "#ifdef CHECKS\n"
3284 << "bool check_all() {\n"
3285 << "#if defined(CHIT_SHADER) || defined(AHIT_SHADER)\n"
3286 << " if (gl_HitKindEXT != results.kind[gl_LaunchIDEXT.x])\n"
3287 << " return false;\n"
3288 << "#endif\n"
3289 << " return true;\n"
3290 << "}\n"
3291 << "#endif\n";
3292 const std::string preamble = preambleSrc.str();
3293
3294 std::ostringstream raygenSrc;
3295 raygenSrc << "$preamble$\n"
3296 << "struct Payload { uint x; };\n"
3297 << "layout(location = 0) rayPayloadEXT Payload payload;\n"
3298 << "void main() {\n"
3299 << " payload.x = 0;\n"
3300 << " uint i = gl_LaunchIDEXT.x;\n"
3301 << " results.chit[i] = 0;\n"
3302 << " results.ahit[i] = 0;\n"
3303 << " Ray ray = results.ray[i];\n"
3304 << " traceRayEXT(scene, 0, 0xff, 0, 0, 0, ray.pos, ray.tmin, ray.dir, ray.tmax, 0);\n"
3305 << "}";
3306 std::string raygen = raygenSrc.str();
3307 raygen = generateShaderSource(raygen.c_str(), "", DEFINE_RAY | DEFINE_SCENE);
3308 raygen = replaceString(raygen, "$preamble$", preamble);
3309 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR))
3310 << glu::RaygenSource(raygen) << buildOptions;
3311
3312 std::ostringstream missSrc;
3313 missSrc << "#define CHECKS\n"
3314 << "#define MISS_SHADER\n"
3315 << "$preamble$\n"
3316 << "struct Payload { uint x; };\n"
3317 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3318 << "void main() {\n"
3319 << "}";
3320 std::string miss = missSrc.str();
3321 miss = generateShaderSource(miss.c_str(), "", DEFINE_RAY);
3322 miss = replaceString(miss, "$preamble$", preamble);
3323 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR))
3324 << glu::MissSource(miss) << buildOptions;
3325
3326 std::ostringstream closestHitSrc;
3327 closestHitSrc << "#define CHECKS\n"
3328 << "#define CHIT_SHADER\n"
3329 << "$preamble$\n"
3330 << "struct Payload { uint x; };\n"
3331 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3332 << "hitAttributeEXT vec2 attribs; "
3333 << "void main() {\n"
3334 << " results.debug[gl_LaunchIDEXT.x] = gl_HitKindEXT;\n"
3335 << " if (check_all())\n"
3336 << " results.chit[gl_LaunchIDEXT.x] = 1;\n"
3337 << "}";
3338 std::string closestHit = closestHitSrc.str();
3339 closestHit = generateShaderSource(closestHit.c_str(), "", DEFINE_RAY);
3340 closestHit = replaceString(closestHit, "$preamble$", preamble);
3341 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR))
3342 << glu::ClosestHitSource(closestHit) << buildOptions;
3343
3344 std::ostringstream anyHitSrc;
3345 anyHitSrc << "#define CHECKS\n"
3346 << "#define AHIT_SHADER\n"
3347 << "$preamble$\n"
3348 << "struct Payload { uint x; };\n"
3349 << "layout(location = 0) rayPayloadInEXT Payload payload;\n"
3350 << "hitAttributeEXT vec2 attribs; "
3351 << "void main() {\n"
3352 << " if (check_all())\n"
3353 << " results.ahit[gl_LaunchIDEXT.x] = 1;\n"
3354 << "}";
3355 std::string anyHit = anyHitSrc.str();
3356 anyHit = generateShaderSource(anyHit.c_str(), "", DEFINE_RAY);
3357 anyHit = replaceString(anyHit, "$preamble$", preamble);
3358 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR))
3359 << glu::AnyHitSource(anyHit) << buildOptions;
3360
3361 std::ostringstream isectSrc;
3362 isectSrc << "#define CHECKS\n"
3363 << "#define ISECT_SHADER\n"
3364 << "$preamble$\n"
3365 << "hitAttributeEXT vec2 dummy;\n"
3366 << "void main() {\n"
3367 << " reportIntersectionEXT(gl_RayTminEXT, results.kind[gl_LaunchIDEXT.x]);\n"
3368 << "}";
3369 std::string isect = isectSrc.str();
3370 isect = generateShaderSource(isect.c_str(), "", DEFINE_RAY);
3371 isect = replaceString(isect, "$preamble$", preamble);
3372 programCollection.glslSources.add(getShaderIdentifier(m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR))
3373 << glu::IntersectionSource(isect) << buildOptions;
3374 }
3375 }
3376
createInstance(Context & context) const3377 TestInstance *RayTracingIndirectTestCase::createInstance(Context &context) const
3378 {
3379 return new RayTracingIndirectTestInstance(context, m_data);
3380 }
3381
createPipelineAndShaderBindingTables(de::MovePtr<RayTracingPipeline> & rayTracingPipeline,bool aabb,VkPipelineLayout pipelineLayout)3382 Move<VkPipeline> RayTracingIndirectTestInstance::createPipelineAndShaderBindingTables(
3383 de::MovePtr<RayTracingPipeline> &rayTracingPipeline, bool aabb, VkPipelineLayout pipelineLayout)
3384 {
3385 const InstanceInterface &vki = m_context.getInstanceInterface();
3386 const DeviceInterface &vk = m_context.getDeviceInterface();
3387 const VkDevice device = m_context.getDevice();
3388 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3389 Allocator &allocator = m_context.getDefaultAllocator();
3390
3391 const uint32_t shaderGroupHandleSize = getShaderGroupSize(vki, physicalDevice);
3392 const uint32_t shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
3393
3394 rayTracingPipeline->addShader(
3395 VK_SHADER_STAGE_RAYGEN_BIT_KHR,
3396 createShaderModule(
3397 vk, device,
3398 m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_RAYGEN_BIT_KHR)), 0),
3399 0);
3400 rayTracingPipeline->addShader(
3401 VK_SHADER_STAGE_MISS_BIT_KHR,
3402 createShaderModule(
3403 vk, device, m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_MISS_BIT_KHR)),
3404 0),
3405 1);
3406 for (uint32_t g = 0; g < m_numGeoms; ++g)
3407 {
3408 rayTracingPipeline->addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
3409 createShaderModule(vk, device,
3410 m_context.getBinaryCollection().get(getShaderIdentifier(
3411 m_data, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)),
3412 0),
3413 2 + g);
3414 rayTracingPipeline->addShader(
3415 VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
3416 createShaderModule(
3417 vk, device,
3418 m_context.getBinaryCollection().get(getShaderIdentifier(m_data, VK_SHADER_STAGE_ANY_HIT_BIT_KHR)), 0),
3419 2 + g);
3420
3421 if (aabb)
3422 {
3423 rayTracingPipeline->addShader(VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
3424 createShaderModule(vk, device,
3425 m_context.getBinaryCollection().get(getShaderIdentifier(
3426 m_data, VK_SHADER_STAGE_INTERSECTION_BIT_KHR)),
3427 0),
3428 2 + g);
3429 }
3430 }
3431 Move<VkPipeline> pipeline = rayTracingPipeline->createPipeline(vk, device, pipelineLayout);
3432
3433 m_raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
3434 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
3435 m_missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
3436 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
3437 m_hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(
3438 vk, device, *pipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, m_numGeoms);
3439
3440 m_raygenShaderBindingTableRegion =
3441 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vk, device, m_raygenShaderBindingTable->get(), 0),
3442 shaderGroupHandleSize, shaderGroupHandleSize);
3443 m_missShaderBindingTableRegion =
3444 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vk, device, m_missShaderBindingTable->get(), 0),
3445 shaderGroupHandleSize, shaderGroupHandleSize);
3446 m_hitShaderBindingTableRegion =
3447 makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vk, device, m_hitShaderBindingTable->get(), 0),
3448 shaderGroupHandleSize, shaderGroupHandleSize);
3449 m_callableShaderBindingTableRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
3450
3451 return pipeline;
3452 }
3453
createPipelineLayoutAndSet(uint32_t setCount,vk::Move<VkDescriptorPool> & descriptorPool,vk::Move<VkDescriptorSetLayout> & descriptorSetLayout,std::vector<vk::Move<VkDescriptorSet>> & descriptorSets,vk::Move<VkPipelineLayout> & pipelineLayout)3454 void RayTracingIndirectTestInstance::createPipelineLayoutAndSet(uint32_t setCount,
3455 vk::Move<VkDescriptorPool> &descriptorPool,
3456 vk::Move<VkDescriptorSetLayout> &descriptorSetLayout,
3457 std::vector<vk::Move<VkDescriptorSet>> &descriptorSets,
3458 vk::Move<VkPipelineLayout> &pipelineLayout)
3459 {
3460 const DeviceInterface &vk = m_context.getDeviceInterface();
3461 const VkDevice device = m_context.getDevice();
3462
3463 vk::DescriptorPoolBuilder descriptorPoolBuilder;
3464
3465 uint32_t storageBufCount = 2 * setCount;
3466
3467 const VkDescriptorType accelType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
3468
3469 descriptorPoolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufCount);
3470 descriptorPoolBuilder.addType(accelType, setCount);
3471
3472 descriptorPool =
3473 descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setCount);
3474
3475 vk::DescriptorSetLayoutBuilder setLayoutBuilder;
3476
3477 setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES);
3478 setLayoutBuilder.addSingleBinding(accelType, ALL_RAY_TRACING_STAGES);
3479 setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ALL_RAY_TRACING_STAGES);
3480
3481 descriptorSetLayout = setLayoutBuilder.build(vk, device);
3482
3483 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
3484 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
3485 DE_NULL, // const void* pNext;
3486 *descriptorPool, // VkDescriptorPool descriptorPool;
3487 1u, // uint32_t setLayoutCount;
3488 &descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
3489 };
3490
3491 for (uint32_t i = 0; i < setCount; ++i)
3492 descriptorSets.push_back(allocateDescriptorSet(vk, device, &descriptorSetAllocateInfo));
3493
3494 const VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
3495 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
3496 DE_NULL, // const void* pNext;
3497 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
3498 1u, // uint32_t setLayoutCount;
3499 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
3500 0u, // uint32_t pushConstantRangeCount;
3501 nullptr, // const VkPushConstantRange* pPushConstantRanges;
3502 };
3503
3504 pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutInfo);
3505 }
3506
initTopAccelerationStructure(std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> & blas)3507 de::SharedPtr<TopLevelAccelerationStructure> RayTracingIndirectTestInstance::initTopAccelerationStructure(
3508 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> &blas)
3509 {
3510 de::SharedPtr<TopLevelAccelerationStructure> tlas =
3511 de::SharedPtr<TopLevelAccelerationStructure>(makeTopLevelAccelerationStructure().release());
3512
3513 VkTransformMatrixKHR transform = identityMatrix3x4;
3514 if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
3515 {
3516 tcu::Vec3 instanceOffset = tcu::Vec3(2.0f, 4.0f, 8.0f);
3517 transform.matrix[0][3] = instanceOffset[0];
3518 transform.matrix[1][3] = instanceOffset[1];
3519 transform.matrix[2][3] = instanceOffset[2];
3520 }
3521
3522 for (size_t i = 0; i < blas.size(); ++i)
3523 {
3524 tlas->addInstance(blas[i], transform, 1000 + static_cast<uint32_t>(i));
3525 }
3526
3527 return tlas;
3528 }
3529
3530 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> RayTracingIndirectTestInstance::
initBottomAccelerationStructures()3531 initBottomAccelerationStructures()
3532 {
3533 const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3534
3535 uint32_t numInstances = m_data.id == TEST_ID_INDICES_INDIRECT ? 5 : 1;
3536
3537 if (m_data.id == TEST_ID_INDICES_INDIRECT || m_data.id == TEST_ID_TRANSFORMS_INDIRECT ||
3538 m_data.id == TEST_ID_TMINMAX_INDIRECT)
3539 {
3540 m_geomsPerInstance = m_data.id == TEST_ID_INDICES_INDIRECT ? 3 : 1;
3541 m_primsPerGeometry = m_data.id == TEST_ID_INDICES_INDIRECT ? 4 : 1;
3542
3543 m_numGeoms = numInstances * m_geomsPerInstance;
3544
3545 for (uint32_t i = 0; i < m_numGeoms; ++i)
3546 {
3547 std::vector<tcu::Vec3> geomPrims;
3548
3549 for (uint32_t j = 0; j < m_primsPerGeometry; ++j)
3550 {
3551 const uint32_t primId = (i * m_primsPerGeometry) + j;
3552 float dx = 10.0f * static_cast<float>(primId);
3553 if (aabb == false)
3554 {
3555 geomPrims.push_back(tcu::Vec3(dx + -1.0f, -1.0f, 1.0f));
3556 geomPrims.push_back(tcu::Vec3(dx + 1.0f, -1.0f, 1.0f));
3557 geomPrims.push_back(tcu::Vec3(dx + 0.0f, 1.0f, 1.0f));
3558 }
3559 else
3560 {
3561 geomPrims.push_back(tcu::Vec3(dx - 1.0f, -1.0f, 1.0f)); // min x/y/z
3562 geomPrims.push_back(tcu::Vec3(dx + 1.0f, 1.0f, 2.0f)); // max x/y/z
3563 }
3564 }
3565 m_geomData.push_back(geomPrims);
3566 }
3567 }
3568 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT || m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3569 {
3570 m_geomsPerInstance = m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT ? 2 : 1;
3571 m_primsPerGeometry = 1;
3572
3573 m_numGeoms = numInstances * m_geomsPerInstance;
3574
3575 for (uint32_t i = 0; i < m_numGeoms; ++i)
3576 {
3577 std::vector<tcu::Vec3> geomPrims;
3578
3579 for (uint32_t j = 0; j < m_primsPerGeometry; ++j)
3580 {
3581 const uint32_t primId = (i * m_primsPerGeometry) + j;
3582 float z = 1.0f + 10.0f * static_cast<float>(primId);
3583
3584 bool ccw = (primId % 2) == 0;
3585
3586 if (aabb == false)
3587 {
3588 if (ccw)
3589 {
3590 geomPrims.push_back(tcu::Vec3(-1.0f, -1.0f, z));
3591 geomPrims.push_back(tcu::Vec3(1.0f, -1.0f, z));
3592 geomPrims.push_back(tcu::Vec3(0.0f, 1.0f, z));
3593 }
3594 else
3595 {
3596 geomPrims.push_back(tcu::Vec3(1.0f, -1.0f, z));
3597 geomPrims.push_back(tcu::Vec3(-1.0f, -1.0f, z));
3598 geomPrims.push_back(tcu::Vec3(0.0f, 1.0f, z));
3599 }
3600 }
3601 else
3602 {
3603 geomPrims.push_back(tcu::Vec3(-1.0f, -1.0f, z)); // min x/y/z
3604 geomPrims.push_back(tcu::Vec3(1.0f, 1.0f, z + 1.0f)); // max x/y/z
3605 }
3606 }
3607 m_geomData.push_back(geomPrims);
3608 }
3609 }
3610
3611 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> blas;
3612
3613 if (!m_geomData.empty())
3614 {
3615 for (uint32_t i = 0; i < numInstances; ++i)
3616 {
3617 de::SharedPtr<BottomLevelAccelerationStructure> accel =
3618 de::SharedPtr<BottomLevelAccelerationStructure>(makeBottomLevelAccelerationStructure().release());
3619 for (uint32_t j = 0; j < m_geomsPerInstance; ++j)
3620 {
3621 accel->addGeometry(m_geomData[(i * m_geomsPerInstance) + j], !aabb, 0U);
3622 }
3623 blas.push_back(accel);
3624 }
3625 }
3626 return blas;
3627 }
3628
3629 struct Ray
3630 {
Rayvkt::RayTracing::__anonbfe5e36a0111::Ray3631 Ray() : o(0.0f), tmin(0.0f), d(0.0f), tmax(0.0f)
3632 {
3633 }
Rayvkt::RayTracing::__anonbfe5e36a0111::Ray3634 Ray(const tcu::Vec3 &io, float imin, const tcu::Vec3 &id, float imax) : o(io), tmin(imin), d(id), tmax(imax)
3635 {
3636 }
3637 tcu::Vec3 o;
3638 float tmin;
3639 tcu::Vec3 d;
3640 float tmax;
3641 };
3642
3643 struct TransformResultData
3644 {
3645
TransformResultDatavkt::RayTracing::__anonbfe5e36a0111::TransformResultData3646 TransformResultData()
3647 : ray()
3648 , worldRayOrig(0.f)
3649 , padding0(0.f)
3650 , worldRayDir(0.f)
3651 , padding1(0.f)
3652 , objectRayOrig(0.f)
3653 , padding2(0.f)
3654 , objectRayDir(0.f)
3655 , padding3(0.f)
3656 , objectToWorld0(0.f)
3657 , padding4(0.f)
3658 , objectToWorld1(0.f)
3659 , padding5(0.f)
3660 , objectToWorld2(0.f)
3661 , padding6(0.f)
3662 , objectToWorld3(0.f)
3663 , padding7(0.f)
3664 , worldToObject0(0.f)
3665 , padding8(0.f)
3666 , worldToObject1(0.f)
3667 , padding9(0.f)
3668 , worldToObject2(0.f)
3669 , padding10(0.f)
3670 , worldToObject3(0.f)
3671 , padding11(0.f)
3672 , missResult(0)
3673 , closestHitResult(0)
3674 , anyHitResult(0)
3675 , isectResult(0)
3676 {
3677 }
3678
3679 Ray ray;
3680 tcu::Vec3 worldRayOrig;
3681 float padding0;
3682 tcu::Vec3 worldRayDir;
3683 float padding1;
3684 tcu::Vec3 objectRayOrig;
3685 float padding2;
3686 tcu::Vec3 objectRayDir;
3687 float padding3;
3688 tcu::Vec3 objectToWorld0;
3689 float padding4;
3690 tcu::Vec3 objectToWorld1;
3691 float padding5;
3692 tcu::Vec3 objectToWorld2;
3693 float padding6;
3694 tcu::Vec3 objectToWorld3;
3695 float padding7;
3696 tcu::Vec3 worldToObject0;
3697 float padding8;
3698 tcu::Vec3 worldToObject1;
3699 float padding9;
3700 tcu::Vec3 worldToObject2;
3701 float padding10;
3702 tcu::Vec3 worldToObject3;
3703 float padding11;
3704 uint32_t missResult;
3705 uint32_t closestHitResult;
3706 uint32_t anyHitResult;
3707 uint32_t isectResult;
3708 };
3709
3710 struct TMinMaxResultData
3711 {
3712 Ray ray;
3713 float miss_maxt;
3714 float chit_maxt;
3715 float ahit_maxt;
3716 float isect_maxt;
3717 uint32_t missResult;
3718 uint32_t closestHitResult;
3719 uint32_t anyHitResult;
3720 uint32_t isectResult;
3721 float debug;
3722 };
3723
3724 struct IncomingFlagsResultData
3725 {
3726 Ray ray[2];
3727 uint32_t flags;
3728 uint32_t miss[2];
3729 uint32_t chit[2];
3730 uint32_t ahit[2];
3731 uint32_t isect[2];
3732 };
3733
3734 struct HitKindResultData
3735 {
3736 Ray ray[2];
3737 uint32_t kind[2];
3738 uint32_t chit[2];
3739 uint32_t ahit[2];
3740 uint32_t debug[2];
3741 };
3742
initializeParameters()3743 void RayTracingIndirectTestInstance::initializeParameters()
3744 {
3745 const VkDevice device = m_context.getDevice();
3746 const DeviceInterface &vk = m_context.getDeviceInterface();
3747 Allocator &allocator = m_context.getDefaultAllocator();
3748
3749 const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3750
3751 if (m_data.id == TEST_ID_INDICES_INDIRECT)
3752 {
3753 std::vector<Ray> rays;
3754 for (uint32_t g = 0; g < m_numGeoms; ++g)
3755 {
3756 for (uint32_t p = 0; p < m_primsPerGeometry; ++p)
3757 {
3758 tcu::Vec3 center =
3759 aabb ? (m_geomData[g][2 * p + 0] + m_geomData[g][2 * p + 1]) * 0.5f :
3760 (m_geomData[g][3 * p + 0] + m_geomData[g][3 * p + 1] + m_geomData[g][3 * p + 2]) *
3761 (1.0f / 3.0f);
3762
3763 Ray r;
3764
3765 r.o = tcu::Vec3(center[0], center[1], 0.0f);
3766 r.d = tcu::Vec3(0.0f, 0.0f, 1.0f);
3767 r.tmin = 0.0f;
3768 r.tmax = 1000.0f;
3769
3770 rays.push_back(r);
3771 }
3772 }
3773 const VkBufferCreateInfo resultBufferCreateInfo =
3774 makeBufferCreateInfo(rays.size() * sizeof(uint32_t) * 8, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3775 m_resultBuffer = de::MovePtr<BufferWithMemory>(
3776 new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3777
3778 const VkBufferCreateInfo rayBufferCreateInfo =
3779 makeBufferCreateInfo(rays.size() * sizeof(Ray), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3780 m_rayBuffer = de::MovePtr<BufferWithMemory>(
3781 new BufferWithMemory(vk, device, allocator, rayBufferCreateInfo, MemoryRequirement::HostVisible));
3782
3783 memcpy(m_rayBuffer->getAllocation().getHostPtr(), &rays[0], rays.size() * sizeof(Ray));
3784 flushMappedMemoryRange(vk, device, m_rayBuffer->getAllocation().getMemory(),
3785 m_rayBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
3786 }
3787 else if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
3788 {
3789 const VkBufferCreateInfo resultBufferCreateInfo =
3790 makeBufferCreateInfo(sizeof(TransformResultData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3791 m_resultBuffer = de::MovePtr<BufferWithMemory>(
3792 new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3793
3794 TransformResultData *resultData = (TransformResultData *)m_resultBuffer->getAllocation().getHostPtr();
3795 *resultData = {};
3796
3797 VkTransformMatrixKHR transform = identityMatrix3x4;
3798 tcu::Vec3 instanceOffset = tcu::Vec3(2.0f, 4.0f, 8.0f);
3799 transform.matrix[0][3] = instanceOffset[0];
3800 transform.matrix[1][3] = instanceOffset[1];
3801 transform.matrix[2][3] = instanceOffset[2];
3802
3803 {
3804 tcu::Vec3 center = aabb ? (m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3805 (m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3806
3807 center = center + instanceOffset;
3808
3809 Ray r;
3810
3811 r.o = tcu::Vec3(center[0], center[1], 0.0f);
3812 r.d = tcu::Vec3(0.0f, 0.0f, 1.0f);
3813 r.tmin = 0.0f;
3814 r.tmax = 1000.0f;
3815
3816 if (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR)
3817 {
3818 r.d[2] = -1.0f;
3819 }
3820
3821 resultData->ray = r;
3822 }
3823
3824 resultData->worldRayOrig = resultData->ray.o;
3825 resultData->worldRayDir = resultData->ray.d;
3826 resultData->objectRayOrig = resultData->worldRayOrig - instanceOffset;
3827 resultData->objectRayDir = resultData->worldRayDir;
3828
3829 resultData->objectToWorld0 = tcu::Vec3(transform.matrix[0][0], transform.matrix[1][0], transform.matrix[2][0]);
3830 resultData->objectToWorld1 = tcu::Vec3(transform.matrix[0][1], transform.matrix[1][1], transform.matrix[2][1]);
3831 resultData->objectToWorld2 = tcu::Vec3(transform.matrix[0][2], transform.matrix[1][2], transform.matrix[2][2]);
3832 resultData->objectToWorld3 = tcu::Vec3(transform.matrix[0][3], transform.matrix[1][3], transform.matrix[2][3]);
3833
3834 resultData->worldToObject0 = tcu::Vec3(transform.matrix[0][0], transform.matrix[0][1], transform.matrix[0][2]);
3835 resultData->worldToObject1 = tcu::Vec3(transform.matrix[1][0], transform.matrix[1][1], transform.matrix[1][2]);
3836 resultData->worldToObject2 = tcu::Vec3(transform.matrix[2][0], transform.matrix[2][1], transform.matrix[2][2]);
3837 resultData->worldToObject3 =
3838 tcu::Vec3(-transform.matrix[0][3], -transform.matrix[1][3], -transform.matrix[2][3]);
3839 }
3840 else if (m_data.id == TEST_ID_TMINMAX_INDIRECT)
3841 {
3842 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(
3843 sizeof(TMinMaxResultData) * m_numGeoms * m_primsPerGeometry, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3844 m_resultBuffer = de::MovePtr<BufferWithMemory>(
3845 new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3846
3847 TMinMaxResultData *resultData = (TMinMaxResultData *)m_resultBuffer->getAllocation().getHostPtr();
3848 *resultData = {};
3849 {
3850 tcu::Vec3 center = aabb ? (m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3851 (m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3852
3853 Ray r;
3854
3855 r.o = tcu::Vec3(center[0], center[1], 0.0f);
3856 r.d = tcu::Vec3(0.0f, 0.0f, 1.0f);
3857 r.tmin = 0.05f;
3858 r.tmax = 1000.0f;
3859
3860 if (m_data.stage == VK_SHADER_STAGE_MISS_BIT_KHR)
3861 {
3862 r.d[2] = -1.0f;
3863 }
3864
3865 resultData->ray = r;
3866 }
3867
3868 resultData->miss_maxt = resultData->ray.tmax;
3869 resultData->isect_maxt = resultData->ray.tmax;
3870 resultData->chit_maxt = aabb ? 1.5f : 1.0f;
3871 resultData->ahit_maxt = aabb ? 1.5f : 1.0f;
3872 resultData->isect_maxt = resultData->ray.tmax;
3873 resultData->debug = -2.0f;
3874 }
3875 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT)
3876 {
3877 const VkBufferCreateInfo resultBufferCreateInfo =
3878 makeBufferCreateInfo(sizeof(IncomingFlagsResultData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3879 m_resultBuffer = de::MovePtr<BufferWithMemory>(
3880 new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3881
3882 IncomingFlagsResultData *resultData = (IncomingFlagsResultData *)m_resultBuffer->getAllocation().getHostPtr();
3883 *resultData = {};
3884
3885 for (uint32_t i = 0; i < 2; ++i)
3886 {
3887 tcu::Vec3 center = aabb ? (m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3888 (m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3889
3890 Ray r;
3891
3892 r.o = tcu::Vec3(center[0], center[1], 0.0f);
3893 r.d = tcu::Vec3(0.0f, 0.0f, (i == 0) ? -1.0f : 1.0f);
3894 r.tmin = 0.05f;
3895 r.tmax = 1000.0f;
3896
3897 resultData->ray[i] = r;
3898 }
3899
3900 if (m_data.opaque)
3901 resultData->flags |= (1 << RAY_FLAG_BIT_OPAQUE_EXT);
3902 if (m_data.skipClosestHit)
3903 resultData->flags |= (1 << RAY_FLAG_BIT_SKIP_CLOSEST_HIT_SHADER_EXT);
3904 }
3905 else if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
3906 {
3907 const VkBufferCreateInfo resultBufferCreateInfo =
3908 makeBufferCreateInfo(sizeof(HitKindResultData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3909 m_resultBuffer = de::MovePtr<BufferWithMemory>(
3910 new BufferWithMemory(vk, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
3911
3912 HitKindResultData *resultData = (HitKindResultData *)m_resultBuffer->getAllocation().getHostPtr();
3913 *resultData = {};
3914
3915 for (uint32_t i = 0; i < 2; ++i)
3916 {
3917 tcu::Vec3 center = aabb ? (m_geomData[0][0] + m_geomData[0][1]) * 0.5f :
3918 (m_geomData[0][0] + m_geomData[0][1] + m_geomData[0][2]) * (1.0f / 3.0f);
3919
3920 Ray r;
3921
3922 r.o = tcu::Vec3(center[0], center[1], 0.0f);
3923 r.d = tcu::Vec3(0.0f, 0.0f, (i == 1) ? -1.0f : 1.0f);
3924
3925 if (i == 1)
3926 r.o += tcu::Vec3(0, 0, 100.0f);
3927
3928 r.tmin = 0.05f;
3929 r.tmax = 1000.0f;
3930
3931 resultData->ray[i] = r;
3932 }
3933
3934 resultData->kind[0] = 255;
3935 resultData->kind[1] = 254;
3936 }
3937 }
3938
verifyResults()3939 bool RayTracingIndirectTestInstance::verifyResults()
3940 {
3941 const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
3942
3943 if (m_data.id == TEST_ID_INDICES_INDIRECT)
3944 {
3945 uint32_t *resultData = (uint32_t *)m_resultBuffer->getAllocation().getHostPtr();
3946 for (uint32_t r = 0; r < m_numGeoms * m_primsPerGeometry; ++r)
3947 {
3948 uint32_t primitiveId = r % m_primsPerGeometry;
3949 uint32_t instanceId = (r / m_primsPerGeometry) / m_geomsPerInstance;
3950 uint32_t instanceCustomIndex = 1000 + instanceId;
3951
3952 if (resultData[4 * r + 0] != primitiveId)
3953 return false;
3954
3955 if (resultData[4 * r + 2] != instanceId)
3956 return false;
3957
3958 if (resultData[4 * r + 3] != instanceCustomIndex)
3959 return false;
3960 }
3961 }
3962 else if (m_data.id == TEST_ID_TRANSFORMS_INDIRECT)
3963 {
3964 TransformResultData *resultData = (TransformResultData *)m_resultBuffer->getAllocation().getHostPtr();
3965 if (resultData->anyHitResult != 1 || resultData->closestHitResult != 1)
3966 {
3967 return false;
3968 }
3969
3970 if (aabb && resultData->isectResult != 1)
3971 {
3972 return false;
3973 }
3974 }
3975 else if (m_data.id == TEST_ID_TMINMAX_INDIRECT)
3976 {
3977 TMinMaxResultData *resultData = (TMinMaxResultData *)m_resultBuffer->getAllocation().getHostPtr();
3978 if (resultData->anyHitResult != 1 || resultData->closestHitResult != 1)
3979 {
3980 return false;
3981 }
3982
3983 if (aabb && resultData->isectResult != 1)
3984 {
3985 return false;
3986 }
3987 }
3988 else if (m_data.id == TEST_ID_INCOMING_RAY_FLAGS_INDIRECT)
3989 {
3990 IncomingFlagsResultData *resultData = (IncomingFlagsResultData *)m_resultBuffer->getAllocation().getHostPtr();
3991
3992 uint32_t miss[2] = {1, 0};
3993 uint32_t chitMin[2] = {0, 1};
3994 uint32_t chitMax[2] = {0, 1};
3995 uint32_t ahitMin[2] = {0, 1};
3996 uint32_t ahitMax[2] = {0, 2};
3997 uint32_t isectMin[2] = {0, 0};
3998 uint32_t isectMax[2] = {0, 0};
3999
4000 if (aabb)
4001 {
4002 isectMin[1] = 1;
4003 isectMax[1] = 2;
4004 }
4005
4006 if (m_data.opaque)
4007 {
4008 ahitMin[1] = 0;
4009 ahitMax[1] = 0;
4010 }
4011
4012 if (m_data.skipClosestHit)
4013 {
4014 chitMin[1] = 0;
4015 chitMax[1] = 0;
4016 }
4017
4018 for (uint32_t i = 0; i < 2; ++i)
4019 {
4020 if (resultData->miss[i] != miss[i])
4021 return false;
4022 if (resultData->chit[i] < chitMin[i])
4023 return false;
4024 if (resultData->chit[i] > chitMax[i])
4025 return false;
4026 if (resultData->ahit[i] < ahitMin[i])
4027 return false;
4028 if (resultData->ahit[i] > ahitMax[i])
4029 return false;
4030 if (resultData->isect[i] < isectMin[i])
4031 return false;
4032 if (resultData->isect[i] > isectMax[i])
4033 return false;
4034 }
4035 }
4036 else if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
4037 {
4038 HitKindResultData *resultData = (HitKindResultData *)m_resultBuffer->getAllocation().getHostPtr();
4039 for (uint32_t i = 0; i < 2; ++i)
4040 {
4041 if (resultData->chit[i] != 1)
4042 return false;
4043
4044 if (resultData->ahit[i] != 1)
4045 return false;
4046 }
4047 }
4048 else
4049 {
4050 return false;
4051 }
4052 return true;
4053 }
4054
iterate(void)4055 tcu::TestStatus RayTracingIndirectTestInstance::iterate(void)
4056 {
4057 const VkDevice device = m_context.getDevice();
4058 const DeviceInterface &vk = m_context.getDeviceInterface();
4059 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
4060 Allocator &allocator = m_context.getDefaultAllocator();
4061
4062 const bool aabb = (m_data.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
4063
4064 vk::Move<VkDescriptorPool> descriptorPool;
4065 vk::Move<VkDescriptorSetLayout> descriptorSetLayout;
4066 std::vector<vk::Move<VkDescriptorSet>> descriptorSet;
4067 vk::Move<VkPipelineLayout> pipelineLayout;
4068
4069 createPipelineLayoutAndSet(1u, descriptorPool, descriptorSetLayout, descriptorSet, pipelineLayout);
4070
4071 std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> blas = initBottomAccelerationStructures();
4072
4073 de::SharedPtr<TopLevelAccelerationStructure> tlas = initTopAccelerationStructure(blas);
4074
4075 de::MovePtr<RayTracingPipeline> rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
4076 Move<VkPipeline> pipeline = createPipelineAndShaderBindingTables(rayTracingPipeline, aabb, *pipelineLayout);
4077
4078 initializeParameters();
4079
4080 const VkDescriptorBufferInfo resultDescriptorInfo =
4081 makeDescriptorBufferInfo(m_resultBuffer->get(), 0, VK_WHOLE_SIZE);
4082
4083 const Move<VkCommandPool> cmdPool = createCommandPool(vk, device, 0, queueFamilyIndex);
4084 const Move<VkCommandBuffer> cmdBuffer =
4085 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4086
4087 beginCommandBuffer(vk, *cmdBuffer);
4088
4089 for (const auto &accel : blas)
4090 {
4091 accel->createAndBuild(vk, device, *cmdBuffer, allocator);
4092 }
4093 tlas->createAndBuild(vk, device, *cmdBuffer, allocator);
4094
4095 VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet = {
4096 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
4097 DE_NULL, // const void* pNext;
4098 1u, // uint32_t accelerationStructureCount;
4099 tlas->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
4100 };
4101
4102 if (m_rayBuffer)
4103 {
4104 const VkDescriptorBufferInfo rayDescriptorInfo = makeDescriptorBufferInfo(m_rayBuffer->get(), 0, VK_WHOLE_SIZE);
4105
4106 DescriptorSetUpdateBuilder()
4107 .writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(0u),
4108 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
4109 .writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(1u),
4110 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
4111 .writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(2u),
4112 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &rayDescriptorInfo)
4113 .update(vk, device);
4114 }
4115 else
4116 {
4117 DescriptorSetUpdateBuilder()
4118 .writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(0u),
4119 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
4120 .writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(1u),
4121 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
4122 .update(vk, device);
4123 }
4124
4125 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1,
4126 &descriptorSet[0].get(), 0, DE_NULL);
4127
4128 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline);
4129
4130 uint32_t rayCount = m_numGeoms * m_primsPerGeometry;
4131 if (m_data.id == TEST_ID_HIT_KIND_INDIRECT)
4132 {
4133 rayCount *= 2;
4134 }
4135
4136 VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo = {rayCount, 1, 1, 0};
4137
4138 VkBufferCreateInfo indirectBufferCreateInfo =
4139 makeBufferCreateInfo(sizeof(VkAccelerationStructureBuildRangeInfoKHR),
4140 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
4141 de::MovePtr<BufferWithMemory> indirectBuffer = de::MovePtr<BufferWithMemory>(
4142 new BufferWithMemory(vk, device, allocator, indirectBufferCreateInfo,
4143 MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress));
4144
4145 deMemcpy(indirectBuffer->getAllocation().getHostPtr(), (void *)&buildRangeInfo,
4146 sizeof(VkAccelerationStructureBuildRangeInfoKHR));
4147 invalidateMappedMemoryRange(vk, device, indirectBuffer->getAllocation().getMemory(),
4148 indirectBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
4149
4150 cmdTraceRaysIndirect(vk, *cmdBuffer, &m_raygenShaderBindingTableRegion, &m_missShaderBindingTableRegion,
4151 &m_hitShaderBindingTableRegion, &m_callableShaderBindingTableRegion,
4152 getBufferDeviceAddress(vk, device, indirectBuffer->get(), 0));
4153
4154 endCommandBuffer(vk, *cmdBuffer);
4155
4156 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
4157
4158 invalidateMappedMemoryRange(vk, device, m_resultBuffer->getAllocation().getMemory(),
4159 m_resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
4160
4161 return verifyResults() ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Invalid results");
4162 }
4163
4164 static const struct Stages
4165 {
4166 const char *name;
4167 VkShaderStageFlagBits stage;
4168 } stages[]{
4169 {"rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR}, {"ahit", VK_SHADER_STAGE_ANY_HIT_BIT_KHR},
4170 {"chit", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR}, {"sect", VK_SHADER_STAGE_INTERSECTION_BIT_KHR},
4171 {"miss", VK_SHADER_STAGE_MISS_BIT_KHR}, {"call", VK_SHADER_STAGE_CALLABLE_BIT_KHR},
4172 };
4173
4174 static const struct GeomTypes
4175 {
4176 const char *name;
4177 GeomType geomType;
4178 } geomTypes[] = {
4179 {"triangles", GEOM_TYPE_TRIANGLES},
4180 {"aabs", GEOM_TYPE_AABBS},
4181 };
4182
createLaunchTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)4183 void createLaunchTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *builtinGroup, TestId id, const char *name,
4184 const VkShaderStageFlags shaderStageFlags)
4185 {
4186 const struct
4187 {
4188 uint32_t width;
4189 uint32_t height;
4190 uint32_t depth;
4191 } sizes[] = {
4192 {1, 1, 1}, {16, 16, 16}, {256, 256, 1}, {16384, 1, 1}, {1, 16384, 1},
4193 {1, 1, 16384}, {128, 128, 128}, {2048, 4096, 1}, {317, 3331, 1}, {1, 1331, 111},
4194 };
4195
4196 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4197
4198 for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4199 {
4200 if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4201 continue;
4202
4203 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
4204 {
4205 const uint32_t width = sizes[sizeNdx].width;
4206 const uint32_t height = sizes[sizeNdx].height;
4207 const uint32_t depth = sizes[sizeNdx].depth;
4208 const bool plain = isPlain(width, height, depth);
4209 const uint32_t k = (plain ? 1 : 6);
4210 const uint32_t largestGroup = k * width * height * depth;
4211 const uint32_t squaresGroupCount = largestGroup;
4212 const uint32_t geometriesGroupCount = 1;
4213 const uint32_t instancesGroupCount = 1;
4214 const CaseDef caseDef = {
4215 id, // TestId id;
4216 name, // const char* name;
4217 width, // uint32_t width;
4218 height, // uint32_t height;
4219 depth, // uint32_t depth;
4220 depth, // uint32_t raysDepth;
4221 VK_FORMAT_R32_SINT, // VkFormat format;
4222 false, // bool fixedPointScalarOutput;
4223 false, // bool fixedPointVectorOutput;
4224 false, // bool fixedPointMatrixOutput;
4225 GEOM_TYPE_TRIANGLES, // GeomType geomType;
4226 squaresGroupCount, // uint32_t squaresGroupCount;
4227 geometriesGroupCount, // uint32_t geometriesGroupCount;
4228 instancesGroupCount, // uint32_t instancesGroupCount;
4229 stages[stageNdx].stage, // VkShaderStageFlagBits stage;
4230 false, // bool skipTriangles;
4231 false, // bool skipAABSs;
4232 false, // bool opaque;
4233 false, // bool frontFace;
4234 0u, // VkPipelineCreateFlags pipelineCreateFlags;
4235 false, // bool useSpecConstants;
4236 false, // bool skipClosestHit;
4237 false, // bool useMaintenance5;
4238 };
4239 const std::string suffix =
4240 de::toString(caseDef.width) + '_' + de::toString(caseDef.height) + '_' + de::toString(caseDef.depth);
4241 const std::string testName = string(stages[stageNdx].name) + '_' + suffix;
4242
4243 group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4244 }
4245 }
4246
4247 builtinGroup->addChild(group.release());
4248 }
4249
createScalarTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)4250 void createScalarTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *builtinGroup, TestId id, const char *name,
4251 const VkShaderStageFlags shaderStageFlags)
4252 {
4253 const struct
4254 {
4255 uint32_t width;
4256 uint32_t height;
4257 TestId id;
4258 } sizes[] = {
4259 {16, 16, TEST_ID_HIT_KIND_EXT}, {16, 16, TEST_ID_HIT_T_EXT}, {16, 16, TEST_ID_RAY_T_MIN_EXT},
4260 {16, 16, TEST_ID_RAY_T_MAX_EXT}, {32, 32, TEST_ID_LAST}, {64, 64, TEST_ID_LAST},
4261 {256, 256, TEST_ID_LAST},
4262 };
4263 const bool fourGeometryGroups = id == TEST_ID_HIT_KIND_EXT || id == TEST_ID_HIT_T_EXT ||
4264 id == TEST_ID_RAY_T_MIN_EXT || id == TEST_ID_RAY_T_MAX_EXT;
4265 const bool fixedPointScalarOutput =
4266 id == TEST_ID_HIT_T_EXT || id == TEST_ID_RAY_T_MIN_EXT || id == TEST_ID_RAY_T_MAX_EXT;
4267 const uint32_t imageDepth = 1;
4268 const uint32_t rayDepth = 1;
4269
4270 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4271
4272 for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
4273 for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4274 {
4275 const GeomType geomType = geomTypes[geomTypesNdx].geomType;
4276
4277 if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4278 continue;
4279
4280 if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR &&
4281 geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
4282 continue;
4283
4284 bool testAdded = false;
4285 bool generalTestsStarted = false;
4286
4287 for (size_t sizesNdx = 0; sizesNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizesNdx)
4288 {
4289 const bool specializedTest = (sizes[sizesNdx].id != TEST_ID_LAST);
4290 const uint32_t width = sizes[sizesNdx].width;
4291 const uint32_t height = sizes[sizesNdx].height;
4292 const uint32_t instancesGroupCount = fourGeometryGroups ? 1 : 4;
4293 const uint32_t geometriesGroupCount = fourGeometryGroups ? 4 : 8;
4294 const uint32_t largestGroup = width * height / geometriesGroupCount / instancesGroupCount;
4295 const uint32_t squaresGroupCount = largestGroup;
4296 const CaseDef caseDef = {
4297 id, // TestId id;
4298 name, // const char* name;
4299 width, // uint32_t width;
4300 height, // uint32_t height;
4301 imageDepth, // uint32_t depth;
4302 rayDepth, // uint32_t raysDepth;
4303 VK_FORMAT_R32_SINT, // VkFormat format;
4304 fixedPointScalarOutput, // bool fixedPointScalarOutput;
4305 false, // bool fixedPointVectorOutput;
4306 false, // bool fixedPointMatrixOutput;
4307 geomType, // GeomType geomType;
4308 squaresGroupCount, // uint32_t squaresGroupCount;
4309 geometriesGroupCount, // uint32_t geometriesGroupCount;
4310 instancesGroupCount, // uint32_t instancesGroupCount;
4311 stages[stageNdx].stage, // VkShaderStageFlagBits stage;
4312 false, // bool skipTriangles;
4313 false, // bool skipAABSs;
4314 false, // bool opaque;
4315 false, // bool frontFace;
4316 0u, // VkPipelineCreateFlags pipelineCreateFlags;
4317 false, // bool useSpecConstants;
4318 false, // bool skipClosestHit;
4319 false, // bool useMaintenance5;
4320 };
4321 const std::string suffix = '_' + de::toString(caseDef.width) + '_' + de::toString(caseDef.height);
4322 const std::string testName = string(stages[stageNdx].name) + '_' + geomTypes[geomTypesNdx].name +
4323 (specializedTest ? "" : suffix);
4324
4325 if (specializedTest)
4326 {
4327 DE_UNREF(generalTestsStarted);
4328 DE_ASSERT(!generalTestsStarted);
4329
4330 if (sizes[sizesNdx].id != id)
4331 continue;
4332 }
4333 else
4334 {
4335 generalTestsStarted = true;
4336 }
4337
4338 group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4339 testAdded = true;
4340
4341 if (specializedTest)
4342 break;
4343 }
4344
4345 DE_ASSERT(testAdded);
4346 DE_UNREF(testAdded);
4347 }
4348
4349 builtinGroup->addChild(group.release());
4350 }
4351
createRayFlagsTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)4352 void createRayFlagsTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *builtinGroup, TestId id, const char *name,
4353 const VkShaderStageFlags shaderStageFlags)
4354 {
4355 const uint32_t width = 16;
4356 const uint32_t height = 16;
4357 const uint32_t imageDepth = 1;
4358 const uint32_t rayDepth = 1;
4359
4360 const struct Opaques
4361 {
4362 const char *name;
4363 bool flag;
4364 } opaques[] = {
4365 {"opaque", true},
4366 {"noopaque", false},
4367 };
4368 const struct Faces
4369 {
4370 const char *name;
4371 bool flag;
4372 } faces[] = {
4373 {"frontface", true},
4374 {"backface", false},
4375 };
4376 const struct SkipRayFlags
4377 {
4378 const char *name;
4379 bool skipTriangles;
4380 bool skipAABBs;
4381 } skipRayFlags[] = {
4382 {"raynoskipflags", false, false},
4383 {"rayskiptriangles", true, false},
4384 {"rayskipaabbs", false, true},
4385 };
4386 const struct PipelineFlags
4387 {
4388 const char *name;
4389 VkPipelineCreateFlags flag;
4390 } pipelineFlags[] = {
4391 {"pipelinenoskipflags", static_cast<VkPipelineCreateFlags>(0)},
4392 {"pipelineskiptriangles", VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR},
4393 {"pipelineskipaabbs", VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR},
4394 };
4395
4396 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4397
4398 for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
4399 {
4400 const GeomType geomType = geomTypes[geomTypesNdx].geomType;
4401 de::MovePtr<tcu::TestCaseGroup> geomGroup(new tcu::TestCaseGroup(testCtx, geomTypes[geomTypesNdx].name));
4402
4403 for (size_t skipRayFlagsNdx = 0; skipRayFlagsNdx < DE_LENGTH_OF_ARRAY(skipRayFlags); ++skipRayFlagsNdx)
4404 {
4405 de::MovePtr<tcu::TestCaseGroup> rayFlagsGroup(
4406 new tcu::TestCaseGroup(testCtx, skipRayFlags[skipRayFlagsNdx].name));
4407
4408 for (size_t pipelineFlagsNdx = 0; pipelineFlagsNdx < DE_LENGTH_OF_ARRAY(pipelineFlags); ++pipelineFlagsNdx)
4409 {
4410 const bool skipTriangles =
4411 (skipRayFlags[skipRayFlagsNdx].skipTriangles ||
4412 (pipelineFlags[pipelineFlagsNdx].flag & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR));
4413 const bool skipAABBs =
4414 (skipRayFlags[skipRayFlagsNdx].skipAABBs ||
4415 (pipelineFlags[pipelineFlagsNdx].flag & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR));
4416
4417 // Skipping both triangles and AABBs is not legal according to the spec.
4418 if (skipTriangles && skipAABBs)
4419 continue;
4420
4421 // Skipping - SkipTrianglesKHR is mutually exclusive with CullBackFacingTrianglesKHR and CullFrontFacingTrianglesKHR
4422 if ((geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES) &&
4423 skipRayFlags[skipRayFlagsNdx].skipTriangles &&
4424 (pipelineFlags[pipelineFlagsNdx].flag == static_cast<VkPipelineCreateFlags>(0)))
4425 {
4426 continue;
4427 }
4428
4429 de::MovePtr<tcu::TestCaseGroup> pipelineFlagsGroup(
4430 new tcu::TestCaseGroup(testCtx, pipelineFlags[pipelineFlagsNdx].name));
4431
4432 for (size_t opaquesNdx = 0; opaquesNdx < DE_LENGTH_OF_ARRAY(opaques); ++opaquesNdx)
4433 for (size_t facesNdx = 0; facesNdx < DE_LENGTH_OF_ARRAY(faces); ++facesNdx)
4434 {
4435 const std::string geomPropertiesGroupName =
4436 string(opaques[opaquesNdx].name) + '_' + string(faces[facesNdx].name);
4437 de::MovePtr<tcu::TestCaseGroup> geomPropertiesGroup(
4438 new tcu::TestCaseGroup(testCtx, geomPropertiesGroupName.c_str()));
4439
4440 for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4441 {
4442 if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4443 continue;
4444
4445 if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR &&
4446 geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
4447 continue;
4448
4449 const uint32_t instancesGroupCount = 1;
4450 const uint32_t geometriesGroupCount = 1;
4451 const uint32_t squaresGroupCount =
4452 width * height / geometriesGroupCount / instancesGroupCount;
4453 const CaseDef caseDef = {
4454 id, // TestId id;
4455 name, // const char* name;
4456 width, // uint32_t width;
4457 height, // uint32_t height;
4458 imageDepth, // uint32_t depth;
4459 rayDepth, // uint32_t raysDepth;
4460 VK_FORMAT_R32_SINT, // VkFormat format;
4461 false, // bool fixedPointScalarOutput;
4462 false, // bool fixedPointVectorOutput;
4463 false, // bool fixedPointMatrixOutput;
4464 geomType, // GeomType geomType;
4465 squaresGroupCount, // uint32_t squaresGroupCount;
4466 geometriesGroupCount, // uint32_t geometriesGroupCount;
4467 instancesGroupCount, // uint32_t instancesGroupCount;
4468 stages[stageNdx].stage, // VkShaderStageFlagBits stage;
4469 skipRayFlags[skipRayFlagsNdx].skipTriangles, // bool skipTriangles;
4470 skipRayFlags[skipRayFlagsNdx].skipAABBs, // bool skipAABSs;
4471 opaques[opaquesNdx].flag, // bool opaque;
4472 faces[facesNdx].flag, // bool frontFace;
4473 pipelineFlags[pipelineFlagsNdx].flag, // VkPipelineCreateFlags pipelineCreateFlags;
4474 false, // bool useSpecConstants;
4475 false, // bool skipClosestHit;
4476 false, // bool useMaintenance5;
4477 };
4478 const std::string testName = string(stages[stageNdx].name);
4479
4480 geomPropertiesGroup->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4481 }
4482
4483 pipelineFlagsGroup->addChild(geomPropertiesGroup.release());
4484 }
4485
4486 rayFlagsGroup->addChild(pipelineFlagsGroup.release());
4487 }
4488
4489 geomGroup->addChild(rayFlagsGroup.release());
4490 }
4491
4492 group->addChild(geomGroup.release());
4493 }
4494
4495 {
4496 de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
4497 CaseDef caseDef{
4498 TEST_ID_INCOMING_RAY_FLAGS_EXT, // TestId id;
4499 name, // const char* name;
4500 width, // uint32_t width;
4501 height, // uint32_t height;
4502 imageDepth, // uint32_t depth;
4503 rayDepth, // uint32_t raysDepth;
4504 VK_FORMAT_R32_SINT, // VkFormat format;
4505 false, // bool fixedPointScalarOutput;
4506 false, // bool fixedPointVectorOutput;
4507 false, // bool fixedPointMatrixOutput;
4508 GEOM_TYPE_TRIANGLES, // GeomType geomType;
4509 width * height, // uint32_t squaresGroupCount;
4510 1, // uint32_t geometriesGroupCount;
4511 1, // uint32_t instancesGroupCount;
4512 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, // VkShaderStageFlagBits stage;
4513 false, // bool skipTriangles;
4514 false, // bool skipAABSs;
4515 false, // bool opaque;
4516 true, // bool frontFace;
4517 VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR, // VkPipelineCreateFlags pipelineCreateFlags;
4518 false, // bool useSpecConstants;
4519 false, // bool skipClosestHit;
4520 true, // bool useMaintenance5;
4521 };
4522
4523 miscGroup->addChild(new RayTracingTestCase(testCtx, "pipelineskiptriangles_maintenance5", caseDef));
4524 caseDef.pipelineCreateFlags = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR;
4525 miscGroup->addChild(new RayTracingTestCase(testCtx, "pipelineskipaabbs_maintenance5", caseDef));
4526
4527 group->addChild(miscGroup.release());
4528 }
4529
4530 builtinGroup->addChild(group.release());
4531 }
4532
createMultiOutputTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup,TestId id,const char * name,const VkShaderStageFlags shaderStageFlags)4533 void createMultiOutputTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *builtinGroup, TestId id, const char *name,
4534 const VkShaderStageFlags shaderStageFlags)
4535 {
4536 const bool fixedPointVectorOutput = id == TEST_ID_WORLD_RAY_ORIGIN_EXT || id == TEST_ID_WORLD_RAY_DIRECTION_EXT ||
4537 id == TEST_ID_OBJECT_RAY_ORIGIN_EXT || id == TEST_ID_OBJECT_RAY_DIRECTION_EXT;
4538 const bool fixedPointMatrixOutput = id == TEST_ID_OBJECT_TO_WORLD_EXT || id == TEST_ID_WORLD_TO_OBJECT_EXT ||
4539 id == TEST_ID_OBJECT_TO_WORLD_3X4_EXT || id == TEST_ID_WORLD_TO_OBJECT_3X4_EXT;
4540 const uint32_t imageDepth = fixedPointMatrixOutput ? 4 * 4 : fixedPointVectorOutput ? 4 : 0;
4541 const uint32_t rayDepth = 1;
4542
4543 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, de::toLower(name).c_str()));
4544
4545 DE_ASSERT(imageDepth != 0);
4546
4547 for (size_t geomTypesNdx = 0; geomTypesNdx < DE_LENGTH_OF_ARRAY(geomTypes); ++geomTypesNdx)
4548 for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4549 {
4550 const GeomType geomType = geomTypes[geomTypesNdx].geomType;
4551
4552 if ((shaderStageFlags & stages[stageNdx].stage) == 0)
4553 continue;
4554
4555 if (stages[stageNdx].stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR &&
4556 geomTypes[geomTypesNdx].geomType == GEOM_TYPE_TRIANGLES)
4557 continue;
4558
4559 const uint32_t width = 4;
4560 const uint32_t height = 4;
4561 const uint32_t instancesGroupCount = 4;
4562 const uint32_t geometriesGroupCount = 1;
4563 const uint32_t largestGroup = width * height / geometriesGroupCount / instancesGroupCount;
4564 const uint32_t squaresGroupCount = largestGroup;
4565 const CaseDef caseDef = {
4566 id, // TestId id;
4567 name, // const char* name;
4568 width, // uint32_t width;
4569 height, // uint32_t height;
4570 imageDepth, // uint32_t depth;
4571 rayDepth, // uint32_t raysDepth;
4572 VK_FORMAT_R32_SINT, // VkFormat format;
4573 false, // bool fixedPointScalarOutput;
4574 fixedPointVectorOutput, // bool fixedPointVectorOutput;
4575 fixedPointMatrixOutput, // bool fixedPointMatrixOutput;
4576 geomType, // GeomType geomType;
4577 squaresGroupCount, // uint32_t squaresGroupCount;
4578 geometriesGroupCount, // uint32_t geometriesGroupCount;
4579 instancesGroupCount, // uint32_t instancesGroupCount;
4580 stages[stageNdx].stage, // VkShaderStageFlagBits stage;
4581 false, // bool rayFlagSkipTriangles;
4582 false, // bool rayFlagSkipAABSs;
4583 false, // bool opaque;
4584 false, // bool frontFace;
4585 0u, // VkPipelineCreateFlags pipelineCreateFlags;
4586 false, // bool useSpecConstants;
4587 false, // bool skipClosestHit;
4588 false, // bool useMaintenance5;
4589 };
4590 const std::string testName = string(stages[stageNdx].name) + '_' + geomTypes[geomTypesNdx].name;
4591
4592 group->addChild(new RayTracingTestCase(testCtx, testName.c_str(), caseDef));
4593 }
4594
4595 builtinGroup->addChild(group.release());
4596 }
4597
createIndirectTestCases(tcu::TestContext & testCtx,tcu::TestCaseGroup * indirectGroup,TestId id,const char * name)4598 void createIndirectTestCases(tcu::TestContext &testCtx, tcu::TestCaseGroup *indirectGroup, TestId id, const char *name)
4599 {
4600 const struct
4601 {
4602 VkShaderStageFlagBits stage;
4603 const char *name;
4604 } types[] = {
4605 {VK_SHADER_STAGE_RAYGEN_BIT_KHR, "triangles"},
4606 {VK_SHADER_STAGE_INTERSECTION_BIT_KHR, "aabbs"},
4607 };
4608
4609 const CaseDef caseDef = {
4610 id, // TestId id;
4611 "", // const char* name;
4612 0, // uint32_t width;
4613 0, // uint32_t height;
4614 0, // uint32_t depth;
4615 0, // uint32_t raysDepth;
4616 VK_FORMAT_R32_SINT, // VkFormat format;
4617 false, // bool fixedPointScalarOutput;
4618 false, // bool fixedPointVectorOutput;
4619 false, // bool fixedPointMatrixOutput;
4620 GEOM_TYPE_TRIANGLES, // GeomType geomType;
4621 0, // uint32_t squaresGroupCount;
4622 0, // uint32_t geometriesGroupCount;
4623 0, // uint32_t instancesGroupCount;
4624 VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM, // VkShaderStageFlagBits stage;
4625 false, // bool rayFlagSkipTriangles;
4626 false, // bool rayFlagSkipAABSs;
4627 false, // bool opaque;
4628 false, // bool frontFace;
4629 0u, // VkPipelineCreateFlags pipelineCreateFlags;
4630 false, // bool useSpecConstants;
4631 false, // bool skipClosestHit;
4632 false, // bool useMaintenance5;
4633 };
4634
4635 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, name));
4636
4637 for (size_t typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
4638 {
4639 CaseDef params = caseDef;
4640 params.stage = types[typeNdx].stage;
4641 group->addChild(new RayTracingIndirectTestCase(testCtx, types[typeNdx].name, params));
4642 }
4643 indirectGroup->addChild(group.release());
4644 }
4645
createIndirectFlagsTestCases(tcu::TestContext & testCtx,tcu::TestCaseGroup * indirectGroup,TestId id,const char * name)4646 void createIndirectFlagsTestCases(tcu::TestContext &testCtx, tcu::TestCaseGroup *indirectGroup, TestId id,
4647 const char *name)
4648 {
4649 const struct
4650 {
4651 VkShaderStageFlagBits stage;
4652 const char *name;
4653 } types[] = {
4654 {VK_SHADER_STAGE_RAYGEN_BIT_KHR, "triangles"},
4655 {VK_SHADER_STAGE_INTERSECTION_BIT_KHR, "aabbs"},
4656 };
4657
4658 const struct
4659 {
4660 bool opaque;
4661 bool skipClosestHit;
4662 const char *name;
4663 } flags[] = {
4664 {false, false, "none"},
4665 {true, false, "opaque"},
4666 {false, true, "skip_closest_hit"},
4667 };
4668
4669 const CaseDef caseDef = {
4670 id, // TestId id;
4671 "", // const char* name;
4672 0, // uint32_t width;
4673 0, // uint32_t height;
4674 0, // uint32_t depth;
4675 0, // uint32_t raysDepth;
4676 VK_FORMAT_R32_SINT, // VkFormat format;
4677 false, // bool fixedPointScalarOutput;
4678 false, // bool fixedPointVectorOutput;
4679 false, // bool fixedPointMatrixOutput;
4680 GEOM_TYPE_TRIANGLES, // GeomType geomType;
4681 0, // uint32_t squaresGroupCount;
4682 0, // uint32_t geometriesGroupCount;
4683 0, // uint32_t instancesGroupCount;
4684 VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM, // VkShaderStageFlagBits stage;
4685 false, // bool rayFlagSkipTriangles;
4686 false, // bool rayFlagSkipAABSs;
4687 false, // bool opaque;
4688 false, // bool frontFace;
4689 0u, // VkPipelineCreateFlags pipelineCreateFlags;
4690 false, // bool useSpecConstants;
4691 false, // bool skipClosestHit;
4692 false, // bool useMaintenance5;
4693 };
4694
4695 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, name));
4696
4697 for (size_t typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
4698 {
4699 CaseDef params = caseDef;
4700 params.stage = types[typeNdx].stage;
4701 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, types[typeNdx].name));
4702
4703 for (size_t flagsNdx = 0; flagsNdx < DE_LENGTH_OF_ARRAY(flags); ++flagsNdx)
4704 {
4705 params.opaque = flags[flagsNdx].opaque;
4706 params.skipClosestHit = flags[flagsNdx].skipClosestHit;
4707 typeGroup->addChild(new RayTracingIndirectTestCase(testCtx, flags[flagsNdx].name, params));
4708 }
4709 testGroup->addChild(typeGroup.release());
4710 }
4711 indirectGroup->addChild(testGroup.release());
4712 }
4713
createIndirectTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * builtinGroup)4714 void createIndirectTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *builtinGroup)
4715 {
4716 typedef void CreateIndirectTestsFunc(tcu::TestContext & testCtx, tcu::TestCaseGroup * group, TestId id,
4717 const char *name);
4718
4719 const struct
4720 {
4721 TestId id;
4722 const char *name;
4723 CreateIndirectTestsFunc *createTestsFunc;
4724 } tests[] = {
4725 {TEST_ID_INDICES_INDIRECT, "indices", createIndirectTestCases},
4726 {TEST_ID_TRANSFORMS_INDIRECT, "transforms", createIndirectTestCases},
4727 {TEST_ID_TMINMAX_INDIRECT, "t_min_max", createIndirectTestCases},
4728 {TEST_ID_INCOMING_RAY_FLAGS_INDIRECT, "incoming_flag", createIndirectFlagsTestCases},
4729 {TEST_ID_HIT_KIND_INDIRECT, "hit_kind", createIndirectTestCases},
4730 };
4731
4732 // Test builtins using indirect trace rays
4733 de::MovePtr<tcu::TestCaseGroup> indirectGroup(new tcu::TestCaseGroup(testCtx, "indirect"));
4734
4735 for (size_t testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
4736 {
4737 tests[testNdx].createTestsFunc(testCtx, indirectGroup.get(), tests[testNdx].id, tests[testNdx].name);
4738 }
4739 builtinGroup->addChild(indirectGroup.release());
4740 }
4741 } // namespace
4742
createBuiltinTests(tcu::TestContext & testCtx)4743 tcu::TestCaseGroup *createBuiltinTests(tcu::TestContext &testCtx)
4744 {
4745 typedef void CreateBuiltinTestsFunc(tcu::TestContext & testCtx, tcu::TestCaseGroup * group, TestId id,
4746 const char *name, const VkShaderStageFlags);
4747
4748 const VkShaderStageFlagBits R = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
4749 const VkShaderStageFlagBits A = VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
4750 const VkShaderStageFlagBits C = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
4751 const VkShaderStageFlagBits M = VK_SHADER_STAGE_MISS_BIT_KHR;
4752 const VkShaderStageFlagBits I = VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
4753 const VkShaderStageFlagBits L = VK_SHADER_STAGE_CALLABLE_BIT_KHR;
4754
4755 const struct
4756 {
4757 TestId id;
4758 const char *name;
4759 VkShaderStageFlags stages;
4760 CreateBuiltinTestsFunc *createBuiltinTestsFunc;
4761 } tests[] = {
4762 {TEST_ID_LAUNCH_ID_EXT, "LaunchIDEXT", R | A | C | I | M | L, createLaunchTests},
4763 {TEST_ID_LAUNCH_SIZE_EXT, "LaunchSizeEXT", R | A | C | I | M | L, createLaunchTests},
4764 {TEST_ID_PRIMITIVE_ID, "PrimitiveID", A | C | I, createScalarTests},
4765 {TEST_ID_INSTANCE_ID, "InstanceID", A | C | I, createScalarTests},
4766 {TEST_ID_INSTANCE_CUSTOM_INDEX_EXT, "InstanceCustomIndexEXT", A | C | I, createScalarTests},
4767 {TEST_ID_GEOMETRY_INDEX_EXT, "GeometryIndexEXT", A | C | I, createScalarTests},
4768 {TEST_ID_WORLD_RAY_ORIGIN_EXT, "WorldRayOriginEXT", A | C | I | M, createMultiOutputTests},
4769 {TEST_ID_WORLD_RAY_DIRECTION_EXT, "WorldRayDirectionEXT", A | C | I | M, createMultiOutputTests},
4770 {TEST_ID_OBJECT_RAY_ORIGIN_EXT, "ObjectRayOriginEXT", A | C | I, createMultiOutputTests},
4771 {TEST_ID_OBJECT_RAY_DIRECTION_EXT, "ObjectRayDirectionEXT", A | C | I, createMultiOutputTests},
4772 {TEST_ID_RAY_T_MIN_EXT, "RayTminEXT", A | C | I | M, createScalarTests},
4773 {TEST_ID_RAY_T_MAX_EXT, "RayTmaxEXT", A | C | I | M, createScalarTests},
4774 {TEST_ID_INCOMING_RAY_FLAGS_EXT, "IncomingRayFlagsEXT", A | C | I | M, createRayFlagsTests},
4775 {TEST_ID_HIT_T_EXT, "HitTEXT", A | C, createScalarTests},
4776 {TEST_ID_HIT_KIND_EXT, "HitKindEXT", A | C, createScalarTests},
4777 {TEST_ID_OBJECT_TO_WORLD_EXT, "ObjectToWorldEXT", A | C | I, createMultiOutputTests},
4778 {TEST_ID_WORLD_TO_OBJECT_EXT, "WorldToObjectEXT", A | C | I, createMultiOutputTests},
4779 {TEST_ID_OBJECT_TO_WORLD_3X4_EXT, "ObjectToWorld3x4EXT", A | C | I, createMultiOutputTests},
4780 {TEST_ID_WORLD_TO_OBJECT_3X4_EXT, "WorldToObject3x4EXT", A | C | I, createMultiOutputTests},
4781 };
4782
4783 // Ray tracing shader builtin tests
4784 de::MovePtr<tcu::TestCaseGroup> builtinGroup(new tcu::TestCaseGroup(testCtx, "builtin"));
4785
4786 for (size_t testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
4787 {
4788 tests[testNdx].createBuiltinTestsFunc(testCtx, builtinGroup.get(), tests[testNdx].id, tests[testNdx].name,
4789 tests[testNdx].stages);
4790 }
4791
4792 {
4793 createIndirectTests(testCtx, builtinGroup.get());
4794 }
4795
4796 return builtinGroup.release();
4797 }
4798
createSpecConstantTests(tcu::TestContext & testCtx)4799 tcu::TestCaseGroup *createSpecConstantTests(tcu::TestContext &testCtx)
4800 {
4801 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "spec_constants"));
4802
4803 const VkShaderStageFlags stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
4804 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR |
4805 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR;
4806 const uint32_t width = 256u;
4807 const uint32_t height = 256u;
4808 const uint32_t depth = 1u;
4809 const bool plain = isPlain(width, height, depth);
4810 const uint32_t k = (plain ? 1 : 6);
4811 const uint32_t largestGroup = k * width * height * depth;
4812 const uint32_t squaresGroupCount = largestGroup;
4813 const uint32_t geometriesGroupCount = 1;
4814 const uint32_t instancesGroupCount = 1;
4815
4816 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
4817 {
4818 if ((stageFlags & stages[stageNdx].stage) == 0)
4819 continue;
4820
4821 const CaseDef caseDef = {
4822 TEST_ID_LAUNCH_ID_EXT, // TestId id;
4823 "LaunchIDEXT", // const char* name;
4824 width, // uint32_t width;
4825 height, // uint32_t height;
4826 depth, // uint32_t depth;
4827 depth, // uint32_t raysDepth;
4828 VK_FORMAT_R32_SINT, // VkFormat format;
4829 false, // bool fixedPointScalarOutput;
4830 false, // bool fixedPointVectorOutput;
4831 false, // bool fixedPointMatrixOutput;
4832 GEOM_TYPE_TRIANGLES, // GeomType geomType;
4833 squaresGroupCount, // uint32_t squaresGroupCount;
4834 geometriesGroupCount, // uint32_t geometriesGroupCount;
4835 instancesGroupCount, // uint32_t instancesGroupCount;
4836 stages[stageNdx].stage, // VkShaderStageFlagBits stage;
4837 false, // bool skipTriangles;
4838 false, // bool skipAABSs;
4839 false, // bool opaque;
4840 false, // bool frontFace;
4841 0u, // VkPipelineCreateFlags pipelineCreateFlags;
4842 true, // bool useSpecConstants;
4843 false, // bool skipClosestHit;
4844 false, // bool useMaintenance5;
4845 };
4846
4847 group->addChild(new RayTracingTestCase(testCtx, stages[stageNdx].name, caseDef));
4848 }
4849
4850 return group.release();
4851 }
4852
4853 } // namespace RayTracing
4854 } // namespace vkt
4855