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