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