From 0d0c6d38f0ea0e5d3dcec1062ebcd515603258f9 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Sun, 23 Jul 2017 16:08:26 -0600 Subject: [PATCH] GLSL 4.6: Implement atomic counter ops and SPV_KHR_shader_atomic_counter_ops. --- SPIRV/GlslangToSpv.cpp | 34 +++++++++++++++ SPIRV/doc.cpp | 2 + Test/450.vert | 12 ++++++ Test/baseResults/450.vert.out | 42 ++++++++++++++++--- Test/baseResults/spv.460.frag.out | 51 +++++++++++++++++++++++ Test/spv.460.frag | 17 ++++++++ glslang/Include/intermediate.h | 9 ++++ glslang/MachineIndependent/Initialize.cpp | 32 ++++++++++++-- glslang/MachineIndependent/intermOut.cpp | 10 +++++ gtests/Spv.FromFile.cpp | 1 + 10 files changed, 202 insertions(+), 8 deletions(-) create mode 100755 Test/baseResults/spv.460.frag.out create mode 100644 Test/spv.460.frag diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 36b27075a..1661d5b1e 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1745,6 +1745,20 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt atomic = true; break; + case glslang::EOpAtomicCounterAdd: + case glslang::EOpAtomicCounterSubtract: + case glslang::EOpAtomicCounterMin: + case glslang::EOpAtomicCounterMax: + case glslang::EOpAtomicCounterAnd: + case glslang::EOpAtomicCounterOr: + case glslang::EOpAtomicCounterXor: + case glslang::EOpAtomicCounterExchange: + case glslang::EOpAtomicCounterCompSwap: + builder.addExtension("SPV_KHR_shader_atomic_counter_ops"); + builder.addCapability(spv::CapabilityAtomicStorageOps); + atomic = true; + break; + default: break; } @@ -1815,6 +1829,15 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpAtomicXor: case glslang::EOpAtomicExchange: case glslang::EOpAtomicCompSwap: + case glslang::EOpAtomicCounterAdd: + case glslang::EOpAtomicCounterSubtract: + case glslang::EOpAtomicCounterMin: + case glslang::EOpAtomicCounterMax: + case glslang::EOpAtomicCounterAnd: + case glslang::EOpAtomicCounterOr: + case glslang::EOpAtomicCounterXor: + case glslang::EOpAtomicCounterExchange: + case glslang::EOpAtomicCounterCompSwap: if (arg == 0) lvalue = true; break; @@ -4619,34 +4642,45 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv switch (op) { case glslang::EOpAtomicAdd: case glslang::EOpImageAtomicAdd: + case glslang::EOpAtomicCounterAdd: opCode = spv::OpAtomicIAdd; break; + case glslang::EOpAtomicCounterSubtract: + opCode = spv::OpAtomicISub; + break; case glslang::EOpAtomicMin: case glslang::EOpImageAtomicMin: + case glslang::EOpAtomicCounterMin: opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMin : spv::OpAtomicSMin; break; case glslang::EOpAtomicMax: case glslang::EOpImageAtomicMax: + case glslang::EOpAtomicCounterMax: opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMax : spv::OpAtomicSMax; break; case glslang::EOpAtomicAnd: case glslang::EOpImageAtomicAnd: + case glslang::EOpAtomicCounterAnd: opCode = spv::OpAtomicAnd; break; case glslang::EOpAtomicOr: case glslang::EOpImageAtomicOr: + case glslang::EOpAtomicCounterOr: opCode = spv::OpAtomicOr; break; case glslang::EOpAtomicXor: case glslang::EOpImageAtomicXor: + case glslang::EOpAtomicCounterXor: opCode = spv::OpAtomicXor; break; case glslang::EOpAtomicExchange: case glslang::EOpImageAtomicExchange: + case glslang::EOpAtomicCounterExchange: opCode = spv::OpAtomicExchange; break; case glslang::EOpAtomicCompSwap: case glslang::EOpImageAtomicCompSwap: + case glslang::EOpAtomicCounterCompSwap: opCode = spv::OpAtomicCompareExchange; break; case glslang::EOpAtomicCounterIncrement: diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp index fb0cc36ea..b47fa4889 100755 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -846,6 +846,8 @@ const char* CapabilityString(int info) case 5009: return "ImageGatherBiasLodAMD"; #endif + case 4445: return "AtomicStorageOps"; + case 4447: return "SampleMaskPostDepthCoverage"; #ifdef NV_EXTENSIONS case 5251: return "GeometryShaderPassthroughNV"; diff --git a/Test/450.vert b/Test/450.vert index 4a376a306..17d1abbbb 100644 --- a/Test/450.vert +++ b/Test/450.vert @@ -22,8 +22,20 @@ out SA outSA; struct SS { float f; S s; }; out SS outSS; +layout(binding = 0) uniform atomic_uint aui; +uint ui; + void foo() { SS::f; + atomicCounterAdd(aui, ui); // ERROR, need 4.6 + atomicCounterSubtract(aui, ui); // ERROR, need 4.6 + atomicCounterMin(aui, ui); // ERROR, need 4.6 + atomicCounterMax(aui, ui); // ERROR, need 4.6 + atomicCounterAnd(aui, ui); // ERROR, need 4.6 + atomicCounterOr(aui, ui); // ERROR, need 4.6 + atomicCounterXor(aui, ui); // ERROR, need 4.6 + atomicCounterExchange(aui, ui); // ERROR, need 4.6 + atomicCounterCompSwap(aui, ui, ui); // ERROR, need 4.6 } ; // ERROR: no extraneous semicolons diff --git a/Test/baseResults/450.vert.out b/Test/baseResults/450.vert.out index cd150e3dd..1005642d0 100644 --- a/Test/baseResults/450.vert.out +++ b/Test/baseResults/450.vert.out @@ -1,9 +1,18 @@ 450.vert ERROR: 0:12: 'out' : cannot be bool ERROR: 0:13: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: outo -ERROR: 0:27: '::' : not supported -ERROR: 0:29: 'extraneous semicolon' : not supported for this version or the enabled extensions -ERROR: 4 compilation errors. No code generated. +ERROR: 0:30: '::' : not supported +ERROR: 0:31: 'atomicCounterAdd' : no matching overloaded function found +ERROR: 0:32: 'atomicCounterSubtract' : no matching overloaded function found +ERROR: 0:33: 'atomicCounterMin' : no matching overloaded function found +ERROR: 0:34: 'atomicCounterMax' : no matching overloaded function found +ERROR: 0:35: 'atomicCounterAnd' : no matching overloaded function found +ERROR: 0:36: 'atomicCounterOr' : no matching overloaded function found +ERROR: 0:37: 'atomicCounterXor' : no matching overloaded function found +ERROR: 0:38: 'atomicCounterExchange' : no matching overloaded function found +ERROR: 0:39: 'atomicCounterCompSwap' : no matching overloaded function found +ERROR: 0:41: 'extraneous semicolon' : not supported for this version or the enabled extensions +ERROR: 13 compilation errors. No code generated. Shader version: 450 @@ -21,8 +30,27 @@ ERROR: node is still EOpNull! 0:9 2 (const int) 0:9 Constant: 0:9 4.500000 -0:25 Function Definition: foo( ( global void) -0:25 Function Parameters: +0:28 Function Definition: foo( ( global void) +0:28 Function Parameters: +0:? Sequence +0:31 Constant: +0:31 0.000000 +0:32 Constant: +0:32 0.000000 +0:33 Constant: +0:33 0.000000 +0:34 Constant: +0:34 0.000000 +0:35 Constant: +0:35 0.000000 +0:36 Constant: +0:36 0.000000 +0:37 Constant: +0:37 0.000000 +0:38 Constant: +0:38 0.000000 +0:39 Constant: +0:39 0.000000 0:? Linker Objects 0:? 'anon@0' ( out block{ out 3-element array of float CullDistance gl_CullDistance}) 0:? 'outb' ( smooth out bool) @@ -34,6 +62,8 @@ ERROR: node is still EOpNull! 0:? 'outsa' ( smooth out 4-element array of structure{ global float f}) 0:? 'outSA' ( smooth out structure{ global 4-element array of float f}) 0:? 'outSS' ( smooth out structure{ global float f, global structure{ global float f} s}) +0:? 'aui' (layout( binding=0 offset=0) uniform atomic_uint) +0:? 'ui' ( global uint) 0:? 'gl_VertexID' ( gl_VertexId int VertexId) 0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId) @@ -67,6 +97,8 @@ ERROR: node is still EOpNull! 0:? 'outsa' ( smooth out 4-element array of structure{ global float f}) 0:? 'outSA' ( smooth out structure{ global 4-element array of float f}) 0:? 'outSS' ( smooth out structure{ global float f, global structure{ global float f} s}) +0:? 'aui' (layout( binding=0 offset=0) uniform atomic_uint) +0:? 'ui' ( global uint) 0:? 'gl_VertexID' ( gl_VertexId int VertexId) 0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId) diff --git a/Test/baseResults/spv.460.frag.out b/Test/baseResults/spv.460.frag.out new file mode 100755 index 000000000..4e827a00b --- /dev/null +++ b/Test/baseResults/spv.460.frag.out @@ -0,0 +1,51 @@ +spv.460.frag +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 32 + + Capability Shader + Capability AtomicStorage + Capability AtomicStorageOps + Extension "SPV_KHR_shader_atomic_counter_ops" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" + ExecutionMode 4 OriginLowerLeft + Source GLSL 460 + Name 4 "main" + Name 8 "aui" + Name 10 "ui" + Decorate 8(aui) Offset 0 + Decorate 8(aui) Binding 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypePointer AtomicCounter 6(int) + 8(aui): 7(ptr) Variable AtomicCounter + 9: TypePointer Private 6(int) + 10(ui): 9(ptr) Variable Private + 12: 6(int) Constant 1 + 13: 6(int) Constant 0 + 4(main): 2 Function None 3 + 5: Label + 11: 6(int) Load 10(ui) + 14: 6(int) AtomicIAdd 8(aui) 12 13 11 + 15: 6(int) Load 10(ui) + 16: 6(int) AtomicISub 8(aui) 12 13 15 + 17: 6(int) Load 10(ui) + 18: 6(int) AtomicUMin 8(aui) 12 13 17 + 19: 6(int) Load 10(ui) + 20: 6(int) AtomicUMax 8(aui) 12 13 19 + 21: 6(int) Load 10(ui) + 22: 6(int) AtomicAnd 8(aui) 12 13 21 + 23: 6(int) Load 10(ui) + 24: 6(int) AtomicOr 8(aui) 12 13 23 + 25: 6(int) Load 10(ui) + 26: 6(int) AtomicXor 8(aui) 12 13 25 + 27: 6(int) Load 10(ui) + 28: 6(int) AtomicExchange 8(aui) 12 13 27 + 29: 6(int) Load 10(ui) + 30: 6(int) Load 10(ui) + 31: 6(int) AtomicCompareExchange 8(aui) 12 13 13 30 29 + Return + FunctionEnd diff --git a/Test/spv.460.frag b/Test/spv.460.frag new file mode 100644 index 000000000..9eb8bf46f --- /dev/null +++ b/Test/spv.460.frag @@ -0,0 +1,17 @@ +#version 460 core + +layout(binding = 0) uniform atomic_uint aui; +uint ui; + +void main() +{ + atomicCounterAdd(aui, ui); + atomicCounterSubtract(aui, ui); + atomicCounterMin(aui, ui); + atomicCounterMax(aui, ui); + atomicCounterAnd(aui, ui); + atomicCounterOr(aui, ui); + atomicCounterXor(aui, ui); + atomicCounterExchange(aui, ui); + atomicCounterCompSwap(aui, ui, ui); +} diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 0922d125a..e289efd42 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -420,6 +420,15 @@ enum TOperator { EOpAtomicCounterIncrement, EOpAtomicCounterDecrement, EOpAtomicCounter, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, EOpAny, EOpAll, diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 5cd167e04..921d83a9f 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -1375,9 +1375,23 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV if ((profile != EEsProfile && version >= 300) || (profile == EEsProfile && version >= 310)) { commonBuiltins.append( - "uint atomicCounterIncrement(atomic_uint x);" - "uint atomicCounterDecrement(atomic_uint x);" - "uint atomicCounter(atomic_uint x);" + "uint atomicCounterIncrement(atomic_uint);" + "uint atomicCounterDecrement(atomic_uint);" + "uint atomicCounter(atomic_uint);" + + "\n"); + } + if (profile != EEsProfile && version >= 460) { + commonBuiltins.append( + "uint atomicCounterAdd(atomic_uint, uint);" + "uint atomicCounterSubtract(atomic_uint, uint);" + "uint atomicCounterMin(atomic_uint, uint);" + "uint atomicCounterMax(atomic_uint, uint);" + "uint atomicCounterAnd(atomic_uint, uint);" + "uint atomicCounterOr(atomic_uint, uint);" + "uint atomicCounterXor(atomic_uint, uint);" + "uint atomicCounterExchange(atomic_uint, uint);" + "uint atomicCounterCompSwap(atomic_uint, uint, uint);" "\n"); } @@ -5909,6 +5923,18 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement); symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter); + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicCounterAdd); + symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract); + symbolTable.relateToOperator("atomicCounterMin", EOpAtomicCounterMin); + symbolTable.relateToOperator("atomicCounterMax", EOpAtomicCounterMax); + symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicCounterAnd); + symbolTable.relateToOperator("atomicCounterOr", EOpAtomicCounterOr); + symbolTable.relateToOperator("atomicCounterXor", EOpAtomicCounterXor); + symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicCounterExchange); + symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap); + } + symbolTable.relateToOperator("fma", EOpFma); symbolTable.relateToOperator("frexp", EOpFrexp); symbolTable.relateToOperator("ldexp", EOpLdexp); diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index ba7e0f59f..479f15d8d 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -682,6 +682,16 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpAtomicExchange: out.debug << "AtomicExchange"; break; case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break; + case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break; + case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break; + case EOpAtomicCounterMin: out.debug << "AtomicCounterMin"; break; + case EOpAtomicCounterMax: out.debug << "AtomicCounterMax"; break; + case EOpAtomicCounterAnd: out.debug << "AtomicCounterAnd"; break; + case EOpAtomicCounterOr: out.debug << "AtomicCounterOr"; break; + case EOpAtomicCounterXor: out.debug << "AtomicCounterXor"; break; + case EOpAtomicCounterExchange: out.debug << "AtomicCounterExchange"; break; + case EOpAtomicCounterCompSwap: out.debug << "AtomicCounterCompSwap"; break; + case EOpImageQuerySize: out.debug << "imageQuerySize"; break; case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break; case EOpImageLoad: out.debug << "imageLoad"; break; diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index dfad30c72..3a236b7f3 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -360,6 +360,7 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( Glsl, CompileOpenGLToSpirvTest, ::testing::ValuesIn(std::vector<std::string>({ + "spv.460.frag", "spv.atomic.comp", "spv.glFragColor.frag", "spv.specConst.vert", -- GitLab