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