\r
in atomic_uint acin; // ERROR\r
atomic_uint acg; // ERROR\r
-\r
+uniform atomic_uint;\r
+uniform atomic_uint aNoBind; // ERROR, no binding\r
+layout(binding=0, offset=32) uniform atomic_uint aOffset;\r
+layout(binding=0, offset=4) uniform atomic_uint;\r
+layout(binding=0) uniform atomic_uint bar3; // offset is 4\r
+layout(binding=0) uniform atomic_uint ac[3]; // offset = 8\r
+layout(binding=0) uniform atomic_uint ad; // offset = 20\r
+layout(offset=8) uniform atomic_uint bar4; // ERROR, no binding\r
+layout(binding = 0, offset = 12) uniform atomic_uint overlap; // ERROR, overlapping offsets\r
+layout(binding = 20) uniform atomic_uint bigBind; // ERROR, binding too big\r
ERROR: 0:128: 'atomic_uint' : samplers and atomic_uints cannot be output parameters \r
ERROR: 0:130: 'return' : type does not match, or is not convertible to, the function's return type \r
ERROR: 0:136: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter\r
+ERROR: 0:136: 'atomic_uint' : layout(binding=X) is required \r
ERROR: 0:141: 'atomic_uint' : atomic counters can only be highp \r
-ERROR: 0:141: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
-ERROR: 0:143: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
+ERROR: 0:141: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 0:143: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
ERROR: 0:149: '[]' : scalar integer expression required \r
ERROR: 0:166: 'precision' : can only apply highp to atomic_uint \r
ERROR: 0:168: 'precise' : Reserved word. \r
ERROR: 0:174: 'uimage2DMSArray' : Reserved word. \r
ERROR: 0:174: 'sampler/image' : type requires declaration of default precision qualifier \r
ERROR: 0:174: '' : image variables not declared 'writeonly' must have a format layout qualifier \r
-ERROR: 56 compilation errors. No code generated.\r
+ERROR: 57 compilation errors. No code generated.\r
\r
\r
Shader version: 310\r
0:128 'c' (out highp atomic_uint)\r
0:130 Sequence\r
0:130 Branch: Return with expression\r
-0:130 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:130 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:131 Branch: Return with expression\r
0:131 Function Call: atomicCounter(au1; (highp uint)\r
-0:131 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:131 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:134 Function Definition: mainAC( (void)\r
0:134 Function Parameters: \r
0:? Sequence\r
0:137 move second child to first child (highp uint)\r
0:137 'val' (highp uint)\r
0:137 Function Call: atomicCounter(au1; (highp uint)\r
-0:137 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:137 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:138 Function Call: atomicCounterDecrement(au1; (highp uint)\r
-0:138 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:138 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:146 Function Definition: opac( (void)\r
0:146 Function Parameters: \r
0:? Sequence\r
0:149 indirect index (highp int)\r
0:149 'a' (3-element array of highp int)\r
-0:149 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:149 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:150 direct index (layout(binding=2 offset=4 ) highp atomic_uint)\r
0:150 'countArr' (layout(binding=2 offset=4 ) uniform 4-element array of highp atomic_uint)\r
0:150 Constant:\r
0:? 'i4bad' (layout(r8_snorm ) uniform highp iimage2D)\r
0:? 'i5bad' (layout(rgba32ui ) uniform highp iimage2D)\r
0:? 'i6bad' (layout(r8ui ) uniform highp iimage2D)\r
-0:? 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:? 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:? 'counterBad' (layout(binding=1 ) uniform mediump atomic_uint)\r
0:? 'countArr' (layout(binding=2 offset=4 ) uniform 4-element array of highp atomic_uint)\r
0:? 'i' (uniform highp int)\r
0:128 'c' (out highp atomic_uint)\r
0:130 Sequence\r
0:130 Branch: Return with expression\r
-0:130 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:130 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:131 Branch: Return with expression\r
0:131 Function Call: atomicCounter(au1; (highp uint)\r
-0:131 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:131 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:134 Function Definition: mainAC( (void)\r
0:134 Function Parameters: \r
0:? Sequence\r
0:137 move second child to first child (highp uint)\r
0:137 'val' (highp uint)\r
0:137 Function Call: atomicCounter(au1; (highp uint)\r
-0:137 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:137 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:138 Function Call: atomicCounterDecrement(au1; (highp uint)\r
-0:138 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:138 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:146 Function Definition: opac( (void)\r
0:146 Function Parameters: \r
0:? Sequence\r
0:149 indirect index (highp int)\r
0:149 'a' (3-element array of highp int)\r
-0:149 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:149 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:150 direct index (layout(binding=2 offset=4 ) highp atomic_uint)\r
0:150 'countArr' (layout(binding=2 offset=4 ) uniform 4-element array of highp atomic_uint)\r
0:150 Constant:\r
0:? 'i4bad' (layout(r8_snorm ) uniform highp iimage2D)\r
0:? 'i5bad' (layout(rgba32ui ) uniform highp iimage2D)\r
0:? 'i6bad' (layout(r8ui ) uniform highp iimage2D)\r
-0:? 'counter' (layout(binding=0 ) uniform highp atomic_uint)\r
+0:? 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint)\r
0:? 'counterBad' (layout(binding=1 ) uniform mediump atomic_uint)\r
0:? 'countArr' (layout(binding=2 offset=4 ) uniform 4-element array of highp atomic_uint)\r
0:? 'i' (uniform highp int)\r
ERROR: 0:10: 'atomic_uint' : samplers and atomic_uints cannot be output parameters \r
ERROR: 0:12: 'return' : type does not match, or is not convertible to, the function's return type \r
ERROR: 0:18: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter\r
-ERROR: 0:23: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
-ERROR: 0:28: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'layout(binding=0 ) uniform atomic_uint' and a right operand of type 'layout(binding=0 ) uniform atomic_uint' (or there is no acceptable conversion)\r
-ERROR: 0:29: '-' : wrong operand type no operation '-' exists that takes an operand of type layout(binding=0 ) uniform atomic_uint (or there is no acceptable conversion)\r
+ERROR: 0:18: 'atomic_uint' : layout(binding=X) is required \r
+ERROR: 0:23: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 0:28: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'layout(binding=0 offset=0 ) uniform atomic_uint' and a right operand of type 'layout(binding=0 offset=0 ) uniform atomic_uint' (or there is no acceptable conversion)\r
+ERROR: 0:29: '-' : wrong operand type no operation '-' exists that takes an operand of type layout(binding=0 offset=0 ) uniform atomic_uint (or there is no acceptable conversion)\r
ERROR: 0:31: '[]' : scalar integer expression required \r
ERROR: 0:34: 'assign' : l-value required "counter" (can't modify a uniform)\r
-ERROR: 0:34: 'assign' : cannot convert from 'const int' to 'layout(binding=0 ) uniform atomic_uint'\r
+ERROR: 0:34: 'assign' : cannot convert from 'const int' to 'layout(binding=0 offset=0 ) uniform atomic_uint'\r
ERROR: 0:37: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: acin\r
+ERROR: 0:37: 'atomic_uint' : layout(binding=X) is required \r
ERROR: 0:38: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: acg\r
-ERROR: 11 compilation errors. No code generated.\r
+ERROR: 0:38: 'atomic_uint' : layout(binding=X) is required \r
+ERROR: 0:40: 'atomic_uint' : layout(binding=X) is required \r
+ERROR: 0:46: 'atomic_uint' : layout(binding=X) is required \r
+ERROR: 0:47: 'offset' : atomic counters sharing the same offset: 12\r
+ERROR: 0:48: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 18 compilation errors. No code generated.\r
\r
\r
Shader version: 420\r
0:10 'c' (out atomic_uint)\r
0:12 Sequence\r
0:12 Branch: Return with expression\r
-0:12 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:12 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:13 Branch: Return with expression\r
0:13 Function Call: atomicCounter(au1; (uint)\r
-0:13 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:13 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:16 Function Definition: main( (void)\r
0:16 Function Parameters: \r
0:? Sequence\r
0:19 move second child to first child (uint)\r
0:19 'val' (uint)\r
0:19 Function Call: atomicCounter(au1; (uint)\r
-0:19 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:19 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:20 Function Call: atomicCounterDecrement(au1; (uint)\r
-0:20 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:20 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:26 Function Definition: opac( (void)\r
0:26 Function Parameters: \r
0:28 Sequence\r
-0:28 'counter' (layout(binding=0 ) uniform atomic_uint)\r
-0:29 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:28 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
+0:29 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:31 indirect index (int)\r
0:31 'a' (3-element array of int)\r
-0:31 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:31 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:32 direct index (layout(binding=1 offset=3 ) atomic_uint)\r
0:32 'countArr' (layout(binding=1 offset=3 ) uniform 4-element array of atomic_uint)\r
0:32 Constant:\r
0:33 indirect index (layout(binding=1 offset=3 ) atomic_uint)\r
0:33 'countArr' (layout(binding=1 offset=3 ) uniform 4-element array of atomic_uint)\r
0:33 'i' (uniform int)\r
-0:34 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:34 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:? Linker Objects\r
-0:? 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:? 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:? 'countArr' (layout(binding=1 offset=3 ) uniform 4-element array of atomic_uint)\r
0:? 'i' (uniform int)\r
0:? 'acin' (smooth in atomic_uint)\r
0:? 'acg' (atomic_uint)\r
+0:? 'aNoBind' (uniform atomic_uint)\r
+0:? 'aOffset' (layout(binding=0 offset=32 ) uniform atomic_uint)\r
+0:? 'bar3' (layout(binding=0 offset=4 ) uniform atomic_uint)\r
+0:? 'ac' (layout(binding=0 offset=8 ) uniform 3-element array of atomic_uint)\r
+0:? 'ad' (layout(binding=0 offset=20 ) uniform atomic_uint)\r
+0:? 'bar4' (layout(offset=8 ) uniform atomic_uint)\r
+0:? 'overlap' (layout(binding=0 offset=12 ) uniform atomic_uint)\r
+0:? 'bigBind' (layout(binding=20 ) uniform atomic_uint)\r
\r
\r
Linked fragment stage:\r
0:10 'c' (out atomic_uint)\r
0:12 Sequence\r
0:12 Branch: Return with expression\r
-0:12 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:12 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:13 Branch: Return with expression\r
0:13 Function Call: atomicCounter(au1; (uint)\r
-0:13 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:13 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:16 Function Definition: main( (void)\r
0:16 Function Parameters: \r
0:? Sequence\r
0:19 move second child to first child (uint)\r
0:19 'val' (uint)\r
0:19 Function Call: atomicCounter(au1; (uint)\r
-0:19 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:19 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:20 Function Call: atomicCounterDecrement(au1; (uint)\r
-0:20 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:20 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:26 Function Definition: opac( (void)\r
0:26 Function Parameters: \r
0:28 Sequence\r
-0:28 'counter' (layout(binding=0 ) uniform atomic_uint)\r
-0:29 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:28 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
+0:29 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:31 indirect index (int)\r
0:31 'a' (3-element array of int)\r
-0:31 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:31 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:32 direct index (layout(binding=1 offset=3 ) atomic_uint)\r
0:32 'countArr' (layout(binding=1 offset=3 ) uniform 4-element array of atomic_uint)\r
0:32 Constant:\r
0:33 indirect index (layout(binding=1 offset=3 ) atomic_uint)\r
0:33 'countArr' (layout(binding=1 offset=3 ) uniform 4-element array of atomic_uint)\r
0:33 'i' (uniform int)\r
-0:34 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:34 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:? Linker Objects\r
-0:? 'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:? 'counter' (layout(binding=0 offset=0 ) uniform atomic_uint)\r
0:? 'countArr' (layout(binding=1 offset=3 ) uniform 4-element array of atomic_uint)\r
0:? 'i' (uniform int)\r
0:? 'acin' (smooth in atomic_uint)\r
0:? 'acg' (atomic_uint)\r
+0:? 'aNoBind' (uniform atomic_uint)\r
+0:? 'aOffset' (layout(binding=0 offset=32 ) uniform atomic_uint)\r
+0:? 'bar3' (layout(binding=0 offset=4 ) uniform atomic_uint)\r
+0:? 'ac' (layout(binding=0 offset=8 ) uniform 3-element array of atomic_uint)\r
+0:? 'ad' (layout(binding=0 offset=20 ) uniform atomic_uint)\r
+0:? 'bar4' (layout(offset=8 ) uniform atomic_uint)\r
+0:? 'overlap' (layout(binding=0 offset=12 ) uniform atomic_uint)\r
+0:? 'bigBind' (layout(binding=20 ) uniform atomic_uint)\r
\r
ERROR: 0:50: 'stream' : there is no such layout identifier for this stage taking an assigned value \r
ERROR: 0:55: 'stream' : there is no such layout identifier for this stage taking an assigned value \r
ERROR: 0:80: 's17' : redefinition \r
-ERROR: 0:85: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
-ERROR: 0:87: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
-WARNING: 0:89: 'layout' : useless application of layout qualifier \r
+ERROR: 0:85: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 0:87: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 0:89: 'binding' : atomic_uint binding is too large \r
ERROR: 0:91: 'bar' : redefinition \r
-ERROR: 0:92: 'offset' : a binding is required \r
+ERROR: 0:92: 'atomic_uint' : layout(binding=X) is required \r
ERROR: 0:94: 'a2' : redefinition \r
-ERROR: 0:95: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
-ERROR: 0:96: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
-ERROR: 0:97: 'binding' : cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings \r
+ERROR: 0:95: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 0:96: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
+ERROR: 0:97: 'binding' : atomic_uint binding is too large; see gl_MaxAtomicCounterBindings \r
ERROR: 0:106: '' : vertex input cannot be further qualified \r
ERROR: 0:106: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_FrontColor\r
ERROR: 0:112: 'ColorIvn' : identifier not previously declared \r
ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array \r
ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array \r
ERROR: 0:194: 'constructor' : constructing from a non-dereferenced array \r
-ERROR: 36 compilation errors. No code generated.\r
+ERROR: 37 compilation errors. No code generated.\r
\r
\r
Shader version: 430\r
+ exactly one main
+ ES 3.0: fragment outputs all have locations, if more than one
+ location aliasing/overlap (except desktop vertex shader inputs)
- - Non ES: binding overlap for atomic counters
+ + binding overlap for atomic counters
+ Non ES: geometry shader input array sizes and input layout qualifier declaration
+ Non ES: read or write to both gl_ClipVertex and gl_ClipDistance
+ Non ES: write to only one of gl_FragColor, gl_FragData, or user-declared
+ value checking of uniform initializers
+ location match
- block matching
- - component/binding/index/offset match check
+ + component/binding/index/offset match check
+ compute shader layout(local_size_*) matching
+ mixed es/non-es profiles are an error
+ - binding overlap for atomic counters
- matching redeclarations of interface blocks
- 4.3: implicit array sizing is cross shader within a stage
- 4.4: If gl_FragCoord is redeclared in any fragment shader in a program, it must be redeclared in all the fragment shaders in that program that have a static use gl_FragCoord
+ Texture gather
+ Bitfield operations
+ Integer mix function
- - overlapping bindings
- - offset post incrementing
- - overlapping offsets
+ + overlapping bindings/offsets and offset post increment
+ frexp/ldexp
+ packUnorm4x8(),packSnorm4x8(), unpackUnorm4x8(), unpackSnorm4x8()
+ 2DMS samplers and images
+ Parameter qualifiers can include precision and memory qualifiers.
+ Add a new atomic_uint type to support atomic counters. Also, add built-in functions for manipulating atomic counters.
+ atomicCounterIncrement, atomicCounterDecrement, and atomicCounter
- - Add layout qualifier identifiers binding and offset to bind units to sampler and image variable declarations, atomic counters, and uniform blocks.
+ + Add layout qualifier identifiers binding and offset to bind units to sampler and image variable declarations, atomic counters, and uniform blocks.
+ Add built-in functions to pack/unpack 16 bit floating-point numbers (ARB_shading_language_pack2f).
+ packHalf2x16 and unpackHalf2x16
+ packSnorm2x16and unpackSnorm2x16
contextPragma(true, false), loopNestingLevel(0), controlFlowNestingLevel(0), structNestingLevel(0),
tokensBeforeEOF(false), limits(resources.limits), currentScanner(0),
numErrors(0), parsingBuiltins(pb), afterEOF(false),
- anyIndexLimits(false)
+ atomicUintOffsets(0), anyIndexLimits(false)
{
// ensure we always have a linkage node, even if empty, to simplify tree topology algorithms
linkage = new TIntermAggregate;
globalBufferDefaults.layoutPacking = ElpShared;
globalInputDefaults.clear();
-
globalOutputDefaults.clear();
// "Shaders in the transform
globalOutputDefaults.layoutStream = 0;
}
+TParseContext::~TParseContext()
+{
+ delete [] atomicUintOffsets;
+}
+
void TParseContext::setLimits(const TBuiltInResource& r)
{
resources = r;
! limits.generalVaryingIndexing;
intermediate.setLimits(resources);
+
+ // "Each binding point tracks its own current default offset for
+ // inheritance of subsequent variables using the same binding. The initial state of compilation is that all
+ // binding points have an offset of 0."
+ atomicUintOffsets = new int[resources.maxAtomicCounterBindings];
+ for (int b = 0; b < resources.maxAtomicCounterBindings; ++b)
+ atomicUintOffsets[b] = 0;
}
//
// "The offset qualifier can only be used on block members of blocks..."
if (qualifier.hasOffset() && type.getBasicType() != EbtAtomicUint)
error(loc, "cannot specify on a variable declaration", "offset", "");
- if (qualifier.hasOffset() && ! qualifier.hasBinding() && type.getBasicType() == EbtAtomicUint)
- error(loc, "a binding is required", "offset", "");
- if (qualifier.hasBinding() && (int)qualifier.layoutBinding >= resources.maxAtomicCounterBindings && type.getBasicType() == EbtAtomicUint)
- error(loc, "cannot be greater-than-or-equal to gl_MaxAtomicCounterBindings", "binding", "");
// "The align qualifier can only be used on blocks or block members..."
if (qualifier.hasAlign())
error(loc, "cannot specify on a variable declaration", "align", "");
if (lastBinding >= resources.maxCombinedTextureImageUnits)
error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
}
+ if (type.getBasicType() == EbtAtomicUint) {
+ if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
+ error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
+ return;
+ }
+ }
+ }
+
+ // atomic_uint
+ if (type.getBasicType() == EbtAtomicUint) {
+ if (! type.getQualifier().hasBinding())
+ error(loc, "layout(binding=X) is required", "atomic_uint", "");
}
// "The offset qualifier can only be used on block members of blocks..."
}
}
+// Correct and/or advance an object's offset layout qualifier.
+void TParseContext::fixOffset(TSourceLoc loc, TSymbol& symbol)
+{
+ const TQualifier& qualifier = symbol.getType().getQualifier();
+ if (symbol.getType().getBasicType() == EbtAtomicUint) {
+ if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) {
+
+ // Set the offset
+ int offset;
+ if (qualifier.hasOffset())
+ offset = qualifier.layoutOffset;
+ else
+ offset = atomicUintOffsets[qualifier.layoutBinding];
+ symbol.getWritableType().getQualifier().layoutOffset = offset;
+
+ // Check for overlap
+ int numOffsets = 4;
+ if (symbol.getType().isArray())
+ numOffsets *= symbol.getType().getArraySize();
+ int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
+ if (repeated >= 0)
+ error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated);
+
+ // Bump the default offset
+ atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets;
+ }
+ }
+}
+
//
// Look up a function name in the symbol table, and make sure it is a function.
//
return findFunction120(loc, call, builtIn);
}
+// When a declaration includes a type, but not a variable name, it can be
+// to establish defaults.
+void TParseContext::declareTypeDefaults(TSourceLoc loc, const TPublicType& publicType)
+{
+ if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && publicType.qualifier.hasOffset()) {
+ if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
+ error(loc, "atomic_uint binding is too large", "binding", "");
+ return;
+ }
+ atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
+ return;
+ }
+
+ if (publicType.qualifier.hasLayout())
+ warn(loc, "useless application of layout qualifier", "layout", "");
+}
+
//
// Do everything necessary to handle a variable (non-block) declaration.
// Either redeclaring a variable, or making a new one, updating the symbol
initNode = executeInitializer(loc, identifier, initializer, variable);
}
- // look for errors/adjustments in layout qualifier use
+ // look for errors in layout qualifier use
layoutObjectCheck(loc, *symbol);
+ fixOffset(loc, *symbol);
// see if it's a linker-level object to track
if (newDeclaration && symbolTable.atGlobalLevel())
public:
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, EShLanguage, TInfoSink&,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
+ virtual ~TParseContext();
void setLimits(const TBuiltInResource&);
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false);
void layoutTypeCheck(TSourceLoc, const TType&);
void layoutQualifierCheck(TSourceLoc, const TQualifier&);
void checkNoShaderLayouts(TSourceLoc, const TShaderQualifiers&);
+ void fixOffset(TSourceLoc, TSymbol&);
const TFunction* findFunction(TSourceLoc loc, const TFunction& call, bool& builtIn);
const TFunction* findFunctionExact(TSourceLoc loc, const TFunction& call, bool& builtIn);
const TFunction* findFunction120(TSourceLoc loc, const TFunction& call, bool& builtIn);
const TFunction* findFunction400(TSourceLoc loc, const TFunction& call, bool& builtIn);
+ void declareTypeDefaults(TSourceLoc, const TPublicType&);
TIntermNode* declareVariable(TSourceLoc, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator);
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TQualifier globalUniformDefaults;
TQualifier globalInputDefaults;
TQualifier globalOutputDefaults;
+ int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
TString currentCaller;
TIdSetType inductiveLoopIds;
bool anyIndexLimits;
: fully_specified_type {\r
$$.type = $1;\r
$$.intermNode = 0;\r
- if ($$.type.qualifier.hasLayout())\r
- parseContext.warn($1.loc, "useless application of layout qualifier", "layout", "");\r
+ parseContext.declareTypeDefaults($$.loc, $$.type);\r
}\r
| fully_specified_type IDENTIFIER {\r
$$.type = $1;\r
symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation ||\r
symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent ||\r
symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex ||\r
- symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding) {\r
+ symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding ||\r
+ (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) {\r
error(infoSink, "Layout qualification must match:");\r
writeTypeComparison = true;\r
}\r
return -1; // no collision\r
}\r
\r
+// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions\r
+// as the accumulation is done.\r
+//\r
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.\r
+//\r
+int TIntermediate::addUsedOffsets(int binding, int offset, int numOffsets)\r
+{\r
+ TRange bindingRange(binding, binding);\r
+ TRange offsetRange(offset, offset + numOffsets - 1);\r
+ TOffsetRange range(bindingRange, offsetRange);\r
+\r
+ // check for collisions, except for vertex inputs on desktop\r
+ for (size_t r = 0; r < usedAtomics.size(); ++r) {\r
+ if (range.overlap(usedAtomics[r])) {\r
+ // there is a collision; pick one\r
+ return std::max(offset, usedAtomics[r].offset.start);\r
+ }\r
+ }\r
+\r
+ usedAtomics.push_back(range);\r
+\r
+ return -1; // no collision\r
+}\r
+\r
// Recursively figure out how many locations are used up by an input or output type.\r
// Return the size of type, as measured by "locations".\r
int TIntermediate::computeTypeLocationSize(const TType& type) const\r
int index;
};
+// An IO range is a 2-D rectangle; the set of (binding, offset) pairs all lying
+// within the same binding and offset range.
+struct TOffsetRange {
+ TOffsetRange(TRange binding, TRange offset)
+ : binding(binding), offset(offset) { }
+ bool overlap(const TOffsetRange& rhs) const
+ {
+ return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
+ }
+ TRange binding;
+ TRange offset;
+};
+
// Things that need to be tracked per xfb buffer.
struct TXfbBuffer {
TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { }
bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
+ int addUsedOffsets(int binding, int offset, int numOffsets);
int computeTypeLocationSize(const TType&) const;
bool setXfbBufferStride(int buffer, int stride)
typedef std::list<TCall> TGraph;
TGraph callGraph;
- std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
- std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform and buffers
- std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
+ std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
+ std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
+ std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
+ std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
private:
void operator=(TIntermediate&); // prevent assignments