diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 14f536ac..943743ad 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3252,6 +3252,18 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: libCall = spv::GLSLstd450Bad; break; + case glslang::EOpAnyInvocation: + builder.addCapability(spv::CapabilityGroups); + unaryOp = spv::OpGroupAny; + break; + case glslang::EOpAllInvocations: + builder.addCapability(spv::CapabilityGroups); + unaryOp = spv::OpGroupAll; + break; + case glslang::EOpAllInvocationsEqual: + builder.addCapability(spv::CapabilityGroups); + break; + default: return 0; } @@ -3261,8 +3273,27 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: std::vector args; args.push_back(operand); id = builder.createBuiltinCall(typeId, stdBuiltins, libCall, args); - } else - id = builder.createUnaryOp(unaryOp, typeId, operand); + } else { + if (op == glslang::EOpAnyInvocation || op == glslang::EOpAllInvocations || op == glslang::EOpAllInvocationsEqual) { + std::vector operands; + operands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); + operands.push_back(operand); + + if (op == glslang::EOpAnyInvocation || op == glslang::EOpAllInvocations) + id = builder.createOp(unaryOp, typeId, operands); + else if (op == glslang::EOpAllInvocationsEqual) { + spv::Id groupAll = builder.createOp(spv::OpGroupAll, typeId, operands); + spv::Id groupAny = builder.createOp(spv::OpGroupAny, typeId, operands); + + id = builder.createBinOp(spv::OpLogicalOr, + typeId, + groupAll, + builder.createUnaryOp(spv::OpLogicalNot, typeId, groupAny)); + } + } + else + id = builder.createUnaryOp(unaryOp, typeId, operand); + } return builder.setPrecision(id, precision); } diff --git a/Test/baseResults/spv.shaderGroupVote.comp.out b/Test/baseResults/spv.shaderGroupVote.comp.out new file mode 100644 index 00000000..e63164d0 --- /dev/null +++ b/Test/baseResults/spv.shaderGroupVote.comp.out @@ -0,0 +1,71 @@ +spv.shaderGroupVote.comp +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked compute stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 37 + + Capability Shader + Capability Groups + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" + ExecutionMode 4 LocalSize 4 4 1 + Source GLSL 450 + SourceExtension "GL_ARB_shader_group_vote" + Name 4 "main" + Name 8 "b1" + Name 10 "Buffers" + MemberName 10(Buffers) 0 "b" + Name 12 "" + MemberDecorate 10(Buffers) 0 Offset 0 + Decorate 10(Buffers) BufferBlock + Decorate 12 DescriptorSet 0 + Decorate 12 Binding 0 + Decorate 36 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeBool + 7: TypePointer Function 6(bool) + 9: TypeInt 32 0 + 10(Buffers): TypeStruct 9(int) + 11: TypePointer Uniform 10(Buffers) + 12: 11(ptr) Variable Uniform + 13: TypeInt 32 1 + 14: 13(int) Constant 0 + 15: TypePointer Uniform 9(int) + 18: 9(int) Constant 0 + 21: 9(int) Constant 3 + 31: 9(int) Constant 1 + 34: TypeVector 9(int) 3 + 35: 9(int) Constant 4 + 36: 34(ivec3) ConstantComposite 35 35 31 + 4(main): 2 Function None 3 + 5: Label + 8(b1): 7(ptr) Variable Function + 16: 15(ptr) AccessChain 12 14 + 17: 9(int) Load 16 + 19: 6(bool) INotEqual 17 18 + Store 8(b1) 19 + 20: 6(bool) Load 8(b1) + 22: 6(bool) GroupAny 21 20 + Store 8(b1) 22 + 23: 6(bool) Load 8(b1) + 24: 6(bool) GroupAll 21 23 + Store 8(b1) 24 + 25: 6(bool) Load 8(b1) + 26: 6(bool) GroupAll 21 25 + 27: 6(bool) GroupAny 21 25 + 28: 6(bool) LogicalNot 27 + 29: 6(bool) LogicalOr 26 28 + Store 8(b1) 29 + 30: 6(bool) Load 8(b1) + 32: 9(int) Select 30 31 18 + 33: 15(ptr) AccessChain 12 14 + Store 33 32 + Return + FunctionEnd diff --git a/Test/spv.shaderGroupVote.comp b/Test/spv.shaderGroupVote.comp new file mode 100644 index 00000000..c0b1fe72 --- /dev/null +++ b/Test/spv.shaderGroupVote.comp @@ -0,0 +1,21 @@ +#version 450 + +#extension GL_ARB_shader_group_vote : enable + +layout(local_size_x = 4, local_size_y = 4) in; + +layout(std430, binding = 0) buffer Buffers +{ + bool b; +}; + +void main() +{ + bool b1 = b; + + b1 = anyInvocationARB(b1); + b1 = allInvocationsARB(b1); + b1 = allInvocationsEqualARB(b1); + + b = b1; +} diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 5167b13c..703607da 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -73,6 +73,7 @@ spv.precision.frag spv.prepost.frag spv.qualifiers.vert spv.shaderBallot.comp +spv.shaderGroupVote.comp spv.shiftOps.frag spv.simpleFunctionCall.frag spv.simpleMat.vert diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index ef2547a7..6353a0a0 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -287,6 +287,10 @@ enum TOperator { EOpReadInvocation, EOpReadFirstInvocation, + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + EOpAtomicAdd, EOpAtomicMin, EOpAtomicMax, diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index ac9dfc79..3daa28bb 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -1363,6 +1363,16 @@ void TBuiltIns::initialize(int version, EProfile profile, int spv, int vulkan) "\n"); } + // GL_ARB_shader_group_vote + if (profile != EEsProfile && version >= 430) { + commonBuiltins.append( + "bool anyInvocationARB(bool);" + "bool allInvocationsARB(bool);" + "bool allInvocationsEqualARB(bool);" + + "\n"); + } + //============================================================================ // // Prototypes for built-in functions seen by vertex shaders only. @@ -3477,6 +3487,10 @@ void IdentifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLan BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); + + symbolTable.setFunctionExtensions("anyInvocationARB", 1, &E_GL_ARB_shader_group_vote); + symbolTable.setFunctionExtensions("allInvocationsARB", 1, &E_GL_ARB_shader_group_vote); + symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote); } // Compatibility variables, vertex only @@ -4065,6 +4079,10 @@ void IdentifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLan symbolTable.relateToOperator("ballotARB", EOpBallot); symbolTable.relateToOperator("readInvocationARB", EOpReadInvocation); symbolTable.relateToOperator("readFirstInvocationARB", EOpReadFirstInvocation); + + symbolTable.relateToOperator("anyInvocationARB", EOpAnyInvocation); + symbolTable.relateToOperator("allInvocationsARB", EOpAllInvocations); + symbolTable.relateToOperator("allInvocationsEqualARB", EOpAllInvocationsEqual); } } diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 42eca96d..eeff270a 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -171,6 +171,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable; extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable; extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable; + extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable; extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable; extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable; extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable; @@ -273,6 +274,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_ARB_shader_image_load_store 1\n" "#define GL_ARB_shader_atomic_counters 1\n" "#define GL_ARB_shader_draw_parameters 1\n" + "#define GL_ARB_shader_group_vote 1\n" "#define GL_ARB_derivative_control 1\n" "#define GL_ARB_shader_texture_image_samples 1\n" "#define GL_ARB_viewport_array 1\n" diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index 93db6c3e..ba08ca3c 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -108,6 +108,7 @@ const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attri const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; +const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 4a7ee653..d3d90c58 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -353,6 +353,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) case EOpBallot: out.debug << "ballot"; break; case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break; + case EOpAnyInvocation: out.debug << "anyInvocation"; break; + case EOpAllInvocations: out.debug << "allInvocations"; break; + case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break; default: out.debug.message(EPrefixError, "Bad unary op"); } diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index e3595446..8a4d0e25 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -139,6 +139,7 @@ INSTANTIATE_TEST_CASE_P( "spv.prepost.frag", "spv.qualifiers.vert", "spv.shaderBallot.comp", + "spv.shaderGroupVote.comp", "spv.shiftOps.frag", "spv.simpleFunctionCall.frag", "spv.simpleMat.vert",