1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------ 2e5c31af7Sopenharmony_ci * OpenGL Conformance Tests 3e5c31af7Sopenharmony_ci * ------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2017-2019 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * Copyright (c) 2017 Codeplay Software Ltd. 7e5c31af7Sopenharmony_ci * Copyright (c) 2019 NVIDIA Corporation. 8e5c31af7Sopenharmony_ci * 9e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 10e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 11e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 14e5c31af7Sopenharmony_ci * 15e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 16e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 17e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 19e5c31af7Sopenharmony_ci * limitations under the License. 20e5c31af7Sopenharmony_ci * 21e5c31af7Sopenharmony_ci */ /*! 22e5c31af7Sopenharmony_ci * \file 23e5c31af7Sopenharmony_ci * \brief Subgroups Tests 24e5c31af7Sopenharmony_ci */ /*--------------------------------------------------------------------*/ 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "glcSubgroupsQuadTests.hpp" 27e5c31af7Sopenharmony_ci#include "glcSubgroupsTestsUtils.hpp" 28e5c31af7Sopenharmony_ci 29e5c31af7Sopenharmony_ci#include <string> 30e5c31af7Sopenharmony_ci#include <vector> 31e5c31af7Sopenharmony_ci 32e5c31af7Sopenharmony_ciusing namespace tcu; 33e5c31af7Sopenharmony_ciusing namespace std; 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_cinamespace glc 36e5c31af7Sopenharmony_ci{ 37e5c31af7Sopenharmony_cinamespace subgroups 38e5c31af7Sopenharmony_ci{ 39e5c31af7Sopenharmony_cinamespace 40e5c31af7Sopenharmony_ci{ 41e5c31af7Sopenharmony_cienum OpType 42e5c31af7Sopenharmony_ci{ 43e5c31af7Sopenharmony_ci OPTYPE_QUAD_BROADCAST = 0, 44e5c31af7Sopenharmony_ci OPTYPE_QUAD_SWAP_HORIZONTAL, 45e5c31af7Sopenharmony_ci OPTYPE_QUAD_SWAP_VERTICAL, 46e5c31af7Sopenharmony_ci OPTYPE_QUAD_SWAP_DIAGONAL, 47e5c31af7Sopenharmony_ci OPTYPE_LAST 48e5c31af7Sopenharmony_ci}; 49e5c31af7Sopenharmony_ci 50e5c31af7Sopenharmony_cistatic bool checkVertexPipelineStages(std::vector<const void*> datas, 51e5c31af7Sopenharmony_ci deUint32 width, deUint32) 52e5c31af7Sopenharmony_ci{ 53e5c31af7Sopenharmony_ci return glc::subgroups::check(datas, width, 1); 54e5c31af7Sopenharmony_ci} 55e5c31af7Sopenharmony_ci 56e5c31af7Sopenharmony_cistatic bool checkComputeStage(std::vector<const void*> datas, 57e5c31af7Sopenharmony_ci const deUint32 numWorkgroups[3], const deUint32 localSize[3], 58e5c31af7Sopenharmony_ci deUint32) 59e5c31af7Sopenharmony_ci{ 60e5c31af7Sopenharmony_ci return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1); 61e5c31af7Sopenharmony_ci} 62e5c31af7Sopenharmony_ci 63e5c31af7Sopenharmony_cistd::string getOpTypeName(int opType) 64e5c31af7Sopenharmony_ci{ 65e5c31af7Sopenharmony_ci switch (opType) 66e5c31af7Sopenharmony_ci { 67e5c31af7Sopenharmony_ci default: 68e5c31af7Sopenharmony_ci DE_FATAL("Unsupported op type"); 69e5c31af7Sopenharmony_ci return ""; 70e5c31af7Sopenharmony_ci case OPTYPE_QUAD_BROADCAST: 71e5c31af7Sopenharmony_ci return "subgroupQuadBroadcast"; 72e5c31af7Sopenharmony_ci case OPTYPE_QUAD_SWAP_HORIZONTAL: 73e5c31af7Sopenharmony_ci return "subgroupQuadSwapHorizontal"; 74e5c31af7Sopenharmony_ci case OPTYPE_QUAD_SWAP_VERTICAL: 75e5c31af7Sopenharmony_ci return "subgroupQuadSwapVertical"; 76e5c31af7Sopenharmony_ci case OPTYPE_QUAD_SWAP_DIAGONAL: 77e5c31af7Sopenharmony_ci return "subgroupQuadSwapDiagonal"; 78e5c31af7Sopenharmony_ci } 79e5c31af7Sopenharmony_ci} 80e5c31af7Sopenharmony_ci 81e5c31af7Sopenharmony_cistruct CaseDefinition 82e5c31af7Sopenharmony_ci{ 83e5c31af7Sopenharmony_ci int opType; 84e5c31af7Sopenharmony_ci ShaderStageFlags shaderStage; 85e5c31af7Sopenharmony_ci Format format; 86e5c31af7Sopenharmony_ci int direction; 87e5c31af7Sopenharmony_ci}; 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_civoid initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef) 90e5c31af7Sopenharmony_ci{ 91e5c31af7Sopenharmony_ci std::string swapTable[OPTYPE_LAST]; 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_ci subgroups::setFragmentShaderFrameBuffer(programCollection); 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_ci if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage) 96e5c31af7Sopenharmony_ci subgroups::setVertexShaderFrameBuffer(programCollection); 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_BROADCAST] = ""; 99e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_SWAP_HORIZONTAL] = " const uint swapTable[4] = uint[](1u, 0u, 3u, 2u);\n"; 100e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_SWAP_VERTICAL] = " const uint swapTable[4] = uint[](2u, 3u, 0u, 1u);\n"; 101e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_SWAP_DIAGONAL] = " const uint swapTable[4] = uint[](3u, 2u, 1u, 0u);\n"; 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage) 104e5c31af7Sopenharmony_ci { 105e5c31af7Sopenharmony_ci std::ostringstream vertexSrc; 106e5c31af7Sopenharmony_ci vertexSrc << "${VERSION_DECL}\n" 107e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_quad: enable\n" 108e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_ballot: enable\n" 109e5c31af7Sopenharmony_ci << "layout(location = 0) in highp vec4 in_position;\n" 110e5c31af7Sopenharmony_ci << "layout(location = 0) out float result;\n" 111e5c31af7Sopenharmony_ci << "layout(binding = 0, std140) uniform Buffer0\n" 112e5c31af7Sopenharmony_ci << "{\n" 113e5c31af7Sopenharmony_ci << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n" 114e5c31af7Sopenharmony_ci << "};\n" 115e5c31af7Sopenharmony_ci << "\n" 116e5c31af7Sopenharmony_ci << "void main (void)\n" 117e5c31af7Sopenharmony_ci << "{\n" 118e5c31af7Sopenharmony_ci << " uvec4 mask = subgroupBallot(true);\n" 119e5c31af7Sopenharmony_ci << swapTable[caseDef.opType]; 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == caseDef.opType) 122e5c31af7Sopenharmony_ci { 123e5c31af7Sopenharmony_ci vertexSrc << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 124e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << "u);\n" 125e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + " << caseDef.direction << "u;\n"; 126e5c31af7Sopenharmony_ci } 127e5c31af7Sopenharmony_ci else 128e5c31af7Sopenharmony_ci { 129e5c31af7Sopenharmony_ci vertexSrc << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 130e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n" 131e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + swapTable[gl_SubgroupInvocationID & 0x3u];\n"; 132e5c31af7Sopenharmony_ci } 133e5c31af7Sopenharmony_ci 134e5c31af7Sopenharmony_ci vertexSrc << " if (subgroupBallotBitExtract(mask, otherID))\n" 135e5c31af7Sopenharmony_ci << " {\n" 136e5c31af7Sopenharmony_ci << " result = (op == data[otherID]) ? 1.0f : 0.0f;\n" 137e5c31af7Sopenharmony_ci << " }\n" 138e5c31af7Sopenharmony_ci << " else\n" 139e5c31af7Sopenharmony_ci << " {\n" 140e5c31af7Sopenharmony_ci << " result = 1.0f;\n" // Invocation we read from was inactive, so we can't verify results! 141e5c31af7Sopenharmony_ci << " }\n" 142e5c31af7Sopenharmony_ci << " gl_Position = in_position;\n" 143e5c31af7Sopenharmony_ci << " gl_PointSize = 1.0f;\n" 144e5c31af7Sopenharmony_ci << "}\n"; 145e5c31af7Sopenharmony_ci programCollection.add("vert") << glu::VertexSource(vertexSrc.str()); 146e5c31af7Sopenharmony_ci } 147e5c31af7Sopenharmony_ci else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage) 148e5c31af7Sopenharmony_ci { 149e5c31af7Sopenharmony_ci std::ostringstream geometry; 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci geometry << "${VERSION_DECL}\n" 152e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_quad: enable\n" 153e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_ballot: enable\n" 154e5c31af7Sopenharmony_ci << "layout(points) in;\n" 155e5c31af7Sopenharmony_ci << "layout(points, max_vertices = 1) out;\n" 156e5c31af7Sopenharmony_ci << "layout(location = 0) out float out_color;\n" 157e5c31af7Sopenharmony_ci << "layout(binding = 0, std140) uniform Buffer0\n" 158e5c31af7Sopenharmony_ci << "{\n" 159e5c31af7Sopenharmony_ci << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n" 160e5c31af7Sopenharmony_ci << "};\n" 161e5c31af7Sopenharmony_ci << "\n" 162e5c31af7Sopenharmony_ci << "void main (void)\n" 163e5c31af7Sopenharmony_ci << "{\n" 164e5c31af7Sopenharmony_ci << " uvec4 mask = subgroupBallot(true);\n" 165e5c31af7Sopenharmony_ci << swapTable[caseDef.opType]; 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == caseDef.opType) 168e5c31af7Sopenharmony_ci { 169e5c31af7Sopenharmony_ci geometry << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 170e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << "u);\n" 171e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + " << caseDef.direction << "u;\n"; 172e5c31af7Sopenharmony_ci } 173e5c31af7Sopenharmony_ci else 174e5c31af7Sopenharmony_ci { 175e5c31af7Sopenharmony_ci geometry << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 176e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n" 177e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + swapTable[gl_SubgroupInvocationID & 0x3u];\n"; 178e5c31af7Sopenharmony_ci } 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_ci geometry << " if (subgroupBallotBitExtract(mask, otherID))\n" 181e5c31af7Sopenharmony_ci << " {\n" 182e5c31af7Sopenharmony_ci << " out_color = (op == data[otherID]) ? 1.0 : 0.0;\n" 183e5c31af7Sopenharmony_ci << " }\n" 184e5c31af7Sopenharmony_ci << " else\n" 185e5c31af7Sopenharmony_ci << " {\n" 186e5c31af7Sopenharmony_ci << " out_color = 1.0;\n" // Invocation we read from was inactive, so we can't verify results! 187e5c31af7Sopenharmony_ci << " }\n" 188e5c31af7Sopenharmony_ci << " gl_Position = gl_in[0].gl_Position;\n" 189e5c31af7Sopenharmony_ci << " EmitVertex();\n" 190e5c31af7Sopenharmony_ci << " EndPrimitive();\n" 191e5c31af7Sopenharmony_ci << "}\n"; 192e5c31af7Sopenharmony_ci 193e5c31af7Sopenharmony_ci programCollection.add("geometry") << glu::GeometrySource(geometry.str()); 194e5c31af7Sopenharmony_ci } 195e5c31af7Sopenharmony_ci else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage) 196e5c31af7Sopenharmony_ci { 197e5c31af7Sopenharmony_ci std::ostringstream controlSource; 198e5c31af7Sopenharmony_ci 199e5c31af7Sopenharmony_ci controlSource << "${VERSION_DECL}\n" 200e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_quad: enable\n" 201e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_ballot: enable\n" 202e5c31af7Sopenharmony_ci << "layout(vertices = 2) out;\n" 203e5c31af7Sopenharmony_ci << "layout(location = 0) out float out_color[];\n" 204e5c31af7Sopenharmony_ci << "layout(binding = 0, std140) uniform Buffer0\n" 205e5c31af7Sopenharmony_ci << "{\n" 206e5c31af7Sopenharmony_ci << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n" 207e5c31af7Sopenharmony_ci << "};\n" 208e5c31af7Sopenharmony_ci << "\n" 209e5c31af7Sopenharmony_ci << "void main (void)\n" 210e5c31af7Sopenharmony_ci << "{\n" 211e5c31af7Sopenharmony_ci << " if (gl_InvocationID == 0)\n" 212e5c31af7Sopenharmony_ci <<" {\n" 213e5c31af7Sopenharmony_ci << " gl_TessLevelOuter[0] = 1.0f;\n" 214e5c31af7Sopenharmony_ci << " gl_TessLevelOuter[1] = 1.0f;\n" 215e5c31af7Sopenharmony_ci << " }\n" 216e5c31af7Sopenharmony_ci << " uvec4 mask = subgroupBallot(true);\n" 217e5c31af7Sopenharmony_ci << swapTable[caseDef.opType]; 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == caseDef.opType) 220e5c31af7Sopenharmony_ci { 221e5c31af7Sopenharmony_ci controlSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 222e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << "u);\n" 223e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + " << caseDef.direction << "u;\n"; 224e5c31af7Sopenharmony_ci } 225e5c31af7Sopenharmony_ci else 226e5c31af7Sopenharmony_ci { 227e5c31af7Sopenharmony_ci controlSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 228e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n" 229e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + swapTable[gl_SubgroupInvocationID & 0x3u];\n"; 230e5c31af7Sopenharmony_ci } 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci controlSource << " if (subgroupBallotBitExtract(mask, otherID))\n" 233e5c31af7Sopenharmony_ci << " {\n" 234e5c31af7Sopenharmony_ci << " out_color[gl_InvocationID] = (op == data[otherID]) ? 1.0 : 0.0;\n" 235e5c31af7Sopenharmony_ci << " }\n" 236e5c31af7Sopenharmony_ci << " else\n" 237e5c31af7Sopenharmony_ci << " {\n" 238e5c31af7Sopenharmony_ci << " out_color[gl_InvocationID] = 1.0; \n"// Invocation we read from was inactive, so we can't verify results! 239e5c31af7Sopenharmony_ci << " }\n" 240e5c31af7Sopenharmony_ci << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 241e5c31af7Sopenharmony_ci << "}\n"; 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str()); 244e5c31af7Sopenharmony_ci subgroups::setTesEvalShaderFrameBuffer(programCollection); 245e5c31af7Sopenharmony_ci } 246e5c31af7Sopenharmony_ci else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage) 247e5c31af7Sopenharmony_ci { 248e5c31af7Sopenharmony_ci ostringstream evaluationSource; 249e5c31af7Sopenharmony_ci evaluationSource << "${VERSION_DECL}\n" 250e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_quad: enable\n" 251e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_ballot: enable\n" 252e5c31af7Sopenharmony_ci << "layout(isolines, equal_spacing, ccw ) in;\n" 253e5c31af7Sopenharmony_ci << "layout(location = 0) out float out_color;\n" 254e5c31af7Sopenharmony_ci << "layout(binding = 0, std140) uniform Buffer0\n" 255e5c31af7Sopenharmony_ci << "{\n" 256e5c31af7Sopenharmony_ci << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[" << subgroups::maxSupportedSubgroupSize() << "];\n" 257e5c31af7Sopenharmony_ci << "};\n" 258e5c31af7Sopenharmony_ci << "\n" 259e5c31af7Sopenharmony_ci << "void main (void)\n" 260e5c31af7Sopenharmony_ci << "{\n" 261e5c31af7Sopenharmony_ci << " uvec4 mask = subgroupBallot(true);\n" 262e5c31af7Sopenharmony_ci << swapTable[caseDef.opType]; 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == caseDef.opType) 265e5c31af7Sopenharmony_ci { 266e5c31af7Sopenharmony_ci evaluationSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 267e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << "u);\n" 268e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + " << caseDef.direction << "u;\n"; 269e5c31af7Sopenharmony_ci } 270e5c31af7Sopenharmony_ci else 271e5c31af7Sopenharmony_ci { 272e5c31af7Sopenharmony_ci evaluationSource << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 273e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n" 274e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + swapTable[gl_SubgroupInvocationID & 0x3u];\n"; 275e5c31af7Sopenharmony_ci } 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_ci evaluationSource << " if (subgroupBallotBitExtract(mask, otherID))\n" 278e5c31af7Sopenharmony_ci << " {\n" 279e5c31af7Sopenharmony_ci << " out_color = (op == data[otherID]) ? 1.0 : 0.0;\n" 280e5c31af7Sopenharmony_ci << " }\n" 281e5c31af7Sopenharmony_ci << " else\n" 282e5c31af7Sopenharmony_ci << " {\n" 283e5c31af7Sopenharmony_ci << " out_color = 1.0;\n" // Invocation we read from was inactive, so we can't verify results! 284e5c31af7Sopenharmony_ci << " }\n" 285e5c31af7Sopenharmony_ci << " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n" 286e5c31af7Sopenharmony_ci << "}\n"; 287e5c31af7Sopenharmony_ci 288e5c31af7Sopenharmony_ci subgroups::setTesCtrlShaderFrameBuffer(programCollection); 289e5c31af7Sopenharmony_ci programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str()); 290e5c31af7Sopenharmony_ci } 291e5c31af7Sopenharmony_ci else 292e5c31af7Sopenharmony_ci { 293e5c31af7Sopenharmony_ci DE_FATAL("Unsupported shader stage"); 294e5c31af7Sopenharmony_ci } 295e5c31af7Sopenharmony_ci} 296e5c31af7Sopenharmony_ci 297e5c31af7Sopenharmony_civoid initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) 298e5c31af7Sopenharmony_ci{ 299e5c31af7Sopenharmony_ci std::string swapTable[OPTYPE_LAST]; 300e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_BROADCAST] = ""; 301e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_SWAP_HORIZONTAL] = " const uint swapTable[4] = uint[](1u, 0u, 3u, 2u);\n"; 302e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_SWAP_VERTICAL] = " const uint swapTable[4] = uint[](2u, 3u, 0u, 1u);\n"; 303e5c31af7Sopenharmony_ci swapTable[OPTYPE_QUAD_SWAP_DIAGONAL] = " const uint swapTable[4] = uint[](3u, 2u, 1u, 0u);\n"; 304e5c31af7Sopenharmony_ci 305e5c31af7Sopenharmony_ci if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) 306e5c31af7Sopenharmony_ci { 307e5c31af7Sopenharmony_ci std::ostringstream src; 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci src << "${VERSION_DECL}\n" 310e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_quad: enable\n" 311e5c31af7Sopenharmony_ci << "#extension GL_KHR_shader_subgroup_ballot: enable\n" 312e5c31af7Sopenharmony_ci << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n" 313e5c31af7Sopenharmony_ci << "layout(binding = 0, std430) buffer Buffer0\n" 314e5c31af7Sopenharmony_ci << "{\n" 315e5c31af7Sopenharmony_ci << " uint result[];\n" 316e5c31af7Sopenharmony_ci << "};\n" 317e5c31af7Sopenharmony_ci << "layout(binding = 1, std430) buffer Buffer1\n" 318e5c31af7Sopenharmony_ci << "{\n" 319e5c31af7Sopenharmony_ci << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data[];\n" 320e5c31af7Sopenharmony_ci << "};\n" 321e5c31af7Sopenharmony_ci << "\n" 322e5c31af7Sopenharmony_ci << "void main (void)\n" 323e5c31af7Sopenharmony_ci << "{\n" 324e5c31af7Sopenharmony_ci << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n" 325e5c31af7Sopenharmony_ci << " highp uint offset = globalSize.x * ((globalSize.y * " 326e5c31af7Sopenharmony_ci "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + " 327e5c31af7Sopenharmony_ci "gl_GlobalInvocationID.x;\n" 328e5c31af7Sopenharmony_ci << " uvec4 mask = subgroupBallot(true);\n" 329e5c31af7Sopenharmony_ci << swapTable[caseDef.opType]; 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_ci 332e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == caseDef.opType) 333e5c31af7Sopenharmony_ci { 334e5c31af7Sopenharmony_ci src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 335e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << "u);\n" 336e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + " << caseDef.direction << "u;\n"; 337e5c31af7Sopenharmony_ci } 338e5c31af7Sopenharmony_ci else 339e5c31af7Sopenharmony_ci { 340e5c31af7Sopenharmony_ci src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 341e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n" 342e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + swapTable[gl_SubgroupInvocationID & 0x3u];\n"; 343e5c31af7Sopenharmony_ci } 344e5c31af7Sopenharmony_ci 345e5c31af7Sopenharmony_ci src << " if (subgroupBallotBitExtract(mask, otherID))\n" 346e5c31af7Sopenharmony_ci << " {\n" 347e5c31af7Sopenharmony_ci << " result[offset] = (op == data[otherID]) ? 1u : 0u;\n" 348e5c31af7Sopenharmony_ci << " }\n" 349e5c31af7Sopenharmony_ci << " else\n" 350e5c31af7Sopenharmony_ci << " {\n" 351e5c31af7Sopenharmony_ci << " result[offset] = 1u; // Invocation we read from was inactive, so we can't verify results!\n" 352e5c31af7Sopenharmony_ci << " }\n" 353e5c31af7Sopenharmony_ci << "}\n"; 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ci programCollection.add("comp") << glu::ComputeSource(src.str()); 356e5c31af7Sopenharmony_ci } 357e5c31af7Sopenharmony_ci else 358e5c31af7Sopenharmony_ci { 359e5c31af7Sopenharmony_ci std::ostringstream src; 360e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == caseDef.opType) 361e5c31af7Sopenharmony_ci { 362e5c31af7Sopenharmony_ci src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 363e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID], " << caseDef.direction << "u);\n" 364e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + " << caseDef.direction << "u;\n"; 365e5c31af7Sopenharmony_ci } 366e5c31af7Sopenharmony_ci else 367e5c31af7Sopenharmony_ci { 368e5c31af7Sopenharmony_ci src << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " 369e5c31af7Sopenharmony_ci << getOpTypeName(caseDef.opType) << "(data[gl_SubgroupInvocationID]);\n" 370e5c31af7Sopenharmony_ci << " uint otherID = (gl_SubgroupInvocationID & ~0x3u) + swapTable[gl_SubgroupInvocationID & 0x3u];\n"; 371e5c31af7Sopenharmony_ci } 372e5c31af7Sopenharmony_ci const string sourceType = src.str(); 373e5c31af7Sopenharmony_ci 374e5c31af7Sopenharmony_ci { 375e5c31af7Sopenharmony_ci const string vertex = 376e5c31af7Sopenharmony_ci "${VERSION_DECL}\n" 377e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_quad: enable\n" 378e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_ballot: enable\n" 379e5c31af7Sopenharmony_ci "layout(binding = 0, std430) buffer Buffer0\n" 380e5c31af7Sopenharmony_ci "{\n" 381e5c31af7Sopenharmony_ci " uint result[];\n" 382e5c31af7Sopenharmony_ci "} b0;\n" 383e5c31af7Sopenharmony_ci "layout(binding = 4, std430) readonly buffer Buffer4\n" 384e5c31af7Sopenharmony_ci "{\n" 385e5c31af7Sopenharmony_ci " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n" 386e5c31af7Sopenharmony_ci "};\n" 387e5c31af7Sopenharmony_ci "\n" 388e5c31af7Sopenharmony_ci "void main (void)\n" 389e5c31af7Sopenharmony_ci "{\n" 390e5c31af7Sopenharmony_ci " uvec4 mask = subgroupBallot(true);\n" 391e5c31af7Sopenharmony_ci + swapTable[caseDef.opType] 392e5c31af7Sopenharmony_ci + sourceType + 393e5c31af7Sopenharmony_ci " if (subgroupBallotBitExtract(mask, otherID))\n" 394e5c31af7Sopenharmony_ci " {\n" 395e5c31af7Sopenharmony_ci " b0.result[gl_VertexID] = (op == data[otherID]) ? 1u : 0u;\n" 396e5c31af7Sopenharmony_ci " }\n" 397e5c31af7Sopenharmony_ci " else\n" 398e5c31af7Sopenharmony_ci " {\n" 399e5c31af7Sopenharmony_ci " b0.result[gl_VertexID] = 1u; // Invocation we read from was inactive, so we can't verify results!\n" 400e5c31af7Sopenharmony_ci " }\n" 401e5c31af7Sopenharmony_ci " float pixelSize = 2.0f/1024.0f;\n" 402e5c31af7Sopenharmony_ci " float pixelPosition = pixelSize/2.0f - 1.0f;\n" 403e5c31af7Sopenharmony_ci " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n" 404e5c31af7Sopenharmony_ci "}\n"; 405e5c31af7Sopenharmony_ci programCollection.add("vert") << glu::VertexSource(vertex); 406e5c31af7Sopenharmony_ci } 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_ci { 409e5c31af7Sopenharmony_ci const string tesc = 410e5c31af7Sopenharmony_ci "${VERSION_DECL}\n" 411e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_quad: enable\n" 412e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_ballot: enable\n" 413e5c31af7Sopenharmony_ci "layout(vertices=1) out;\n" 414e5c31af7Sopenharmony_ci "layout(binding = 1, std430) buffer Buffer1\n" 415e5c31af7Sopenharmony_ci "{\n" 416e5c31af7Sopenharmony_ci " uint result[];\n" 417e5c31af7Sopenharmony_ci "} b1;\n" 418e5c31af7Sopenharmony_ci "layout(binding = 4, std430) readonly buffer Buffer4\n" 419e5c31af7Sopenharmony_ci "{\n" 420e5c31af7Sopenharmony_ci " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n" 421e5c31af7Sopenharmony_ci "};\n" 422e5c31af7Sopenharmony_ci "\n" 423e5c31af7Sopenharmony_ci "void main (void)\n" 424e5c31af7Sopenharmony_ci "{\n" 425e5c31af7Sopenharmony_ci " uvec4 mask = subgroupBallot(true);\n" 426e5c31af7Sopenharmony_ci + swapTable[caseDef.opType] 427e5c31af7Sopenharmony_ci + sourceType + 428e5c31af7Sopenharmony_ci " if (subgroupBallotBitExtract(mask, otherID))\n" 429e5c31af7Sopenharmony_ci " {\n" 430e5c31af7Sopenharmony_ci " b1.result[gl_PrimitiveID] = (op == data[otherID]) ? 1u : 0u;\n" 431e5c31af7Sopenharmony_ci " }\n" 432e5c31af7Sopenharmony_ci " else\n" 433e5c31af7Sopenharmony_ci " {\n" 434e5c31af7Sopenharmony_ci " b1.result[gl_PrimitiveID] = 1u; // Invocation we read from was inactive, so we can't verify results!\n" 435e5c31af7Sopenharmony_ci " }\n" 436e5c31af7Sopenharmony_ci " if (gl_InvocationID == 0)\n" 437e5c31af7Sopenharmony_ci " {\n" 438e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 1.0f;\n" 439e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 1.0f;\n" 440e5c31af7Sopenharmony_ci " }\n" 441e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 442e5c31af7Sopenharmony_ci "}\n"; 443e5c31af7Sopenharmony_ci programCollection.add("tesc") << glu::TessellationControlSource(tesc); 444e5c31af7Sopenharmony_ci } 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_ci { 447e5c31af7Sopenharmony_ci const string tese = 448e5c31af7Sopenharmony_ci "${VERSION_DECL}\n" 449e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_quad: enable\n" 450e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_ballot: enable\n" 451e5c31af7Sopenharmony_ci "layout(isolines) in;\n" 452e5c31af7Sopenharmony_ci "layout(binding = 2, std430) buffer Buffer2\n" 453e5c31af7Sopenharmony_ci "{\n" 454e5c31af7Sopenharmony_ci " uint result[];\n" 455e5c31af7Sopenharmony_ci "} b2;\n" 456e5c31af7Sopenharmony_ci "layout(binding = 4, std430) readonly buffer Buffer4\n" 457e5c31af7Sopenharmony_ci "{\n" 458e5c31af7Sopenharmony_ci " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n" 459e5c31af7Sopenharmony_ci "};\n" 460e5c31af7Sopenharmony_ci "\n" 461e5c31af7Sopenharmony_ci "void main (void)\n" 462e5c31af7Sopenharmony_ci "{\n" 463e5c31af7Sopenharmony_ci " uvec4 mask = subgroupBallot(true);\n" 464e5c31af7Sopenharmony_ci + swapTable[caseDef.opType] 465e5c31af7Sopenharmony_ci + sourceType + 466e5c31af7Sopenharmony_ci " if (subgroupBallotBitExtract(mask, otherID))\n" 467e5c31af7Sopenharmony_ci " {\n" 468e5c31af7Sopenharmony_ci " b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = (op == data[otherID]) ? 1u : 0u;\n" 469e5c31af7Sopenharmony_ci " }\n" 470e5c31af7Sopenharmony_ci " else\n" 471e5c31af7Sopenharmony_ci " {\n" 472e5c31af7Sopenharmony_ci " b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = 1u; // Invocation we read from was inactive, so we can't verify results!\n" 473e5c31af7Sopenharmony_ci " }\n" 474e5c31af7Sopenharmony_ci " float pixelSize = 2.0f/1024.0f;\n" 475e5c31af7Sopenharmony_ci " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n" 476e5c31af7Sopenharmony_ci "}\n"; 477e5c31af7Sopenharmony_ci programCollection.add("tese") << glu::TessellationEvaluationSource(tese); 478e5c31af7Sopenharmony_ci } 479e5c31af7Sopenharmony_ci 480e5c31af7Sopenharmony_ci { 481e5c31af7Sopenharmony_ci const string geometry = 482e5c31af7Sopenharmony_ci // version added by addGeometryShadersFromTemplate 483e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_quad: enable\n" 484e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_ballot: enable\n" 485e5c31af7Sopenharmony_ci "layout(${TOPOLOGY}) in;\n" 486e5c31af7Sopenharmony_ci "layout(points, max_vertices = 1) out;\n" 487e5c31af7Sopenharmony_ci "layout(binding = 3, std430) buffer Buffer3\n" 488e5c31af7Sopenharmony_ci "{\n" 489e5c31af7Sopenharmony_ci " uint result[];\n" 490e5c31af7Sopenharmony_ci "} b3;\n" 491e5c31af7Sopenharmony_ci "layout(binding = 4, std430) readonly buffer Buffer4\n" 492e5c31af7Sopenharmony_ci "{\n" 493e5c31af7Sopenharmony_ci " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n" 494e5c31af7Sopenharmony_ci "};\n" 495e5c31af7Sopenharmony_ci "\n" 496e5c31af7Sopenharmony_ci "void main (void)\n" 497e5c31af7Sopenharmony_ci "{\n" 498e5c31af7Sopenharmony_ci " uvec4 mask = subgroupBallot(true);\n" 499e5c31af7Sopenharmony_ci + swapTable[caseDef.opType] 500e5c31af7Sopenharmony_ci + sourceType + 501e5c31af7Sopenharmony_ci " if (subgroupBallotBitExtract(mask, otherID))\n" 502e5c31af7Sopenharmony_ci " {\n" 503e5c31af7Sopenharmony_ci " b3.result[gl_PrimitiveIDIn] = (op == data[otherID]) ? 1u : 0u;\n" 504e5c31af7Sopenharmony_ci " }\n" 505e5c31af7Sopenharmony_ci " else\n" 506e5c31af7Sopenharmony_ci " {\n" 507e5c31af7Sopenharmony_ci " b3.result[gl_PrimitiveIDIn] = 1u; // Invocation we read from was inactive, so we can't verify results!\n" 508e5c31af7Sopenharmony_ci " }\n" 509e5c31af7Sopenharmony_ci " gl_Position = gl_in[0].gl_Position;\n" 510e5c31af7Sopenharmony_ci " EmitVertex();\n" 511e5c31af7Sopenharmony_ci " EndPrimitive();\n" 512e5c31af7Sopenharmony_ci "}\n"; 513e5c31af7Sopenharmony_ci subgroups::addGeometryShadersFromTemplate(geometry, programCollection); 514e5c31af7Sopenharmony_ci } 515e5c31af7Sopenharmony_ci 516e5c31af7Sopenharmony_ci { 517e5c31af7Sopenharmony_ci const string fragment = 518e5c31af7Sopenharmony_ci "${VERSION_DECL}\n" 519e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_quad: enable\n" 520e5c31af7Sopenharmony_ci "#extension GL_KHR_shader_subgroup_ballot: enable\n" 521e5c31af7Sopenharmony_ci "precision highp int;\n" 522e5c31af7Sopenharmony_ci "precision highp float;\n" 523e5c31af7Sopenharmony_ci "layout(location = 0) out uint result;\n" 524e5c31af7Sopenharmony_ci "layout(binding = 4, std430) readonly buffer Buffer4\n" 525e5c31af7Sopenharmony_ci "{\n" 526e5c31af7Sopenharmony_ci " " + subgroups::getFormatNameForGLSL(caseDef.format) + " data[];\n" 527e5c31af7Sopenharmony_ci "};\n" 528e5c31af7Sopenharmony_ci "void main (void)\n" 529e5c31af7Sopenharmony_ci "{\n" 530e5c31af7Sopenharmony_ci " uvec4 mask = subgroupBallot(true);\n" 531e5c31af7Sopenharmony_ci + swapTable[caseDef.opType] 532e5c31af7Sopenharmony_ci + sourceType + 533e5c31af7Sopenharmony_ci " if (subgroupBallotBitExtract(mask, otherID))\n" 534e5c31af7Sopenharmony_ci " {\n" 535e5c31af7Sopenharmony_ci " result = (op == data[otherID]) ? 1u : 0u;\n" 536e5c31af7Sopenharmony_ci " }\n" 537e5c31af7Sopenharmony_ci " else\n" 538e5c31af7Sopenharmony_ci " {\n" 539e5c31af7Sopenharmony_ci " result = 1u; // Invocation we read from was inactive, so we can't verify results!\n" 540e5c31af7Sopenharmony_ci " }\n" 541e5c31af7Sopenharmony_ci "}\n"; 542e5c31af7Sopenharmony_ci programCollection.add("fragment") << glu::FragmentSource(fragment); 543e5c31af7Sopenharmony_ci } 544e5c31af7Sopenharmony_ci subgroups::addNoSubgroupShader(programCollection); 545e5c31af7Sopenharmony_ci } 546e5c31af7Sopenharmony_ci} 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_civoid supportedCheck (Context& context, CaseDefinition caseDef) 549e5c31af7Sopenharmony_ci{ 550e5c31af7Sopenharmony_ci if (!subgroups::isSubgroupSupported(context)) 551e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Subgroup operations are not supported"); 552e5c31af7Sopenharmony_ci 553e5c31af7Sopenharmony_ci if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_QUAD_BIT)) 554e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Device does not support subgroup quad operations"); 555e5c31af7Sopenharmony_ci 556e5c31af7Sopenharmony_ci 557e5c31af7Sopenharmony_ci if (subgroups::isDoubleFormat(caseDef.format) && 558e5c31af7Sopenharmony_ci !subgroups::isDoubleSupportedForDevice(context)) 559e5c31af7Sopenharmony_ci { 560e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Device does not support subgroup double operations"); 561e5c31af7Sopenharmony_ci } 562e5c31af7Sopenharmony_ci} 563e5c31af7Sopenharmony_ci 564e5c31af7Sopenharmony_citcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef) 565e5c31af7Sopenharmony_ci{ 566e5c31af7Sopenharmony_ci if (!subgroups::areSubgroupOperationsSupportedForStage( 567e5c31af7Sopenharmony_ci context, caseDef.shaderStage)) 568e5c31af7Sopenharmony_ci { 569e5c31af7Sopenharmony_ci if (subgroups::areSubgroupOperationsRequiredForStage( 570e5c31af7Sopenharmony_ci caseDef.shaderStage)) 571e5c31af7Sopenharmony_ci { 572e5c31af7Sopenharmony_ci return tcu::TestStatus::fail( 573e5c31af7Sopenharmony_ci "Shader stage " + 574e5c31af7Sopenharmony_ci subgroups::getShaderStageName(caseDef.shaderStage) + 575e5c31af7Sopenharmony_ci " is required to support subgroup operations!"); 576e5c31af7Sopenharmony_ci } 577e5c31af7Sopenharmony_ci else 578e5c31af7Sopenharmony_ci { 579e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage"); 580e5c31af7Sopenharmony_ci } 581e5c31af7Sopenharmony_ci } 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci subgroups::SSBOData inputData; 584e5c31af7Sopenharmony_ci inputData.format = caseDef.format; 585e5c31af7Sopenharmony_ci inputData.layout = subgroups::SSBOData::LayoutStd140; 586e5c31af7Sopenharmony_ci inputData.numElements = subgroups::maxSupportedSubgroupSize(); 587e5c31af7Sopenharmony_ci inputData.initializeType = subgroups::SSBOData::InitializeNonZero; 588e5c31af7Sopenharmony_ci inputData.binding = 0u; 589e5c31af7Sopenharmony_ci 590e5c31af7Sopenharmony_ci if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage) 591e5c31af7Sopenharmony_ci return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages); 592e5c31af7Sopenharmony_ci else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage) 593e5c31af7Sopenharmony_ci return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages); 594e5c31af7Sopenharmony_ci else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage) 595e5c31af7Sopenharmony_ci return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT); 596e5c31af7Sopenharmony_ci else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage) 597e5c31af7Sopenharmony_ci return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT); 598e5c31af7Sopenharmony_ci else 599e5c31af7Sopenharmony_ci TCU_THROW(InternalError, "Unhandled shader stage"); 600e5c31af7Sopenharmony_ci} 601e5c31af7Sopenharmony_ci 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_citcu::TestStatus test(Context& context, const CaseDefinition caseDef) 604e5c31af7Sopenharmony_ci{ 605e5c31af7Sopenharmony_ci if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) 606e5c31af7Sopenharmony_ci { 607e5c31af7Sopenharmony_ci if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage)) 608e5c31af7Sopenharmony_ci { 609e5c31af7Sopenharmony_ci return tcu::TestStatus::fail( 610e5c31af7Sopenharmony_ci "Shader stage " + 611e5c31af7Sopenharmony_ci subgroups::getShaderStageName(caseDef.shaderStage) + 612e5c31af7Sopenharmony_ci " is required to support subgroup operations!"); 613e5c31af7Sopenharmony_ci } 614e5c31af7Sopenharmony_ci subgroups::SSBOData inputData; 615e5c31af7Sopenharmony_ci inputData.format = caseDef.format; 616e5c31af7Sopenharmony_ci inputData.layout = subgroups::SSBOData::LayoutStd430; 617e5c31af7Sopenharmony_ci inputData.numElements = subgroups::maxSupportedSubgroupSize(); 618e5c31af7Sopenharmony_ci inputData.initializeType = subgroups::SSBOData::InitializeNonZero; 619e5c31af7Sopenharmony_ci inputData.binding = 1u; 620e5c31af7Sopenharmony_ci 621e5c31af7Sopenharmony_ci return subgroups::makeComputeTest(context, FORMAT_R32_UINT, &inputData, 1, checkComputeStage); 622e5c31af7Sopenharmony_ci } 623e5c31af7Sopenharmony_ci else 624e5c31af7Sopenharmony_ci { 625e5c31af7Sopenharmony_ci int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR); 626e5c31af7Sopenharmony_ci 627e5c31af7Sopenharmony_ci ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages); 628e5c31af7Sopenharmony_ci 629e5c31af7Sopenharmony_ci if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context)) 630e5c31af7Sopenharmony_ci { 631e5c31af7Sopenharmony_ci if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0) 632e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes"); 633e5c31af7Sopenharmony_ci else 634e5c31af7Sopenharmony_ci stages = SHADER_STAGE_FRAGMENT_BIT; 635e5c31af7Sopenharmony_ci } 636e5c31af7Sopenharmony_ci 637e5c31af7Sopenharmony_ci if ((ShaderStageFlags)0u == stages) 638e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader"); 639e5c31af7Sopenharmony_ci 640e5c31af7Sopenharmony_ci subgroups::SSBOData inputData; 641e5c31af7Sopenharmony_ci inputData.format = caseDef.format; 642e5c31af7Sopenharmony_ci inputData.layout = subgroups::SSBOData::LayoutStd430; 643e5c31af7Sopenharmony_ci inputData.numElements = subgroups::maxSupportedSubgroupSize(); 644e5c31af7Sopenharmony_ci inputData.initializeType = subgroups::SSBOData::InitializeNonZero; 645e5c31af7Sopenharmony_ci inputData.binding = 4u; 646e5c31af7Sopenharmony_ci inputData.stages = stages; 647e5c31af7Sopenharmony_ci 648e5c31af7Sopenharmony_ci return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages); 649e5c31af7Sopenharmony_ci } 650e5c31af7Sopenharmony_ci} 651e5c31af7Sopenharmony_ci} 652e5c31af7Sopenharmony_ci 653e5c31af7Sopenharmony_cideqp::TestCaseGroup* createSubgroupsQuadTests(deqp::Context& testCtx) 654e5c31af7Sopenharmony_ci{ 655e5c31af7Sopenharmony_ci de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup( 656e5c31af7Sopenharmony_ci testCtx, "graphics", "Subgroup arithmetic category tests: graphics")); 657e5c31af7Sopenharmony_ci de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup( 658e5c31af7Sopenharmony_ci testCtx, "compute", "Subgroup arithmetic category tests: compute")); 659e5c31af7Sopenharmony_ci de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup( 660e5c31af7Sopenharmony_ci testCtx, "framebuffer", "Subgroup arithmetic category tests: framebuffer")); 661e5c31af7Sopenharmony_ci 662e5c31af7Sopenharmony_ci const Format formats[] = 663e5c31af7Sopenharmony_ci { 664e5c31af7Sopenharmony_ci FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT, 665e5c31af7Sopenharmony_ci FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT, 666e5c31af7Sopenharmony_ci FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT, 667e5c31af7Sopenharmony_ci FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT, 668e5c31af7Sopenharmony_ci FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT, 669e5c31af7Sopenharmony_ci FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT, 670e5c31af7Sopenharmony_ci FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT, 671e5c31af7Sopenharmony_ci FORMAT_R32_BOOL, FORMAT_R32G32_BOOL, 672e5c31af7Sopenharmony_ci FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL, 673e5c31af7Sopenharmony_ci }; 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ci const ShaderStageFlags stages[] = 676e5c31af7Sopenharmony_ci { 677e5c31af7Sopenharmony_ci SHADER_STAGE_VERTEX_BIT, 678e5c31af7Sopenharmony_ci SHADER_STAGE_TESS_EVALUATION_BIT, 679e5c31af7Sopenharmony_ci SHADER_STAGE_TESS_CONTROL_BIT, 680e5c31af7Sopenharmony_ci SHADER_STAGE_GEOMETRY_BIT, 681e5c31af7Sopenharmony_ci }; 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ci for (int direction = 0; direction < 4; ++direction) 684e5c31af7Sopenharmony_ci { 685e5c31af7Sopenharmony_ci for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex) 686e5c31af7Sopenharmony_ci { 687e5c31af7Sopenharmony_ci const Format format = formats[formatIndex]; 688e5c31af7Sopenharmony_ci 689e5c31af7Sopenharmony_ci for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex) 690e5c31af7Sopenharmony_ci { 691e5c31af7Sopenharmony_ci const std::string op = de::toLower(getOpTypeName(opTypeIndex)); 692e5c31af7Sopenharmony_ci std::ostringstream name; 693e5c31af7Sopenharmony_ci name << de::toLower(op); 694e5c31af7Sopenharmony_ci 695e5c31af7Sopenharmony_ci if (OPTYPE_QUAD_BROADCAST == opTypeIndex) 696e5c31af7Sopenharmony_ci { 697e5c31af7Sopenharmony_ci name << "_" << direction; 698e5c31af7Sopenharmony_ci } 699e5c31af7Sopenharmony_ci else 700e5c31af7Sopenharmony_ci { 701e5c31af7Sopenharmony_ci if (0 != direction) 702e5c31af7Sopenharmony_ci { 703e5c31af7Sopenharmony_ci // We don't need direction for swap operations. 704e5c31af7Sopenharmony_ci continue; 705e5c31af7Sopenharmony_ci } 706e5c31af7Sopenharmony_ci } 707e5c31af7Sopenharmony_ci 708e5c31af7Sopenharmony_ci name << "_" << subgroups::getFormatNameForGLSL(format); 709e5c31af7Sopenharmony_ci 710e5c31af7Sopenharmony_ci { 711e5c31af7Sopenharmony_ci const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format, direction}; 712e5c31af7Sopenharmony_ci SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), name.str(), "", supportedCheck, initPrograms, test, caseDef); 713e5c31af7Sopenharmony_ci } 714e5c31af7Sopenharmony_ci 715e5c31af7Sopenharmony_ci { 716e5c31af7Sopenharmony_ci const CaseDefinition caseDef = 717e5c31af7Sopenharmony_ci { 718e5c31af7Sopenharmony_ci opTypeIndex, 719e5c31af7Sopenharmony_ci SHADER_STAGE_ALL_GRAPHICS, 720e5c31af7Sopenharmony_ci format, 721e5c31af7Sopenharmony_ci direction 722e5c31af7Sopenharmony_ci }; 723e5c31af7Sopenharmony_ci SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), name.str(), "", supportedCheck, initPrograms, test, caseDef); 724e5c31af7Sopenharmony_ci } 725e5c31af7Sopenharmony_ci for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex) 726e5c31af7Sopenharmony_ci { 727e5c31af7Sopenharmony_ci const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format, direction}; 728e5c31af7Sopenharmony_ci SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(), name.str()+"_"+ getShaderStageName(caseDef.shaderStage), "", 729e5c31af7Sopenharmony_ci supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef); 730e5c31af7Sopenharmony_ci } 731e5c31af7Sopenharmony_ci 732e5c31af7Sopenharmony_ci } 733e5c31af7Sopenharmony_ci } 734e5c31af7Sopenharmony_ci } 735e5c31af7Sopenharmony_ci 736e5c31af7Sopenharmony_ci de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup( 737e5c31af7Sopenharmony_ci testCtx, "quad", "Subgroup quad category tests")); 738e5c31af7Sopenharmony_ci 739e5c31af7Sopenharmony_ci group->addChild(graphicGroup.release()); 740e5c31af7Sopenharmony_ci group->addChild(computeGroup.release()); 741e5c31af7Sopenharmony_ci group->addChild(framebufferGroup.release()); 742e5c31af7Sopenharmony_ci 743e5c31af7Sopenharmony_ci return group.release(); 744e5c31af7Sopenharmony_ci} 745e5c31af7Sopenharmony_ci} // subgroups 746e5c31af7Sopenharmony_ci} // glc 747