• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * OpenGL Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group Inc.
6  * Copyright (c) 2017 Codeplay Software Ltd.
7  * Copyright (c) 2019 NVIDIA Corporation.
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 "glcSubgroupsShuffleTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
28 
29 #include <string>
30 #include <vector>
31 
32 using namespace tcu;
33 using namespace std;
34 
35 namespace glc
36 {
37 namespace subgroups
38 {
39 namespace
40 {
41 enum OpType
42 {
43 	OPTYPE_SHUFFLE = 0,
44 	OPTYPE_SHUFFLE_XOR,
45 	OPTYPE_SHUFFLE_UP,
46 	OPTYPE_SHUFFLE_DOWN,
47 	OPTYPE_LAST
48 };
49 
checkVertexPipelineStages(std::vector<const void * > datas,deUint32 width,deUint32)50 static bool checkVertexPipelineStages(std::vector<const void*> datas,
51 									  deUint32 width, deUint32)
52 {
53 	return glc::subgroups::check(datas, width, 1);
54 }
55 
checkComputeStage(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)56 static bool checkComputeStage(std::vector<const void*> datas,
57 						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
58 						 deUint32)
59 {
60 	return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
61 }
62 
getOpTypeName(int opType)63 std::string getOpTypeName(int opType)
64 {
65 	switch (opType)
66 	{
67 		default:
68 			DE_FATAL("Unsupported op type");
69 			return "";
70 		case OPTYPE_SHUFFLE:
71 			return "subgroupShuffle";
72 		case OPTYPE_SHUFFLE_XOR:
73 			return "subgroupShuffleXor";
74 		case OPTYPE_SHUFFLE_UP:
75 			return "subgroupShuffleUp";
76 		case OPTYPE_SHUFFLE_DOWN:
77 			return "subgroupShuffleDown";
78 	}
79 }
80 
81 struct CaseDefinition
82 {
83 	int					opType;
84 	ShaderStageFlags	shaderStage;
85 	Format				format;
86 };
87 
to_string(int x)88 const std::string to_string(int x) {
89 	std::ostringstream oss;
90 	oss << x;
91 	return oss.str();
92 }
93 
DeclSource(CaseDefinition caseDef,int baseBinding)94 const std::string DeclSource(CaseDefinition caseDef, int baseBinding)
95 {
96 	return
97 		"layout(binding = " + to_string(baseBinding) + ", std430) readonly buffer BufferB0\n"
98 		"{\n"
99 		"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data1[];\n"
100 		"};\n"
101 		"layout(binding = " + to_string(baseBinding + 1) + ", std430) readonly buffer BufferB1\n"
102 		"{\n"
103 		"  uint data2[];\n"
104 		"};\n";
105 }
106 
TestSource(CaseDefinition caseDef)107 const std::string TestSource(CaseDefinition caseDef)
108 {
109 	std::string						idTable[OPTYPE_LAST];
110 	idTable[OPTYPE_SHUFFLE]			= "id_in";
111 	idTable[OPTYPE_SHUFFLE_XOR]		= "gl_SubgroupInvocationID ^ id_in";
112 	idTable[OPTYPE_SHUFFLE_UP]		= "gl_SubgroupInvocationID - id_in";
113 	idTable[OPTYPE_SHUFFLE_DOWN]	= "gl_SubgroupInvocationID + id_in";
114 
115 	const std::string testSource =
116 		"  uint temp_res;\n"
117 		"  uvec4 mask = subgroupBallot(true);\n"
118 		"  uint id_in = data2[gl_SubgroupInvocationID] & (gl_SubgroupSize - 1u);\n"
119 		"  " + subgroups::getFormatNameForGLSL(caseDef.format) + " op = "
120 		+ getOpTypeName(caseDef.opType) + "(data1[gl_SubgroupInvocationID], id_in);\n"
121 		"  uint id = " + idTable[caseDef.opType] + ";\n"
122 		"  if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
123 		"  {\n"
124 		"    temp_res = (op == data1[id]) ? 1u : 0u;\n"
125 		"  }\n"
126 		"  else\n"
127 		"  {\n"
128 		"    temp_res = 1u; // Invocation we read from was inactive, so we can't verify results!\n"
129 		"  }\n";
130 
131 	return testSource;
132 }
133 
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)134 void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
135 {
136 	subgroups::setFragmentShaderFrameBuffer(programCollection);
137 
138 	if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
139 		subgroups::setVertexShaderFrameBuffer(programCollection);
140 
141 	const std::string extSource =
142 	(OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType) ?
143 		"#extension GL_KHR_shader_subgroup_shuffle: enable\n" :
144 		"#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
145 
146 	const std::string testSource = TestSource(caseDef);
147 
148 	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
149 	{
150 		std::ostringstream vertexSrc;
151 		vertexSrc << "${VERSION_DECL}\n"
152 			<< extSource
153 			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
154 			<< "layout(location = 0) in highp vec4 in_position;\n"
155 			<< "layout(location = 0) out float result;\n"
156 			<< "layout(binding = 0, std140) uniform Buffer0\n"
157 			<< "{\n"
158 			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
159 			<< "};\n"
160 			<< "layout(binding = 1, std140) uniform Buffer1\n"
161 			<< "{\n"
162 			<< "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
163 			<< "};\n"
164 			<< "\n"
165 			<< "void main (void)\n"
166 			<< "{\n"
167 			<< testSource
168 			<< "  result = float(temp_res);\n"
169 			<< "  gl_Position = in_position;\n"
170 			<< "  gl_PointSize = 1.0f;\n"
171 			<< "}\n";
172 		programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
173 	}
174 	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
175 	{
176 		std::ostringstream geometry;
177 
178 		geometry << "${VERSION_DECL}\n"
179 			<< extSource
180 			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
181 			<< "layout(points) in;\n"
182 			<< "layout(points, max_vertices = 1) out;\n"
183 			<< "layout(location = 0) out float out_color;\n"
184 			<< "layout(binding = 0, std140) uniform Buffer0\n"
185 			<< "{\n"
186 			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
187 			<< "};\n"
188 			<< "layout(binding = 1, std140) uniform Buffer1\n"
189 			<< "{\n"
190 			<< "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
191 			<< "};\n"
192 			<< "\n"
193 			<< "void main (void)\n"
194 			<< "{\n"
195 			<< testSource
196 			<< "  out_color = float(temp_res);\n"
197 			<< "  gl_Position = gl_in[0].gl_Position;\n"
198 			<< "  EmitVertex();\n"
199 			<< "  EndPrimitive();\n"
200 			<< "}\n";
201 
202 		programCollection.add("geometry") << glu::GeometrySource(geometry.str());
203 	}
204 	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
205 	{
206 		std::ostringstream controlSource;
207 
208 		controlSource << "${VERSION_DECL}\n"
209 			<< extSource
210 			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
211 			<< "layout(vertices = 2) out;\n"
212 			<< "layout(location = 0) out float out_color[];\n"
213 			<< "layout(binding = 0, std140) uniform Buffer0\n"
214 			<< "{\n"
215 			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
216 			<< "};\n"
217 			<< "layout(binding = 1, std140) uniform Buffer1\n"
218 			<< "{\n"
219 			<< "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
220 			<< "};\n"
221 			<< "\n"
222 			<< "void main (void)\n"
223 			<< "{\n"
224 			<< "  if (gl_InvocationID == 0)\n"
225 			<<"  {\n"
226 			<< "    gl_TessLevelOuter[0] = 1.0f;\n"
227 			<< "    gl_TessLevelOuter[1] = 1.0f;\n"
228 			<< "  }\n"
229 			<< testSource
230 			<< "  out_color[gl_InvocationID] = float(temp_res);\n"
231 			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
232 			<< "}\n";
233 
234 		programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
235 		subgroups::setTesEvalShaderFrameBuffer(programCollection);
236 
237 	}
238 	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
239 	{
240 		std::ostringstream evaluationSource;
241 		evaluationSource << "${VERSION_DECL}\n"
242 			<< extSource
243 			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
244 			<< "layout(isolines, equal_spacing, ccw ) in;\n"
245 			<< "layout(location = 0) out float out_color;\n"
246 			<< "layout(binding = 0, std140) uniform Buffer0\n"
247 			<< "{\n"
248 			<< "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
249 			<< "};\n"
250 			<< "layout(binding = 1, std140) uniform Buffer1\n"
251 			<< "{\n"
252 			<< "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
253 			<< "};\n"
254 			<< "\n"
255 			<< "void main (void)\n"
256 			<< "{\n"
257 			<< testSource
258 			<< "  out_color = float(temp_res);\n"
259 			<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
260 			<< "}\n";
261 
262 		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
263 		programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
264 	}
265 	else
266 	{
267 		DE_FATAL("Unsupported shader stage");
268 	}
269 }
270 
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)271 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
272 {
273 	const std::string versionSource =
274 		"${VERSION_DECL}\n";
275 	const std::string vSource =
276 		"#extension GL_KHR_shader_subgroup_ballot: enable\n";
277 	const std::string eSource =
278 	(OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType) ?
279 		"#extension GL_KHR_shader_subgroup_shuffle: enable\n" :
280 		"#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
281 	const std::string extSource = vSource + eSource;
282 
283 	const std::string testSource = TestSource(caseDef);
284 
285 	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
286 	{
287 		std::ostringstream src;
288 
289 		src << versionSource + extSource
290 			<< "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
291 			<< "layout(binding = 0, std430) buffer Buffer0\n"
292 			<< "{\n"
293 			<< "  uint result[];\n"
294 			<< "};\n"
295 			<< DeclSource(caseDef, 1)
296 			<< "\n"
297 			<< "void main (void)\n"
298 			<< "{\n"
299 			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
300 			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
301 			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
302 			"gl_GlobalInvocationID.x;\n"
303 			<< testSource
304 			<< "  result[offset] = temp_res;\n"
305 			<< "}\n";
306 
307 		programCollection.add("comp") << glu::ComputeSource(src.str());
308 	}
309 	else
310 	{
311 		const std::string declSource = DeclSource(caseDef, 4);
312 
313 		{
314 			const string vertex =
315 				versionSource + extSource +
316 				"layout(binding = 0, std430) buffer Buffer0\n"
317 				"{\n"
318 				"  uint result[];\n"
319 				"} b0;\n"
320 				+ declSource +
321 				"\n"
322 				"void main (void)\n"
323 				"{\n"
324 				+ testSource +
325 				"  b0.result[gl_VertexID] = temp_res;\n"
326 				"  float pixelSize = 2.0f/1024.0f;\n"
327 				"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
328 				"  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
329 				"  gl_PointSize = 1.0f;\n"
330 				"}\n";
331 
332 			programCollection.add("vert") << glu::VertexSource(vertex);
333 		}
334 
335 		{
336 			const string tesc =
337 				versionSource + extSource +
338 				"layout(vertices=1) out;\n"
339 				"layout(binding = 1, std430)  buffer Buffer1\n"
340 				"{\n"
341 				"  uint result[];\n"
342 				"} b1;\n"
343 				+ declSource +
344 				"\n"
345 				"void main (void)\n"
346 				"{\n"
347 				+ testSource +
348 				"  b1.result[gl_PrimitiveID] = temp_res;\n"
349 				"  if (gl_InvocationID == 0)\n"
350 				"  {\n"
351 				"    gl_TessLevelOuter[0] = 1.0f;\n"
352 				"    gl_TessLevelOuter[1] = 1.0f;\n"
353 				"  }\n"
354 				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
355 				"}\n";
356 
357 			programCollection.add("tesc") << glu::TessellationControlSource(tesc);
358 		}
359 
360 		{
361 			const string tese =
362 				versionSource + extSource +
363 				"layout(isolines) in;\n"
364 				"layout(binding = 2, std430) buffer Buffer2\n"
365 				"{\n"
366 				"  uint result[];\n"
367 				"} b2;\n"
368 				+ declSource +
369 				"\n"
370 				"void main (void)\n"
371 				"{\n"
372 				+ testSource +
373 				"  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = temp_res;\n"
374 				"  float pixelSize = 2.0f/1024.0f;\n"
375 				"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
376 				"}\n";
377 
378 			programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
379 		}
380 
381 		{
382 			const string geometry =
383 				// version is added by addGeometryShadersFromTemplate
384 				extSource +
385 				"layout(${TOPOLOGY}) in;\n"
386 				"layout(points, max_vertices = 1) out;\n"
387 				"layout(binding = 3, std430) buffer Buffer3\n"
388 				"{\n"
389 				"  uint result[];\n"
390 				"} b3;\n"
391 				+ declSource +
392 				"\n"
393 				"void main (void)\n"
394 				"{\n"
395 				+ testSource +
396 				"  b3.result[gl_PrimitiveIDIn] = temp_res;\n"
397 				"  gl_Position = gl_in[0].gl_Position;\n"
398 				"  EmitVertex();\n"
399 				"  EndPrimitive();\n"
400 				"}\n";
401 
402 			subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
403 		}
404 		{
405 			const string fragment =
406 				versionSource + extSource +
407 				"precision highp int;\n"
408 				"precision highp float;\n"
409 				"layout(location = 0) out uint result;\n"
410 				+ declSource +
411 				"void main (void)\n"
412 				"{\n"
413 				+ testSource +
414 				"  result = temp_res;\n"
415 				"}\n";
416 
417 			programCollection.add("fragment") << glu::FragmentSource(fragment);
418 		}
419 
420 		subgroups::addNoSubgroupShader(programCollection);
421 	}
422 }
423 
supportedCheck(Context & context,CaseDefinition caseDef)424 void supportedCheck (Context& context, CaseDefinition caseDef)
425 {
426 	if (!subgroups::isSubgroupSupported(context))
427 		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
428 
429 	switch (caseDef.opType)
430 	{
431 		case OPTYPE_SHUFFLE:
432 		case OPTYPE_SHUFFLE_XOR:
433 			if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_BIT))
434 			{
435 				TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
436 			}
437 			break;
438 		default:
439 			if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
440 			{
441 				TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
442 			}
443 			break;
444 	}
445 
446 	if (subgroups::isDoubleFormat(caseDef.format) &&
447 			!subgroups::isDoubleSupportedForDevice(context))
448 		TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
449 }
450 
noSSBOtest(Context & context,const CaseDefinition caseDef)451 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
452 {
453 	if (!subgroups::areSubgroupOperationsSupportedForStage(
454 				context, caseDef.shaderStage))
455 	{
456 		if (subgroups::areSubgroupOperationsRequiredForStage(
457 					caseDef.shaderStage))
458 		{
459 			return tcu::TestStatus::fail(
460 					   "Shader stage " +
461 					   subgroups::getShaderStageName(caseDef.shaderStage) +
462 					   " is required to support subgroup operations!");
463 		}
464 		else
465 		{
466 			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
467 		}
468 	}
469 
470 	subgroups::SSBOData inputData[2];
471 	inputData[0].format = caseDef.format;
472 	inputData[0].layout = subgroups::SSBOData::LayoutStd140;
473 	inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
474 	inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
475 	inputData[0].binding = 0u;
476 
477 	inputData[1].format = FORMAT_R32_UINT;
478 	inputData[1].layout = subgroups::SSBOData::LayoutStd140;
479 	inputData[1].numElements = inputData[0].numElements;
480 	inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
481 	inputData[1].binding = 1u;
482 
483 	if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
484 		return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages);
485 	else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
486 		return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages);
487 	else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
488 		return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
489 	else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
490 		return subgroups::makeTessellationEvaluationFrameBufferTest(context,  FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
491 	else
492 		TCU_THROW(InternalError, "Unhandled shader stage");
493 }
494 
495 
test(Context & context,const CaseDefinition caseDef)496 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
497 {
498 	switch (caseDef.opType)
499 	{
500 		case OPTYPE_SHUFFLE:
501 		case OPTYPE_SHUFFLE_XOR:
502 			if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_BIT))
503 			{
504 				TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
505 			}
506 			break;
507 		default:
508 			if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
509 			{
510 				TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
511 			}
512 			break;
513 	}
514 
515 	if (subgroups::isDoubleFormat(caseDef.format) && !subgroups::isDoubleSupportedForDevice(context))
516 	{
517 		TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
518 	}
519 
520 	if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
521 	{
522 		if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
523 		{
524 			return tcu::TestStatus::fail(
525 					   "Shader stage " +
526 					   subgroups::getShaderStageName(caseDef.shaderStage) +
527 					   " is required to support subgroup operations!");
528 		}
529 		subgroups::SSBOData inputData[2];
530 		inputData[0].format = caseDef.format;
531 		inputData[0].layout = subgroups::SSBOData::LayoutStd430;
532 		inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
533 		inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
534 		inputData[0].binding = 1u;
535 
536 		inputData[1].format = FORMAT_R32_UINT;
537 		inputData[1].layout = subgroups::SSBOData::LayoutStd430;
538 		inputData[1].numElements = inputData[0].numElements;
539 		inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
540 		inputData[1].binding = 2u;
541 
542 		return subgroups::makeComputeTest(context, FORMAT_R32_UINT, inputData, 2, checkComputeStage);
543 	}
544 
545 	else
546 	{
547 		int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
548 
549 		ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
550 
551 		if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
552 		{
553 			if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
554 				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
555 			else
556 				stages = SHADER_STAGE_FRAGMENT_BIT;
557 		}
558 
559 		if ((ShaderStageFlags)0u == stages)
560 			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
561 
562 		subgroups::SSBOData inputData[2];
563 		inputData[0].format			= caseDef.format;
564 		inputData[0].layout			= subgroups::SSBOData::LayoutStd430;
565 		inputData[0].numElements	= subgroups::maxSupportedSubgroupSize();
566 		inputData[0].initializeType	= subgroups::SSBOData::InitializeNonZero;
567 		inputData[0].binding		= 4u;
568 		inputData[0].stages			= stages;
569 
570 		inputData[1].format			= FORMAT_R32_UINT;
571 		inputData[1].layout			= subgroups::SSBOData::LayoutStd430;
572 		inputData[1].numElements	= inputData[0].numElements;
573 		inputData[1].initializeType	= subgroups::SSBOData::InitializeNonZero;
574 		inputData[1].binding		= 5u;
575 		inputData[1].stages			= stages;
576 
577 		return subgroups::allStages(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, stages);
578 	}
579 }
580 }
581 
createSubgroupsShuffleTests(deqp::Context & testCtx)582 deqp::TestCaseGroup* createSubgroupsShuffleTests(deqp::Context& testCtx)
583 {
584 
585 	de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
586 		testCtx, "graphics", "Subgroup shuffle category tests: graphics"));
587 	de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
588 		testCtx, "compute", "Subgroup shuffle category tests: compute"));
589 	de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
590 		testCtx, "framebuffer", "Subgroup shuffle category tests: framebuffer"));
591 
592 	const Format formats[] =
593 	{
594 		FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT,
595 		FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT,
596 		FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
597 		FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT,
598 		FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
599 		FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT,
600 		FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
601 		FORMAT_R32_BOOL, FORMAT_R32G32_BOOL,
602 		FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
603 	};
604 
605 	const ShaderStageFlags stages[] =
606 	{
607 		SHADER_STAGE_VERTEX_BIT,
608 		SHADER_STAGE_TESS_EVALUATION_BIT,
609 		SHADER_STAGE_TESS_CONTROL_BIT,
610 		SHADER_STAGE_GEOMETRY_BIT,
611 	};
612 
613 	for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
614 	{
615 		const Format format = formats[formatIndex];
616 
617 		for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
618 		{
619 
620 			const string name =
621 				de::toLower(getOpTypeName(opTypeIndex)) +
622 				"_" + subgroups::getFormatNameForGLSL(format);
623 
624 			{
625 				const CaseDefinition caseDef =
626 				{
627 					opTypeIndex,
628 					SHADER_STAGE_ALL_GRAPHICS,
629 					format
630 				};
631 				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
632 			}
633 
634 			{
635 				const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
636 				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
637 			}
638 
639 			for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
640 			{
641 				const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
642 				SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(), name + "_" + getShaderStageName(caseDef.shaderStage), "",
643 											supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
644 			}
645 		}
646 	}
647 
648 	de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
649 		testCtx, "shuffle", "Subgroup shuffle category tests"));
650 
651 	group->addChild(graphicGroup.release());
652 	group->addChild(computeGroup.release());
653 	group->addChild(framebufferGroup.release());
654 
655 	return group.release();
656 }
657 
658 } // subgroups
659 } // glc
660