1 /*------------------------------------------------------------------------
2 * OpenGL Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017-2019 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
7 * Copyright (c) 2019 NVIDIA Corporation.
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief Subgroups Tests
24 */ /*--------------------------------------------------------------------*/
26 #include "glcSubgroupsVoteTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
31 #include "tcuStringTemplate.hpp"
52 static bool checkVertexPipelineStages(std::vector<const void*> datas,
53 deUint32 width, deUint32)
55 return glc::subgroups::check(datas, width, 0x1F);
58 static bool checkFragmentPipelineStages(std::vector<const void*> datas,
59 deUint32 width, deUint32 height, deUint32)
61 const deUint32* data =
62 reinterpret_cast<const deUint32*>(datas[0]);
63 for (deUint32 x = 0u; x < width; ++x)
65 for (deUint32 y = 0u; y < height; ++y)
67 const deUint32 ndx = (x * height + y);
68 deUint32 val = data[ndx] & 0x1F;
70 if (data[ndx] & 0x40) //Helper fragment shader invocation was executed
75 else //Helper fragment shader invocation was not executed yet
85 static bool checkComputeStage(std::vector<const void*> datas,
86 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
89 return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 0x1F);
92 std::string getOpTypeName(int opType)
97 DE_FATAL("Unsupported op type");
100 return "subgroupAll";
102 return "subgroupAny";
103 case OPTYPE_ALLEQUAL:
104 return "subgroupAllEqual";
108 struct CaseDefinition
111 ShaderStageFlags shaderStage;
115 void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
117 const bool formatIsBoolean =
118 FORMAT_R32_BOOL == caseDef.format || FORMAT_R32G32_BOOL == caseDef.format || FORMAT_R32G32B32_BOOL == caseDef.format || FORMAT_R32G32B32A32_BOOL == caseDef.format;
120 if (SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage)
121 subgroups::setFragmentShaderFrameBuffer(programCollection);
123 if (SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
125 const string vertex = "#version 450\n"
128 " vec2 uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));\n"
129 " gl_Position = vec4(uv * 4.0f -2.0f, 0.0f, 1.0f);\n"
130 " gl_PointSize = 1.0f;\n"
132 programCollection.add("vert") << glu::VertexSource(vertex);
134 else if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
135 subgroups::setVertexShaderFrameBuffer(programCollection);
137 const string source =
138 (OPTYPE_ALL == caseDef.opType) ?
139 " result = " + getOpTypeName(caseDef.opType) +
140 "(true) ? 0x1 : 0;\n"
141 " result |= " + getOpTypeName(caseDef.opType) +
142 "(false) ? 0 : 0x1A;\n"
144 : (OPTYPE_ANY == caseDef.opType) ?
145 " result = " + getOpTypeName(caseDef.opType) +
146 "(true) ? 0x1 : 0;\n"
147 " result |= " + getOpTypeName(caseDef.opType) +
148 "(false) ? 0 : 0x1A;\n"
150 : (OPTYPE_ALLEQUAL == caseDef.opType) ?
151 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
152 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect())\n;" : "(12.0 * float(data[gl_SubgroupInvocationID]) + gl_SubgroupInvocationID);\n") +
153 " result = " + getOpTypeName(caseDef.opType) + "("
154 + subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x1 : 0;\n"
155 " result |= " + getOpTypeName(caseDef.opType) +
156 "(gl_SubgroupInvocationID) ? 0 : 0x2;\n"
157 " result |= " + getOpTypeName(caseDef.opType) +
158 "(data[0]) ? 0x4 : 0;\n"
159 " result |= " + getOpTypeName(caseDef.opType) +
160 "(valueEqual) ? 0x8 : 0x0;\n"
161 " result |= " + getOpTypeName(caseDef.opType) +
162 "(valueNoEqual) ? 0x0 : 0x10;\n"
163 " if (subgroupElect()) result |= 0x2 | 0x10;\n"
166 if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
168 std::ostringstream vertexSrc;
169 vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
170 << "#extension GL_KHR_shader_subgroup_vote: enable\n"
171 << "layout(location = 0) out float out_color;\n"
172 << "layout(location = 0) in highp vec4 in_position;\n"
173 << "layout(binding = 0) uniform Buffer1\n"
175 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
178 << "void main (void)\n"
182 << " out_color = float(result);\n"
183 << " gl_Position = in_position;\n"
184 << " gl_PointSize = 1.0f;\n"
187 programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
189 else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
191 std::ostringstream geometry;
193 geometry << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
194 << "#extension GL_KHR_shader_subgroup_vote: enable\n"
195 << "layout(points) in;\n"
196 << "layout(points, max_vertices = 1) out;\n"
197 << "layout(location = 0) out float out_color;\n"
198 << "layout(set = 0, binding = 0) uniform Buffer1\n"
200 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
203 << "void main (void)\n"
207 << " out_color = float(result);\n"
208 << " gl_Position = gl_in[0].gl_Position;\n"
209 << " EmitVertex();\n"
210 << " EndPrimitive();\n"
213 programCollection.add("geometry") << glu::GeometrySource(geometry.str());
215 else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
217 std::ostringstream controlSource;
218 controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
219 << "#extension GL_KHR_shader_subgroup_vote: enable\n"
220 << "layout(vertices = 2) out;\n"
221 << "layout(location = 0) out float out_color[];\n"
222 << "layout(set = 0, binding = 0) uniform Buffer1\n"
224 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
227 << "void main (void)\n"
230 << " if (gl_InvocationID == 0)\n"
232 << " gl_TessLevelOuter[0] = 1.0f;\n"
233 << " gl_TessLevelOuter[1] = 1.0f;\n"
236 << " out_color[gl_InvocationID] = float(result);"
237 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
240 programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
241 subgroups::setTesEvalShaderFrameBuffer(programCollection);
243 else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
245 std::ostringstream evaluationSource;
246 evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
247 << "#extension GL_KHR_shader_subgroup_vote: enable\n"
248 << "#extension GL_EXT_tessellation_shader : require\n"
249 << "layout(isolines, equal_spacing, ccw ) in;\n"
250 << "layout(location = 0) out float out_color;\n"
251 << "layout(set = 0, binding = 0) uniform Buffer1\n"
253 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
256 << "void main (void)\n"
259 << " highp uint offset = gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5);\n"
261 << " out_color = float(result);\n"
262 << " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
265 subgroups::setTesCtrlShaderFrameBuffer(programCollection);
266 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
268 else if (SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
270 const string sourceFragment =
271 (OPTYPE_ALL == caseDef.opType) ?
272 " result |= " + getOpTypeName(caseDef.opType) +
273 "(!gl_HelperInvocation) ? 0x0 : 0x1;\n"
274 " result |= " + getOpTypeName(caseDef.opType) +
275 "(false) ? 0 : 0x1A;\n"
277 : (OPTYPE_ANY == caseDef.opType) ?
278 " result |= " + getOpTypeName(caseDef.opType) +
279 "(gl_HelperInvocation) ? 0x1 : 0x0;\n"
280 " result |= " + getOpTypeName(caseDef.opType) +
281 "(false) ? 0 : 0x1A;\n"
283 : (OPTYPE_ALLEQUAL == caseDef.opType) ?
284 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
285 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + int(gl_FragCoord.x*gl_SubgroupInvocationID));\n") +
286 " result |= " + getOpTypeName(caseDef.opType) + "("
287 + subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x10 : 0;\n"
288 " result |= " + getOpTypeName(caseDef.opType) +
289 "(gl_SubgroupInvocationID) ? 0 : 0x2;\n"
290 " result |= " + getOpTypeName(caseDef.opType) +
291 "(data[0]) ? 0x4 : 0;\n"
292 " result |= " + getOpTypeName(caseDef.opType) +
293 "(valueEqual) ? 0x8 : 0x0;\n"
294 " result |= " + getOpTypeName(caseDef.opType) +
295 "(gl_HelperInvocation) ? 0x0 : 0x1;\n"
296 " if (subgroupElect()) result |= 0x2 | 0x10;\n"
299 std::ostringstream fragmentSource;
300 fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
301 << "#extension GL_KHR_shader_subgroup_vote: enable\n"
302 << "layout(location = 0) out uint out_color;\n"
303 << "layout(set = 0, binding = 0) uniform Buffer1\n"
305 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
310 << " uint result = 0u;\n"
311 << " if (dFdx(gl_SubgroupInvocationID * gl_FragCoord.x * gl_FragCoord.y) - dFdy(gl_SubgroupInvocationID * gl_FragCoord.x * gl_FragCoord.y) > 0.0f)\n"
313 << " result |= 0x20;\n" // to be sure that compiler doesn't remove dFdx and dFdy executions
315 << " bool helper = subgroupAny(gl_HelperInvocation);\n"
318 << " result |= 0x40;\n"
321 << " out_color = result;\n"
324 programCollection.add("fragment") << glu::FragmentSource(fragmentSource.str());
328 DE_FATAL("Unsupported shader stage");
332 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
334 const bool formatIsBoolean =
335 FORMAT_R32_BOOL == caseDef.format || FORMAT_R32G32_BOOL == caseDef.format || FORMAT_R32G32B32_BOOL == caseDef.format || FORMAT_R32G32B32A32_BOOL == caseDef.format;
336 if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
338 std::ostringstream src;
340 src << "#version 450\n"
341 << "#extension GL_KHR_shader_subgroup_vote: enable\n"
342 << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
343 << "layout(binding = 0, std430) buffer Buffer1\n"
345 << " uint result[];\n"
347 << "layout(binding = 1, std430) buffer Buffer2\n"
349 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
352 << "void main (void)\n"
354 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
355 << " highp uint offset = globalSize.x * ((globalSize.y * "
356 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
357 "gl_GlobalInvocationID.x;\n";
358 if (OPTYPE_ALL == caseDef.opType)
360 src << " result[offset] = " << getOpTypeName(caseDef.opType)
361 << "(true) ? 0x1 : 0;\n"
362 << " result[offset] |= " << getOpTypeName(caseDef.opType)
363 << "(false) ? 0 : 0x1A;\n"
364 << " result[offset] |= " << getOpTypeName(caseDef.opType)
365 << "(data[gl_SubgroupInvocationID] > 0) ? 0x4 : 0;\n";
367 else if (OPTYPE_ANY == caseDef.opType)
369 src << " result[offset] = " << getOpTypeName(caseDef.opType)
370 << "(true) ? 0x1 : 0;\n"
371 << " result[offset] |= " << getOpTypeName(caseDef.opType)
372 << "(false) ? 0 : 0x1A;\n"
373 << " result[offset] |= " << getOpTypeName(caseDef.opType)
374 << "(data[gl_SubgroupInvocationID] == data[0]) ? 0x4 : 0;\n";
377 else if (OPTYPE_ALLEQUAL == caseDef.opType)
379 src << " " << subgroups::getFormatNameForGLSL(caseDef.format) <<" valueEqual = " << subgroups::getFormatNameForGLSL(caseDef.format) << "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n"
380 << " " << subgroups::getFormatNameForGLSL(caseDef.format) <<" valueNoEqual = " << subgroups::getFormatNameForGLSL(caseDef.format) << (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + offset);\n")
381 <<" result[offset] = " << getOpTypeName(caseDef.opType) << "("
382 << subgroups::getFormatNameForGLSL(caseDef.format) << "(1)) ? 0x1 : 0x0;\n"
383 << " result[offset] |= " << getOpTypeName(caseDef.opType)
384 << "(gl_SubgroupInvocationID) ? 0x0 : 0x2;\n"
385 << " result[offset] |= " << getOpTypeName(caseDef.opType)
386 << "(data[0]) ? 0x4 : 0x0;\n"
387 << " result[offset] |= "<< getOpTypeName(caseDef.opType)
388 << "(valueEqual) ? 0x8 : 0x0;\n"
389 << " result[offset] |= "<< getOpTypeName(caseDef.opType)
390 << "(valueNoEqual) ? 0x0 : 0x10;\n"
391 << " if (subgroupElect()) result[offset] |= 0x2 | 0x10;\n";
396 programCollection.add("comp") << glu::ComputeSource(src.str());
400 const string source =
401 (OPTYPE_ALL == caseDef.opType) ?
402 " b${SSBO1}.result[offset] = " + getOpTypeName(caseDef.opType) +
403 "(true) ? 0x1 : 0;\n"
404 " b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
405 "(false) ? 0 : 0x1A;\n"
406 " b${SSBO1}.result[offset] |= 0x4;\n"
407 : (OPTYPE_ANY == caseDef.opType) ?
408 " b${SSBO1}.result[offset] = " + getOpTypeName(caseDef.opType) +
409 "(true) ? 0x1 : 0;\n"
410 " b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
411 "(false) ? 0 : 0x1A;\n"
412 " b${SSBO1}.result[offset] |= 0x4;\n"
413 : (OPTYPE_ALLEQUAL == caseDef.opType) ?
414 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
415 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + gl_SubgroupInvocationID);\n") +
416 " b${SSBO1}.result[offset] = " + getOpTypeName(caseDef.opType) + "("
417 + subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x1 : 0;\n"
418 " b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
419 "(gl_SubgroupInvocationID) ? 0 : 0x2;\n"
420 " b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
421 "(data[0]) ? 0x4 : 0;\n"
422 " b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
423 "(valueEqual) ? 0x8 : 0x0;\n"
424 " b${SSBO1}.result[offset] |= " + getOpTypeName(caseDef.opType) +
425 "(valueNoEqual) ? 0x0 : 0x10;\n"
426 " if (subgroupElect()) b${SSBO1}.result[offset] |= 0x2 | 0x10;\n"
429 tcu::StringTemplate sourceTemplate(source);
431 const string formatString = subgroups::getFormatNameForGLSL(caseDef.format);
434 map<string, string> bufferNameMapping;
435 bufferNameMapping.insert(pair<string, string>("SSBO1", "0"));
437 const string vertex =
439 "#extension GL_KHR_shader_subgroup_vote: enable\n"
440 "layout(binding = 0, std430) buffer Buffer0\n"
444 "layout(binding = 4, std430) readonly buffer Buffer4\n"
446 " " + formatString + " data[];\n"
451 " highp uint offset = gl_VertexID;\n"
452 + sourceTemplate.specialize(bufferNameMapping) +
453 " float pixelSize = 2.0f/1024.0f;\n"
454 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
455 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
456 " gl_PointSize = 1.0f;\n"
458 programCollection.add("vert") << glu::VertexSource(vertex);
462 map<string, string> bufferNameMapping;
463 bufferNameMapping.insert(pair<string, string>("SSBO1", "1"));
467 "#extension GL_KHR_shader_subgroup_vote: enable\n"
468 "layout(vertices=1) out;\n"
469 "layout(binding = 1, std430) buffer Buffer1\n"
473 "layout(binding = 4, std430) readonly buffer Buffer4\n"
475 " " + formatString + " data[];\n"
480 " highp uint offset = gl_PrimitiveID;\n"
481 + sourceTemplate.specialize(bufferNameMapping) +
482 " if (gl_InvocationID == 0)\n"
484 " gl_TessLevelOuter[0] = 1.0f;\n"
485 " gl_TessLevelOuter[1] = 1.0f;\n"
487 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
490 programCollection.add("tesc") << glu::TessellationControlSource(tesc);
494 map<string, string> bufferNameMapping;
495 bufferNameMapping.insert(pair<string, string>("SSBO1", "2"));
499 "#extension GL_KHR_shader_subgroup_vote: enable\n"
500 "layout(isolines) in;\n"
501 "layout(binding = 2, std430) buffer Buffer2\n"
505 "layout(binding = 4, std430) readonly buffer Buffer4\n"
507 " " + formatString + " data[];\n"
512 " highp uint offset = gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5);\n"
513 + sourceTemplate.specialize(bufferNameMapping) +
514 " float pixelSize = 2.0f/1024.0f;\n"
515 " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
518 programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
522 map<string, string> bufferNameMapping;
523 bufferNameMapping.insert(pair<string, string>("SSBO1", "3"));
525 const string geometry =
527 "#extension GL_KHR_shader_subgroup_vote: enable\n"
528 "layout(${TOPOLOGY}) in;\n"
529 "layout(points, max_vertices = 1) out;\n"
530 "layout(binding = 3, std430) buffer Buffer3\n"
534 "layout(binding = 4, std430) readonly buffer Buffer4\n"
536 " " + formatString + " data[];\n"
541 " highp uint offset = gl_PrimitiveIDIn;\n"
542 + sourceTemplate.specialize(bufferNameMapping) +
543 " gl_Position = gl_in[0].gl_Position;\n"
548 subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
552 const string sourceFragment =
553 (OPTYPE_ALL == caseDef.opType) ?
554 " result = " + getOpTypeName(caseDef.opType) +
555 "(true) ? 0x1 : 0;\n"
556 " result |= " + getOpTypeName(caseDef.opType) +
557 "(false) ? 0 : 0x1A;\n"
559 : (OPTYPE_ANY == caseDef.opType) ?
560 " result = " + getOpTypeName(caseDef.opType) +
561 "(true) ? 0x1 : 0;\n"
562 " result |= " + getOpTypeName(caseDef.opType) +
563 "(false) ? 0 : 0x1A;\n"
565 : (OPTYPE_ALLEQUAL == caseDef.opType) ?
566 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + "(1.25 * float(data[gl_SubgroupInvocationID]) + 5.0);\n" +
567 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " valueNoEqual = " + subgroups::getFormatNameForGLSL(caseDef.format) + (formatIsBoolean ? "(subgroupElect());\n" : "(12.0 * float(data[gl_SubgroupInvocationID]) + int(gl_FragCoord.x*gl_SubgroupInvocationID));\n") +
568 " result = " + getOpTypeName(caseDef.opType) + "("
569 + subgroups::getFormatNameForGLSL(caseDef.format) + "(1)) ? 0x1 : 0;\n"
570 " result |= " + getOpTypeName(caseDef.opType) +
571 "(gl_SubgroupInvocationID) ? 0 : 0x2;\n"
572 " result |= " + getOpTypeName(caseDef.opType) +
573 "(data[0]) ? 0x4 : 0;\n"
574 " result |= " + getOpTypeName(caseDef.opType) +
575 "(valueEqual) ? 0x8 : 0x0;\n"
576 " result |= " + getOpTypeName(caseDef.opType) +
577 "(valueNoEqual) ? 0x0 : 0x10;\n"
578 " if (subgroupElect()) result |= 0x2 | 0x10;\n"
580 const string fragment =
582 "#extension GL_KHR_shader_subgroup_vote: enable\n"
583 "layout(location = 0) out uint result;\n"
584 "layout(binding = 4, std430) readonly buffer Buffer4\n"
586 " " + formatString + " data[];\n"
593 programCollection.add("fragment") << glu::FragmentSource(fragment);
596 subgroups::addNoSubgroupShader(programCollection);
600 void supportedCheck (Context& context, CaseDefinition caseDef)
602 if (!subgroups::isSubgroupSupported(context))
603 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
605 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_VOTE_BIT))
607 TCU_THROW(NotSupportedError, "Device does not support subgroup vote operations");
610 if (subgroups::isDoubleFormat(caseDef.format) &&
611 !subgroups::isDoubleSupportedForDevice(context))
613 TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
617 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
619 if (!subgroups::areSubgroupOperationsSupportedForStage(
620 context, caseDef.shaderStage))
622 if (subgroups::areSubgroupOperationsRequiredForStage(
623 caseDef.shaderStage))
625 return tcu::TestStatus::fail(
627 subgroups::getShaderStageName(caseDef.shaderStage) +
628 " is required to support subgroup operations!");
632 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
636 subgroups::SSBOData inputData;
637 inputData.format = caseDef.format;
638 inputData.numElements = subgroups::maxSupportedSubgroupSize();
639 inputData.initializeType = OPTYPE_ALLEQUAL == caseDef.opType ? subgroups::SSBOData::InitializeZero : subgroups::SSBOData::InitializeNonZero;
641 if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
642 return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
643 else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
644 return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
645 else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
646 return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
647 else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
648 return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
649 else if (SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
650 return subgroups::makeFragmentFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkFragmentPipelineStages);
652 TCU_THROW(InternalError, "Unhandled shader stage");
656 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
658 if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
660 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
662 return tcu::TestStatus::fail(
664 subgroups::getShaderStageName(caseDef.shaderStage) +
665 " is required to support subgroup operations!");
668 subgroups::SSBOData inputData;
669 inputData.format = caseDef.format;
670 inputData.numElements = subgroups::maxSupportedSubgroupSize();
671 inputData.initializeType = OPTYPE_ALLEQUAL == caseDef.opType ? subgroups::SSBOData::InitializeZero : subgroups::SSBOData::InitializeNonZero;
672 inputData.binding = 1u;
674 return subgroups::makeComputeTest(context, FORMAT_R32_UINT, &inputData,
675 1, checkComputeStage);
679 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
681 ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
683 if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
685 if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
686 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
688 stages = SHADER_STAGE_FRAGMENT_BIT;
691 if ((ShaderStageFlags)0u == stages)
692 TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
694 subgroups::SSBOData inputData;
695 inputData.format = caseDef.format;
696 inputData.numElements = subgroups::maxSupportedSubgroupSize();
697 inputData.initializeType = OPTYPE_ALLEQUAL == caseDef.opType ? subgroups::SSBOData::InitializeZero : subgroups::SSBOData::InitializeNonZero;
698 inputData.binding = 4u;
699 inputData.stages = stages;
701 return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
707 deqp::TestCaseGroup* createSubgroupsVoteTests(deqp::Context& testCtx)
709 de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
710 testCtx, "graphics", "Subgroup arithmetic category tests: graphics"));
711 de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
712 testCtx, "compute", "Subgroup arithmetic category tests: compute"));
713 de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
714 testCtx, "framebuffer", "Subgroup arithmetic category tests: framebuffer"));
716 de::MovePtr<deqp::TestCaseGroup> fragHelperGroup(new deqp::TestCaseGroup(
717 testCtx, "frag_helper", "Subgroup arithmetic category tests: fragment helper invocation"));
719 const ShaderStageFlags stages[] =
721 SHADER_STAGE_VERTEX_BIT,
722 SHADER_STAGE_TESS_EVALUATION_BIT,
723 SHADER_STAGE_TESS_CONTROL_BIT,
724 SHADER_STAGE_GEOMETRY_BIT,
727 const Format formats[] =
729 FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT,
730 FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT,
731 FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
732 FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT,
733 FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
734 FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT,
735 FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
736 FORMAT_R32_BOOL, FORMAT_R32G32_BOOL,
737 FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
740 for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
742 const Format format = formats[formatIndex];
744 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
746 // Skip the typed tests for all but subgroupAllEqual()
747 if ((FORMAT_R32_UINT != format) && (OPTYPE_ALLEQUAL != opTypeIndex))
752 const std::string op = de::toLower(getOpTypeName(opTypeIndex));
755 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
756 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(),
757 op + "_" + subgroups::getFormatNameForGLSL(format),
758 "", supportedCheck, initPrograms, test, caseDef);
762 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS, format};
763 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(),
764 op + "_" + subgroups::getFormatNameForGLSL(format),
765 "", supportedCheck, initPrograms, test, caseDef);
768 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
770 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
771 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
773 subgroups::getFormatNameForGLSL(format)
774 + "_" + getShaderStageName(caseDef.shaderStage), "",
775 supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
778 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_FRAGMENT_BIT, format};
779 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(fragHelperGroup.get(),
781 subgroups::getFormatNameForGLSL(format)
782 + "_" + getShaderStageName(caseDef.shaderStage), "",
783 supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
787 de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
788 testCtx, "vote", "Subgroup vote category tests"));
790 group->addChild(graphicGroup.release());
791 group->addChild(computeGroup.release());
792 group->addChild(framebufferGroup.release());
793 group->addChild(fragHelperGroup.release());
795 return group.release();