From 338b185a2b2d2887ba8e8d7b742e714b366bc488 Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Thu, 5 May 2016 20:38:33 +0800 Subject: [PATCH] Implement the extension GL_ARB_shader_group_vote. --- SPIRV/GlslangToSpv.cpp | 35 ++++++++- Test/baseResults/spv.shaderGroupVote.comp.out | 71 +++++++++++++++++++ Test/spv.shaderGroupVote.comp | 21 ++++++ Test/test-spirv-list | 1 + glslang/Include/intermediate.h | 4 ++ glslang/MachineIndependent/Initialize.cpp | 22 +++++- glslang/MachineIndependent/Versions.cpp | 2 + glslang/MachineIndependent/Versions.h | 1 + glslang/MachineIndependent/intermOut.cpp | 4 ++ gtests/Spv.FromFile.cpp | 1 + 10 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 Test/baseResults/spv.shaderGroupVote.comp.out create mode 100644 Test/spv.shaderGroupVote.comp diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 0c62d52e..ea6b2b46 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3234,6 +3234,18 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv: libCall = spv::GLSLstd450FindSMsb; 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; } @@ -3243,8 +3255,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 dfc6db7b..b607d838 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -72,6 +72,7 @@ spv.intOps.vert spv.precision.frag spv.prepost.frag spv.qualifiers.vert +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 1dd55a7b..c397557a 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -283,6 +283,10 @@ enum TOperator { EOpMemoryBarrierShared, // compute only EOpGroupMemoryBarrier, // compute only + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + EOpAtomicAdd, EOpAtomicMin, EOpAtomicMax, diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 0b27ddd9..86943a59 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -1325,6 +1325,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. @@ -3394,7 +3404,7 @@ void IdentifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLan switch(language) { case EShLangVertex: - if (profile != EEsProfile && version >= 440) { + if (profile != EEsProfile) { symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters); symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters); symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters); @@ -3404,6 +3414,12 @@ void IdentifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLan BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable); } + if (profile != EEsProfile) { + 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 if (spv == 0) { BuiltInVariable("gl_Color", EbvColor, symbolTable); @@ -3987,6 +4003,10 @@ void IdentifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLan symbolTable.relateToOperator("textureOffsetClampARB", EOpTextureOffsetClamp); symbolTable.relateToOperator("textureGradClampARB", EOpTextureGradClamp); symbolTable.relateToOperator("textureGradOffsetClampARB", EOpTextureGradOffsetClamp); + + 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 911535af..12696a99 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; @@ -272,6 +273,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 779ba9f2..5a712867 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 82e71600..4efb4c9d 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -351,6 +351,10 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) case EOpNoise: out.debug << "noise"; 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 e5040b22..dad17c8d 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -138,6 +138,7 @@ INSTANTIATE_TEST_CASE_P( "spv.precision.frag", "spv.prepost.frag", "spv.qualifiers.vert", + "spv.shaderGroupVote.comp", "spv.shiftOps.frag", "spv.simpleFunctionCall.frag", "spv.simpleMat.vert",