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 "vktSubgroupsBallotBroadcastTests.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_BROADCAST = 0,
42 OPTYPE_BROADCAST_NONCONST,
43 OPTYPE_BROADCAST_FIRST,
44 OPTYPE_LAST
45 };
46
47 struct CaseDefinition
48 {
49 OpType opType;
50 VkShaderStageFlags shaderStage;
51 VkFormat format;
52 de::SharedPtr<bool> geometryPointSizeSupported;
53 bool extShaderSubGroupBallotTests;
54 bool subgroupSizeControl;
55 uint32_t requiredSubgroupSize;
56 bool requires8BitUniformBuffer;
57 bool requires16BitUniformBuffer;
58 };
59
checkVertexPipelineStages(const void * internalData,vector<const void * > datas,uint32_t width,uint32_t)60 bool checkVertexPipelineStages(const void *internalData, vector<const void *> datas, uint32_t width, uint32_t)
61 {
62 DE_UNREF(internalData);
63
64 return subgroups::check(datas, width, 3);
65 }
66
checkComputeOrMesh(const void * internalData,vector<const void * > datas,const uint32_t numWorkgroups[3],const uint32_t localSize[3],uint32_t)67 bool checkComputeOrMesh(const void *internalData, vector<const void *> datas, const uint32_t numWorkgroups[3],
68 const uint32_t localSize[3], uint32_t)
69 {
70 DE_UNREF(internalData);
71
72 return subgroups::checkComputeOrMesh(datas, numWorkgroups, localSize, 3);
73 }
74
getOpTypeCaseName(OpType opType)75 string getOpTypeCaseName(OpType opType)
76 {
77 switch (opType)
78 {
79 case OPTYPE_BROADCAST:
80 return "subgroupbroadcast";
81 case OPTYPE_BROADCAST_NONCONST:
82 return "subgroupbroadcast_nonconst";
83 case OPTYPE_BROADCAST_FIRST:
84 return "subgroupbroadcastfirst";
85 default:
86 TCU_THROW(InternalError, "Unsupported op type");
87 }
88 }
89
getExtHeader(const CaseDefinition & caseDef)90 string getExtHeader(const CaseDefinition &caseDef)
91 {
92 return (caseDef.extShaderSubGroupBallotTests ? "#extension GL_ARB_shader_ballot: enable\n"
93 "#extension GL_KHR_shader_subgroup_basic: enable\n"
94 "#extension GL_ARB_gpu_shader_int64: enable\n" :
95 "#extension GL_KHR_shader_subgroup_ballot: enable\n") +
96 subgroups::getAdditionalExtensionForFormat(caseDef.format);
97 }
98
getTestSrc(const CaseDefinition & caseDef)99 string getTestSrc(const CaseDefinition &caseDef)
100 {
101 ostringstream bdy;
102 string broadcast;
103 string broadcastFirst;
104 string mask;
105 int max;
106 const string fmt = subgroups::getFormatNameForGLSL(caseDef.format);
107
108 if (caseDef.extShaderSubGroupBallotTests)
109 {
110 broadcast = "readInvocationARB";
111 broadcastFirst = "readFirstInvocationARB";
112 mask = "mask = ballotARB(true);\n";
113 max = 64;
114
115 bdy << " uint64_t mask;\n"
116 << mask << " uint sgSize = gl_SubGroupSizeARB;\n"
117 << " uint sgInvocation = gl_SubGroupInvocationARB;\n";
118 }
119 else
120 {
121 broadcast = "subgroupBroadcast";
122 broadcastFirst = "subgroupBroadcastFirst";
123 mask = "mask = subgroupBallot(true);\n";
124
125 if (caseDef.subgroupSizeControl)
126 max = caseDef.requiredSubgroupSize;
127 else
128 max = (int)subgroups::maxSupportedSubgroupSize();
129
130 bdy << " uvec4 mask = subgroupBallot(true);\n"
131 << " uint sgSize = gl_SubgroupSize;\n"
132 << " uint sgInvocation = gl_SubgroupInvocationID;\n";
133 }
134
135 if (caseDef.opType == OPTYPE_BROADCAST)
136 {
137 bdy << " tempRes = 0x3;\n"
138 << " " << fmt << " ops[" << max << "];\n"
139 << " " << fmt << " d = data[sgInvocation];\n";
140
141 for (int i = 0; i < max; i++)
142 bdy << " ops[" << i << "] = " << broadcast << "(d, " << i << "u);\n";
143
144 bdy << " for(int id = 0; id < sgSize; id++)\n"
145 << " {\n"
146 << " if (subgroupBallotBitExtract(mask, id) && ops[id] != data[id])\n"
147 << " {\n"
148 << " tempRes = 0;\n"
149 << " }\n"
150 << " };\n";
151 }
152 else if (caseDef.opType == OPTYPE_BROADCAST_NONCONST)
153 {
154 const string validate = " if (subgroupBallotBitExtract(mask, id) && op != data[id])\n"
155 " tempRes = 0;\n";
156
157 bdy << " tempRes= 0x3;\n"
158 << " for (uint id = 0; id < sgSize; id++)\n"
159 << " {\n"
160 << " " << fmt << " op = " << broadcast << "(data[sgInvocation], id);\n"
161 << validate << " }\n"
162 << " // Test lane id that is only uniform across active lanes\n"
163 << " if (sgInvocation >= sgSize / 2)\n"
164 << " {\n"
165 << " uint id = sgInvocation & ~((sgSize / 2) - 1);\n"
166 << " " << fmt << " op = " << broadcast << "(data[sgInvocation], id);\n"
167 << validate << " }\n";
168 }
169 else if (caseDef.opType == OPTYPE_BROADCAST_FIRST)
170 {
171 bdy << " tempRes = 0;\n"
172 << " uint firstActive = 0;\n"
173 << " for (uint i = 0; i < sgSize; i++)\n"
174 << " {\n"
175 << " if (subgroupBallotBitExtract(mask, i))\n"
176 << " {\n"
177 << " firstActive = i;\n"
178 << " break;\n"
179 << " }\n"
180 << " }\n"
181 << " tempRes |= (" << broadcastFirst << "(data[sgInvocation]) == data[firstActive]) ? 0x1 : 0;\n"
182 << " // make the firstActive invocation inactive now\n"
183 << " if (firstActive != sgInvocation)\n"
184 << " {\n"
185 << mask << " for (uint i = 0; i < sgSize; i++)\n"
186 << " {\n"
187 << " if (subgroupBallotBitExtract(mask, i))\n"
188 << " {\n"
189 << " firstActive = i;\n"
190 << " break;\n"
191 << " }\n"
192 << " }\n"
193 << " tempRes |= (" << broadcastFirst << "(data[sgInvocation]) == data[firstActive]) ? 0x2 : 0;\n"
194 << " }\n"
195 << " else\n"
196 << " {\n"
197 << " // the firstActive invocation didn't partake in the second result so set it to true\n"
198 << " tempRes |= 0x2;\n"
199 << " }\n";
200 }
201 else
202 TCU_THROW(InternalError, "Unknown operation type");
203
204 return bdy.str();
205 }
206
getHelperFunctionARB(const CaseDefinition & caseDef)207 string getHelperFunctionARB(const CaseDefinition &caseDef)
208 {
209 ostringstream bdy;
210
211 if (caseDef.extShaderSubGroupBallotTests == false)
212 return "";
213
214 bdy << "bool subgroupBallotBitExtract(uint64_t value, uint index)\n";
215 bdy << "{\n";
216 bdy << " if (index > 63)\n";
217 bdy << " return false;\n";
218 bdy << " uint64_t mask = 1ul << index;\n";
219 bdy << " if (bool((value & mask)) == true)\n";
220 bdy << " return true;\n";
221 bdy << " return false;\n";
222 bdy << "}\n";
223
224 return bdy.str();
225 }
226
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)227 void initFrameBufferPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
228 {
229 const SpirvVersion spirvVersion =
230 (caseDef.opType == OPTYPE_BROADCAST_NONCONST) ? SPIRV_VERSION_1_5 : SPIRV_VERSION_1_3;
231 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, spirvVersion, 0u);
232 const string extHeader = getExtHeader(caseDef);
233 const string testSrc = getTestSrc(caseDef);
234 const string helperStr = getHelperFunctionARB(caseDef);
235
236 subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format,
237 *caseDef.geometryPointSizeSupported, extHeader, testSrc, helperStr);
238 }
239
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)240 void initPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
241 {
242 const bool spirv15required = caseDef.opType == OPTYPE_BROADCAST_NONCONST;
243 #ifndef CTS_USES_VULKANSC
244 const bool spirv14required =
245 (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
246 #else
247 const bool spirv14required = false;
248 #endif // CTS_USES_VULKANSC
249 const SpirvVersion spirvVersion = spirv15required ? SPIRV_VERSION_1_5 :
250 spirv14required ? SPIRV_VERSION_1_4 :
251 SPIRV_VERSION_1_3;
252 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, spirvVersion, 0u,
253 (spirv14required && !spirv15required));
254 const string extHeader = getExtHeader(caseDef);
255 const string testSrc = getTestSrc(caseDef);
256 const string helperStr = getHelperFunctionARB(caseDef);
257
258 subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format,
259 *caseDef.geometryPointSizeSupported, extHeader, testSrc, helperStr);
260 }
261
supportedCheck(Context & context,CaseDefinition caseDef)262 void supportedCheck(Context &context, CaseDefinition caseDef)
263 {
264 if (!subgroups::isSubgroupSupported(context))
265 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
266
267 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
268 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
269
270 if (!subgroups::isFormatSupportedForDevice(context, caseDef.format))
271 TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
272
273 if (caseDef.requires16BitUniformBuffer)
274 {
275 if (!subgroups::is16BitUBOStorageSupported(context))
276 {
277 TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
278 }
279 }
280
281 if (caseDef.requires8BitUniformBuffer)
282 {
283 if (!subgroups::is8BitUBOStorageSupported(context))
284 {
285 TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
286 }
287 }
288
289 if (caseDef.extShaderSubGroupBallotTests)
290 {
291 context.requireDeviceFunctionality("VK_EXT_shader_subgroup_ballot");
292
293 if (!subgroups::isInt64SupportedForDevice(context))
294 TCU_THROW(NotSupportedError, "Device does not support int64 data types");
295 }
296
297 if ((caseDef.opType == OPTYPE_BROADCAST_NONCONST) && !subgroups::isSubgroupBroadcastDynamicIdSupported(context))
298 TCU_THROW(NotSupportedError, "Device does not support SubgroupBroadcastDynamicId");
299
300 if (caseDef.subgroupSizeControl)
301 {
302 context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
303
304 #ifndef CTS_USES_VULKANSC
305 const VkPhysicalDeviceSubgroupSizeControlFeatures &subgroupSizeControlFeatures =
306 context.getSubgroupSizeControlFeatures();
307 const VkPhysicalDeviceSubgroupSizeControlProperties &subgroupSizeControlProperties =
308 context.getSubgroupSizeControlProperties();
309 #else
310 const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT &subgroupSizeControlFeatures =
311 context.getSubgroupSizeControlFeaturesEXT();
312 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT &subgroupSizeControlProperties =
313 context.getSubgroupSizeControlPropertiesEXT();
314 #endif // CTS_USES_VULKANSC
315
316 if (subgroupSizeControlFeatures.subgroupSizeControl == false)
317 TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
318
319 if (subgroupSizeControlFeatures.computeFullSubgroups == false)
320 TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
321
322 if (caseDef.requiredSubgroupSize < subgroupSizeControlProperties.minSubgroupSize ||
323 caseDef.requiredSubgroupSize > subgroupSizeControlProperties.maxSubgroupSize)
324 {
325 TCU_THROW(NotSupportedError, "Unsupported subgroup size");
326 }
327
328 if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
329 TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
330 }
331
332 *caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
333
334 #ifndef CTS_USES_VULKANSC
335 if (isAllRayTracingStages(caseDef.shaderStage))
336 {
337 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
338 }
339 else if (isAllMeshShadingStages(caseDef.shaderStage))
340 {
341 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
342 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
343
344 if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
345 {
346 const auto &features = context.getMeshShaderFeaturesEXT();
347 if (!features.taskShader)
348 TCU_THROW(NotSupportedError, "Task shaders not supported");
349 }
350 }
351 #endif // CTS_USES_VULKANSC
352
353 subgroups::supportedCheckShader(context, caseDef.shaderStage);
354 }
355
noSSBOtest(Context & context,const CaseDefinition caseDef)356 TestStatus noSSBOtest(Context &context, const CaseDefinition caseDef)
357 {
358 const VkDeviceSize numElements = caseDef.extShaderSubGroupBallotTests ? 64u : subgroups::maxSupportedSubgroupSize();
359 const subgroups::SSBOData inputData = {
360 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
361 subgroups::SSBOData::LayoutStd140, // InputDataLayoutType layout;
362 caseDef.format, // vk::VkFormat format;
363 numElements, // vk::VkDeviceSize numElements;
364 subgroups::SSBOData::BindingUBO, // BindingType bindingType;
365 };
366
367 switch (caseDef.shaderStage)
368 {
369 case VK_SHADER_STAGE_VERTEX_BIT:
370 return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
371 checkVertexPipelineStages);
372 case VK_SHADER_STAGE_GEOMETRY_BIT:
373 return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
374 checkVertexPipelineStages);
375 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
376 return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
377 checkVertexPipelineStages, caseDef.shaderStage);
378 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
379 return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
380 checkVertexPipelineStages, caseDef.shaderStage);
381 default:
382 TCU_THROW(InternalError, "Unhandled shader stage");
383 }
384 }
385
test(Context & context,const CaseDefinition caseDef)386 TestStatus test(Context &context, const CaseDefinition caseDef)
387 {
388 const VkDeviceSize numElements = caseDef.extShaderSubGroupBallotTests ? 64u : subgroups::maxSupportedSubgroupSize();
389 const bool isCompute = isAllComputeStages(caseDef.shaderStage);
390 #ifndef CTS_USES_VULKANSC
391 const bool isMesh = isAllMeshShadingStages(caseDef.shaderStage);
392 #else
393 const bool isMesh = false;
394 #endif // CTS_USES_VULKANSC
395
396 DE_ASSERT(!(isCompute && isMesh));
397
398 if (isCompute || isMesh)
399 {
400 const subgroups::SSBOData inputData = {
401 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
402 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
403 caseDef.format, // vk::VkFormat format;
404 numElements, // vk::VkDeviceSize numElements;
405 };
406
407 if (isCompute)
408 {
409 if (caseDef.subgroupSizeControl)
410 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
411 checkComputeOrMesh, caseDef.requiredSubgroupSize);
412 else
413 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
414 checkComputeOrMesh);
415 }
416 else
417 {
418 if (caseDef.subgroupSizeControl)
419 return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, nullptr, checkComputeOrMesh,
420 caseDef.requiredSubgroupSize);
421 else
422 return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, nullptr, checkComputeOrMesh);
423 }
424 }
425 else if (isAllGraphicsStages(caseDef.shaderStage))
426 {
427 const VkShaderStageFlags stages = subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
428 const subgroups::SSBOData inputData = {
429 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
430 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
431 caseDef.format, // vk::VkFormat format;
432 numElements, // vk::VkDeviceSize numElements;
433 subgroups::SSBOData::BindingSSBO, // bool isImage;
434 4u, // uint32_t binding;
435 stages, // vk::VkShaderStageFlagBits stages;
436 };
437
438 return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages,
439 stages);
440 }
441 #ifndef CTS_USES_VULKANSC
442 else if (isAllRayTracingStages(caseDef.shaderStage))
443 {
444 const VkShaderStageFlags stages = subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
445 const subgroups::SSBOData inputData = {
446 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
447 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
448 caseDef.format, // vk::VkFormat format;
449 numElements, // vk::VkDeviceSize numElements;
450 subgroups::SSBOData::BindingSSBO, // bool isImage;
451 6u, // uint32_t binding;
452 stages, // vk::VkShaderStageFlagBits stages;
453 };
454
455 return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL,
456 checkVertexPipelineStages, stages);
457 }
458 #endif // CTS_USES_VULKANSC
459 else
460 TCU_THROW(InternalError, "Unknown stage or invalid stage set");
461 }
462 } // namespace
463
464 namespace vkt
465 {
466 namespace subgroups
467 {
createSubgroupsBallotBroadcastTests(TestContext & testCtx)468 TestCaseGroup *createSubgroupsBallotBroadcastTests(TestContext &testCtx)
469 {
470 de::MovePtr<TestCaseGroup> group(new TestCaseGroup(testCtx, "ballot_broadcast"));
471 de::MovePtr<TestCaseGroup> graphicGroup(new TestCaseGroup(testCtx, "graphics"));
472 de::MovePtr<TestCaseGroup> computeGroup(new TestCaseGroup(testCtx, "compute"));
473 de::MovePtr<TestCaseGroup> framebufferGroup(new TestCaseGroup(testCtx, "framebuffer"));
474 #ifndef CTS_USES_VULKANSC
475 de::MovePtr<TestCaseGroup> raytracingGroup(new TestCaseGroup(testCtx, "ray_tracing"));
476 de::MovePtr<TestCaseGroup> meshGroup(new TestCaseGroup(testCtx, "mesh"));
477 de::MovePtr<TestCaseGroup> meshGroupARB(new TestCaseGroup(testCtx, "mesh"));
478 #endif // CTS_USES_VULKANSC
479
480 de::MovePtr<TestCaseGroup> groupARB(new TestCaseGroup(testCtx, "ext_shader_subgroup_ballot"));
481 de::MovePtr<TestCaseGroup> graphicGroupARB(new TestCaseGroup(testCtx, "graphics"));
482 de::MovePtr<TestCaseGroup> computeGroupARB(new TestCaseGroup(testCtx, "compute"));
483 de::MovePtr<TestCaseGroup> framebufferGroupARB(new TestCaseGroup(testCtx, "framebuffer"));
484
485 const VkShaderStageFlags fbStages[] = {
486 VK_SHADER_STAGE_VERTEX_BIT,
487 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
488 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
489 VK_SHADER_STAGE_GEOMETRY_BIT,
490 };
491 #ifndef CTS_USES_VULKANSC
492 const VkShaderStageFlags meshStages[] = {
493 VK_SHADER_STAGE_MESH_BIT_EXT,
494 VK_SHADER_STAGE_TASK_BIT_EXT,
495 };
496 #endif // CTS_USES_VULKANSC
497 const bool boolValues[] = {false, true};
498
499 {
500 const vector<VkFormat> formats = subgroups::getAllFormats();
501
502 for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
503 {
504 const VkFormat format = formats[formatIndex];
505 // Vector, boolean and double types are not supported by functions defined in VK_EXT_shader_subgroup_ballot.
506 const bool formatTypeIsSupportedARB =
507 format == VK_FORMAT_R32_SINT || format == VK_FORMAT_R32_UINT || format == VK_FORMAT_R32_SFLOAT;
508 const bool needs8BitUBOStorage = isFormat8bitTy(format);
509 const bool needs16BitUBOStorage = isFormat16BitTy(format);
510
511 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
512 {
513 const OpType opType = static_cast<OpType>(opTypeIndex);
514 const string name = getOpTypeCaseName(opType) + "_" + subgroups::getFormatNameForGLSL(format);
515
516 for (size_t extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(boolValues); ++extNdx)
517 {
518 const bool extShaderSubGroupBallotTests = boolValues[extNdx];
519
520 if (extShaderSubGroupBallotTests && !formatTypeIsSupportedARB)
521 continue;
522
523 {
524 TestCaseGroup *testGroup =
525 extShaderSubGroupBallotTests ? computeGroupARB.get() : computeGroup.get();
526 {
527 const CaseDefinition caseDef = {
528 opType, // OpType opType;
529 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags shaderStage;
530 format, // VkFormat format;
531 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
532 extShaderSubGroupBallotTests, // bool extShaderSubGroupBallotTests;
533 false, // bool subgroupSizeControl;
534 0u, // uint32_t requiredSubgroupSize;
535 false, // bool requires8BitUniformBuffer;
536 false, // bool requires16BitUniformBuffer;
537 };
538
539 addFunctionCaseWithPrograms(testGroup, name, supportedCheck, initPrograms, test, caseDef);
540 }
541
542 for (uint32_t subgroupSize = 1; subgroupSize <= subgroups::maxSupportedSubgroupSize();
543 subgroupSize *= 2)
544 {
545 const CaseDefinition caseDef = {
546 opType, // OpType opType;
547 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags shaderStage;
548 format, // VkFormat format;
549 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
550 extShaderSubGroupBallotTests, // bool extShaderSubGroupBallotTests;
551 true, // bool subgroupSizeControl;
552 subgroupSize, // uint32_t requiredSubgroupSize;
553 false, // bool requires8BitUniformBuffer;
554 false // bool requires16BitUniformBuffer;
555 };
556 const string testName = name + "_requiredsubgroupsize" + de::toString(subgroupSize);
557
558 addFunctionCaseWithPrograms(testGroup, testName, supportedCheck, initPrograms, test,
559 caseDef);
560 }
561 }
562
563 #ifndef CTS_USES_VULKANSC
564 for (const auto &stage : meshStages)
565 {
566 const auto stageName = "_" + getShaderStageName(stage);
567
568 TestCaseGroup *testGroup = extShaderSubGroupBallotTests ? meshGroupARB.get() : meshGroup.get();
569 {
570 const CaseDefinition caseDef = {
571 opType, // OpType opType;
572 stage, // VkShaderStageFlags shaderStage;
573 format, // VkFormat format;
574 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
575 extShaderSubGroupBallotTests, // bool extShaderSubGroupBallotTests;
576 false, // bool subgroupSizeControl;
577 0u, // uint32_t requiredSubgroupSize;
578 false, // bool requires8BitUniformBuffer;
579 false, // bool requires16BitUniformBuffer;
580 };
581
582 addFunctionCaseWithPrograms(testGroup, name + stageName, supportedCheck, initPrograms, test,
583 caseDef);
584 }
585
586 for (uint32_t subgroupSize = 1; subgroupSize <= subgroups::maxSupportedSubgroupSize();
587 subgroupSize *= 2)
588 {
589 const CaseDefinition caseDef = {
590 opType, // OpType opType;
591 stage, // VkShaderStageFlags shaderStage;
592 format, // VkFormat format;
593 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
594 extShaderSubGroupBallotTests, // bool extShaderSubGroupBallotTests;
595 true, // bool subgroupSizeControl;
596 subgroupSize, // uint32_t requiredSubgroupSize;
597 false, // bool requires8BitUniformBuffer;
598 false, // bool requires16BitUniformBuffer;
599 };
600 const string testName =
601 name + "_requiredsubgroupsize" + de::toString(subgroupSize) + stageName;
602
603 addFunctionCaseWithPrograms(testGroup, testName, supportedCheck, initPrograms, test,
604 caseDef);
605 }
606 }
607 #endif // CTS_USES_VULKANSC
608
609 {
610 TestCaseGroup *testGroup =
611 extShaderSubGroupBallotTests ? graphicGroupARB.get() : graphicGroup.get();
612 const CaseDefinition caseDef = {
613 opType, // OpType opType;
614 VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags shaderStage;
615 format, // VkFormat format;
616 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
617 extShaderSubGroupBallotTests, // bool extShaderSubGroupBallotTests;
618 false, // bool subgroupSizeControl;
619 0u, // uint32_t requiredSubgroupSize;
620 false, // bool requires8BitUniformBuffer;
621 false // bool requires16BitUniformBuffer;
622 };
623
624 addFunctionCaseWithPrograms(testGroup, name, supportedCheck, initPrograms, test, caseDef);
625 }
626
627 {
628 TestCaseGroup *testGroup =
629 extShaderSubGroupBallotTests ? framebufferGroupARB.get() : framebufferGroup.get();
630
631 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
632 {
633 const CaseDefinition caseDef = {
634 opType, // OpType opType;
635 fbStages[stageIndex], // VkShaderStageFlags shaderStage;
636 format, // VkFormat format;
637 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
638 extShaderSubGroupBallotTests, // bool extShaderSubGroupBallotTests;
639 false, // bool subgroupSizeControl;
640 0u, // uint32_t requiredSubgroupSize;
641 bool(needs8BitUBOStorage), // bool requires8BitUniformBuffer;
642 bool(needs16BitUBOStorage) // bool requires16BitUniformBuffer;
643 };
644
645 addFunctionCaseWithPrograms(testGroup, name + getShaderStageName(caseDef.shaderStage),
646 supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
647 }
648 }
649 }
650 }
651 }
652 }
653
654 #ifndef CTS_USES_VULKANSC
655 {
656 const vector<VkFormat> formats = subgroups::getAllRayTracingFormats();
657
658 for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
659 {
660 const VkFormat format = formats[formatIndex];
661 const string formatName = subgroups::getFormatNameForGLSL(format);
662
663 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
664 {
665 const OpType opType = static_cast<OpType>(opTypeIndex);
666 const string name = getOpTypeCaseName(opType) + "_" + formatName;
667 const CaseDefinition caseDef = {
668 opType, // OpType opType;
669 SHADER_STAGE_ALL_RAY_TRACING, // VkShaderStageFlags shaderStage;
670 format, // VkFormat format;
671 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
672 false, // bool extShaderSubGroupBallotTests;
673 false, // bool subgroupSizeControl;
674 0, // int requiredSubgroupSize;
675 false, // bool requires8BitUniformBuffer;
676 false // bool requires16BitUniformBuffer;
677 };
678
679 addFunctionCaseWithPrograms(raytracingGroup.get(), name, supportedCheck, initPrograms, test, caseDef);
680 }
681 }
682 }
683 #endif // CTS_USES_VULKANSC
684
685 groupARB->addChild(graphicGroupARB.release());
686 groupARB->addChild(computeGroupARB.release());
687 groupARB->addChild(framebufferGroupARB.release());
688
689 group->addChild(graphicGroup.release());
690 group->addChild(computeGroup.release());
691 group->addChild(framebufferGroup.release());
692 #ifndef CTS_USES_VULKANSC
693 group->addChild(raytracingGroup.release());
694 group->addChild(meshGroup.release());
695 groupARB->addChild(meshGroupARB.release());
696 #endif // CTS_USES_VULKANSC
697 group->addChild(groupARB.release());
698
699 return group.release();
700 }
701 } // namespace subgroups
702 } // namespace vkt
703