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