xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/ray_tracing/vktRayTracingBuiltinTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 &params, 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 &params, 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