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