Implement the extension GL_ARB_shader_group_vote.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 0c62d52..ea6b2b4 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -3234,6 +3234,18 @@
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 @@
std::vector<spv::Id> 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<spv::Id> 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 0000000..e63164d
--- /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 0000000..c0b1fe7
--- /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 dfc6db7..b607d83 100644
--- a/Test/test-spirv-list
+++ b/Test/test-spirv-list
@@ -72,6 +72,7 @@
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 1dd55a7..c397557 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -283,6 +283,10 @@
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 0b27ddd..86943a5 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -1325,6 +1325,16 @@
"\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 @@
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 @@
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 @@
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 911535a..12696a9 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -171,6 +171,7 @@
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 @@
"#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 779ba9f..5a71286 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -108,6 +108,7 @@
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 82e7160..4efb4c9 100644
--- a/glslang/MachineIndependent/intermOut.cpp
+++ b/glslang/MachineIndependent/intermOut.cpp
@@ -351,6 +351,10 @@
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 e5040b2..dad17c8 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -138,6 +138,7 @@
"spv.precision.frag",
"spv.prepost.frag",
"spv.qualifiers.vert",
+ "spv.shaderGroupVote.comp",
"spv.shiftOps.frag",
"spv.simpleFunctionCall.frag",
"spv.simpleMat.vert",