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 "vktSubgroupsArithmeticTests.hpp"
27 #include "vktSubgroupsScanHelpers.hpp"
28 #include "vktSubgroupsTestsUtils.hpp"
29
30 #include <string>
31 #include <vector>
32
33 using namespace tcu;
34 using namespace std;
35 using namespace vk;
36 using namespace vkt;
37
38 namespace
39 {
40 enum OpType
41 {
42 OPTYPE_ADD = 0,
43 OPTYPE_MUL,
44 OPTYPE_MIN,
45 OPTYPE_MAX,
46 OPTYPE_AND,
47 OPTYPE_OR,
48 OPTYPE_XOR,
49 OPTYPE_INCLUSIVE_ADD,
50 OPTYPE_INCLUSIVE_MUL,
51 OPTYPE_INCLUSIVE_MIN,
52 OPTYPE_INCLUSIVE_MAX,
53 OPTYPE_INCLUSIVE_AND,
54 OPTYPE_INCLUSIVE_OR,
55 OPTYPE_INCLUSIVE_XOR,
56 OPTYPE_EXCLUSIVE_ADD,
57 OPTYPE_EXCLUSIVE_MUL,
58 OPTYPE_EXCLUSIVE_MIN,
59 OPTYPE_EXCLUSIVE_MAX,
60 OPTYPE_EXCLUSIVE_AND,
61 OPTYPE_EXCLUSIVE_OR,
62 OPTYPE_EXCLUSIVE_XOR,
63 OPTYPE_LAST
64 };
65
66 struct CaseDefinition
67 {
68 Operator op;
69 ScanType scanType;
70 VkShaderStageFlags shaderStage;
71 VkFormat format;
72 de::SharedPtr<bool> geometryPointSizeSupported;
73 deBool requiredSubgroupSize;
74 };
75
getOperator(OpType opType)76 static Operator getOperator (OpType opType)
77 {
78 switch (opType)
79 {
80 case OPTYPE_ADD:
81 case OPTYPE_INCLUSIVE_ADD:
82 case OPTYPE_EXCLUSIVE_ADD:
83 return OPERATOR_ADD;
84 case OPTYPE_MUL:
85 case OPTYPE_INCLUSIVE_MUL:
86 case OPTYPE_EXCLUSIVE_MUL:
87 return OPERATOR_MUL;
88 case OPTYPE_MIN:
89 case OPTYPE_INCLUSIVE_MIN:
90 case OPTYPE_EXCLUSIVE_MIN:
91 return OPERATOR_MIN;
92 case OPTYPE_MAX:
93 case OPTYPE_INCLUSIVE_MAX:
94 case OPTYPE_EXCLUSIVE_MAX:
95 return OPERATOR_MAX;
96 case OPTYPE_AND:
97 case OPTYPE_INCLUSIVE_AND:
98 case OPTYPE_EXCLUSIVE_AND:
99 return OPERATOR_AND;
100 case OPTYPE_OR:
101 case OPTYPE_INCLUSIVE_OR:
102 case OPTYPE_EXCLUSIVE_OR:
103 return OPERATOR_OR;
104 case OPTYPE_XOR:
105 case OPTYPE_INCLUSIVE_XOR:
106 case OPTYPE_EXCLUSIVE_XOR:
107 return OPERATOR_XOR;
108 default:
109 DE_FATAL("Unsupported op type");
110 return OPERATOR_ADD;
111 }
112 }
113
getScanType(OpType opType)114 static ScanType getScanType(OpType opType)
115 {
116 switch (opType)
117 {
118 case OPTYPE_ADD:
119 case OPTYPE_MUL:
120 case OPTYPE_MIN:
121 case OPTYPE_MAX:
122 case OPTYPE_AND:
123 case OPTYPE_OR:
124 case OPTYPE_XOR:
125 return SCAN_REDUCE;
126 case OPTYPE_INCLUSIVE_ADD:
127 case OPTYPE_INCLUSIVE_MUL:
128 case OPTYPE_INCLUSIVE_MIN:
129 case OPTYPE_INCLUSIVE_MAX:
130 case OPTYPE_INCLUSIVE_AND:
131 case OPTYPE_INCLUSIVE_OR:
132 case OPTYPE_INCLUSIVE_XOR:
133 return SCAN_INCLUSIVE;
134 case OPTYPE_EXCLUSIVE_ADD:
135 case OPTYPE_EXCLUSIVE_MUL:
136 case OPTYPE_EXCLUSIVE_MIN:
137 case OPTYPE_EXCLUSIVE_MAX:
138 case OPTYPE_EXCLUSIVE_AND:
139 case OPTYPE_EXCLUSIVE_OR:
140 case OPTYPE_EXCLUSIVE_XOR:
141 return SCAN_EXCLUSIVE;
142 default:
143 DE_FATAL("Unsupported op type");
144 return SCAN_REDUCE;
145 }
146 }
147
checkVertexPipelineStages(const void * internalData,vector<const void * > datas,deUint32 width,deUint32)148 static bool checkVertexPipelineStages (const void* internalData,
149 vector<const void*> datas,
150 deUint32 width,
151 deUint32)
152 {
153 DE_UNREF(internalData);
154
155 return subgroups::check(datas, width, 0x3);
156 }
157
checkComputeOrMesh(const void * internalData,vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)158 static bool checkComputeOrMesh (const void* internalData,
159 vector<const void*> datas,
160 const deUint32 numWorkgroups[3],
161 const deUint32 localSize[3],
162 deUint32)
163 {
164 DE_UNREF(internalData);
165
166 return subgroups::checkComputeOrMesh(datas, numWorkgroups, localSize, 0x3);
167 }
168
getOpTypeName(Operator op,ScanType scanType)169 string getOpTypeName (Operator op, ScanType scanType)
170 {
171 return getScanOpName("subgroup", "", op, scanType);
172 }
173
getExtHeader(const CaseDefinition & caseDef)174 string getExtHeader (const CaseDefinition& caseDef)
175 {
176 return "#extension GL_KHR_shader_subgroup_arithmetic: enable\n"
177 "#extension GL_KHR_shader_subgroup_ballot: enable\n" +
178 subgroups::getAdditionalExtensionForFormat(caseDef.format);
179 }
180
getIndexVars(const CaseDefinition & caseDef)181 string getIndexVars (const CaseDefinition& caseDef)
182 {
183 switch (caseDef.scanType)
184 {
185 case SCAN_REDUCE: return " uint start = 0, end = gl_SubgroupSize;\n";
186 case SCAN_INCLUSIVE: return " uint start = 0, end = gl_SubgroupInvocationID + 1;\n";
187 case SCAN_EXCLUSIVE: return " uint start = 0, end = gl_SubgroupInvocationID;\n";
188 default: TCU_THROW(InternalError, "Unreachable");
189 }
190 }
191
getTestSrc(const CaseDefinition & caseDef)192 string getTestSrc (const CaseDefinition& caseDef)
193 {
194 const string indexVars = getIndexVars(caseDef);
195
196 return " uvec4 mask = subgroupBallot(true);\n"
197 + indexVars +
198 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " ref = "
199 + getIdentity(caseDef.op, caseDef.format) + ";\n"
200 " tempRes = 0;\n"
201 " for (uint index = start; index < end; index++)\n"
202 " {\n"
203 " if (subgroupBallotBitExtract(mask, index))\n"
204 " {\n"
205 " ref = " + getOpOperation(caseDef.op, caseDef.format, "ref", "data[index]") + ";\n"
206 " }\n"
207 " }\n"
208 " tempRes = " + getCompare(caseDef.op, caseDef.format, "ref", getOpTypeName(caseDef.op, caseDef.scanType) + "(data[gl_SubgroupInvocationID])") + " ? 0x1 : 0;\n"
209 " if (1 == (gl_SubgroupInvocationID % 2))\n"
210 " {\n"
211 " mask = subgroupBallot(true);\n"
212 " ref = " + getIdentity(caseDef.op, caseDef.format) + ";\n"
213 " for (uint index = start; index < end; index++)\n"
214 " {\n"
215 " if (subgroupBallotBitExtract(mask, index))\n"
216 " {\n"
217 " ref = " + getOpOperation(caseDef.op, caseDef.format, "ref", "data[index]") + ";\n"
218 " }\n"
219 " }\n"
220 " tempRes |= " + getCompare(caseDef.op, caseDef.format, "ref", getOpTypeName(caseDef.op, caseDef.scanType) + "(data[gl_SubgroupInvocationID])") + " ? 0x2 : 0;\n"
221 " }\n"
222 " else\n"
223 " {\n"
224 " tempRes |= 0x2;\n"
225 " }\n";
226 }
227
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)228 void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
229 {
230 const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
231 const string extHeader = getExtHeader(caseDef);
232 const string testSrc = getTestSrc(caseDef);
233
234 subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, extHeader, testSrc, "");
235 }
236
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)237 void initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
238 {
239 #ifndef CTS_USES_VULKANSC
240 const bool spirv14required = (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
241 #else
242 const bool spirv14required = false;
243 #endif // CTS_USES_VULKANSC
244 const SpirvVersion spirvVersion = spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3;
245 const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, spirvVersion, 0u, spirv14required);
246 const string extHeader = getExtHeader(caseDef);
247 const string testSrc = getTestSrc(caseDef);
248
249 subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, extHeader, testSrc, "");
250 }
251
supportedCheck(Context & context,CaseDefinition caseDef)252 void supportedCheck (Context& context, CaseDefinition caseDef)
253 {
254 if (!subgroups::isSubgroupSupported(context))
255 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
256
257 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_ARITHMETIC_BIT))
258 TCU_THROW(NotSupportedError, "Device does not support subgroup arithmetic operations");
259
260 if (!subgroups::isFormatSupportedForDevice(context, caseDef.format))
261 TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations");
262
263 if (caseDef.requiredSubgroupSize)
264 {
265 context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
266
267 #ifndef CTS_USES_VULKANSC
268 const VkPhysicalDeviceSubgroupSizeControlFeatures& subgroupSizeControlFeatures = context.getSubgroupSizeControlFeatures();
269 const VkPhysicalDeviceSubgroupSizeControlProperties& subgroupSizeControlProperties = context.getSubgroupSizeControlProperties();
270 #else
271 const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT& subgroupSizeControlFeatures = context.getSubgroupSizeControlFeaturesEXT();
272 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
273 #endif // CTS_USES_VULKANSC
274
275 if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
276 TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
277
278 if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
279 TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
280
281 if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
282 TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
283 }
284
285 *caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
286
287 #ifndef CTS_USES_VULKANSC
288 if (isAllRayTracingStages(caseDef.shaderStage))
289 {
290 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
291 }
292 else if (isAllMeshShadingStages(caseDef.shaderStage))
293 {
294 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
295 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
296
297 if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
298 {
299 const auto& features = context.getMeshShaderFeaturesEXT();
300 if (!features.taskShader)
301 TCU_THROW(NotSupportedError, "Task shaders not supported");
302 }
303 }
304 #endif // CTS_USES_VULKANSC
305
306 subgroups::supportedCheckShader(context, caseDef.shaderStage);
307 }
308
noSSBOtest(Context & context,const CaseDefinition caseDef)309 TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
310 {
311 const subgroups::SSBOData inputData =
312 {
313 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
314 subgroups::SSBOData::LayoutStd140, // InputDataLayoutType layout;
315 caseDef.format, // vk::VkFormat format;
316 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
317 subgroups::SSBOData::BindingUBO, // BindingType bindingType;
318 };
319
320 switch (caseDef.shaderStage)
321 {
322 case VK_SHADER_STAGE_VERTEX_BIT: return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages);
323 case VK_SHADER_STAGE_GEOMETRY_BIT: return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages);
324 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
325 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, caseDef.shaderStage);
326 default: TCU_THROW(InternalError, "Unhandled shader stage");
327 }
328 }
329
test(Context & context,const CaseDefinition caseDef)330 TestStatus test (Context& context, const CaseDefinition caseDef)
331 {
332 const bool isCompute = isAllComputeStages(caseDef.shaderStage);
333 #ifndef CTS_USES_VULKANSC
334 const bool isMesh = isAllMeshShadingStages(caseDef.shaderStage);
335 #else
336 const bool isMesh = false;
337 #endif // CTS_USES_VULKANSC
338 DE_ASSERT(!(isCompute && isMesh));
339
340 if (isCompute || isMesh)
341 {
342 #ifndef CTS_USES_VULKANSC
343 const VkPhysicalDeviceSubgroupSizeControlProperties& subgroupSizeControlProperties = context.getSubgroupSizeControlProperties();
344 #else
345 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
346 #endif // CTS_USES_VULKANSC
347 TestLog& log = context.getTestContext().getLog();
348 const subgroups::SSBOData inputData =
349 {
350 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
351 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
352 caseDef.format, // vk::VkFormat format;
353 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
354 };
355
356 if (caseDef.requiredSubgroupSize == DE_FALSE)
357 {
358 if (isMesh)
359 return subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh);
360 else
361 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh);
362 }
363
364 log << TestLog::Message << "Testing required subgroup size range [" << subgroupSizeControlProperties.minSubgroupSize << ", "
365 << subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
366
367 // According to the spec, requiredSubgroupSize must be a power-of-two integer.
368 for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
369 {
370 TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
371
372 if (isCompute)
373 result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh, size);
374 else
375 result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkComputeOrMesh, size);
376
377 if (result.getCode() != QP_TEST_RESULT_PASS)
378 {
379 log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
380 return result;
381 }
382 }
383
384 return TestStatus::pass("OK");
385 }
386 else if (isAllGraphicsStages(caseDef.shaderStage))
387 {
388 const VkShaderStageFlags stages = subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
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 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
395 subgroups::SSBOData::BindingSSBO, // bool isImage;
396 4u, // deUint32 binding;
397 stages, // vk::VkShaderStageFlags stages;
398 };
399
400 return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages);
401 }
402 #ifndef CTS_USES_VULKANSC
403 else if (isAllRayTracingStages(caseDef.shaderStage))
404 {
405 const VkShaderStageFlags stages = subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
406 const subgroups::SSBOData inputData =
407 {
408 subgroups::SSBOData::InitializeNonZero, // InputDataInitializeType initializeType;
409 subgroups::SSBOData::LayoutStd430, // InputDataLayoutType layout;
410 caseDef.format, // vk::VkFormat format;
411 subgroups::maxSupportedSubgroupSize(), // vk::VkDeviceSize numElements;
412 subgroups::SSBOData::BindingSSBO, // bool isImage;
413 6u, // deUint32 binding;
414 stages, // vk::VkShaderStageFlags stages;
415 };
416
417 return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages);
418 }
419 #endif // CTS_USES_VULKANSC
420 else
421 TCU_THROW(InternalError, "Unknown stage or invalid stage set");
422 }
423 }
424
425 namespace vkt
426 {
427 namespace subgroups
428 {
createSubgroupsArithmeticTests(TestContext & testCtx)429 TestCaseGroup* createSubgroupsArithmeticTests (TestContext& testCtx)
430 {
431 de::MovePtr<TestCaseGroup> group (new TestCaseGroup(testCtx, "arithmetic", "Subgroup arithmetic category tests"));
432
433 de::MovePtr<TestCaseGroup> graphicGroup (new TestCaseGroup(testCtx, "graphics", "Subgroup arithmetic category tests: graphics"));
434 de::MovePtr<TestCaseGroup> computeGroup (new TestCaseGroup(testCtx, "compute", "Subgroup arithmetic category tests: compute"));
435 de::MovePtr<TestCaseGroup> framebufferGroup (new TestCaseGroup(testCtx, "framebuffer", "Subgroup arithmetic category tests: framebuffer"));
436 #ifndef CTS_USES_VULKANSC
437 de::MovePtr<TestCaseGroup> raytracingGroup (new TestCaseGroup(testCtx, "ray_tracing", "Subgroup arithmetic category tests: ray tracing"));
438 de::MovePtr<TestCaseGroup> meshGroup (new TestCaseGroup(testCtx, "mesh", "Subgroup arithmetic category tests: mesh"));
439 #endif // CTS_USES_VULKANSC
440
441 const VkShaderStageFlags fbStages[] =
442 {
443 VK_SHADER_STAGE_VERTEX_BIT,
444 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
445 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
446 VK_SHADER_STAGE_GEOMETRY_BIT,
447 };
448 #ifndef CTS_USES_VULKANSC
449 const VkShaderStageFlags meshStages[] =
450 {
451 VK_SHADER_STAGE_MESH_BIT_EXT,
452 VK_SHADER_STAGE_TASK_BIT_EXT,
453 };
454 #endif // CTS_USES_VULKANSC
455 const deBool boolValues[] =
456 {
457 DE_FALSE,
458 DE_TRUE
459 };
460
461 {
462 const vector<VkFormat> formats = subgroups::getAllFormats();
463
464 for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
465 {
466 const VkFormat format = formats[formatIndex];
467 const string formatName = subgroups::getFormatNameForGLSL(format);
468 const bool isBool = subgroups::isFormatBool(format);
469 const bool isFloat = subgroups::isFormatFloat(format);
470
471 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
472 {
473 const OpType opType = static_cast<OpType>(opTypeIndex);
474 const Operator op = getOperator(opType);
475 const ScanType st = getScanType(opType);
476 const bool isBitwiseOp = (op == OPERATOR_AND || op == OPERATOR_OR || op == OPERATOR_XOR);
477
478 // Skip float with bitwise category.
479 if (isFloat && isBitwiseOp)
480 continue;
481
482 // Skip bool when its not the bitwise category.
483 if (isBool && !isBitwiseOp)
484 continue;
485
486 const string name = de::toLower(getOpTypeName(op, st)) + "_" + formatName;
487
488 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
489 {
490 const deBool requiredSubgroupSize = boolValues[groupSizeNdx];
491 const string testName = name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
492 const CaseDefinition caseDef =
493 {
494 op, // Operator op;
495 st, // ScanType scanType;
496 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags shaderStage;
497 format, // VkFormat format;
498 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
499 requiredSubgroupSize // deBool requiredSubgroupSize;
500 };
501
502 addFunctionCaseWithPrograms(computeGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
503 }
504
505 #ifndef CTS_USES_VULKANSC
506 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
507 {
508 for (const auto& meshStage : meshStages)
509 {
510 const deBool requiredSubgroupSize = boolValues[groupSizeNdx];
511 const string testName = name + "_" + getShaderStageName(meshStage) + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
512 const CaseDefinition caseDef =
513 {
514 op, // Operator op;
515 st, // ScanType scanType;
516 meshStage, // VkShaderStageFlags shaderStage;
517 format, // VkFormat format;
518 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
519 requiredSubgroupSize // deBool requiredSubgroupSize;
520 };
521
522 addFunctionCaseWithPrograms(meshGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
523 }
524 }
525 #endif // CTS_USES_VULKANSC
526
527 {
528 const CaseDefinition caseDef =
529 {
530 op, // Operator op;
531 st, // ScanType scanType;
532 VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags shaderStage;
533 format, // VkFormat format;
534 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
535 DE_FALSE // deBool requiredSubgroupSize;
536 };
537
538 addFunctionCaseWithPrograms(graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
539 }
540
541 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
542 {
543 const CaseDefinition caseDef =
544 {
545 op, // Operator op;
546 st, // ScanType scanType;
547 fbStages[stageIndex], // VkShaderStageFlags shaderStage;
548 format, // VkFormat format;
549 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
550 DE_FALSE // deBool requiredSubgroupSize;
551 };
552 const string testName = name + "_" + getShaderStageName(caseDef.shaderStage);
553
554 addFunctionCaseWithPrograms(framebufferGroup.get(), testName, "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
555 }
556 }
557 }
558 }
559
560 #ifndef CTS_USES_VULKANSC
561 {
562 const vector<VkFormat> formats = subgroups::getAllRayTracingFormats();
563
564 for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
565 {
566 const VkFormat format = formats[formatIndex];
567 const string formatName = subgroups::getFormatNameForGLSL(format);
568 const bool isBool = subgroups::isFormatBool(format);
569 const bool isFloat = subgroups::isFormatFloat(format);
570
571 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
572 {
573 const OpType opType = static_cast<OpType>(opTypeIndex);
574 const Operator op = getOperator(opType);
575 const ScanType st = getScanType(opType);
576 const bool isBitwiseOp = (op == OPERATOR_AND || op == OPERATOR_OR || op == OPERATOR_XOR);
577
578 // Skip float with bitwise category.
579 if (isFloat && isBitwiseOp)
580 continue;
581
582 // Skip bool when its not the bitwise category.
583 if (isBool && !isBitwiseOp)
584 continue;
585
586 {
587 const CaseDefinition caseDef =
588 {
589 op, // Operator op;
590 st, // ScanType scanType;
591 SHADER_STAGE_ALL_RAY_TRACING, // VkShaderStageFlags shaderStage;
592 format, // VkFormat format;
593 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
594 DE_FALSE // deBool requiredSubgroupSize;
595 };
596 const string name = de::toLower(getOpTypeName(op, st)) + "_" + formatName;
597
598 addFunctionCaseWithPrograms(raytracingGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
599 }
600 }
601 }
602 }
603 #endif // CTS_USES_VULKANSC
604
605 group->addChild(graphicGroup.release());
606 group->addChild(computeGroup.release());
607 group->addChild(framebufferGroup.release());
608 #ifndef CTS_USES_VULKANSC
609 group->addChild(raytracingGroup.release());
610 group->addChild(meshGroup.release());
611 #endif // CTS_USES_VULKANSC
612
613 return group.release();
614 }
615 } // subgroups
616 } // vkt
617