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