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 "vktSubgroupsBallotOtherTests.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_INVERSE_BALLOT = 0,
42 OPTYPE_BALLOT_BIT_EXTRACT,
43 OPTYPE_BALLOT_BIT_COUNT,
44 OPTYPE_BALLOT_INCLUSIVE_BIT_COUNT,
45 OPTYPE_BALLOT_EXCLUSIVE_BIT_COUNT,
46 OPTYPE_BALLOT_FIND_LSB,
47 OPTYPE_BALLOT_FIND_MSB,
48 OPTYPE_LAST
49 };
50
51 struct CaseDefinition
52 {
53 OpType opType;
54 VkShaderStageFlags shaderStage;
55 de::SharedPtr<bool> geometryPointSizeSupported;
56 deBool requiredSubgroupSize;
57 };
58
checkVertexPipelineStages(const void * internalData,vector<const void * > datas,deUint32 width,deUint32)59 bool checkVertexPipelineStages (const void* internalData,
60 vector<const void*> datas,
61 deUint32 width,
62 deUint32)
63 {
64 DE_UNREF(internalData);
65
66 return subgroups::check(datas, width, 0xf);
67 }
68
checkComputeOrMesh(const void * internalData,vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)69 bool checkComputeOrMesh (const void* internalData,
70 vector<const void*> datas,
71 const deUint32 numWorkgroups[3],
72 const deUint32 localSize[3],
73 deUint32)
74 {
75 DE_UNREF(internalData);
76
77 return subgroups::checkComputeOrMesh(datas, numWorkgroups, localSize, 0xf);
78 }
79
getOpTypeName(OpType opType)80 string getOpTypeName (OpType opType)
81 {
82 switch (opType)
83 {
84 case OPTYPE_INVERSE_BALLOT: return "subgroupInverseBallot";
85 case OPTYPE_BALLOT_BIT_EXTRACT: return "subgroupBallotBitExtract";
86 case OPTYPE_BALLOT_BIT_COUNT: return "subgroupBallotBitCount";
87 case OPTYPE_BALLOT_INCLUSIVE_BIT_COUNT: return "subgroupBallotInclusiveBitCount";
88 case OPTYPE_BALLOT_EXCLUSIVE_BIT_COUNT: return "subgroupBallotExclusiveBitCount";
89 case OPTYPE_BALLOT_FIND_LSB: return "subgroupBallotFindLSB";
90 case OPTYPE_BALLOT_FIND_MSB: return "subgroupBallotFindMSB";
91 default: TCU_THROW(InternalError, "Unsupported op type");
92 }
93 }
94
getExtHeader(const CaseDefinition &)95 string getExtHeader (const CaseDefinition&)
96 {
97 return "#extension GL_KHR_shader_subgroup_ballot: enable\n";
98 }
99
getPerStageHeadDeclarations(const CaseDefinition & caseDef)100 vector<string> getPerStageHeadDeclarations (const CaseDefinition& caseDef)
101 {
102 const deUint32 stageCount = subgroups::getStagesCount(caseDef.shaderStage);
103 const bool fragment = (caseDef.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT) != 0;
104 vector<string> result (stageCount, string());
105
106 if (fragment)
107 result.reserve(result.size() + 1);
108
109 for (size_t i = 0; i < result.size(); ++i)
110 {
111 result[i] =
112 "layout(set = 0, binding = " + de::toString(i) + ", std430) buffer Buffer1\n"
113 "{\n"
114 " uint result[];\n"
115 "};\n";
116 }
117
118 if (fragment)
119 {
120 const string fragPart =
121 "layout(location = 0) out uint result;\n"
122 "precision highp int;\n";
123
124 result.push_back(fragPart);
125 }
126
127 return result;
128 }
129
getFramebufferPerStageHeadDeclarations(const CaseDefinition & caseDef)130 vector<string> getFramebufferPerStageHeadDeclarations (const CaseDefinition& caseDef)
131 {
132 vector<string> result;
133
134 DE_UNREF(caseDef);
135
136 result.push_back("layout(location = 0) out float result;\n");
137 result.push_back("layout(location = 0) out float out_color;\n");
138 result.push_back("layout(location = 0) out float out_color[];\n");
139 result.push_back("layout(location = 0) out float out_color;\n");
140
141 return result;
142 }
143
getTestString(const CaseDefinition & caseDef)144 string getTestString (const CaseDefinition& caseDef)
145 {
146 ostringstream bdy;
147
148 bdy << " uvec4 allOnes = uvec4(0xFFFFFFFF);\n"
149 << " uvec4 allZeros = uvec4(0);\n"
150 << " uint tempResult = 0;\n"
151 << "#define MAKE_HIGH_BALLOT_RESULT(i) uvec4("
152 << "i >= 32 ? 0 : (0xFFFFFFFF << i), "
153 << "i >= 64 ? 0 : (0xFFFFFFFF << ((i < 32) ? 0 : (i - 32))), "
154 << "i >= 96 ? 0 : (0xFFFFFFFF << ((i < 64) ? 0 : (i - 64))), "
155 << "i >= 128 ? 0 : (0xFFFFFFFF << ((i < 96) ? 0 : (i - 96))))\n"
156 << "#define MAKE_SINGLE_BIT_BALLOT_RESULT(i) uvec4("
157 << "i >= 32 ? 0 : 0x1 << i, "
158 << "i < 32 || i >= 64 ? 0 : 0x1 << (i - 32), "
159 << "i < 64 || i >= 96 ? 0 : 0x1 << (i - 64), "
160 << "i < 96 || i >= 128 ? 0 : 0x1 << (i - 96))\n";
161
162 switch (caseDef.opType)
163 {
164 default:
165 DE_FATAL("Unknown op type!");
166 break;
167 case OPTYPE_INVERSE_BALLOT:
168 bdy << " tempResult |= subgroupInverseBallot(allOnes) ? 0x1 : 0;\n"
169 << " tempResult |= subgroupInverseBallot(allZeros) ? 0 : 0x2;\n"
170 << " tempResult |= subgroupInverseBallot(subgroupBallot(true)) ? 0x4 : 0;\n"
171 << " tempResult |= 0x8;\n";
172 break;
173 case OPTYPE_BALLOT_BIT_EXTRACT:
174 bdy << " tempResult |= subgroupBallotBitExtract(allOnes, gl_SubgroupInvocationID) ? 0x1 : 0;\n"
175 << " tempResult |= subgroupBallotBitExtract(allZeros, gl_SubgroupInvocationID) ? 0 : 0x2;\n"
176 << " tempResult |= subgroupBallotBitExtract(subgroupBallot(true), gl_SubgroupInvocationID) ? 0x4 : 0;\n"
177 << " tempResult |= 0x8;\n"
178 << " for (uint i = 0; i < gl_SubgroupSize; i++)\n"
179 << " {\n"
180 << " if (!subgroupBallotBitExtract(allOnes, gl_SubgroupInvocationID))\n"
181 << " {\n"
182 << " tempResult &= ~0x8;\n"
183 << " }\n"
184 << " }\n";
185 break;
186 case OPTYPE_BALLOT_BIT_COUNT:
187 bdy << " /* To ensure a 32-bit computation, use a variable with default highp precision. */\n"
188 << " uint SubgroupSize = gl_SubgroupSize;\n"
189 << " tempResult |= SubgroupSize == subgroupBallotBitCount(allOnes) ? 0x1 : 0;\n"
190 << " tempResult |= 0 == subgroupBallotBitCount(allZeros) ? 0x2 : 0;\n"
191 << " tempResult |= 0 < subgroupBallotBitCount(subgroupBallot(true)) ? 0x4 : 0;\n"
192 << " tempResult |= 0 == subgroupBallotBitCount(MAKE_HIGH_BALLOT_RESULT(SubgroupSize)) ? 0x8 : 0;\n";
193 break;
194 case OPTYPE_BALLOT_INCLUSIVE_BIT_COUNT:
195 bdy << " uint inclusiveOffset = gl_SubgroupInvocationID + 1;\n"
196 << " tempResult |= inclusiveOffset == subgroupBallotInclusiveBitCount(allOnes) ? 0x1 : 0;\n"
197 << " tempResult |= 0 == subgroupBallotInclusiveBitCount(allZeros) ? 0x2 : 0;\n"
198 << " tempResult |= 0 < subgroupBallotInclusiveBitCount(subgroupBallot(true)) ? 0x4 : 0;\n"
199 << " tempResult |= 0x8;\n"
200 << " for (uint i = 0; i < 128; i++)\n"
201 << " {\n"
202 << " uint ref = inclusiveOffset - min(inclusiveOffset, i);\n"
203 << " uvec4 b = MAKE_HIGH_BALLOT_RESULT(i);\n"
204 << " uint inclusiveBitCount = subgroupBallotInclusiveBitCount(b);\n"
205 << " if (inclusiveBitCount != ref)\n"
206 << " {\n"
207 << " tempResult &= ~0x8;\n"
208 << " }\n"
209 << " }\n";
210 break;
211 case OPTYPE_BALLOT_EXCLUSIVE_BIT_COUNT:
212 bdy << " uint exclusiveOffset = gl_SubgroupInvocationID;\n"
213 << " tempResult |= exclusiveOffset == subgroupBallotExclusiveBitCount(allOnes) ? 0x1 : 0;\n"
214 << " tempResult |= 0 == subgroupBallotExclusiveBitCount(allZeros) ? 0x2 : 0;\n"
215 << " tempResult |= 0x4;\n"
216 << " tempResult |= 0x8;\n"
217 << " for (uint i = 0; i < 128; i++)\n"
218 << " {\n"
219 << " uint ref = exclusiveOffset - min(exclusiveOffset, i);\n"
220 << " uvec4 b = MAKE_HIGH_BALLOT_RESULT(i);\n"
221 << " uint exclusiveBitCount = subgroupBallotExclusiveBitCount(b);\n"
222 << " if (exclusiveBitCount != ref)\n"
223 << " {\n"
224 << " tempResult &= ~0x8;\n"
225 << " }\n"
226 << " }\n";
227 break;
228 case OPTYPE_BALLOT_FIND_LSB:
229 bdy << " tempResult |= 0 == subgroupBallotFindLSB(allOnes) ? 0x1 : 0;\n"
230 << " if (subgroupElect())\n"
231 << " {\n"
232 << " tempResult |= 0x2;\n"
233 << " }\n"
234 << " else\n"
235 << " {\n"
236 << " tempResult |= 0 < subgroupBallotFindLSB(subgroupBallot(true)) ? 0x2 : 0;\n"
237 << " }\n"
238 << " tempResult |= gl_SubgroupSize > subgroupBallotFindLSB(subgroupBallot(true)) ? 0x4 : 0;\n"
239 << " tempResult |= 0x8;\n"
240 << " for (uint i = 0; i < gl_SubgroupSize; i++)\n"
241 << " {\n"
242 << " if (i != subgroupBallotFindLSB(MAKE_HIGH_BALLOT_RESULT(i)))\n"
243 << " {\n"
244 << " tempResult &= ~0x8;\n"
245 << " }\n"
246 << " }\n";
247 break;
248 case OPTYPE_BALLOT_FIND_MSB:
249 bdy << " tempResult |= (gl_SubgroupSize - 1) == subgroupBallotFindMSB(allOnes) ? 0x1 : 0;\n"
250 << " if (subgroupElect())\n"
251 << " {\n"
252 << " tempResult |= 0x2;\n"
253 << " }\n"
254 << " else\n"
255 << " {\n"
256 << " tempResult |= 0 < subgroupBallotFindMSB(subgroupBallot(true)) ? 0x2 : 0;\n"
257 << " }\n"
258 << " tempResult |= gl_SubgroupSize > subgroupBallotFindMSB(subgroupBallot(true)) ? 0x4 : 0;\n"
259 << " tempResult |= 0x8;\n"
260 << " for (uint i = 0; i < gl_SubgroupSize; i++)\n"
261 << " {\n"
262 << " if (i != subgroupBallotFindMSB(MAKE_SINGLE_BIT_BALLOT_RESULT(i)))\n"
263 << " {\n"
264 << " tempResult &= ~0x8;\n"
265 << " }\n"
266 << " }\n";
267 break;
268 }
269
270 bdy << " tempRes = tempResult;\n";
271
272 return bdy.str();
273 }
274
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)275 void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
276 {
277 const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
278 const string extHeader = getExtHeader(caseDef);
279 const string testSrc = getTestString(caseDef);
280 const vector<string> headDeclarations = getFramebufferPerStageHeadDeclarations(caseDef);
281 const bool pointSizeSupported = *caseDef.geometryPointSizeSupported;
282
283 subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, pointSizeSupported, extHeader, testSrc, "", headDeclarations);
284 }
285
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)286 void initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
287 {
288 #ifndef CTS_USES_VULKANSC
289 const bool spirv14required = (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
290 #else
291 const bool spirv14required = false;
292 #endif // CTS_USES_VULKANSC
293 const SpirvVersion spirvVersion = (spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3);
294 const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, spirvVersion, 0u, spirv14required);
295 const string extHeader = getExtHeader(caseDef);
296 const string testSrc = getTestString(caseDef);
297 const vector<string> headDeclarations = getPerStageHeadDeclarations(caseDef);
298 const bool pointSizeSupported = *caseDef.geometryPointSizeSupported;
299
300 subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, pointSizeSupported, extHeader, testSrc, "", headDeclarations);
301 }
302
supportedCheck(Context & context,CaseDefinition caseDef)303 void supportedCheck (Context& context, CaseDefinition caseDef)
304 {
305 if (!subgroups::isSubgroupSupported(context))
306 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
307
308 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
309 {
310 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
311 }
312
313 if (caseDef.requiredSubgroupSize)
314 {
315 context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
316
317 #ifndef CTS_USES_VULKANSC
318 const VkPhysicalDeviceSubgroupSizeControlFeatures& subgroupSizeControlFeatures = context.getSubgroupSizeControlFeatures();
319 const VkPhysicalDeviceSubgroupSizeControlProperties& subgroupSizeControlProperties = context.getSubgroupSizeControlProperties();
320 #else
321 const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT& subgroupSizeControlFeatures = context.getSubgroupSizeControlFeaturesEXT();
322 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
323 #endif // CTS_USES_VULKANSC
324
325 if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
326 TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
327
328 if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
329 TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
330
331 if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
332 TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
333 }
334
335 *caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
336
337 #ifndef CTS_USES_VULKANSC
338 if (isAllRayTracingStages(caseDef.shaderStage))
339 {
340 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
341 }
342 else if (isAllMeshShadingStages(caseDef.shaderStage))
343 {
344 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
345 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
346
347 if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
348 {
349 const auto& features = context.getMeshShaderFeaturesEXT();
350 if (!features.taskShader)
351 TCU_THROW(NotSupportedError, "Task shaders not supported");
352 }
353 }
354 #endif // CTS_USES_VULKANSC
355
356 subgroups::supportedCheckShader(context, caseDef.shaderStage);
357 }
358
noSSBOtest(Context & context,const CaseDefinition caseDef)359 TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
360 {
361 switch (caseDef.shaderStage)
362 {
363 case VK_SHADER_STAGE_VERTEX_BIT: return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages);
364 case VK_SHADER_STAGE_GEOMETRY_BIT: return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages);
365 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages);
366 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages);
367 default: TCU_THROW(InternalError, "Unhandled shader stage");
368 }
369 }
370
test(Context & context,const CaseDefinition caseDef)371 TestStatus test (Context& context, const CaseDefinition caseDef)
372 {
373 const bool isCompute = isAllComputeStages(caseDef.shaderStage);
374 #ifndef CTS_USES_VULKANSC
375 const bool isMesh = isAllMeshShadingStages(caseDef.shaderStage);
376 #else
377 const bool isMesh = false;
378 #endif // CTS_USES_VULKANSC
379 DE_ASSERT(!(isCompute && isMesh));
380
381 if (isCompute || isMesh)
382 {
383 #ifndef CTS_USES_VULKANSC
384 const VkPhysicalDeviceSubgroupSizeControlProperties& subgroupSizeControlProperties = context.getSubgroupSizeControlProperties();
385 #else
386 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
387 #endif // CTS_USES_VULKANSC
388 TestLog& log = context.getTestContext().getLog();
389
390 if (caseDef.requiredSubgroupSize == DE_FALSE)
391 {
392 if (isCompute)
393 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeOrMesh);
394 else
395 return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, nullptr, 0, nullptr, checkComputeOrMesh);
396 }
397
398 log << TestLog::Message << "Testing required subgroup size range [" << subgroupSizeControlProperties.minSubgroupSize << ", "
399 << subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
400
401 // According to the spec, requiredSubgroupSize must be a power-of-two integer.
402 for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
403 {
404 TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
405
406 if (isCompute)
407 result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0u, DE_NULL, checkComputeOrMesh, size);
408 else
409 result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, nullptr, 0u, nullptr, checkComputeOrMesh, size);
410
411 if (result.getCode() != QP_TEST_RESULT_PASS)
412 {
413 log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
414
415 return result;
416 }
417 }
418
419 return TestStatus::pass("OK");
420 }
421 else if (isAllGraphicsStages(caseDef.shaderStage))
422 {
423 const VkShaderStageFlags stages = subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
424
425 return subgroups::allStages(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages, stages);
426 }
427 #ifndef CTS_USES_VULKANSC
428 else if (isAllRayTracingStages(caseDef.shaderStage))
429 {
430 const VkShaderStageFlags stages = subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
431
432 return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages, stages);
433 }
434 #endif // CTS_USES_VULKANSC
435 else
436 TCU_THROW(InternalError, "Unknown stage or invalid stage set");
437
438 return TestStatus::pass("OK");
439 }
440 }
441
442 namespace vkt
443 {
444 namespace subgroups
445 {
createSubgroupsBallotOtherTests(TestContext & testCtx)446 TestCaseGroup* createSubgroupsBallotOtherTests (TestContext& testCtx)
447 {
448 de::MovePtr<TestCaseGroup> group (new TestCaseGroup(testCtx, "ballot_other", "Subgroup ballot other category tests"));
449 de::MovePtr<TestCaseGroup> graphicGroup (new TestCaseGroup(testCtx, "graphics", "Subgroup ballot other category tests: graphics"));
450 de::MovePtr<TestCaseGroup> computeGroup (new TestCaseGroup(testCtx, "compute", "Subgroup ballot other category tests: compute"));
451 de::MovePtr<TestCaseGroup> framebufferGroup (new TestCaseGroup(testCtx, "framebuffer", "Subgroup ballot other category tests: framebuffer"));
452 #ifndef CTS_USES_VULKANSC
453 de::MovePtr<TestCaseGroup> raytracingGroup (new TestCaseGroup(testCtx, "ray_tracing", "Subgroup ballot other category tests: ray tracing"));
454 de::MovePtr<TestCaseGroup> meshGroup (new TestCaseGroup(testCtx, "mesh", "Subgroup ballot other category tests: mesh shading"));
455 #endif // CTS_USES_VULKANSC
456 const VkShaderStageFlags fbStages[] =
457 {
458 VK_SHADER_STAGE_VERTEX_BIT,
459 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
460 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
461 VK_SHADER_STAGE_GEOMETRY_BIT,
462 };
463 #ifndef CTS_USES_VULKANSC
464 const VkShaderStageFlags meshStages[] =
465 {
466 VK_SHADER_STAGE_MESH_BIT_EXT,
467 VK_SHADER_STAGE_TASK_BIT_EXT,
468 };
469 #endif // CTS_USES_VULKANSC
470 const deBool boolValues[] =
471 {
472 DE_FALSE,
473 DE_TRUE
474 };
475
476 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
477 {
478 const OpType opType = static_cast<OpType>(opTypeIndex);
479 const string op = de::toLower(getOpTypeName(opType));
480
481 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
482 {
483 const deBool requiredSubgroupSize = boolValues[groupSizeNdx];
484 const string testName = op + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
485 const CaseDefinition caseDef =
486 {
487 opType, // OpType opType;
488 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags shaderStage;
489 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
490 requiredSubgroupSize // deBool requiredSubgroupSize;
491 };
492
493 addFunctionCaseWithPrograms(computeGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
494 }
495
496 #ifndef CTS_USES_VULKANSC
497 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
498 {
499 for (const auto& stage : meshStages)
500 {
501 const deBool requiredSubgroupSize = boolValues[groupSizeNdx];
502 const string testName = op + (requiredSubgroupSize ? "_requiredsubgroupsize" : "") + "_" + getShaderStageName(stage);
503 const CaseDefinition caseDef =
504 {
505 opType, // OpType opType;
506 stage, // VkShaderStageFlags shaderStage;
507 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
508 requiredSubgroupSize // deBool requiredSubgroupSize;
509 };
510
511 addFunctionCaseWithPrograms(meshGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
512 }
513 }
514 #endif // CTS_USES_VULKANSC
515
516 {
517 const CaseDefinition caseDef =
518 {
519 opType, // OpType opType;
520 VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags shaderStage;
521 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
522 DE_FALSE // deBool requiredSubgroupSize;
523 };
524
525 addFunctionCaseWithPrograms(graphicGroup.get(), op, "", supportedCheck, initPrograms, test, caseDef);
526 }
527
528 #ifndef CTS_USES_VULKANSC
529 {
530 const CaseDefinition caseDef =
531 {
532 opType, // OpType opType;
533 SHADER_STAGE_ALL_RAY_TRACING, // VkShaderStageFlags shaderStage;
534 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
535 DE_FALSE // deBool requiredSubgroupSize;
536 };
537
538 addFunctionCaseWithPrograms(raytracingGroup.get(), op, "", supportedCheck, initPrograms, test, caseDef);
539 }
540 #endif // CTS_USES_VULKANSC
541
542 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
543 {
544 const CaseDefinition caseDef =
545 {
546 opType, // OpType opType;
547 fbStages[stageIndex], // VkShaderStageFlags shaderStage;
548 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
549 DE_FALSE // deBool requiredSubgroupSize;
550 };
551 const string testName = op + "_" + getShaderStageName(caseDef.shaderStage);
552
553 addFunctionCaseWithPrograms(framebufferGroup.get(), testName, "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
554 }
555 }
556
557 group->addChild(graphicGroup.release());
558 group->addChild(computeGroup.release());
559 group->addChild(framebufferGroup.release());
560 #ifndef CTS_USES_VULKANSC
561 group->addChild(raytracingGroup.release());
562 group->addChild(meshGroup.release());
563 #endif // CTS_USES_VULKANSC
564
565 return group.release();
566 }
567
568 } // subgroups
569 } // vkt
570