1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Google Inc.
7 * Copyright (c) 2017 Codeplay Software Ltd.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 */ /*!
22 * \file
23 * \brief Subgroups Tests
24 */ /*--------------------------------------------------------------------*/
25
26 #include "vktSubgroupsShuffleTests.hpp"
27 #include "vktSubgroupsTestsUtils.hpp"
28
29 #include <string>
30 #include <vector>
31
32 using namespace tcu;
33 using namespace std;
34 using namespace vk;
35 using namespace vkt;
36
37 namespace
38 {
39 enum OpType
40 {
41 OPTYPE_SHUFFLE = 0,
42 OPTYPE_SHUFFLE_XOR,
43 OPTYPE_SHUFFLE_UP,
44 OPTYPE_SHUFFLE_DOWN,
45 OPTYPE_LAST
46 };
47
48 struct CaseDefinition
49 {
50 OpType opType;
51 VkShaderStageFlags shaderStage;
52 VkFormat format;
53 de::SharedPtr<bool> geometryPointSizeSupported;
54 deBool requiredSubgroupSize;
55 };
56
checkVertexPipelineStages(const void * internalData,vector<const void * > datas,deUint32 width,deUint32)57 static bool checkVertexPipelineStages (const void* internalData,
58 vector<const void*> datas,
59 deUint32 width,
60 deUint32)
61 {
62 DE_UNREF(internalData);
63
64 return subgroups::check(datas, width, 1);
65 }
66
checkCompute(const void * internalData,vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)67 static bool checkCompute (const void* internalData,
68 vector<const void*> datas,
69 const deUint32 numWorkgroups[3],
70 const deUint32 localSize[3],
71 deUint32)
72 {
73 DE_UNREF(internalData);
74
75 return subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
76 }
77
getOpTypeName(OpType opType)78 string getOpTypeName (OpType opType)
79 {
80 switch (opType)
81 {
82 case OPTYPE_SHUFFLE: return "subgroupShuffle";
83 case OPTYPE_SHUFFLE_XOR: return "subgroupShuffleXor";
84 case OPTYPE_SHUFFLE_UP: return "subgroupShuffleUp";
85 case OPTYPE_SHUFFLE_DOWN: return "subgroupShuffleDown";
86 default: TCU_THROW(InternalError, "Unsupported op type");
87 }
88 }
89
getExtHeader(const CaseDefinition & caseDef)90 string getExtHeader (const CaseDefinition& caseDef)
91 {
92 const string eSource = (OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType)
93 ? "#extension GL_KHR_shader_subgroup_shuffle: enable\n"
94 : "#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
95
96 return eSource
97 + "#extension GL_KHR_shader_subgroup_ballot: enable\n"
98 + subgroups::getAdditionalExtensionForFormat(caseDef.format);
99 }
100
getPerStageHeadDeclarations(const CaseDefinition & caseDef)101 vector<string> getPerStageHeadDeclarations (const CaseDefinition& caseDef)
102 {
103 const string formatName = subgroups::getFormatNameForGLSL(caseDef.format);
104 const deUint32 stageCount = subgroups::getStagesCount(caseDef.shaderStage);
105 const bool fragment = (caseDef.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT) != 0;
106 const size_t resultSize = stageCount + (fragment ? 1 : 0);
107 vector<string> result (resultSize, string());
108
109 for (deUint32 i = 0; i < result.size(); ++i)
110 {
111 const deUint32 binding0 = i;
112 const deUint32 binding1 = stageCount;
113 const deUint32 binding2 = stageCount + 1;
114 const string buffer1 = (i == stageCount)
115 ? "layout(location = 0) out uint result;\n"
116 : "layout(set = 0, binding = " + de::toString(binding0) + ", std430) buffer Buffer1\n"
117 "{\n"
118 " uint result[];\n"
119 "};\n";
120
121 result[i] =
122 buffer1 +
123 "layout(set = 0, binding = " + de::toString(binding1) + ", std430) readonly buffer Buffer2\n"
124 "{\n"
125 " " + formatName + " data1[];\n"
126 "};\n"
127 "layout(set = 0, binding = " + de::toString(binding2) + ", std430) readonly buffer Buffer3\n"
128 "{\n"
129 " uint data2[];\n"
130 "};\n";
131 }
132
133 return result;
134 }
135
getFramebufferPerStageHeadDeclarations(const CaseDefinition & caseDef)136 vector<string> getFramebufferPerStageHeadDeclarations (const CaseDefinition& caseDef)
137 {
138 const string formatName = subgroups::getFormatNameForGLSL(caseDef.format);
139 const deUint32 stageCount = subgroups::getStagesCount(caseDef.shaderStage);
140 vector<string> result (stageCount, string());
141 const string buffer2
142 {
143 "layout(set = 0, binding = 0) uniform Buffer1\n"
144 "{\n"
145 " " + formatName + " data1[" + de::toString(subgroups::maxSupportedSubgroupSize()) + "];\n"
146 "};\n"
147 "layout(set = 0, binding = 1) uniform Buffer2\n"
148 "{\n"
149 " uint data2[" + de::toString(subgroups::maxSupportedSubgroupSize()) + "];\n"
150 "};\n"
151 };
152
153 for (size_t i = 0; i < result.size(); ++i)
154 {
155 switch (i)
156 {
157 case 0: result[i] = "layout(location = 0) out float result;\n" + buffer2; break;
158 case 1: result[i] = "layout(location = 0) out float out_color;\n" + buffer2; break;
159 case 2: result[i] = "layout(location = 0) out float out_color[];\n" + buffer2; break;
160 case 3: result[i] = "layout(location = 0) out float out_color;\n" + buffer2; break;
161 default: TCU_THROW(InternalError, "Unknown stage");
162 }
163 }
164
165 return result;
166 }
167
getTestSource(const CaseDefinition & caseDef)168 const string getTestSource (const CaseDefinition& caseDef)
169 {
170 const string id = caseDef.opType == OPTYPE_SHUFFLE ? "id_in"
171 : caseDef.opType == OPTYPE_SHUFFLE_XOR ? "gl_SubgroupInvocationID ^ id_in"
172 : caseDef.opType == OPTYPE_SHUFFLE_UP ? "gl_SubgroupInvocationID - id_in"
173 : caseDef.opType == OPTYPE_SHUFFLE_DOWN ? "gl_SubgroupInvocationID + id_in"
174 : "";
175 const string testSource =
176 " uint temp_res;\n"
177 " uvec4 mask = subgroupBallot(true);\n"
178 " uint id_in = data2[gl_SubgroupInvocationID] & (gl_SubgroupSize - 1);\n"
179 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " op = "
180 + getOpTypeName(caseDef.opType) + "(data1[gl_SubgroupInvocationID], id_in);\n"
181 " uint id = " + id + ";\n"
182 " if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
183 " {\n"
184 " temp_res = (op == data1[id]) ? 1 : 0;\n"
185 " }\n"
186 " else\n"
187 " {\n"
188 " temp_res = 1; // Invocation we read from was inactive, so we can't verify results!\n"
189 " }\n"
190 " tempRes = temp_res;\n";
191
192 return testSource;
193 }
194
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)195 void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
196 {
197 const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
198 const string extHeader = getExtHeader(caseDef);
199 const string testSrc = getTestSource(caseDef);
200 const vector<string> headDeclarations = getFramebufferPerStageHeadDeclarations(caseDef);
201 const bool pointSizeSupported = *caseDef.geometryPointSizeSupported;
202
203 subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, pointSizeSupported, extHeader, testSrc, "", headDeclarations);
204 }
205
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)206 void initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
207 {
208 const SpirvVersion spirvVersion = isAllRayTracingStages(caseDef.shaderStage) ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3;
209 const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, spirvVersion, 0u);
210 const string extHeader = getExtHeader(caseDef);
211 const string testSrc = getTestSource(caseDef);
212 const vector<string> headDeclarations = getPerStageHeadDeclarations(caseDef);
213 const bool pointSizeSupported = *caseDef.geometryPointSizeSupported;
214
215 subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, pointSizeSupported, extHeader, testSrc, "", headDeclarations);
216 }
217
supportedCheck(Context & context,CaseDefinition caseDef)218 void supportedCheck (Context& context, CaseDefinition caseDef)
219 {
220 if (!subgroups::isSubgroupSupported(context))
221 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
222
223 switch (caseDef.opType)
224 {
225 case OPTYPE_SHUFFLE:
226 case OPTYPE_SHUFFLE_XOR:
227 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_SHUFFLE_BIT))
228 {
229 TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
230 }
231 break;
232 default:
233 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
234 {
235 TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
236 }
237 break;
238 }
239
240 if (!subgroups::isFormatSupportedForDevice(context, caseDef.format))
241 TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
242
243 if (caseDef.requiredSubgroupSize)
244 {
245 context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
246
247 const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT& subgroupSizeControlFeatures = context.getSubgroupSizeControlFeaturesEXT();
248 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
249
250 if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
251 TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
252
253 if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
254 TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
255
256 if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
257 TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
258 }
259
260 *caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
261
262 if (isAllRayTracingStages(caseDef.shaderStage))
263 {
264 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
265 }
266
267 subgroups::supportedCheckShader(context, caseDef.shaderStage);
268 }
269
noSSBOtest(Context & context,const CaseDefinition caseDef)270 TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
271 {
272 const subgroups::SSBOData inputData[2]
273 {
274 {
275 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
276 subgroups::SSBOData::LayoutStd140, // InputDataLayoutType layout;
277 caseDef.format, // vk::VkFormat format;
278 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
279 },
280 {
281 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
282 subgroups::SSBOData::LayoutStd140, // InputDataLayoutType layout;
283 VK_FORMAT_R32_UINT, // vk::VkFormat format;
284 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
285 }
286 };
287
288 switch (caseDef.shaderStage)
289 {
290 case VK_SHADER_STAGE_VERTEX_BIT: return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages);
291 case VK_SHADER_STAGE_GEOMETRY_BIT: return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages);
292 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
293 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
294 default: TCU_THROW(InternalError, "Unhandled shader stage");
295 }
296 }
297
test(Context & context,const CaseDefinition caseDef)298 TestStatus test (Context& context, const CaseDefinition caseDef)
299 {
300 if (isAllComputeStages(caseDef.shaderStage))
301 {
302 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
303 TestLog& log = context.getTestContext().getLog();
304 const subgroups::SSBOData inputData[2]
305 {
306 {
307 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
308 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
309 caseDef.format, // vk::VkFormat format;
310 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
311 },
312 {
313 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
314 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
315 VK_FORMAT_R32_UINT, // vk::VkFormat format;
316 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
317 },
318 };
319
320 if (caseDef.requiredSubgroupSize == DE_FALSE)
321 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkCompute);
322
323 log << TestLog::Message << "Testing required subgroup size range [" << subgroupSizeControlProperties.minSubgroupSize << ", "
324 << subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
325
326 // According to the spec, requiredSubgroupSize must be a power-of-two integer.
327 for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
328 {
329 TestStatus result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkCompute,
330 size, VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT);
331 if (result.getCode() != QP_TEST_RESULT_PASS)
332 {
333 log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
334 return result;
335 }
336 }
337
338 return TestStatus::pass("OK");
339 }
340 else if (isAllGraphicsStages(caseDef.shaderStage))
341 {
342 const VkShaderStageFlags stages = subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
343 const subgroups::SSBOData inputData[2]
344 {
345 {
346 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
347 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
348 caseDef.format, // vk::VkFormat format;
349 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
350 false, // bool isImage;
351 4u, // deUint32 binding;
352 stages, // vk::VkShaderStageFlags stages;
353 },
354 {
355 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
356 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
357 VK_FORMAT_R32_UINT, // vk::VkFormat format;
358 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
359 false, // bool isImage;
360 5u, // deUint32 binding;
361 stages, // vk::VkShaderStageFlags stages;
362 },
363 };
364
365 return subgroups::allStages(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, stages);
366 }
367 else if (isAllRayTracingStages(caseDef.shaderStage))
368 {
369 const VkShaderStageFlags stages = subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
370 const subgroups::SSBOData inputData[2]
371 {
372 {
373 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
374 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
375 caseDef.format, // vk::VkFormat format;
376 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
377 false, // bool isImage;
378 6u, // deUint32 binding;
379 stages, // vk::VkShaderStageFlags stages;
380 },
381 {
382 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
383 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
384 VK_FORMAT_R32_UINT, // vk::VkFormat format;
385 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
386 false, // bool isImage;
387 7u, // deUint32 binding;
388 stages, // vk::VkShaderStageFlags stages;
389 },
390 };
391
392 return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, inputData, 2, DE_NULL, checkVertexPipelineStages, stages);
393 }
394 else
395 TCU_THROW(InternalError, "Unknown stage or invalid stage set");
396 }
397 }
398
399 namespace vkt
400 {
401 namespace subgroups
402 {
createSubgroupsShuffleTests(TestContext & testCtx)403 TestCaseGroup* createSubgroupsShuffleTests (TestContext& testCtx)
404 {
405 de::MovePtr<TestCaseGroup> group (new TestCaseGroup(testCtx, "shuffle", "Subgroup shuffle category tests"));
406 de::MovePtr<TestCaseGroup> graphicGroup (new TestCaseGroup(testCtx, "graphics", "Subgroup shuffle category tests: graphics"));
407 de::MovePtr<TestCaseGroup> computeGroup (new TestCaseGroup(testCtx, "compute", "Subgroup shuffle category tests: compute"));
408 de::MovePtr<TestCaseGroup> framebufferGroup (new TestCaseGroup(testCtx, "framebuffer", "Subgroup shuffle category tests: framebuffer"));
409 de::MovePtr<TestCaseGroup> raytracingGroup (new TestCaseGroup(testCtx, "ray_tracing", "Subgroup shuffle category tests: ray tracing"));
410 const VkShaderStageFlags stages[] =
411 {
412 VK_SHADER_STAGE_VERTEX_BIT,
413 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
414 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
415 VK_SHADER_STAGE_GEOMETRY_BIT,
416 };
417 const deBool boolValues[] =
418 {
419 DE_FALSE,
420 DE_TRUE
421 };
422
423 {
424 const vector<VkFormat> formats = subgroups::getAllFormats();
425
426 for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
427 {
428 const VkFormat format = formats[formatIndex];
429 const string formatName = subgroups::getFormatNameForGLSL(format);
430
431 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
432 {
433 const OpType opType = static_cast<OpType>(opTypeIndex);
434 const string name = de::toLower(getOpTypeName(opType)) + "_" + formatName;
435
436 {
437 const CaseDefinition caseDef =
438 {
439 opType, // OpType opType;
440 VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags shaderStage;
441 format, // VkFormat format;
442 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
443 DE_FALSE // deBool requiredSubgroupSize;
444 };
445
446 addFunctionCaseWithPrograms(graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
447 }
448
449 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
450 {
451 const deBool requiredSubgroupSize = boolValues[groupSizeNdx];
452 const string testName = name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
453 const CaseDefinition caseDef =
454 {
455 opType, // OpType opType;
456 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags shaderStage;
457 format, // VkFormat format;
458 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
459 requiredSubgroupSize, // deBool requiredSubgroupSize;
460 };
461
462 addFunctionCaseWithPrograms(computeGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
463 }
464
465 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
466 {
467 const CaseDefinition caseDef =
468 {
469 opType, // OpType opType;
470 stages[stageIndex], // VkShaderStageFlags shaderStage;
471 format, // VkFormat format;
472 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
473 DE_FALSE // deBool requiredSubgroupSize;
474 };
475 const string testName = name + "_" + getShaderStageName(caseDef.shaderStage);
476
477 addFunctionCaseWithPrograms(framebufferGroup.get(), testName, "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
478 }
479 }
480 }
481 }
482
483 {
484 const vector<VkFormat> formats = subgroups::getAllRayTracingFormats();
485
486 for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
487 {
488 const VkFormat format = formats[formatIndex];
489 const string formatName = subgroups::getFormatNameForGLSL(format);
490
491 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
492 {
493 const OpType opType = static_cast<OpType>(opTypeIndex);
494 const string name = de::toLower(getOpTypeName(opType)) + "_" + formatName;
495 const CaseDefinition caseDef =
496 {
497 opType, // OpType opType;
498 SHADER_STAGE_ALL_RAY_TRACING, // VkShaderStageFlags shaderStage;
499 format, // VkFormat format;
500 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
501 DE_FALSE // deBool requiredSubgroupSize;
502 };
503
504 addFunctionCaseWithPrograms(raytracingGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
505 }
506 }
507 }
508
509 group->addChild(graphicGroup.release());
510 group->addChild(computeGroup.release());
511 group->addChild(framebufferGroup.release());
512 group->addChild(raytracingGroup.release());
513
514 return group.release();
515 }
516
517 } // subgroups
518 } // vkt
519