diff --git a/Test/atomicAdd.comp b/Test/atomicAdd.comp new file mode 100644 index 00000000..65aa9620 --- /dev/null +++ b/Test/atomicAdd.comp @@ -0,0 +1,19 @@ +#version 320 es +layout(local_size_x = 1) in; + +struct structType{ + int y[3]; +}; + +layout(std430) buffer t2 { + structType f; +} t; + +buffer coherent Buffer { int x; }; +int z; + +void main() { + atomicAdd(x, 1); + atomicAdd(t.f.y[1], 1); + atomicAdd(z, 1); +} diff --git a/Test/baseResults/atomicAdd.comp.out b/Test/baseResults/atomicAdd.comp.out new file mode 100644 index 00000000..6752a713 --- /dev/null +++ b/Test/baseResults/atomicAdd.comp.out @@ -0,0 +1,87 @@ +atomicAdd.comp +ERROR: 0:18: 'atomicAdd' : Atomic memory function can only be used for shader storage block member or shared variable. +ERROR: 1 compilation errors. No code generated. + + +Shader version: 320 +local_size = (1, 1, 1) +ERROR: node is still EOpNull! +0:15 Function Definition: main( ( global void) +0:15 Function Parameters: +0:16 Sequence +0:16 AtomicAdd ( global highp int) +0:16 x: direct index for structure (layout( column_major shared) coherent buffer highp int) +0:16 'anon@0' (layout( column_major shared) coherent buffer block{layout( column_major shared) coherent buffer highp int x}) +0:16 Constant: +0:16 0 (const uint) +0:16 Constant: +0:16 1 (const int) +0:17 AtomicAdd ( global highp int) +0:17 direct index (layout( std430) temp highp int) +0:17 y: direct index for structure (layout( std430) global 3-element array of highp int) +0:17 f: direct index for structure (layout( column_major std430 offset=0) buffer structure{layout( std430) global 3-element array of highp int y}) +0:17 't' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer structure{layout( std430) global 3-element array of highp int y} f}) +0:17 Constant: +0:17 0 (const int) +0:17 Constant: +0:17 0 (const int) +0:17 Constant: +0:17 1 (const int) +0:17 Constant: +0:17 1 (const int) +0:18 AtomicAdd ( global highp int) +0:18 'z' ( global highp int) +0:18 Constant: +0:18 1 (const int) +0:? Linker Objects +0:? 'gl_WorkGroupSize' ( const highp 3-component vector of uint WorkGroupSize) +0:? 1 (const uint) +0:? 1 (const uint) +0:? 1 (const uint) +0:? 't' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer structure{layout( std430) global 3-element array of highp int y} f}) +0:? 'anon@0' (layout( column_major shared) coherent buffer block{layout( column_major shared) coherent buffer highp int x}) +0:? 'z' ( global highp int) + + +Linked compute stage: + + +Shader version: 320 +local_size = (1, 1, 1) +ERROR: node is still EOpNull! +0:15 Function Definition: main( ( global void) +0:15 Function Parameters: +0:16 Sequence +0:16 AtomicAdd ( global highp int) +0:16 x: direct index for structure (layout( column_major shared) coherent buffer highp int) +0:16 'anon@0' (layout( column_major shared) coherent buffer block{layout( column_major shared) coherent buffer highp int x}) +0:16 Constant: +0:16 0 (const uint) +0:16 Constant: +0:16 1 (const int) +0:17 AtomicAdd ( global highp int) +0:17 direct index (layout( std430) temp highp int) +0:17 y: direct index for structure (layout( std430) global 3-element array of highp int) +0:17 f: direct index for structure (layout( column_major std430 offset=0) buffer structure{layout( std430) global 3-element array of highp int y}) +0:17 't' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer structure{layout( std430) global 3-element array of highp int y} f}) +0:17 Constant: +0:17 0 (const int) +0:17 Constant: +0:17 0 (const int) +0:17 Constant: +0:17 1 (const int) +0:17 Constant: +0:17 1 (const int) +0:18 AtomicAdd ( global highp int) +0:18 'z' ( global highp int) +0:18 Constant: +0:18 1 (const int) +0:? Linker Objects +0:? 'gl_WorkGroupSize' ( const highp 3-component vector of uint WorkGroupSize) +0:? 1 (const uint) +0:? 1 (const uint) +0:? 1 (const uint) +0:? 't' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer structure{layout( std430) global 3-element array of highp int y} f}) +0:? 'anon@0' (layout( column_major shared) coherent buffer block{layout( column_major shared) coherent buffer highp int x}) +0:? 'z' ( global highp int) + diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index c2b9edcf..7d32746e 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2409,6 +2409,12 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan arg0->getType().isFloatingDomain()) { requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); } + + const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true); + const TQualifier& qualifier = base->getType().getQualifier(); + if (qualifier.storage != EvqShared && qualifier.storage != EvqBuffer) + error(loc,"Atomic memory function can only be used for shader storage block member or shared variable.", fnCandidate.getName().c_str(), ""); + break; } diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp index 77f0aafb..cedd558e 100644 --- a/gtests/AST.FromFile.cpp +++ b/gtests/AST.FromFile.cpp @@ -282,6 +282,7 @@ INSTANTIATE_TEST_SUITE_P( "terminate.vert", "negativeWorkGroupSize.comp", "textureoffset_sampler2darrayshadow.vert", + "atomicAdd.comp", })), FileNameAsCustomTestSuffix );