1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2023 Advanced Micro Devices, Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21 * \file
22 * \brief ray query multiple rayQuery objects for VK_KHR_ray_query utility functions
23 *//*--------------------------------------------------------------------*/
24 
25 #include "vktRayQueryMultipleRayQueries.hpp"
26 #include "vkRayTracingUtil.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "tcuSurface.hpp"
31 
32 namespace vkt
33 {
34 namespace RayQuery
35 {
36 
37 namespace
38 {
39 
40 using namespace vk;
41 constexpr float MAX_T_VALUE = 10000000.0;
42 
43 struct ResultData
44 {
ResultDatavkt::RayQuery::__anon9a137c920111::ResultData45     ResultData() : x(0.f), y(0.f), z(0.f), w(0.f)
46     {
47     }
ResultDatavkt::RayQuery::__anon9a137c920111::ResultData48     ResultData(const float ix) : x(ix), y(ix), z(ix), w(ix)
49     {
50     }
ResultDatavkt::RayQuery::__anon9a137c920111::ResultData51     ResultData(const float ix, const float iy, const float iz, const float iw) : x(ix), y(iy), z(iz), w(iw)
52     {
53     }
equalvkt::RayQuery::__anon9a137c920111::ResultData54     bool equal(ResultData other)
55     {
56         const float epsilon = 0.000001f;
57         return ((abs(other.x - x) < epsilon) && (abs(other.y - y) < epsilon) && (abs(other.z - z) < epsilon) &&
58                 (abs(other.w - w) < epsilon));
59     }
60 
61     float x;
62     float y;
63     float z;
64     float w;
65 };
66 
computeExpectedResults()67 static std::vector<ResultData> computeExpectedResults()
68 {
69     std::vector<ResultData> expectedResults;
70     expectedResults.push_back(ResultData{0, 3, 6, 0});
71     expectedResults.push_back(ResultData{1, 4, 7, 0});
72     expectedResults.push_back(ResultData{2, 5, 8, 0});
73     expectedResults.push_back(ResultData{10, 13, 16, 0});
74     expectedResults.push_back(ResultData{11, 14, 17, 0});
75     expectedResults.push_back(ResultData{12, 15, 18, 0});
76     return expectedResults;
77 }
78 
79 class MultipleRayQueriesCase : public TestCase
80 {
81 public:
82     MultipleRayQueriesCase(tcu::TestContext &testCtx, const std::string &name, const RayQueryTestParams &params);
~MultipleRayQueriesCase(void)83     virtual ~MultipleRayQueriesCase(void)
84     {
85     }
86 
87     virtual void checkSupport(Context &context) const;
88     virtual void initPrograms(vk::SourceCollections &programCollection) const;
89     virtual TestInstance *createInstance(Context &context) const;
90 
91 protected:
92     RayQueryTestParams m_params;
93 };
94 
95 class MultipleRayQueriesInstance : public TestInstance
96 {
97 public:
98     MultipleRayQueriesInstance(Context &context, const RayQueryTestParams &params);
~MultipleRayQueriesInstance(void)99     virtual ~MultipleRayQueriesInstance(void)
100     {
101     }
102 
103     virtual tcu::TestStatus iterate(void);
104 
105 protected:
106     RayQueryTestParams m_params;
107 };
108 
MultipleRayQueriesCase(tcu::TestContext & testCtx,const std::string & name,const RayQueryTestParams & params)109 MultipleRayQueriesCase::MultipleRayQueriesCase(tcu::TestContext &testCtx, const std::string &name,
110                                                const RayQueryTestParams &params)
111     : TestCase(testCtx, name)
112     , m_params(params)
113 {
114 }
115 
checkSupport(Context & context) const116 void MultipleRayQueriesCase::checkSupport(Context &context) const
117 {
118     context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
119     context.requireDeviceFunctionality("VK_KHR_ray_query");
120 
121     const VkPhysicalDeviceRayQueryFeaturesKHR &rayQueryFeaturesKHR = context.getRayQueryFeatures();
122     if (rayQueryFeaturesKHR.rayQuery == false)
123         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
124 
125     const VkPhysicalDeviceAccelerationStructureFeaturesKHR &accelerationStructureFeaturesKHR =
126         context.getAccelerationStructureFeatures();
127     if (accelerationStructureFeaturesKHR.accelerationStructure == false)
128         TCU_THROW(TestError,
129                   "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
130 
131     const VkPhysicalDeviceFeatures2 &features2 = context.getDeviceFeatures2();
132 
133     if ((m_params.shaderSourceType == RayQueryShaderSourceType::TESSELLATION_CONTROL ||
134          m_params.shaderSourceType == RayQueryShaderSourceType::TESSELLATION_EVALUATION) &&
135         features2.features.tessellationShader == false)
136         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.tessellationShader");
137 
138     if (m_params.shaderSourceType == RayQueryShaderSourceType::GEOMETRY && features2.features.geometryShader == false)
139         TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.geometryShader");
140 
141     switch (m_params.shaderSourceType)
142     {
143     case RayQueryShaderSourceType::VERTEX:
144     case RayQueryShaderSourceType::TESSELLATION_CONTROL:
145     case RayQueryShaderSourceType::TESSELLATION_EVALUATION:
146     case RayQueryShaderSourceType::GEOMETRY:
147         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
148         break;
149     default:
150         break;
151     }
152 
153     if (m_params.shaderSourceType == RayQueryShaderSourceType::RAY_GENERATION ||
154         m_params.shaderSourceType == RayQueryShaderSourceType::INTERSECTION ||
155         m_params.shaderSourceType == RayQueryShaderSourceType::ANY_HIT ||
156         m_params.shaderSourceType == RayQueryShaderSourceType::CLOSEST_HIT ||
157         m_params.shaderSourceType == RayQueryShaderSourceType::MISS ||
158         m_params.shaderSourceType == RayQueryShaderSourceType::CALLABLE)
159     {
160         context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
161 
162         const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
163             context.getRayTracingPipelineFeatures();
164 
165         if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
166             TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
167     }
168 }
169 
initPrograms(vk::SourceCollections & programCollection) const170 void MultipleRayQueriesCase::initPrograms(vk::SourceCollections &programCollection) const
171 {
172     std::string rayQueryPart = "";
173     std::string ifPart       = "";
174     std::string elsePart     = "";
175     std::ostringstream src;
176 
177     // This is rayQueryEXT array version
178     src << "   const int rayQueryCount = 3;\n"
179            "   Ray ray[rayQueryCount];\n"
180            "   ray[0] = rays[index];\n"
181            "   ray[1] = rays[index];\n"
182            "   ray[2] = rays[index];\n"
183            "   ray[1].pos.x += 3.0;\n"
184            "   ray[2].pos.x += 6.0;\n"
185            "   float x = 0;\n"
186            "   float y = 0;\n"
187            "   float z = 0;\n"
188            "   float w = 0;\n"
189            "   float tempResults[] = {0, 0, 0};\n"
190            "   rayQueryEXT rqs[rayQueryCount];\n"
191            "   bool prcds[] = {true, true, true};\n"
192            "\n"
193            "   for (int idx=0;idx<rayQueryCount;++idx)\n"
194            "   {\n"
195            "         rayQueryInitializeEXT(rqs[idx], scene, "
196         << m_params.rayFlags
197         << ", 0xFF, ray[idx].pos, ray[idx].tmin, ray[idx].dir, ray[idx].tmax);\n"
198            "   }\n"
199            "\n"
200            "   bool proceed = true;\n"
201            "   while (proceed)\n" // traverse all rayQueries in parallel to verify rayQueryCount issues
202            "    {\n"
203            "       proceed = false;\n"
204            "        for (int idx=0;idx<rayQueryCount;++idx)\n"
205            "        {\n"
206            "           prcds[idx] = prcds[idx] && rayQueryProceedEXT(rqs[idx]);\n"
207            "            if (prcds[idx])\n"
208            "            {\n"
209            "               if (rayQueryGetIntersectionTypeEXT(rqs[idx], true) == "
210            "gl_RayQueryCommittedIntersectionGeneratedEXT)\n"
211            "               {\n"
212            "                    prcds[idx] = false;\n"
213            "               }\n"
214            "               else if (rayQueryGetIntersectionTypeEXT(rqs[idx], false) == "
215            "gl_RayQueryCandidateIntersectionTriangleEXT)\n"
216            "                {\n"
217            "                    rayQueryConfirmIntersectionEXT(rqs[idx]);\n"
218            "                }\n"
219            "                else if (rayQueryGetIntersectionTypeEXT(rqs[idx], false) == "
220            "gl_RayQueryCandidateIntersectionAABBEXT)\n"
221            "                {\n"
222            "                    rayQueryGenerateIntersectionEXT(rqs[idx], 5.f + ((3 * idx) + (index - 3)) * 10.f );\n"
223            "                }\n"
224            "            }\n"
225            "           proceed = proceed || prcds[idx];\n"
226            "       }\n"
227            "   }\n"
228            "   for (int idx=0;idx<rayQueryCount;++idx)\n"
229            "    {\n"
230            "        if ((rayQueryGetIntersectionTypeEXT(rqs[idx], true) == "
231            "gl_RayQueryCommittedIntersectionTriangleEXT) ||\n"
232            "            (rayQueryGetIntersectionTypeEXT(rqs[idx], true) == "
233            "gl_RayQueryCommittedIntersectionGeneratedEXT))\n"
234            "        {\n"
235            "            uint instIdx = rayQueryGetIntersectionInstanceIdEXT(rqs[idx], true);\n"
236            "           uint primIndex = rayQueryGetIntersectionPrimitiveIndexEXT(rqs[idx], true);\n"
237            "            tempResults[idx] = float(instIdx) * 10.f  +  float(primIndex);\n"
238            "        }\n"
239            "        rayQueryTerminateEXT(rqs[idx]);\n"
240            "   }\n"
241            "\n"
242            "   x = tempResults[0];\n"
243            "   y = tempResults[1];\n"
244            "   z = tempResults[2];\n";
245 
246     rayQueryPart = src.str();
247     generateRayQueryShaders(programCollection, m_params, rayQueryPart, MAX_T_VALUE);
248 }
249 
createInstance(Context & context) const250 TestInstance *MultipleRayQueriesCase::createInstance(Context &context) const
251 {
252     return new MultipleRayQueriesInstance(context, m_params);
253 }
254 
MultipleRayQueriesInstance(Context & context,const RayQueryTestParams & params)255 MultipleRayQueriesInstance::MultipleRayQueriesInstance(Context &context, const RayQueryTestParams &params)
256     : vkt::TestInstance(context)
257     , m_params(params)
258 {
259 }
260 
iterate(void)261 tcu::TestStatus MultipleRayQueriesInstance::iterate(void)
262 {
263     std::vector<tcu::Vec3> emptyVerts;
264 
265     m_params.rays = {Ray{tcu::Vec3(-2.5f, 0.5f, 0.0f), 0.0f, tcu::Vec3(0.0f, 0.0f, 1.0f), MAX_T_VALUE},
266                      Ray{tcu::Vec3(-2.5f, -0.5f, 0.0f), 1.0f, tcu::Vec3(0.0f, 0.0f, 1.0f), MAX_T_VALUE},
267                      Ray{tcu::Vec3(-1.5f, 0.5f, 0.0f), 2.0f, tcu::Vec3(0.0f, 0.0f, 1.0f), MAX_T_VALUE},
268                      Ray{tcu::Vec3(-2.5f, 0.0f, 95.0f), 3.0f, tcu::Vec3(0.0f, 0.0f, 1.0f), MAX_T_VALUE},
269                      Ray{tcu::Vec3(-1.5f, 0.0f, 95.0f), 4.0f, tcu::Vec3(0.0f, 0.0f, 1.0f), MAX_T_VALUE},
270                      Ray{tcu::Vec3(-0.5f, 0.0f, 95.0f), 5.0f, tcu::Vec3(0.0f, 0.0f, 1.0f), MAX_T_VALUE}};
271 
272     const uint32_t width  = static_cast<uint32_t>(m_params.rays.size());
273     const uint32_t height = 1;
274 
275     // instance 0
276     //(-3,1) (-2,1) (-1,1)  (0,1)  (1,1)  (2,1)  (3,1)   (4,1)   (5,1)
277     //   X------X------X      X------X------X       X------X------X
278     //   | {A} /| {C} /       | {D} /| {F} /        | {G} /| {I} /
279     //   | rq1/ | rq1/        | rq2/ | rq2/         | rq3/ | rq3/
280     //   |   /  |   /         |   /  |   /          |   /  |   /
281     //   |  /   |  /          |  /   |  /           |  /   |  /
282     //   | / {B}| /           | / {E}| /            | / {H}| /
283     //   |/ rq1 |/            |/ rq2 |/             |/  rq3|/
284     //   X------X             X------X              X------X
285     //(-3,-1) (-2,-1)       (0,-1) (1,-1)        (3,-1)  (4,-1)
286     //
287 
288     // instance 1
289     // (-3,1) (-2,1) (-1,1) (0,1)  (1,1)  (2,1)  (3,1)  (4,1)  (5,1)  (6,1)
290     //   X------X------X------X------X------X------X------X------X------X
291     //   |      |      |      |      |      |      |      |      |      |
292     //   |      |      |      |      |      |      |      |      |      |
293     //   |      |      |      |      |      |      |      |      |      |
294     //   | {J}  |  {K} |  {L} | {M}  |  {N} | {O}  | {P}  | {Q}  | {R}  |
295     //   | rq1  |  rq1 |  rq1 | rq2  |  rq2 | rq2  | rq3  | rq3  | rq3  |
296     //   |      |      |      |      |      |      |      |      |      |
297     //   X------X------X------X------X------X------X------X------X------X
298     // (-3,-1)(-2,-1) (-1,-1)(0,-1) (1,-1) (2,-1) (3,-1) (4,-1) (5,-1) (6,-1)
299     //
300 
301     std::vector<tcu::Vec3> instance1 = {{-3.0f, 1.0f, 10.f},                                             // (A) - prim 0
302                                         {-2.0f, 1.0f, 10.f}, {-3.0f, -1.0f, 10.f}, {-3.0f, -1.0f, 20.f}, // (B) - prim 1
303                                         {-2.0f, 1.0f, 20.f}, {-2.0f, -1.0f, 20.f}, {-2.0f, 1.0f, 30.f},  // (C) - prim 2
304                                         {-1.0f, 1.0f, 30.f}, {-2.0f, -1.0f, 30.f}, {0.0f, 1.0f, 40.f},   // (D) - prim 3
305                                         {1.0f, 1.0f, 40.f},  {0.0f, -1.0f, 40.f},  {0.0f, -1.0f, 50.f},  // (E) - prim 4
306                                         {1.0f, 1.0f, 50.f},  {1.0f, -1.0f, 50.f},  {1.0f, 1.0f, 60.f},   // (F) - prim 5
307                                         {2.0f, 1.0f, 60.f},  {1.0f, -1.0f, 60.f},  {3.0f, 1.0f, 70.f},   // (G) - prim 6
308                                         {4.0f, 1.0f, 70.f},  {3.0f, -1.0f, 70.f},  {3.0f, -1.0f, 80.f},  // (H) - prim 7
309                                         {4.0f, 1.0f, 80.f},  {4.0f, -1.0f, 80.f},  {4.0f, 1.0f, 90.f},   // (I) - prim 8
310                                         {5.0f, 1.0f, 90.f},  {4.0f, -1.0f, 90.f}};
311 
312     std::vector<tcu::Vec3> instance2 = {{-3.0f, -1.0f, 100.f},                        // (J) - prim 0
313                                         {-2.0f, 1.0f, 100.f},  {-2.0f, -1.0f, 110.f}, // (K) - prim 1
314                                         {-1.0f, 1.0f, 110.f},  {-1.0f, -1.0f, 120.f}, // (L) - prim 2
315                                         {0.0f, 1.0f, 120.f},   {0.0f, -1.0f, 130.f},  // (M) - prim 3
316                                         {1.0f, 1.0f, 130.f},   {1.0f, -1.0f, 140.f},  // (N) - prim 4
317                                         {2.0f, 1.0f, 140.f},   {2.0f, -1.0f, 150.f},  // (O) - prim 5
318                                         {3.0f, 1.0f, 150.f},   {3.0f, -1.0f, 160.f},  // (P) - prim 6
319                                         {4.0f, 1.0f, 160.f},   {4.0f, -1.0f, 170.f},  // (Q) - prim 7
320                                         {5.0f, 1.0f, 170.f},   {5.0f, -1.0f, 180.f},  // (R) - prim 8
321                                         {6.0f, 1.0f, 180.f}};
322 
323     m_params.verts.push_back(instance1);
324     m_params.verts.push_back(emptyVerts);
325     m_params.aabbs.push_back(emptyVerts);
326     m_params.aabbs.push_back(instance2);
327 
328     std::vector<ResultData> expectedResults = computeExpectedResults();
329 
330     std::vector<ResultData> resultData;
331 
332     switch (m_params.pipelineType)
333     {
334     case RayQueryShaderSourcePipeline::COMPUTE:
335     {
336         resultData = rayQueryComputeTestSetup<ResultData>(
337             m_context.getDeviceInterface(), m_context.getDevice(), m_context.getDefaultAllocator(),
338             m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getBinaryCollection(),
339             m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), m_params);
340         break;
341     }
342     case RayQueryShaderSourcePipeline::RAYTRACING:
343     {
344         m_context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
345         const VkPhysicalDeviceRayTracingPipelineFeaturesKHR &rayTracingPipelineFeaturesKHR =
346             m_context.getRayTracingPipelineFeatures();
347 
348         if (rayTracingPipelineFeaturesKHR.rayTracingPipeline == false)
349             TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
350 
351         resultData = rayQueryRayTracingTestSetup<ResultData>(
352             m_context.getDeviceInterface(), m_context.getDevice(), m_context.getDefaultAllocator(),
353             m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getBinaryCollection(),
354             m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), m_params);
355         break;
356     }
357     case RayQueryShaderSourcePipeline::GRAPHICS:
358     {
359         resultData = rayQueryGraphicsTestSetup<ResultData>(
360             m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueueFamilyIndex(),
361             m_context.getDefaultAllocator(), m_context.getBinaryCollection(), m_context.getUniversalQueue(),
362             m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_params);
363         break;
364     }
365     default:
366     {
367         TCU_FAIL("Invalid shader type!");
368     }
369     }
370 
371     bool mismatch = false;
372 
373     tcu::Surface resultImage(width, height);
374     for (uint32_t x = 0; x < static_cast<uint32_t>(resultImage.getWidth()); ++x)
375     {
376         for (uint32_t y = 0; y < static_cast<uint32_t>(resultImage.getHeight()); ++y)
377         {
378             uint32_t index = x * resultImage.getHeight() + y;
379             if (resultData[index].equal(expectedResults[index]))
380             {
381                 resultImage.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
382             }
383             else
384             {
385                 mismatch = true;
386                 resultImage.setPixel(x, y, tcu::RGBA(0, 0, 0, 255));
387             }
388         }
389     }
390 
391     // Write Image
392     m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
393                                         << tcu::TestLog::Image("Result", "Result", resultImage)
394                                         << tcu::TestLog::EndImageSet;
395 
396     if (mismatch)
397         TCU_FAIL("Result data did not match expected output");
398 
399     return tcu::TestStatus::pass("pass");
400 }
401 
402 } // anonymous namespace
403 
createMultipleRayQueryTests(tcu::TestContext & testCtx)404 tcu::TestCaseGroup *createMultipleRayQueryTests(tcu::TestContext &testCtx)
405 {
406     struct ShaderSourceTypeData
407     {
408         RayQueryShaderSourceType shaderSourceType;
409         RayQueryShaderSourcePipeline shaderSourcePipeline;
410         const char *name;
411     } shaderSourceTypes[] = {
412         {RayQueryShaderSourceType::VERTEX, RayQueryShaderSourcePipeline::GRAPHICS, "vertex_shader"},
413         {RayQueryShaderSourceType::TESSELLATION_CONTROL, RayQueryShaderSourcePipeline::GRAPHICS, "tess_control_shader"},
414         {RayQueryShaderSourceType::TESSELLATION_EVALUATION, RayQueryShaderSourcePipeline::GRAPHICS,
415          "tess_evaluation_shader"},
416         {
417             RayQueryShaderSourceType::GEOMETRY,
418             RayQueryShaderSourcePipeline::GRAPHICS,
419             "geometry_shader",
420         },
421         {
422             RayQueryShaderSourceType::FRAGMENT,
423             RayQueryShaderSourcePipeline::GRAPHICS,
424             "fragment_shader",
425         },
426         {
427             RayQueryShaderSourceType::COMPUTE,
428             RayQueryShaderSourcePipeline::COMPUTE,
429             "compute_shader",
430         },
431         {
432             RayQueryShaderSourceType::RAY_GENERATION,
433             RayQueryShaderSourcePipeline::RAYTRACING,
434             "rgen_shader",
435         },
436         {
437             RayQueryShaderSourceType::INTERSECTION,
438             RayQueryShaderSourcePipeline::RAYTRACING,
439             "isect_shader",
440         },
441         {
442             RayQueryShaderSourceType::ANY_HIT,
443             RayQueryShaderSourcePipeline::RAYTRACING,
444             "ahit_shader",
445         },
446         {
447             RayQueryShaderSourceType::CLOSEST_HIT,
448             RayQueryShaderSourcePipeline::RAYTRACING,
449             "chit_shader",
450         },
451         {
452             RayQueryShaderSourceType::MISS,
453             RayQueryShaderSourcePipeline::RAYTRACING,
454             "miss_shader",
455         },
456         {
457             RayQueryShaderSourceType::CALLABLE,
458             RayQueryShaderSourcePipeline::RAYTRACING,
459             "call_shader",
460         },
461     };
462 
463     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "multiple_ray_queries"));
464 
465     for (size_t shaderSourceNdx = 0; shaderSourceNdx < DE_LENGTH_OF_ARRAY(shaderSourceTypes); ++shaderSourceNdx)
466     {
467         RayQueryTestParams testParams{};
468         testParams.shaderSourceType = shaderSourceTypes[shaderSourceNdx].shaderSourceType;
469         testParams.pipelineType     = shaderSourceTypes[shaderSourceNdx].shaderSourcePipeline;
470         group->addChild(
471             new MultipleRayQueriesCase(group->getTestContext(), shaderSourceTypes[shaderSourceNdx].name, testParams));
472     }
473 
474     return group.release();
475 }
476 
477 } // namespace RayQuery
478 } // namespace vkt
479