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 "glcSubgroupsQuadTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
43 OPTYPE_QUAD_BROADCAST = 0,
44 OPTYPE_QUAD_SWAP_HORIZONTAL,
45 OPTYPE_QUAD_SWAP_VERTICAL,
46 OPTYPE_QUAD_SWAP_DIAGONAL,
50 static bool checkVertexPipelineStages(std::vector<const void*> datas,
51 deUint32 width, deUint32)
53 return glc::subgroups::check(datas, width, 1);
56 static bool checkComputeStage(std::vector<const void*> datas,
57 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
60 return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
63 std::string getOpTypeName(int opType)
68 DE_FATAL("Unsupported op type");
70 case OPTYPE_QUAD_BROADCAST:
71 return "subgroupQuadBroadcast";
72 case OPTYPE_QUAD_SWAP_HORIZONTAL:
73 return "subgroupQuadSwapHorizontal";
74 case OPTYPE_QUAD_SWAP_VERTICAL:
75 return "subgroupQuadSwapVertical";
76 case OPTYPE_QUAD_SWAP_DIAGONAL:
77 return "subgroupQuadSwapDiagonal";
84 ShaderStageFlags shaderStage;
89 void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
91 std::string swapTable[OPTYPE_LAST];
93 subgroups::setFragmentShaderFrameBuffer(programCollection);
95 if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
96 subgroups::setVertexShaderFrameBuffer(programCollection);
98 swapTable[OPTYPE_QUAD_BROADCAST] = "";
99 swapTable[OPTYPE_QUAD_SWAP_HORIZONTAL] = " const uint swapTable[4] = {1, 0, 3, 2};\n";
100 swapTable[OPTYPE_QUAD_SWAP_VERTICAL] = " const uint swapTable[4] = {2, 3, 0, 1};\n";
101 swapTable[OPTYPE_QUAD_SWAP_DIAGONAL] = " const uint swapTable[4] = {3, 2, 1, 0};\n";
103 if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
105 std::ostringstream vertexSrc;
106 vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
107 << "#extension GL_KHR_shader_subgroup_quad: enable\n"
108 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
109 << "layout(location = 0) in highp vec4 in_position;\n"
110 << "layout(location = 0) out float result;\n"
111 << "layout(binding = 0) uniform Buffer0\n"
113 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
116 << "void main (void)\n"
118 << " uvec4 mask = subgroupBallot(true);\n"
119 << swapTable[caseDef.opType];
121 if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
123 vertexSrc << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
124 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
125 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
129 vertexSrc << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
130 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
131 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
134 vertexSrc << " if (subgroupBallotBitExtract(mask, otherID))\n"
136 << " result = (op == data[otherID]) ? 1.0f : 0.0f;\n"
140 << " result = 1.0f;\n" // Invocation we read from was inactive, so we can't verify results!
142 << " gl_Position = in_position;\n"
143 << " gl_PointSize = 1.0f;\n"
145 programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
147 else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
149 std::ostringstream geometry;
151 geometry << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
152 << "#extension GL_KHR_shader_subgroup_quad: enable\n"
153 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
154 << "layout(points) in;\n"
155 << "layout(points, max_vertices = 1) out;\n"
156 << "layout(location = 0) out float out_color;\n"
157 << "layout(binding = 0) uniform Buffer0\n"
159 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
162 << "void main (void)\n"
164 << " uvec4 mask = subgroupBallot(true);\n"
165 << swapTable[caseDef.opType];
167 if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
169 geometry << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
170 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
171 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
175 geometry << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
176 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
177 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
180 geometry << " if (subgroupBallotBitExtract(mask, otherID))\n"
182 << " out_color = (op == data[otherID]) ? 1.0 : 0.0;\n"
186 << " out_color = 1.0;\n" // Invocation we read from was inactive, so we can't verify results!
188 << " gl_Position = gl_in[0].gl_Position;\n"
189 << " EmitVertex();\n"
190 << " EndPrimitive();\n"
193 programCollection.add("geometry") << glu::GeometrySource(geometry.str());
195 else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
197 std::ostringstream controlSource;
199 controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
200 << "#extension GL_KHR_shader_subgroup_quad: enable\n"
201 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
202 << "layout(vertices = 2) out;\n"
203 << "layout(location = 0) out float out_color[];\n"
204 << "layout(binding = 0) uniform Buffer0\n"
206 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
209 << "void main (void)\n"
211 << " if (gl_InvocationID == 0)\n"
213 << " gl_TessLevelOuter[0] = 1.0f;\n"
214 << " gl_TessLevelOuter[1] = 1.0f;\n"
216 << " uvec4 mask = subgroupBallot(true);\n"
217 << swapTable[caseDef.opType];
219 if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
221 controlSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
222 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
223 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
227 controlSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
228 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
229 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
232 controlSource << " if (subgroupBallotBitExtract(mask, otherID))\n"
234 << " out_color[gl_InvocationID] = (op == data[otherID]) ? 1.0 : 0.0;\n"
238 << " out_color[gl_InvocationID] = 1.0; \n"// Invocation we read from was inactive, so we can't verify results!
240 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
243 programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
244 subgroups::setTesEvalShaderFrameBuffer(programCollection);
246 else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
248 ostringstream evaluationSource;
249 evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
250 << "#extension GL_KHR_shader_subgroup_quad: enable\n"
251 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
252 << "layout(isolines, equal_spacing, ccw ) in;\n"
253 << "layout(location = 0) out float out_color;\n"
254 << "layout(binding = 0) uniform Buffer0\n"
256 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
259 << "void main (void)\n"
261 << " uvec4 mask = subgroupBallot(true);\n"
262 << swapTable[caseDef.opType];
264 if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
266 evaluationSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
267 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
268 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
272 evaluationSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
273 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
274 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
277 evaluationSource << " if (subgroupBallotBitExtract(mask, otherID))\n"
279 << " out_color = (op == data[otherID]) ? 1.0 : 0.0;\n"
283 << " out_color = 1.0;\n" // Invocation we read from was inactive, so we can't verify results!
285 << " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
288 subgroups::setTesCtrlShaderFrameBuffer(programCollection);
289 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
293 DE_FATAL("Unsupported shader stage");
297 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
299 std::string swapTable[OPTYPE_LAST];
300 swapTable[OPTYPE_QUAD_BROADCAST] = "";
301 swapTable[OPTYPE_QUAD_SWAP_HORIZONTAL] = " const uint swapTable[4] = {1, 0, 3, 2};\n";
302 swapTable[OPTYPE_QUAD_SWAP_VERTICAL] = " const uint swapTable[4] = {2, 3, 0, 1};\n";
303 swapTable[OPTYPE_QUAD_SWAP_DIAGONAL] = " const uint swapTable[4] = {3, 2, 1, 0};\n";
305 if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
307 std::ostringstream src;
309 src << "#version 450\n"
310 << "#extension GL_KHR_shader_subgroup_quad: enable\n"
311 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
312 << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
313 << "layout(binding = 0, std430) buffer Buffer0\n"
315 << " uint result[];\n"
317 << "layout(binding = 1, std430) buffer Buffer1\n"
319 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n"
322 << "void main (void)\n"
324 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
325 << " highp uint offset = globalSize.x * ((globalSize.y * "
326 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
327 "gl_GlobalInvocationID.x;\n"
328 << " uvec4 mask = subgroupBallot(true);\n"
329 << swapTable[caseDef.opType];
332 if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
334 src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
335 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
336 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
340 src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
341 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
342 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
345 src << " if (subgroupBallotBitExtract(mask, otherID))\n"
347 << " result[offset] = (op == data[otherID]) ? 1 : 0;\n"
351 << " result[offset] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
355 programCollection.add("comp") << glu::ComputeSource(src.str());
359 std::ostringstream src;
360 if (OPTYPE_QUAD_BROADCAST == caseDef.opType)
362 src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
363 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << ");\n"
364 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + " << caseDef.direction << ";\n";
368 src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = "
369 << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n"
370 << " uint otherID = (gl_SubgroupInvocationID & ~0x3) + swapTable[gl_SubgroupInvocationID & 0x3];\n";
372 const string sourceType = src.str();
375 const string vertex =
377 "#extension GL_KHR_shader_subgroup_quad: enable\n"
378 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
379 "layout(binding = 0, std430) buffer Buffer0\n"
383 "layout(binding = 4, std430) readonly buffer Buffer4\n"
385 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
390 " uvec4 mask = subgroupBallot(true);\n"
391 + swapTable[caseDef.opType]
393 " if (subgroupBallotBitExtract(mask, otherID))\n"
395 " b0.result[gl_VertexID] = (op == data[otherID]) ? 1 : 0;\n"
399 " b0.result[gl_VertexID] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
401 " float pixelSize = 2.0f/1024.0f;\n"
402 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
403 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
405 programCollection.add("vert") << glu::VertexSource(vertex);
411 "#extension GL_KHR_shader_subgroup_quad: enable\n"
412 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
413 "layout(vertices=1) out;\n"
414 "layout(binding = 1, std430) buffer Buffer1\n"
418 "layout(binding = 4, std430) readonly buffer Buffer4\n"
420 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
425 " uvec4 mask = subgroupBallot(true);\n"
426 + swapTable[caseDef.opType]
428 " if (subgroupBallotBitExtract(mask, otherID))\n"
430 " b1.result[gl_PrimitiveID] = (op == data[otherID]) ? 1 : 0;\n"
434 " b1.result[gl_PrimitiveID] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
436 " if (gl_InvocationID == 0)\n"
438 " gl_TessLevelOuter[0] = 1.0f;\n"
439 " gl_TessLevelOuter[1] = 1.0f;\n"
441 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
443 programCollection.add("tesc") << glu::TessellationControlSource(tesc);
449 "#extension GL_KHR_shader_subgroup_quad: enable\n"
450 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
451 "layout(isolines) in;\n"
452 "layout(binding = 2, std430) buffer Buffer2\n"
456 "layout(binding = 4, std430) readonly buffer Buffer4\n"
458 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
463 " uvec4 mask = subgroupBallot(true);\n"
464 + swapTable[caseDef.opType]
466 " if (subgroupBallotBitExtract(mask, otherID))\n"
468 " b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = (op == data[otherID]) ? 1 : 0;\n"
472 " b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
474 " float pixelSize = 2.0f/1024.0f;\n"
475 " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
477 programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
481 const string geometry =
483 "#extension GL_KHR_shader_subgroup_quad: enable\n"
484 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
485 "layout(${TOPOLOGY}) in;\n"
486 "layout(points, max_vertices = 1) out;\n"
487 "layout(binding = 3, std430) buffer Buffer3\n"
491 "layout(binding = 4, std430) readonly buffer Buffer4\n"
493 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
498 " uvec4 mask = subgroupBallot(true);\n"
499 + swapTable[caseDef.opType]
501 " if (subgroupBallotBitExtract(mask, otherID))\n"
503 " b3.result[gl_PrimitiveIDIn] = (op == data[otherID]) ? 1 : 0;\n"
507 " b3.result[gl_PrimitiveIDIn] = 1; // Invocation we read from was inactive, so we can't verify results!\n"
509 " gl_Position = gl_in[0].gl_Position;\n"
513 subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
517 const string fragment =
519 "#extension GL_KHR_shader_subgroup_quad: enable\n"
520 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
521 "layout(location = 0) out uint result;\n"
522 "layout(binding = 4, std430) readonly buffer Buffer4\n"
524 " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n"
528 " uvec4 mask = subgroupBallot(true);\n"
529 + swapTable[caseDef.opType]
531 " if (subgroupBallotBitExtract(mask, otherID))\n"
533 " result = (op == data[otherID]) ? 1 : 0;\n"
537 " result = 1; // Invocation we read from was inactive, so we can't verify results!\n"
540 programCollection.add("fragment") << glu::FragmentSource(fragment);
542 subgroups::addNoSubgroupShader(programCollection);
546 void supportedCheck (Context& context, CaseDefinition caseDef)
548 if (!subgroups::isSubgroupSupported(context))
549 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
551 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_QUAD_BIT))
552 TCU_THROW(NotSupportedError, "Device does not support subgroup quad operations");
555 if (subgroups::isDoubleFormat(caseDef.format) &&
556 !subgroups::isDoubleSupportedForDevice(context))
558 TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
562 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
564 if (!subgroups::areSubgroupOperationsSupportedForStage(
565 context, caseDef.shaderStage))
567 if (subgroups::areSubgroupOperationsRequiredForStage(
568 caseDef.shaderStage))
570 return tcu::TestStatus::fail(
572 subgroups::getShaderStageName(caseDef.shaderStage) +
573 " is required to support subgroup operations!");
577 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
581 subgroups::SSBOData inputData;
582 inputData.format = caseDef.format;
583 inputData.numElements = subgroups::maxSupportedSubgroupSize();
584 inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
585 inputData.binding = 0u;
587 if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
588 return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
589 else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
590 return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages);
591 else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
592 return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
593 else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
594 return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
596 TCU_THROW(InternalError, "Unhandled shader stage");
600 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
602 if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
604 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
606 return tcu::TestStatus::fail(
608 subgroups::getShaderStageName(caseDef.shaderStage) +
609 " is required to support subgroup operations!");
611 subgroups::SSBOData inputData;
612 inputData.format = caseDef.format;
613 inputData.numElements = subgroups::maxSupportedSubgroupSize();
614 inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
615 inputData.binding = 1u;
617 return subgroups::makeComputeTest(context, FORMAT_R32_UINT, &inputData, 1, checkComputeStage);
621 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
623 ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
625 if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
627 if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
628 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
630 stages = SHADER_STAGE_FRAGMENT_BIT;
633 if ((ShaderStageFlags)0u == stages)
634 TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
636 subgroups::SSBOData inputData;
637 inputData.format = caseDef.format;
638 inputData.numElements = subgroups::maxSupportedSubgroupSize();
639 inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
640 inputData.binding = 4u;
641 inputData.stages = stages;
643 return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
648 deqp::TestCaseGroup* createSubgroupsQuadTests(deqp::Context& testCtx)
650 de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
651 testCtx, "graphics", "Subgroup arithmetic category tests: graphics"));
652 de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
653 testCtx, "compute", "Subgroup arithmetic category tests: compute"));
654 de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
655 testCtx, "framebuffer", "Subgroup arithmetic category tests: framebuffer"));
657 const Format formats[] =
659 FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT,
660 FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT,
661 FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
662 FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT,
663 FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
664 FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT,
665 FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
666 FORMAT_R32_BOOL, FORMAT_R32G32_BOOL,
667 FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
670 const ShaderStageFlags stages[] =
672 SHADER_STAGE_VERTEX_BIT,
673 SHADER_STAGE_TESS_EVALUATION_BIT,
674 SHADER_STAGE_TESS_CONTROL_BIT,
675 SHADER_STAGE_GEOMETRY_BIT,
678 for (int direction = 0; direction < 4; ++direction)
680 for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
682 const Format format = formats[formatIndex];
684 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
686 const std::string op = de::toLower(getOpTypeName(opTypeIndex));
687 std::ostringstream name;
688 name << de::toLower(op);
690 if (OPTYPE_QUAD_BROADCAST == opTypeIndex)
692 name << "_" << direction;
698 // We don't need direction for swap operations.
703 name << "_" << subgroups::getFormatNameForGLSL(format);
706 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format, direction};
707 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), name.str(), "", supportedCheck, initPrograms, test, caseDef);
711 const CaseDefinition caseDef =
714 SHADER_STAGE_ALL_GRAPHICS,
718 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), name.str(), "", supportedCheck, initPrograms, test, caseDef);
720 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
722 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format, direction};
723 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(), name.str()+"_"+ getShaderStageName(caseDef.shaderStage), "",
724 supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
731 de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
732 testCtx, "quad", "Subgroup quad category tests"));
734 group->addChild(graphicGroup.release());
735 group->addChild(computeGroup.release());
736 group->addChild(framebufferGroup.release());
738 return group.release();