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