| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2019 The Khronos Group Inc. |
| * Copyright (c) 2019 Google Inc. |
| * Copyright (c) 2017 Codeplay Software Ltd. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ /*! |
| * \file |
| * \brief Subgroups Tests |
| */ /*--------------------------------------------------------------------*/ |
| |
| #include "vktSubgroupsBuiltinMaskVarTests.hpp" |
| #include "vktSubgroupsTestsUtils.hpp" |
| |
| #include <string> |
| #include <vector> |
| |
| using namespace tcu; |
| using namespace std; |
| using namespace vk; |
| |
| namespace vkt |
| { |
| namespace subgroups |
| { |
| |
| static bool checkVertexPipelineStages(const void* internalData, std::vector<const void*> datas, |
| deUint32 width, deUint32) |
| { |
| DE_UNREF(internalData); |
| return check(datas, width, 1); |
| } |
| |
| static bool checkComputeStage(const void* internalData, std::vector<const void*> datas, |
| const deUint32 numWorkgroups[3], const deUint32 localSize[3], |
| deUint32) |
| { |
| DE_UNREF(internalData); |
| return checkCompute(datas, numWorkgroups, localSize, 1); |
| } |
| |
| namespace |
| { |
| struct CaseDefinition |
| { |
| std::string varName; |
| VkShaderStageFlags shaderStage; |
| de::SharedPtr<bool> geometryPointSizeSupported; |
| deBool requiredSubgroupSize; |
| }; |
| } |
| |
| std::string subgroupComparison (const CaseDefinition& caseDef) |
| { |
| if ("gl_SubgroupEqMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "%56 = OpIEqual %11 %53 %55\n"; |
| else |
| return "%38 = OpIEqual %16 %35 %37\n"; |
| } |
| else if ("gl_SubgroupGeMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "%56 = OpUGreaterThanEqual %11 %53 %55\n"; |
| else |
| return "%38 = OpUGreaterThanEqual %16 %35 %37\n"; |
| } |
| else if ("gl_SubgroupGtMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "%56 = OpUGreaterThan %11 %53 %55\n"; |
| else |
| return "%38 = OpUGreaterThan %16 %35 %37\n"; |
| } |
| else if ("gl_SubgroupLeMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "%56 = OpULessThanEqual %11 %53 %55\n"; |
| else |
| return "%38 = OpULessThanEqual %16 %35 %37\n"; |
| } |
| else if ("gl_SubgroupLtMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "%56 = OpULessThan %11 %53 %55\n"; |
| else |
| return "%38 = OpULessThan %16 %35 %37\n"; |
| } |
| return ""; |
| } |
| |
| std::string varSubgroupMask (const CaseDefinition& caseDef) |
| { |
| if ("gl_SubgroupEqMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "OpDecorate %40 BuiltIn SubgroupEqMask\n"; |
| else |
| return "OpDecorate %22 BuiltIn SubgroupEqMask\n"; |
| } |
| else if ("gl_SubgroupGeMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "OpDecorate %40 BuiltIn SubgroupGeMask\n"; |
| else |
| return "OpDecorate %22 BuiltIn SubgroupGeMask\n"; |
| } |
| else if ("gl_SubgroupGtMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "OpDecorate %40 BuiltIn SubgroupGtMask\n"; |
| else |
| return "OpDecorate %22 BuiltIn SubgroupGtMask\n"; |
| } |
| else if ("gl_SubgroupLeMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "OpDecorate %40 BuiltIn SubgroupLeMask\n"; |
| else |
| return "OpDecorate %22 BuiltIn SubgroupLeMask\n"; |
| } |
| else if ("gl_SubgroupLtMask" == caseDef.varName) |
| { |
| if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| return "OpDecorate %40 BuiltIn SubgroupLtMask\n"; |
| else |
| return "OpDecorate %22 BuiltIn SubgroupLtMask\n"; |
| } |
| return ""; |
| } |
| |
| std::string subgroupMask (const CaseDefinition& caseDef) |
| { |
| std::ostringstream bdy; |
| |
| bdy << " uint tempResult = 0x1;\n" |
| << " uint bit = 0x1;\n" |
| << " uint bitCount = 0x0;\n" |
| << " uvec4 mask = subgroupBallot(true);\n" |
| << " const uvec4 var = " << caseDef.varName << ";\n" |
| << " for (uint i = 0; i < gl_SubgroupSize; i++)\n" |
| << " {\n"; |
| |
| if ("gl_SubgroupEqMask" == caseDef.varName) |
| { |
| bdy << " if ((i == gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n" |
| << " {\n" |
| << " tempResult = 0;\n" |
| << " }\n"; |
| } |
| else if ("gl_SubgroupGeMask" == caseDef.varName) |
| { |
| bdy << " if ((i >= gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n" |
| << " {\n" |
| << " tempResult = 0;\n" |
| << " }\n"; |
| } |
| else if ("gl_SubgroupGtMask" == caseDef.varName) |
| { |
| bdy << " if ((i > gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n" |
| << " {\n" |
| << " tempResult = 0;\n" |
| << " }\n"; |
| } |
| else if ("gl_SubgroupLeMask" == caseDef.varName) |
| { |
| bdy << " if ((i <= gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n" |
| << " {\n" |
| << " tempResult = 0;\n" |
| << " }\n"; |
| } |
| else if ("gl_SubgroupLtMask" == caseDef.varName) |
| { |
| bdy << " if ((i < gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n" |
| << " {\n" |
| << " tempResult = 0;\n" |
| << " }\n"; |
| } |
| |
| bdy << " }\n" |
| << " for (uint i = 0; i < 32; i++)\n" |
| << " {\n" |
| << " if ((var.x & bit) > 0)\n" |
| << " {\n" |
| << " bitCount++;\n" |
| << " }\n" |
| << " if ((var.y & bit) > 0)\n" |
| << " {\n" |
| << " bitCount++;\n" |
| << " }\n" |
| << " if ((var.z & bit) > 0)\n" |
| << " {\n" |
| << " bitCount++;\n" |
| << " }\n" |
| << " if ((var.w & bit) > 0)\n" |
| << " {\n" |
| << " bitCount++;\n" |
| << " }\n" |
| << " bit = bit<<1;\n" |
| << " }\n" |
| << " if (subgroupBallotBitCount(var) != bitCount)\n" |
| << " {\n" |
| << " tempResult = 0;\n" |
| << " }\n"; |
| return bdy.str(); |
| } |
| |
| void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef) |
| { |
| const vk::SpirVAsmBuildOptions buildOptionsSpr (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3); |
| const string comparison = subgroupComparison(caseDef); |
| const string mask = varSubgroupMask(caseDef); |
| |
| subgroups::setFragmentShaderFrameBuffer(programCollection); |
| |
| if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage) |
| subgroups::setVertexShaderFrameBuffer(programCollection); |
| |
| if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage) |
| { |
| /* |
| const string bdy = subgroupMask(caseDef); |
| const string vertex = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(location = 0) out float out_color;\n" |
| "layout(location = 0) in highp vec4 in_position;\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " out_color = float(tempResult);\n" |
| " gl_Position = in_position;\n" |
| " gl_PointSize = 1.0f;\n" |
| "}\n"; |
| programCollection.glslSources.add("vert") |
| << glu::VertexSource(vertex) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u); |
| */ |
| |
| const string vertex = |
| "; SPIR-V\n" |
| "; Version: 1.3\n" |
| "; Generator: Khronos Glslang Reference Front End; 2\n" |
| "; Bound: 123\n" |
| "; Schema: 0\n" |
| "OpCapability Shader\n" |
| "OpCapability GroupNonUniform\n" |
| "OpCapability GroupNonUniformBallot\n" |
| "%1 = OpExtInstImport \"GLSL.std.450\"\n" |
| "OpMemoryModel Logical GLSL450\n" |
| "OpEntryPoint Vertex %4 \"main\" %22 %32 %36 %107 %114 %117\n" |
| + mask + |
| "OpDecorate %32 RelaxedPrecision\n" |
| "OpDecorate %32 BuiltIn SubgroupSize\n" |
| "OpDecorate %33 RelaxedPrecision\n" |
| "OpDecorate %36 RelaxedPrecision\n" |
| "OpDecorate %36 BuiltIn SubgroupLocalInvocationId\n" |
| "OpDecorate %37 RelaxedPrecision\n" |
| "OpDecorate %107 Location 0\n" |
| "OpMemberDecorate %112 0 BuiltIn Position\n" |
| "OpMemberDecorate %112 1 BuiltIn PointSize\n" |
| "OpMemberDecorate %112 2 BuiltIn ClipDistance\n" |
| "OpMemberDecorate %112 3 BuiltIn CullDistance\n" |
| "OpDecorate %112 Block\n" |
| "OpDecorate %117 Location 0\n" |
| "%2 = OpTypeVoid\n" |
| "%3 = OpTypeFunction %2\n" |
| "%6 = OpTypeInt 32 0\n" |
| "%7 = OpTypePointer Function %6\n" |
| "%9 = OpConstant %6 1\n" |
| "%12 = OpConstant %6 0\n" |
| "%13 = OpTypeVector %6 4\n" |
| "%14 = OpTypePointer Function %13\n" |
| "%16 = OpTypeBool\n" |
| "%17 = OpConstantTrue %16\n" |
| "%18 = OpConstant %6 3\n" |
| "%21 = OpTypePointer Input %13\n" |
| "%22 = OpVariable %21 Input\n" |
| "%31 = OpTypePointer Input %6\n" |
| "%32 = OpVariable %31 Input\n" |
| "%36 = OpVariable %31 Input\n" |
| "%46 = OpTypeInt 32 1\n" |
| "%47 = OpConstant %46 1\n" |
| "%56 = OpConstant %6 32\n" |
| "%76 = OpConstant %6 2\n" |
| "%105 = OpTypeFloat 32\n" |
| "%106 = OpTypePointer Output %105\n" |
| "%107 = OpVariable %106 Output\n" |
| "%110 = OpTypeVector %105 4\n" |
| "%111 = OpTypeArray %105 %9\n" |
| "%112 = OpTypeStruct %110 %105 %111 %111\n" |
| "%113 = OpTypePointer Output %112\n" |
| "%114 = OpVariable %113 Output\n" |
| "%115 = OpConstant %46 0\n" |
| "%116 = OpTypePointer Input %110\n" |
| "%117 = OpVariable %116 Input\n" |
| "%119 = OpTypePointer Output %110\n" |
| "%121 = OpConstant %105 1\n" |
| "%4 = OpFunction %2 None %3\n" |
| "%5 = OpLabel\n" |
| "%8 = OpVariable %7 Function\n" |
| "%10 = OpVariable %7 Function\n" |
| "%11 = OpVariable %7 Function\n" |
| "%15 = OpVariable %14 Function\n" |
| "%20 = OpVariable %14 Function\n" |
| "%24 = OpVariable %7 Function\n" |
| "%49 = OpVariable %7 Function\n" |
| "OpStore %8 %9\n" |
| "OpStore %10 %9\n" |
| "OpStore %11 %12\n" |
| "%19 = OpGroupNonUniformBallot %13 %18 %17\n" |
| "OpStore %15 %19\n" |
| "%23 = OpLoad %13 %22\n" |
| "OpStore %20 %23\n" |
| "OpStore %24 %12\n" |
| "OpBranch %25\n" |
| "%25 = OpLabel\n" |
| "OpLoopMerge %27 %28 None\n" |
| "OpBranch %29\n" |
| "%29 = OpLabel\n" |
| "%30 = OpLoad %6 %24\n" |
| "%33 = OpLoad %6 %32\n" |
| "%34 = OpULessThan %16 %30 %33\n" |
| "OpBranchConditional %34 %26 %27\n" |
| "%26 = OpLabel\n" |
| "%35 = OpLoad %6 %24\n" |
| "%37 = OpLoad %6 %36\n" |
| + comparison + |
| "%39 = OpLoad %13 %20\n" |
| "%40 = OpLoad %6 %24\n" |
| "%41 = OpGroupNonUniformBallotBitExtract %16 %18 %39 %40\n" |
| "%42 = OpLogicalNotEqual %16 %38 %41\n" |
| "OpSelectionMerge %44 None\n" |
| "OpBranchConditional %42 %43 %44\n" |
| "%43 = OpLabel\n" |
| "OpStore %8 %12\n" |
| "OpBranch %44\n" |
| "%44 = OpLabel\n" |
| "OpBranch %28\n" |
| "%28 = OpLabel\n" |
| "%45 = OpLoad %6 %24\n" |
| "%48 = OpIAdd %6 %45 %47\n" |
| "OpStore %24 %48\n" |
| "OpBranch %25\n" |
| "%27 = OpLabel\n" |
| "OpStore %49 %12\n" |
| "OpBranch %50\n" |
| "%50 = OpLabel\n" |
| "OpLoopMerge %52 %53 None\n" |
| "OpBranch %54\n" |
| "%54 = OpLabel\n" |
| "%55 = OpLoad %6 %49\n" |
| "%57 = OpULessThan %16 %55 %56\n" |
| "OpBranchConditional %57 %51 %52\n" |
| "%51 = OpLabel\n" |
| "%58 = OpAccessChain %7 %20 %12\n" |
| "%59 = OpLoad %6 %58\n" |
| "%60 = OpLoad %6 %10\n" |
| "%61 = OpBitwiseAnd %6 %59 %60\n" |
| "%62 = OpUGreaterThan %16 %61 %12\n" |
| "OpSelectionMerge %64 None\n" |
| "OpBranchConditional %62 %63 %64\n" |
| "%63 = OpLabel\n" |
| "%65 = OpLoad %6 %11\n" |
| "%66 = OpIAdd %6 %65 %47\n" |
| "OpStore %11 %66\n" |
| "OpBranch %64\n" |
| "%64 = OpLabel\n" |
| "%67 = OpAccessChain %7 %20 %9\n" |
| "%68 = OpLoad %6 %67\n" |
| "%69 = OpLoad %6 %10\n" |
| "%70 = OpBitwiseAnd %6 %68 %69\n" |
| "%71 = OpUGreaterThan %16 %70 %12\n" |
| "OpSelectionMerge %73 None\n" |
| "OpBranchConditional %71 %72 %73\n" |
| "%72 = OpLabel\n" |
| "%74 = OpLoad %6 %11\n" |
| "%75 = OpIAdd %6 %74 %47\n" |
| "OpStore %11 %75\n" |
| "OpBranch %73\n" |
| "%73 = OpLabel\n" |
| "%77 = OpAccessChain %7 %20 %76\n" |
| "%78 = OpLoad %6 %77\n" |
| "%79 = OpLoad %6 %10\n" |
| "%80 = OpBitwiseAnd %6 %78 %79\n" |
| "%81 = OpUGreaterThan %16 %80 %12\n" |
| "OpSelectionMerge %83 None\n" |
| "OpBranchConditional %81 %82 %83\n" |
| "%82 = OpLabel\n" |
| "%84 = OpLoad %6 %11\n" |
| "%85 = OpIAdd %6 %84 %47\n" |
| "OpStore %11 %85\n" |
| "OpBranch %83\n" |
| "%83 = OpLabel\n" |
| "%86 = OpAccessChain %7 %20 %18\n" |
| "%87 = OpLoad %6 %86\n" |
| "%88 = OpLoad %6 %10\n" |
| "%89 = OpBitwiseAnd %6 %87 %88\n" |
| "%90 = OpUGreaterThan %16 %89 %12\n" |
| "OpSelectionMerge %92 None\n" |
| "OpBranchConditional %90 %91 %92\n" |
| "%91 = OpLabel\n" |
| "%93 = OpLoad %6 %11\n" |
| "%94 = OpIAdd %6 %93 %47\n" |
| "OpStore %11 %94\n" |
| "OpBranch %92\n" |
| "%92 = OpLabel\n" |
| "%95 = OpLoad %6 %10\n" |
| "%96 = OpShiftLeftLogical %6 %95 %47\n" |
| "OpStore %10 %96\n" |
| "OpBranch %53\n" |
| "%53 = OpLabel\n" |
| "%97 = OpLoad %6 %49\n" |
| "%98 = OpIAdd %6 %97 %47\n" |
| "OpStore %49 %98\n" |
| "OpBranch %50\n" |
| "%52 = OpLabel\n" |
| "%99 = OpLoad %13 %20\n" |
| "%100 = OpGroupNonUniformBallotBitCount %6 %18 Reduce %99\n" |
| "%101 = OpLoad %6 %11\n" |
| "%102 = OpINotEqual %16 %100 %101\n" |
| "OpSelectionMerge %104 None\n" |
| "OpBranchConditional %102 %103 %104\n" |
| "%103 = OpLabel\n" |
| "OpStore %8 %12\n" |
| "OpBranch %104\n" |
| "%104 = OpLabel\n" |
| "%108 = OpLoad %6 %8\n" |
| "%109 = OpConvertUToF %105 %108\n" |
| "OpStore %107 %109\n" |
| "%118 = OpLoad %110 %117\n" |
| "%120 = OpAccessChain %119 %114 %115\n" |
| "OpStore %120 %118\n" |
| "%122 = OpAccessChain %106 %114 %47\n" |
| "OpStore %122 %121\n" |
| "OpReturn\n" |
| "OpFunctionEnd\n"; |
| programCollection.spirvAsmSources.add("vert") << vertex << buildOptionsSpr; |
| } |
| else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage) |
| { |
| /* |
| const string bdy = subgroupMask(caseDef); |
| const string evaluationSource = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "#extension GL_EXT_tessellation_shader : require\n" |
| "layout(isolines, equal_spacing, ccw ) in;\n" |
| "layout(location = 0) out float out_color;\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " out_color = float(tempResult);\n" |
| " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n" |
| "}\n"; |
| programCollection.glslSources.add("tese") |
| << glu::TessellationEvaluationSource(evaluationSource) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u); |
| */ |
| const string evaluationSource = |
| "; SPIR-V\n" |
| "; Version: 1.3\n" |
| "; Generator: Khronos Glslang Reference Front End; 2\n" |
| "; Bound: 136\n" |
| "; Schema: 0\n" |
| "OpCapability Tessellation\n" |
| "OpCapability GroupNonUniform\n" |
| "OpCapability GroupNonUniformBallot\n" |
| "%1 = OpExtInstImport \"GLSL.std.450\"\n" |
| "OpMemoryModel Logical GLSL450\n" |
| "OpEntryPoint TessellationEvaluation %4 \"main\" %22 %32 %36 %107 %114 %120 %128\n" |
| "OpExecutionMode %4 Isolines\n" |
| "OpExecutionMode %4 SpacingEqual\n" |
| "OpExecutionMode %4 VertexOrderCcw\n" |
| + mask + |
| "OpDecorate %32 RelaxedPrecision\n" |
| "OpDecorate %32 BuiltIn SubgroupSize\n" |
| "OpDecorate %33 RelaxedPrecision\n" |
| "OpDecorate %36 RelaxedPrecision\n" |
| "OpDecorate %36 BuiltIn SubgroupLocalInvocationId\n" |
| "OpDecorate %37 RelaxedPrecision\n" |
| "OpDecorate %107 Location 0\n" |
| "OpMemberDecorate %112 0 BuiltIn Position\n" |
| "OpMemberDecorate %112 1 BuiltIn PointSize\n" |
| "OpMemberDecorate %112 2 BuiltIn ClipDistance\n" |
| "OpMemberDecorate %112 3 BuiltIn CullDistance\n" |
| "OpDecorate %112 Block\n" |
| "OpMemberDecorate %116 0 BuiltIn Position\n" |
| "OpMemberDecorate %116 1 BuiltIn PointSize\n" |
| "OpMemberDecorate %116 2 BuiltIn ClipDistance\n" |
| "OpMemberDecorate %116 3 BuiltIn CullDistance\n" |
| "OpDecorate %116 Block\n" |
| "OpDecorate %128 BuiltIn TessCoord\n" |
| "%2 = OpTypeVoid\n" |
| "%3 = OpTypeFunction %2\n" |
| "%6 = OpTypeInt 32 0\n" |
| "%7 = OpTypePointer Function %6\n" |
| "%9 = OpConstant %6 1\n" |
| "%12 = OpConstant %6 0\n" |
| "%13 = OpTypeVector %6 4\n" |
| "%14 = OpTypePointer Function %13\n" |
| "%16 = OpTypeBool\n" |
| "%17 = OpConstantTrue %16\n" |
| "%18 = OpConstant %6 3\n" |
| "%21 = OpTypePointer Input %13\n" |
| "%22 = OpVariable %21 Input\n" |
| "%31 = OpTypePointer Input %6\n" |
| "%32 = OpVariable %31 Input\n" |
| "%36 = OpVariable %31 Input\n" |
| "%46 = OpTypeInt 32 1\n" |
| "%47 = OpConstant %46 1\n" |
| "%56 = OpConstant %6 32\n" |
| "%76 = OpConstant %6 2\n" |
| "%105 = OpTypeFloat 32\n" |
| "%106 = OpTypePointer Output %105\n" |
| "%107 = OpVariable %106 Output\n" |
| "%110 = OpTypeVector %105 4\n" |
| "%111 = OpTypeArray %105 %9\n" |
| "%112 = OpTypeStruct %110 %105 %111 %111\n" |
| "%113 = OpTypePointer Output %112\n" |
| "%114 = OpVariable %113 Output\n" |
| "%115 = OpConstant %46 0\n" |
| "%116 = OpTypeStruct %110 %105 %111 %111\n" |
| "%117 = OpConstant %6 32\n" |
| "%118 = OpTypeArray %116 %117\n" |
| "%119 = OpTypePointer Input %118\n" |
| "%120 = OpVariable %119 Input\n" |
| "%121 = OpTypePointer Input %110\n" |
| "%126 = OpTypeVector %105 3\n" |
| "%127 = OpTypePointer Input %126\n" |
| "%128 = OpVariable %127 Input\n" |
| "%129 = OpTypePointer Input %105\n" |
| "%134 = OpTypePointer Output %110\n" |
| "%4 = OpFunction %2 None %3\n" |
| "%5 = OpLabel\n" |
| "%8 = OpVariable %7 Function\n" |
| "%10 = OpVariable %7 Function\n" |
| "%11 = OpVariable %7 Function\n" |
| "%15 = OpVariable %14 Function\n" |
| "%20 = OpVariable %14 Function\n" |
| "%24 = OpVariable %7 Function\n" |
| "%49 = OpVariable %7 Function\n" |
| "OpStore %8 %9\n" |
| "OpStore %10 %9\n" |
| "OpStore %11 %12\n" |
| "%19 = OpGroupNonUniformBallot %13 %18 %17\n" |
| "OpStore %15 %19\n" |
| "%23 = OpLoad %13 %22\n" |
| "OpStore %20 %23\n" |
| "OpStore %24 %12\n" |
| "OpBranch %25\n" |
| "%25 = OpLabel\n" |
| "OpLoopMerge %27 %28 None\n" |
| "OpBranch %29\n" |
| "%29 = OpLabel\n" |
| "%30 = OpLoad %6 %24\n" |
| "%33 = OpLoad %6 %32\n" |
| "%34 = OpULessThan %16 %30 %33\n" |
| "OpBranchConditional %34 %26 %27\n" |
| "%26 = OpLabel\n" |
| "%35 = OpLoad %6 %24\n" |
| "%37 = OpLoad %6 %36\n" |
| + comparison + |
| "%39 = OpLoad %13 %20\n" |
| "%40 = OpLoad %6 %24\n" |
| "%41 = OpGroupNonUniformBallotBitExtract %16 %18 %39 %40\n" |
| "%42 = OpLogicalNotEqual %16 %38 %41\n" |
| "OpSelectionMerge %44 None\n" |
| "OpBranchConditional %42 %43 %44\n" |
| "%43 = OpLabel\n" |
| "OpStore %8 %12\n" |
| "OpBranch %44\n" |
| "%44 = OpLabel\n" |
| "OpBranch %28\n" |
| "%28 = OpLabel\n" |
| "%45 = OpLoad %6 %24\n" |
| "%48 = OpIAdd %6 %45 %47\n" |
| "OpStore %24 %48\n" |
| "OpBranch %25\n" |
| "%27 = OpLabel\n" |
| "OpStore %49 %12\n" |
| "OpBranch %50\n" |
| "%50 = OpLabel\n" |
| "OpLoopMerge %52 %53 None\n" |
| "OpBranch %54\n" |
| "%54 = OpLabel\n" |
| "%55 = OpLoad %6 %49\n" |
| "%57 = OpULessThan %16 %55 %56\n" |
| "OpBranchConditional %57 %51 %52\n" |
| "%51 = OpLabel\n" |
| "%58 = OpAccessChain %7 %20 %12\n" |
| "%59 = OpLoad %6 %58\n" |
| "%60 = OpLoad %6 %10\n" |
| "%61 = OpBitwiseAnd %6 %59 %60\n" |
| "%62 = OpUGreaterThan %16 %61 %12\n" |
| "OpSelectionMerge %64 None\n" |
| "OpBranchConditional %62 %63 %64\n" |
| "%63 = OpLabel\n" |
| "%65 = OpLoad %6 %11\n" |
| "%66 = OpIAdd %6 %65 %47\n" |
| "OpStore %11 %66\n" |
| "OpBranch %64\n" |
| "%64 = OpLabel\n" |
| "%67 = OpAccessChain %7 %20 %9\n" |
| "%68 = OpLoad %6 %67\n" |
| "%69 = OpLoad %6 %10\n" |
| "%70 = OpBitwiseAnd %6 %68 %69\n" |
| "%71 = OpUGreaterThan %16 %70 %12\n" |
| "OpSelectionMerge %73 None\n" |
| "OpBranchConditional %71 %72 %73\n" |
| "%72 = OpLabel\n" |
| "%74 = OpLoad %6 %11\n" |
| "%75 = OpIAdd %6 %74 %47\n" |
| "OpStore %11 %75\n" |
| "OpBranch %73\n" |
| "%73 = OpLabel\n" |
| "%77 = OpAccessChain %7 %20 %76\n" |
| "%78 = OpLoad %6 %77\n" |
| "%79 = OpLoad %6 %10\n" |
| "%80 = OpBitwiseAnd %6 %78 %79\n" |
| "%81 = OpUGreaterThan %16 %80 %12\n" |
| "OpSelectionMerge %83 None\n" |
| "OpBranchConditional %81 %82 %83\n" |
| "%82 = OpLabel\n" |
| "%84 = OpLoad %6 %11\n" |
| "%85 = OpIAdd %6 %84 %47\n" |
| "OpStore %11 %85\n" |
| "OpBranch %83\n" |
| "%83 = OpLabel\n" |
| "%86 = OpAccessChain %7 %20 %18\n" |
| "%87 = OpLoad %6 %86\n" |
| "%88 = OpLoad %6 %10\n" |
| "%89 = OpBitwiseAnd %6 %87 %88\n" |
| "%90 = OpUGreaterThan %16 %89 %12\n" |
| "OpSelectionMerge %92 None\n" |
| "OpBranchConditional %90 %91 %92\n" |
| "%91 = OpLabel\n" |
| "%93 = OpLoad %6 %11\n" |
| "%94 = OpIAdd %6 %93 %47\n" |
| "OpStore %11 %94\n" |
| "OpBranch %92\n" |
| "%92 = OpLabel\n" |
| "%95 = OpLoad %6 %10\n" |
| "%96 = OpShiftLeftLogical %6 %95 %47\n" |
| "OpStore %10 %96\n" |
| "OpBranch %53\n" |
| "%53 = OpLabel\n" |
| "%97 = OpLoad %6 %49\n" |
| "%98 = OpIAdd %6 %97 %47\n" |
| "OpStore %49 %98\n" |
| "OpBranch %50\n" |
| "%52 = OpLabel\n" |
| "%99 = OpLoad %13 %20\n" |
| "%100 = OpGroupNonUniformBallotBitCount %6 %18 Reduce %99\n" |
| "%101 = OpLoad %6 %11\n" |
| "%102 = OpINotEqual %16 %100 %101\n" |
| "OpSelectionMerge %104 None\n" |
| "OpBranchConditional %102 %103 %104\n" |
| "%103 = OpLabel\n" |
| "OpStore %8 %12\n" |
| "OpBranch %104\n" |
| "%104 = OpLabel\n" |
| "%108 = OpLoad %6 %8\n" |
| "%109 = OpConvertUToF %105 %108\n" |
| "OpStore %107 %109\n" |
| "%122 = OpAccessChain %121 %120 %115 %115\n" |
| "%123 = OpLoad %110 %122\n" |
| "%124 = OpAccessChain %121 %120 %47 %115\n" |
| "%125 = OpLoad %110 %124\n" |
| "%130 = OpAccessChain %129 %128 %12\n" |
| "%131 = OpLoad %105 %130\n" |
| "%132 = OpCompositeConstruct %110 %131 %131 %131 %131\n" |
| "%133 = OpExtInst %110 %1 FMix %123 %125 %132\n" |
| "%135 = OpAccessChain %134 %114 %115\n" |
| "OpStore %135 %133\n" |
| "OpReturn\n" |
| "OpFunctionEnd\n"; |
| programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr; |
| subgroups::setTesCtrlShaderFrameBuffer(programCollection); |
| } |
| else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) |
| { |
| /* |
| const string bdy = subgroupMask(caseDef); |
| const string controlSource = |
| "#version 450\n" |
| "#extension GL_EXT_tessellation_shader : require\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(vertices = 2) out;\n" |
| "layout(location = 0) out float out_color[];\n" |
| "void main (void)\n" |
| "{\n" |
| " if (gl_InvocationID == 0)\n" |
| " {\n" |
| " gl_TessLevelOuter[0] = 1.0f;\n" |
| " gl_TessLevelOuter[1] = 1.0f;\n" |
| " }\n" |
| + bdy + |
| " out_color[gl_InvocationID] = float(tempResult);\n" |
| " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" |
| "}\n"; |
| programCollection.glslSources.add("tesc") |
| << glu::TessellationControlSource(controlSource) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u); |
| */ |
| const string controlSource = |
| "; SPIR-V\n" |
| "; Version: 1.3\n" |
| "; Generator: Khronos Glslang Reference Front End; 2\n" |
| "; Bound: 146\n" |
| "; Schema: 0\n" |
| "OpCapability Tessellation\n" |
| "OpCapability GroupNonUniform\n" |
| "OpCapability GroupNonUniformBallot\n" |
| "%1 = OpExtInstImport \"GLSL.std.450\"\n" |
| "OpMemoryModel Logical GLSL450\n" |
| "OpEntryPoint TessellationControl %4 \"main\" %8 %20 %40 %50 %54 %123 %133 %139\n" |
| "OpExecutionMode %4 OutputVertices 2\n" |
| "OpDecorate %8 BuiltIn InvocationId\n" |
| "OpDecorate %20 Patch\n" |
| "OpDecorate %20 BuiltIn TessLevelOuter\n" |
| + mask + |
| "OpDecorate %50 RelaxedPrecision\n" |
| "OpDecorate %50 BuiltIn SubgroupSize\n" |
| "OpDecorate %51 RelaxedPrecision\n" |
| "OpDecorate %54 RelaxedPrecision\n" |
| "OpDecorate %54 BuiltIn SubgroupLocalInvocationId\n" |
| "OpDecorate %55 RelaxedPrecision\n" |
| "OpDecorate %123 Location 0\n" |
| "OpMemberDecorate %130 0 BuiltIn Position\n" |
| "OpMemberDecorate %130 1 BuiltIn PointSize\n" |
| "OpMemberDecorate %130 2 BuiltIn ClipDistance\n" |
| "OpMemberDecorate %130 3 BuiltIn CullDistance\n" |
| "OpDecorate %130 Block\n" |
| "OpMemberDecorate %135 0 BuiltIn Position\n" |
| "OpMemberDecorate %135 1 BuiltIn PointSize\n" |
| "OpMemberDecorate %135 2 BuiltIn ClipDistance\n" |
| "OpMemberDecorate %135 3 BuiltIn CullDistance\n" |
| "OpDecorate %135 Block\n" |
| "%2 = OpTypeVoid\n" |
| "%3 = OpTypeFunction %2\n" |
| "%6 = OpTypeInt 32 1\n" |
| "%7 = OpTypePointer Input %6\n" |
| "%8 = OpVariable %7 Input\n" |
| "%10 = OpConstant %6 0\n" |
| "%11 = OpTypeBool\n" |
| "%15 = OpTypeFloat 32\n" |
| "%16 = OpTypeInt 32 0\n" |
| "%17 = OpConstant %16 4\n" |
| "%18 = OpTypeArray %15 %17\n" |
| "%19 = OpTypePointer Output %18\n" |
| "%20 = OpVariable %19 Output\n" |
| "%21 = OpConstant %15 1\n" |
| "%22 = OpTypePointer Output %15\n" |
| "%24 = OpConstant %6 1\n" |
| "%26 = OpTypePointer Function %16\n" |
| "%28 = OpConstant %16 1\n" |
| "%31 = OpConstant %16 0\n" |
| "%32 = OpTypeVector %16 4\n" |
| "%33 = OpTypePointer Function %32\n" |
| "%35 = OpConstantTrue %11\n" |
| "%36 = OpConstant %16 3\n" |
| "%39 = OpTypePointer Input %32\n" |
| "%40 = OpVariable %39 Input\n" |
| "%49 = OpTypePointer Input %16\n" |
| "%50 = OpVariable %49 Input\n" |
| "%54 = OpVariable %49 Input\n" |
| "%72 = OpConstant %16 32\n" |
| "%92 = OpConstant %16 2\n" |
| "%121 = OpTypeArray %15 %92\n" |
| "%122 = OpTypePointer Output %121\n" |
| "%123 = OpVariable %122 Output\n" |
| "%128 = OpTypeVector %15 4\n" |
| "%129 = OpTypeArray %15 %28\n" |
| "%130 = OpTypeStruct %128 %15 %129 %129\n" |
| "%131 = OpTypeArray %130 %92\n" |
| "%132 = OpTypePointer Output %131\n" |
| "%133 = OpVariable %132 Output\n" |
| "%135 = OpTypeStruct %128 %15 %129 %129\n" |
| "%136 = OpConstant %16 32\n" |
| "%137 = OpTypeArray %135 %136\n" |
| "%138 = OpTypePointer Input %137\n" |
| "%139 = OpVariable %138 Input\n" |
| "%141 = OpTypePointer Input %128\n" |
| "%144 = OpTypePointer Output %128\n" |
| "%4 = OpFunction %2 None %3\n" |
| "%5 = OpLabel\n" |
| "%27 = OpVariable %26 Function\n" |
| "%29 = OpVariable %26 Function\n" |
| "%30 = OpVariable %26 Function\n" |
| "%34 = OpVariable %33 Function\n" |
| "%38 = OpVariable %33 Function\n" |
| "%42 = OpVariable %26 Function\n" |
| "%65 = OpVariable %26 Function\n" |
| "%9 = OpLoad %6 %8\n" |
| "%12 = OpIEqual %11 %9 %10\n" |
| "OpSelectionMerge %14 None\n" |
| "OpBranchConditional %12 %13 %14\n" |
| "%13 = OpLabel\n" |
| "%23 = OpAccessChain %22 %20 %10\n" |
| "OpStore %23 %21\n" |
| "%25 = OpAccessChain %22 %20 %24\n" |
| "OpStore %25 %21\n" |
| "OpBranch %14\n" |
| "%14 = OpLabel\n" |
| "OpStore %27 %28\n" |
| "OpStore %29 %28\n" |
| "OpStore %30 %31\n" |
| "%37 = OpGroupNonUniformBallot %32 %36 %35\n" |
| "OpStore %34 %37\n" |
| "%41 = OpLoad %32 %40\n" |
| "OpStore %38 %41\n" |
| "OpStore %42 %31\n" |
| "OpBranch %43\n" |
| "%43 = OpLabel\n" |
| "OpLoopMerge %45 %46 None\n" |
| "OpBranch %47\n" |
| "%47 = OpLabel\n" |
| "%48 = OpLoad %16 %42\n" |
| "%51 = OpLoad %16 %50\n" |
| "%52 = OpULessThan %11 %48 %51\n" |
| "OpBranchConditional %52 %44 %45\n" |
| "%44 = OpLabel\n" |
| "%53 = OpLoad %16 %42\n" |
| "%55 = OpLoad %16 %54\n" |
| + comparison + |
| "%57 = OpLoad %32 %38\n" |
| "%58 = OpLoad %16 %42\n" |
| "%59 = OpGroupNonUniformBallotBitExtract %11 %36 %57 %58\n" |
| "%60 = OpLogicalNotEqual %11 %56 %59\n" |
| "OpSelectionMerge %62 None\n" |
| "OpBranchConditional %60 %61 %62\n" |
| "%61 = OpLabel\n" |
| "OpStore %27 %31\n" |
| "OpBranch %62\n" |
| "%62 = OpLabel\n" |
| "OpBranch %46\n" |
| "%46 = OpLabel\n" |
| "%63 = OpLoad %16 %42\n" |
| "%64 = OpIAdd %16 %63 %24\n" |
| "OpStore %42 %64\n" |
| "OpBranch %43\n" |
| "%45 = OpLabel\n" |
| "OpStore %65 %31\n" |
| "OpBranch %66\n" |
| "%66 = OpLabel\n" |
| "OpLoopMerge %68 %69 None\n" |
| "OpBranch %70\n" |
| "%70 = OpLabel\n" |
| "%71 = OpLoad %16 %65\n" |
| "%73 = OpULessThan %11 %71 %72\n" |
| "OpBranchConditional %73 %67 %68\n" |
| "%67 = OpLabel\n" |
| "%74 = OpAccessChain %26 %38 %31\n" |
| "%75 = OpLoad %16 %74\n" |
| "%76 = OpLoad %16 %29\n" |
| "%77 = OpBitwiseAnd %16 %75 %76\n" |
| "%78 = OpUGreaterThan %11 %77 %31\n" |
| "OpSelectionMerge %80 None\n" |
| "OpBranchConditional %78 %79 %80\n" |
| "%79 = OpLabel\n" |
| "%81 = OpLoad %16 %30\n" |
| "%82 = OpIAdd %16 %81 %24\n" |
| "OpStore %30 %82\n" |
| "OpBranch %80\n" |
| "%80 = OpLabel\n" |
| "%83 = OpAccessChain %26 %38 %28\n" |
| "%84 = OpLoad %16 %83\n" |
| "%85 = OpLoad %16 %29\n" |
| "%86 = OpBitwiseAnd %16 %84 %85\n" |
| "%87 = OpUGreaterThan %11 %86 %31\n" |
| "OpSelectionMerge %89 None\n" |
| "OpBranchConditional %87 %88 %89\n" |
| "%88 = OpLabel\n" |
| "%90 = OpLoad %16 %30\n" |
| "%91 = OpIAdd %16 %90 %24\n" |
| "OpStore %30 %91\n" |
| "OpBranch %89\n" |
| "%89 = OpLabel\n" |
| "%93 = OpAccessChain %26 %38 %92\n" |
| "%94 = OpLoad %16 %93\n" |
| "%95 = OpLoad %16 %29\n" |
| "%96 = OpBitwiseAnd %16 %94 %95\n" |
| "%97 = OpUGreaterThan %11 %96 %31\n" |
| "OpSelectionMerge %99 None\n" |
| "OpBranchConditional %97 %98 %99\n" |
| "%98 = OpLabel\n" |
| "%100 = OpLoad %16 %30\n" |
| "%101 = OpIAdd %16 %100 %24\n" |
| "OpStore %30 %101\n" |
| "OpBranch %99\n" |
| "%99 = OpLabel\n" |
| "%102 = OpAccessChain %26 %38 %36\n" |
| "%103 = OpLoad %16 %102\n" |
| "%104 = OpLoad %16 %29\n" |
| "%105 = OpBitwiseAnd %16 %103 %104\n" |
| "%106 = OpUGreaterThan %11 %105 %31\n" |
| "OpSelectionMerge %108 None\n" |
| "OpBranchConditional %106 %107 %108\n" |
| "%107 = OpLabel\n" |
| "%109 = OpLoad %16 %30\n" |
| "%110 = OpIAdd %16 %109 %24\n" |
| "OpStore %30 %110\n" |
| "OpBranch %108\n" |
| "%108 = OpLabel\n" |
| "%111 = OpLoad %16 %29\n" |
| "%112 = OpShiftLeftLogical %16 %111 %24\n" |
| "OpStore %29 %112\n" |
| "OpBranch %69\n" |
| "%69 = OpLabel\n" |
| "%113 = OpLoad %16 %65\n" |
| "%114 = OpIAdd %16 %113 %24\n" |
| "OpStore %65 %114\n" |
| "OpBranch %66\n" |
| "%68 = OpLabel\n" |
| "%115 = OpLoad %32 %38\n" |
| "%116 = OpGroupNonUniformBallotBitCount %16 %36 Reduce %115\n" |
| "%117 = OpLoad %16 %30\n" |
| "%118 = OpINotEqual %11 %116 %117\n" |
| "OpSelectionMerge %120 None\n" |
| "OpBranchConditional %118 %119 %120\n" |
| "%119 = OpLabel\n" |
| "OpStore %27 %31\n" |
| "OpBranch %120\n" |
| "%120 = OpLabel\n" |
| "%124 = OpLoad %6 %8\n" |
| "%125 = OpLoad %16 %27\n" |
| "%126 = OpConvertUToF %15 %125\n" |
| "%127 = OpAccessChain %22 %123 %124\n" |
| "OpStore %127 %126\n" |
| "%134 = OpLoad %6 %8\n" |
| "%140 = OpLoad %6 %8\n" |
| "%142 = OpAccessChain %141 %139 %140 %10\n" |
| "%143 = OpLoad %128 %142\n" |
| "%145 = OpAccessChain %144 %133 %134 %10\n" |
| "OpStore %145 %143\n" |
| "OpReturn\n" |
| "OpFunctionEnd\n"; |
| programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr; |
| subgroups::setTesEvalShaderFrameBuffer(programCollection); |
| } |
| else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage) |
| { |
| /* |
| const string bdy = subgroupMask(caseDef); |
| const string geometry = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(points) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "layout(location = 0) out float out_color;\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " out_color = float(tempResult);\n" |
| " gl_Position = gl_in[0].gl_Position;\n" |
| " gl_PointSize = gl_in[0].gl_PointSize;\n" |
| " EmitVertex();\n" |
| " EndPrimitive();\n" |
| "}\n"; |
| programCollection.glslSources.add("geometry") |
| << glu::GeometrySource(geometry) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u); |
| */ |
| |
| std::ostringstream geometry; |
| geometry |
| << "; SPIR-V\n" |
| << "; Version: 1.3\n" |
| << "; Generator: Khronos Glslang Reference Front End; 2\n" |
| << "; Bound: 125\n" |
| << "; Schema: 0\n" |
| << "OpCapability Geometry\n" |
| << (*caseDef.geometryPointSizeSupported ? |
| "OpCapability GeometryPointSize\n" : "") |
| << "OpCapability GroupNonUniform\n" |
| << "OpCapability GroupNonUniformBallot\n" |
| << "%1 = OpExtInstImport \"GLSL.std.450\"\n" |
| << "OpMemoryModel Logical GLSL450\n" |
| << "OpEntryPoint Geometry %4 \"main\" %22 %32 %36 %107 %114 %119\n" |
| << "OpExecutionMode %4 InputPoints\n" |
| << "OpExecutionMode %4 Invocations 1\n" |
| << "OpExecutionMode %4 OutputPoints\n" |
| << "OpExecutionMode %4 OutputVertices 1\n" |
| << mask |
| << "OpDecorate %32 RelaxedPrecision\n" |
| << "OpDecorate %32 BuiltIn SubgroupSize\n" |
| << "OpDecorate %33 RelaxedPrecision\n" |
| << "OpDecorate %36 RelaxedPrecision\n" |
| << "OpDecorate %36 BuiltIn SubgroupLocalInvocationId\n" |
| << "OpDecorate %37 RelaxedPrecision\n" |
| << "OpDecorate %107 Location 0\n" |
| << "OpMemberDecorate %112 0 BuiltIn Position\n" |
| << "OpMemberDecorate %112 1 BuiltIn PointSize\n" |
| << "OpMemberDecorate %112 2 BuiltIn ClipDistance\n" |
| << "OpMemberDecorate %112 3 BuiltIn CullDistance\n" |
| << "OpDecorate %112 Block\n" |
| << "OpMemberDecorate %116 0 BuiltIn Position\n" |
| << "OpMemberDecorate %116 1 BuiltIn PointSize\n" |
| << "OpMemberDecorate %116 2 BuiltIn ClipDistance\n" |
| << "OpMemberDecorate %116 3 BuiltIn CullDistance\n" |
| << "OpDecorate %116 Block\n" |
| << "%2 = OpTypeVoid\n" |
| << "%3 = OpTypeFunction %2\n" |
| << "%6 = OpTypeInt 32 0\n" |
| << "%7 = OpTypePointer Function %6\n" |
| << "%9 = OpConstant %6 1\n" |
| << "%12 = OpConstant %6 0\n" |
| << "%13 = OpTypeVector %6 4\n" |
| << "%14 = OpTypePointer Function %13\n" |
| << "%16 = OpTypeBool\n" |
| << "%17 = OpConstantTrue %16\n" |
| << "%18 = OpConstant %6 3\n" |
| << "%21 = OpTypePointer Input %13\n" |
| << "%22 = OpVariable %21 Input\n" |
| << "%31 = OpTypePointer Input %6\n" |
| << "%32 = OpVariable %31 Input\n" |
| << "%36 = OpVariable %31 Input\n" |
| << "%46 = OpTypeInt 32 1\n" |
| << "%47 = OpConstant %46 1\n" |
| << "%56 = OpConstant %6 32\n" |
| << "%76 = OpConstant %6 2\n" |
| << "%105 = OpTypeFloat 32\n" |
| << "%106 = OpTypePointer Output %105\n" |
| << "%107 = OpVariable %106 Output\n" |
| << "%110 = OpTypeVector %105 4\n" |
| << "%111 = OpTypeArray %105 %9\n" |
| << "%112 = OpTypeStruct %110 %105 %111 %111\n" |
| << "%113 = OpTypePointer Output %112\n" |
| << "%114 = OpVariable %113 Output\n" |
| << "%115 = OpConstant %46 0\n" |
| << "%116 = OpTypeStruct %110 %105 %111 %111\n" |
| << "%117 = OpTypeArray %116 %9\n" |
| << "%118 = OpTypePointer Input %117\n" |
| << "%119 = OpVariable %118 Input\n" |
| << "%120 = OpTypePointer Input %110\n" |
| << "%123 = OpTypePointer Output %110\n" |
| << (*caseDef.geometryPointSizeSupported ? |
| "%125 = OpTypePointer Input %105\n" |
| "%126 = OpTypePointer Output %105\n" : "" ) |
| << "%4 = OpFunction %2 None %3\n" |
| << "%5 = OpLabel\n" |
| << "%8 = OpVariable %7 Function\n" |
| << "%10 = OpVariable %7 Function\n" |
| << "%11 = OpVariable %7 Function\n" |
| << "%15 = OpVariable %14 Function\n" |
| << "%20 = OpVariable %14 Function\n" |
| << "%24 = OpVariable %7 Function\n" |
| << "%49 = OpVariable %7 Function\n" |
| << "OpStore %8 %9\n" |
| << "OpStore %10 %9\n" |
| << "OpStore %11 %12\n" |
| << "%19 = OpGroupNonUniformBallot %13 %18 %17\n" |
| << "OpStore %15 %19\n" |
| << "%23 = OpLoad %13 %22\n" |
| << "OpStore %20 %23\n" |
| << "OpStore %24 %12\n" |
| << "OpBranch %25\n" |
| << "%25 = OpLabel\n" |
| << "OpLoopMerge %27 %28 None\n" |
| << "OpBranch %29\n" |
| << "%29 = OpLabel\n" |
| << "%30 = OpLoad %6 %24\n" |
| << "%33 = OpLoad %6 %32\n" |
| << "%34 = OpULessThan %16 %30 %33\n" |
| << "OpBranchConditional %34 %26 %27\n" |
| << "%26 = OpLabel\n" |
| << "%35 = OpLoad %6 %24\n" |
| << "%37 = OpLoad %6 %36\n" |
| << comparison |
| << "%39 = OpLoad %13 %20\n" |
| << "%40 = OpLoad %6 %24\n" |
| << "%41 = OpGroupNonUniformBallotBitExtract %16 %18 %39 %40\n" |
| << "%42 = OpLogicalNotEqual %16 %38 %41\n" |
| << "OpSelectionMerge %44 None\n" |
| << "OpBranchConditional %42 %43 %44\n" |
| << "%43 = OpLabel\n" |
| << "OpStore %8 %12\n" |
| << "OpBranch %44\n" |
| << "%44 = OpLabel\n" |
| << "OpBranch %28\n" |
| << "%28 = OpLabel\n" |
| << "%45 = OpLoad %6 %24\n" |
| << "%48 = OpIAdd %6 %45 %47\n" |
| << "OpStore %24 %48\n" |
| << "OpBranch %25\n" |
| << "%27 = OpLabel\n" |
| << "OpStore %49 %12\n" |
| << "OpBranch %50\n" |
| << "%50 = OpLabel\n" |
| << "OpLoopMerge %52 %53 None\n" |
| << "OpBranch %54\n" |
| << "%54 = OpLabel\n" |
| << "%55 = OpLoad %6 %49\n" |
| << "%57 = OpULessThan %16 %55 %56\n" |
| << "OpBranchConditional %57 %51 %52\n" |
| << "%51 = OpLabel\n" |
| << "%58 = OpAccessChain %7 %20 %12\n" |
| << "%59 = OpLoad %6 %58\n" |
| << "%60 = OpLoad %6 %10\n" |
| << "%61 = OpBitwiseAnd %6 %59 %60\n" |
| << "%62 = OpUGreaterThan %16 %61 %12\n" |
| << "OpSelectionMerge %64 None\n" |
| << "OpBranchConditional %62 %63 %64\n" |
| << "%63 = OpLabel\n" |
| << "%65 = OpLoad %6 %11\n" |
| << "%66 = OpIAdd %6 %65 %47\n" |
| << "OpStore %11 %66\n" |
| << "OpBranch %64\n" |
| << "%64 = OpLabel\n" |
| << "%67 = OpAccessChain %7 %20 %9\n" |
| << "%68 = OpLoad %6 %67\n" |
| << "%69 = OpLoad %6 %10\n" |
| << "%70 = OpBitwiseAnd %6 %68 %69\n" |
| << "%71 = OpUGreaterThan %16 %70 %12\n" |
| << "OpSelectionMerge %73 None\n" |
| << "OpBranchConditional %71 %72 %73\n" |
| << "%72 = OpLabel\n" |
| << "%74 = OpLoad %6 %11\n" |
| << "%75 = OpIAdd %6 %74 %47\n" |
| << "OpStore %11 %75\n" |
| << "OpBranch %73\n" |
| << "%73 = OpLabel\n" |
| << "%77 = OpAccessChain %7 %20 %76\n" |
| << "%78 = OpLoad %6 %77\n" |
| << "%79 = OpLoad %6 %10\n" |
| << "%80 = OpBitwiseAnd %6 %78 %79\n" |
| << "%81 = OpUGreaterThan %16 %80 %12\n" |
| << "OpSelectionMerge %83 None\n" |
| << "OpBranchConditional %81 %82 %83\n" |
| << "%82 = OpLabel\n" |
| << "%84 = OpLoad %6 %11\n" |
| << "%85 = OpIAdd %6 %84 %47\n" |
| << "OpStore %11 %85\n" |
| << "OpBranch %83\n" |
| << "%83 = OpLabel\n" |
| << "%86 = OpAccessChain %7 %20 %18\n" |
| << "%87 = OpLoad %6 %86\n" |
| << "%88 = OpLoad %6 %10\n" |
| << "%89 = OpBitwiseAnd %6 %87 %88\n" |
| << "%90 = OpUGreaterThan %16 %89 %12\n" |
| << "OpSelectionMerge %92 None\n" |
| << "OpBranchConditional %90 %91 %92\n" |
| << "%91 = OpLabel\n" |
| << "%93 = OpLoad %6 %11\n" |
| << "%94 = OpIAdd %6 %93 %47\n" |
| << "OpStore %11 %94\n" |
| << "OpBranch %92\n" |
| << "%92 = OpLabel\n" |
| << "%95 = OpLoad %6 %10\n" |
| << "%96 = OpShiftLeftLogical %6 %95 %47\n" |
| << "OpStore %10 %96\n" |
| << "OpBranch %53\n" |
| << "%53 = OpLabel\n" |
| << "%97 = OpLoad %6 %49\n" |
| << "%98 = OpIAdd %6 %97 %47\n" |
| << "OpStore %49 %98\n" |
| << "OpBranch %50\n" |
| << "%52 = OpLabel\n" |
| << "%99 = OpLoad %13 %20\n" |
| << "%100 = OpGroupNonUniformBallotBitCount %6 %18 Reduce %99\n" |
| << "%101 = OpLoad %6 %11\n" |
| << "%102 = OpINotEqual %16 %100 %101\n" |
| << "OpSelectionMerge %104 None\n" |
| << "OpBranchConditional %102 %103 %104\n" |
| << "%103 = OpLabel\n" |
| << "OpStore %8 %12\n" |
| << "OpBranch %104\n" |
| << "%104 = OpLabel\n" |
| << "%108 = OpLoad %6 %8\n" |
| << "%109 = OpConvertUToF %105 %108\n" |
| << "OpStore %107 %109\n" |
| << "%121 = OpAccessChain %120 %119 %115 %115\n" |
| << "%122 = OpLoad %110 %121\n" |
| << "%124 = OpAccessChain %123 %114 %115\n" |
| << "OpStore %124 %122\n" |
| << (*caseDef.geometryPointSizeSupported ? |
| "%127 = OpAccessChain %125 %119 %115 %47\n" |
| "%128 = OpLoad %105 %127\n" |
| "%129 = OpAccessChain %126 %114 %47\n" |
| "OpStore %129 %128\n" : "") |
| << "OpEmitVertex\n" |
| << "OpEndPrimitive\n" |
| << "OpReturn\n" |
| << "OpFunctionEnd\n"; |
| programCollection.spirvAsmSources.add("geometry") << geometry.str() << buildOptionsSpr; |
| } |
| else |
| { |
| DE_FATAL("Unsupported shader stage"); |
| } |
| } |
| |
| |
| void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) |
| { |
| const string bdy = subgroupMask(caseDef); |
| |
| if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) |
| { |
| std::ostringstream src; |
| |
| src << "#version 450\n" |
| << "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| << "layout (local_size_x_id = 0, local_size_y_id = 1, " |
| "local_size_z_id = 2) in;\n" |
| << "layout(set = 0, binding = 0, std430) buffer Output\n" |
| << "{\n" |
| << " uint result[];\n" |
| << "};\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n" |
| << " highp uint offset = globalSize.x * ((globalSize.y * " |
| "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + " |
| "gl_GlobalInvocationID.x;\n" |
| << bdy |
| << " result[offset] = tempResult;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("comp") |
| << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); |
| } |
| else |
| { |
| { |
| const string vertex = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(set = 0, binding = 0, std430) buffer Output\n" |
| "{\n" |
| " uint result[];\n" |
| "};\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " result[gl_VertexIndex] = tempResult;\n" |
| " float pixelSize = 2.0f/1024.0f;\n" |
| " float pixelPosition = pixelSize/2.0f - 1.0f;\n" |
| " gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n" |
| " gl_PointSize = 1.0f;\n" |
| "}\n"; |
| programCollection.glslSources.add("vert") |
| << glu::VertexSource(vertex) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); |
| } |
| |
| { |
| const string tesc = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(vertices=1) out;\n" |
| "layout(set = 0, binding = 1, std430) buffer Output\n" |
| "{\n" |
| " uint result[];\n" |
| "};\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " result[gl_PrimitiveID] = tempResult;\n" |
| " if (gl_InvocationID == 0)\n" |
| " {\n" |
| " gl_TessLevelOuter[0] = 1.0f;\n" |
| " gl_TessLevelOuter[1] = 1.0f;\n" |
| " }\n" |
| " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" |
| + (*caseDef.geometryPointSizeSupported ? " gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n" : "") + |
| "}\n"; |
| programCollection.glslSources.add("tesc") |
| << glu::TessellationControlSource(tesc) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); |
| } |
| |
| { |
| const string tese = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(isolines) in;\n" |
| "layout(set = 0, binding = 2, std430) buffer Output\n" |
| "{\n" |
| " uint result[];\n" |
| "};\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n" |
| " float pixelSize = 2.0f/1024.0f;\n" |
| " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n" |
| + (*caseDef.geometryPointSizeSupported ? " gl_PointSize = gl_in[0].gl_PointSize;\n" : "") + |
| "}\n"; |
| |
| programCollection.glslSources.add("tese") |
| << glu::TessellationEvaluationSource(tese) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); |
| } |
| |
| { |
| const string geometry = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(${TOPOLOGY}) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "layout(set = 0, binding = 3, std430) buffer Output\n" |
| "{\n" |
| " uint result[];\n" |
| "};\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " result[gl_PrimitiveIDIn] = tempResult;\n" |
| " gl_Position = gl_in[0].gl_Position;\n" |
| + (*caseDef.geometryPointSizeSupported ? " gl_PointSize = gl_in[0].gl_PointSize;\n" : "") + |
| " EmitVertex();\n" |
| " EndPrimitive();\n" |
| "}\n"; |
| |
| subgroups::addGeometryShadersFromTemplate(geometry, vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u), |
| programCollection.glslSources); |
| } |
| |
| { |
| const string fragment = |
| "#version 450\n" |
| "#extension GL_KHR_shader_subgroup_ballot: enable\n" |
| "layout(location = 0) out uint result;\n" |
| "void main (void)\n" |
| "{\n" |
| + bdy + |
| " result = tempResult;\n" |
| "}\n"; |
| |
| programCollection.glslSources.add("fragment") |
| << glu::FragmentSource(fragment)<< vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); |
| } |
| |
| subgroups::addNoSubgroupShader(programCollection); |
| } |
| } |
| |
| void supportedCheck (Context& context, CaseDefinition caseDef) |
| { |
| DE_UNREF(caseDef); |
| if (!subgroups::isSubgroupSupported(context)) |
| TCU_THROW(NotSupportedError, "Subgroup operations are not supported"); |
| |
| if (caseDef.requiredSubgroupSize) |
| { |
| if (!context.requireDeviceFunctionality("VK_EXT_subgroup_size_control")) |
| TCU_THROW(NotSupportedError, "Device does not support VK_EXT_subgroup_size_control extension"); |
| VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroupSizeControlFeatures; |
| subgroupSizeControlFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT; |
| subgroupSizeControlFeatures.pNext = DE_NULL; |
| |
| VkPhysicalDeviceFeatures2 features; |
| features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| features.pNext = &subgroupSizeControlFeatures; |
| |
| context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features); |
| |
| if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE) |
| TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size"); |
| |
| if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE) |
| TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders"); |
| } |
| |
| *caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context); |
| } |
| |
| tcu::TestStatus noSSBOtest(Context& context, const CaseDefinition caseDef) |
| { |
| if (!areSubgroupOperationsSupportedForStage( |
| context, caseDef.shaderStage)) |
| { |
| if (areSubgroupOperationsRequiredForStage(caseDef.shaderStage)) |
| { |
| return tcu::TestStatus::fail( |
| "Shader stage " + getShaderStageName(caseDef.shaderStage) + |
| " is required to support subgroup operations!"); |
| } |
| else |
| { |
| TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage"); |
| } |
| } |
| |
| if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations"); |
| } |
| |
| if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage) |
| return makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages); |
| else if ((VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) & caseDef.shaderStage ) |
| return makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages); |
| |
| return makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages); |
| } |
| |
| |
| tcu::TestStatus test(Context& context, const CaseDefinition caseDef) |
| { |
| if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT)) |
| { |
| TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations"); |
| } |
| |
| if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) |
| { |
| if (!areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage)) |
| { |
| return tcu::TestStatus::fail( |
| "Shader stage " + getShaderStageName(caseDef.shaderStage) + |
| " is required to support subgroup operations!"); |
| } |
| |
| if (caseDef.requiredSubgroupSize == DE_FALSE) |
| return makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeStage); |
| |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| VkPhysicalDeviceSubgroupSizeControlPropertiesEXT subgroupSizeControlProperties; |
| subgroupSizeControlProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT; |
| subgroupSizeControlProperties.pNext = DE_NULL; |
| VkPhysicalDeviceProperties2 properties; |
| properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; |
| properties.pNext = &subgroupSizeControlProperties; |
| |
| context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties); |
| |
| log << tcu::TestLog::Message << "Testing required subgroup size range [" << subgroupSizeControlProperties.minSubgroupSize << ", " |
| << subgroupSizeControlProperties.maxSubgroupSize << "]" << tcu::TestLog::EndMessage; |
| |
| // According to the spec, requiredSubgroupSize must be a power-of-two integer. |
| for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2) |
| { |
| tcu::TestStatus result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeStage, |
| size, VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT); |
| if (result.getCode() != QP_TEST_RESULT_PASS) |
| { |
| log << tcu::TestLog::Message << "subgroupSize " << size << " failed" << tcu::TestLog::EndMessage; |
| return result; |
| } |
| } |
| |
| return tcu::TestStatus::pass("OK"); |
| } |
| else |
| { |
| VkPhysicalDeviceSubgroupProperties subgroupProperties; |
| subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; |
| subgroupProperties.pNext = DE_NULL; |
| |
| VkPhysicalDeviceProperties2 properties; |
| properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; |
| properties.pNext = &subgroupProperties; |
| |
| context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties); |
| |
| VkShaderStageFlagBits stages = (VkShaderStageFlagBits)(caseDef.shaderStage & subgroupProperties.supportedStages); |
| |
| if ( VK_SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context)) |
| { |
| if ( (stages & VK_SHADER_STAGE_FRAGMENT_BIT) == 0) |
| TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes"); |
| else |
| stages = VK_SHADER_STAGE_FRAGMENT_BIT; |
| } |
| |
| if ((VkShaderStageFlagBits)0u == stages) |
| TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader"); |
| |
| return subgroups::allStages(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages, stages); |
| } |
| } |
| |
| tcu::TestCaseGroup* createSubgroupsBuiltinMaskVarTests(tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> graphicGroup(new tcu::TestCaseGroup( |
| testCtx, "graphics", "Subgroup builtin mask category tests: graphics")); |
| de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup( |
| testCtx, "compute", "Subgroup builtin mask category tests: compute")); |
| de::MovePtr<tcu::TestCaseGroup> framebufferGroup(new tcu::TestCaseGroup( |
| testCtx, "framebuffer", "Subgroup builtin mask category tests: framebuffer")); |
| |
| const char* const all_stages_vars[] = |
| { |
| "SubgroupEqMask", |
| "SubgroupGeMask", |
| "SubgroupGtMask", |
| "SubgroupLeMask", |
| "SubgroupLtMask", |
| }; |
| |
| const VkShaderStageFlags stages[] = |
| { |
| VK_SHADER_STAGE_VERTEX_BIT, |
| VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, |
| VK_SHADER_STAGE_GEOMETRY_BIT, |
| }; |
| |
| |
| for (int a = 0; a < DE_LENGTH_OF_ARRAY(all_stages_vars); ++a) |
| { |
| const std::string var = all_stages_vars[a]; |
| const std::string varLower = de::toLower(var); |
| |
| { |
| const CaseDefinition caseDef = {"gl_" + var, VK_SHADER_STAGE_ALL_GRAPHICS, de::SharedPtr<bool>(new bool), DE_FALSE}; |
| addFunctionCaseWithPrograms(graphicGroup.get(), |
| varLower, "", |
| supportedCheck, initPrograms, test, caseDef); |
| } |
| |
| { |
| CaseDefinition caseDef = {"gl_" + var, VK_SHADER_STAGE_COMPUTE_BIT, de::SharedPtr<bool>(new bool), DE_FALSE}; |
| addFunctionCaseWithPrograms(computeGroup.get(), |
| varLower, "", |
| supportedCheck, initPrograms, test, caseDef); |
| } |
| |
| for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex) |
| { |
| const CaseDefinition caseDef = {"gl_" + var, stages[stageIndex], de::SharedPtr<bool>(new bool), DE_FALSE}; |
| addFunctionCaseWithPrograms(framebufferGroup.get(), |
| varLower + "_" + |
| getShaderStageName(caseDef.shaderStage), "", |
| supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef); |
| } |
| } |
| |
| de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup( |
| testCtx, "builtin_mask_var", "Subgroup builtin mask variable tests")); |
| |
| group->addChild(graphicGroup.release()); |
| group->addChild(computeGroup.release()); |
| group->addChild(framebufferGroup.release()); |
| |
| return group.release(); |
| } |
| } // subgroups |
| } // vkt |