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