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