From 04b1c6ed4c1918d691c4a9477bfb7c1e117d16de Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 28 Jan 2014 21:13:59 +0000 Subject: [PATCH] GL_ARB_enhanced_layouts, part 5: uniform offset and align semantics. Numerical computations not yet done. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@25092 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/300.frag | 2 + Test/300layout.vert | 2 +- Test/440.frag | 69 +++++++++++++++++++++ Test/baseResults/300.frag.out | 7 ++- Test/baseResults/300layout.vert.out | 4 +- Test/baseResults/440.frag.out | 58 +++++++++++++++++- Test/baseResults/specExamples.vert.out | 3 +- glslang/Include/Common.h | 9 ++- glslang/Include/Types.h | 32 +++++++--- glslang/Include/revision.h | 4 +- glslang/MachineIndependent/ParseHelper.cpp | 98 ++++++++++++++++++++++-------- glslang/MachineIndependent/ParseHelper.h | 1 + 12 files changed, 243 insertions(+), 46 deletions(-) diff --git a/Test/300.frag b/Test/300.frag index dea0c4e..8b67b98 100644 --- a/Test/300.frag +++ b/Test/300.frag @@ -145,5 +145,7 @@ void foo324(void) mat3x2 m32 = outerProduct(vec2(2,3), vec3(5,7,11));// rows: (10, 14, 22), (15, 21, 33) } +uniform mediump; // ERROR + float imageBuffer; // ERROR, reserved float uimage2DRect; // ERROR, reserved diff --git a/Test/300layout.vert b/Test/300layout.vert index b5e1dbe..06d1206 100644 --- a/Test/300layout.vert +++ b/Test/300layout.vert @@ -51,7 +51,7 @@ shared vec4 compute_only; // ERROR layout(packed) uniform; -layout(packed) float aoeuntaoeu; // ERROR, packed on variable +layout(packed) uniform float aoeuntaoeu; // ERROR, packed on variable layout(location = 40) in float cd; layout(location = 37) in mat4x3 ce; // ERROR, overlap diff --git a/Test/440.frag b/Test/440.frag index 23c43b4..22d46f5 100644 --- a/Test/440.frag +++ b/Test/440.frag @@ -20,3 +20,72 @@ layout(location = 20, component = 3) in float f[6]; layout(location = 30, component = 3) out int be; layout(location = 30, component = 0) out vec3 bf; // ERROR, not the same basic type + +writeonly uniform; // ERROR +readonly in; // ERROR +flat out; // ERROR +mediump uniform; + +layout(offset=12) uniform; // ERROR +layout(offset=12) in; // ERROR +layout(offset=12) out; // ERROR + +layout(align=16) uniform; // ERROR +layout(align=16) in; // ERROR +layout(align=16) out; // ERROR + +layout(offset=12) uniform ubl1 { int a; } inst1; // ERROR +layout(offset=12) in inbl2 { int a; } inst2; // ERROR +layout(offset=12) out inbl3 { int a; } inst3; // ERROR + +layout(align=16, std140) uniform ubl4 { int a; } inst4; +layout(align=16) uniform ubl8 { int a; } inst8; // ERROR, no packing +layout(align=16) in inbl5 { int a; } inst5; // ERROR +layout(align=16) out inbl6 { int a; } inst6; // ERROR + +layout(offset=12) uniform vec4 v1; // ERROR +layout(offset=12) in vec4 v2; // ERROR +layout(offset=12) out vec4 v3; // ERROR + +layout(align=16) uniform vec4 v4; // ERROR +layout(align=16) in vec4 v5; // ERROR +layout(align=16) out vec4 v6; // ERROR + +layout(std140) in; // ERROR +layout(std140) uniform vec4 v7; // ERROR + +layout(align=48) uniform ubl7 { // ERROR, not power of 2 + layout(offset=12, align=4) float f; // ERROR, no packing +} inst7; + +in ibl10 { + layout(offset=12) float f; // ERROR + layout(align=4) float g; // ERROR +} inst10; + +layout(std430) uniform; + +layout(align=32) uniform ubl9 { + float e; + layout(offset=12, align=4) float f; + layout(offset=20) float g; + float h; +} inst9; + +uniform ubl11 { + layout(offset=12, align=4) float f; + float g; +} inst11; + +layout(std140) uniform block { + vec4 a; // a takes offsets 0-15 + layout(offset = 20) vec3 b; // b takes offsets 32-43 + layout(offset = 40) vec2 c; // ERROR, lies within previous member + layout(offset = 48) vec2 d; // d takes offsets 48-55 + layout(align = 16) float e; // e takes offsets 64-67 + layout(align = 2) double f; // f takes offsets 72-79 + layout(align = 6) double g; // ERROR, 6 is not a power of 2 + layout(offset = 80) float h; // h takes offsets 80-83 + layout(align = 64) dvec3 i; // i takes offsets 128-151 + layout(offset = 153, align = 8) float j; // j takes offsets 160-163 +} specExample; diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out index f1f80a8..f9124a0 100644 --- a/Test/baseResults/300.frag.out +++ b/Test/baseResults/300.frag.out @@ -33,9 +33,10 @@ ERROR: 0:122: '=' : can't use with samplers or structs containing samplers ERROR: 0:123: '==' : can't use with samplers or structs containing samplers ERROR: 0:129: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset] ERROR: 0:129: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset] -ERROR: 0:148: 'imageBuffer' : Reserved word. -ERROR: 0:148: '' : syntax error -ERROR: 36 compilation errors. No code generated. +ERROR: 0:148: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) +ERROR: 0:150: 'imageBuffer' : Reserved word. +ERROR: 0:150: '' : syntax error +ERROR: 37 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out index 4ce58fa..0ce4b3c 100644 --- a/Test/baseResults/300layout.vert.out +++ b/Test/baseResults/300layout.vert.out @@ -15,7 +15,7 @@ ERROR: 0:38: 'output block' : not supported with this profile: es ERROR: 0:42: 'location qualifier on output' : not supported in this stage: vertex ERROR: 0:50: 'shared' : not supported with this profile: es ERROR: 0:50: 'shared' : not supported in this stage: vertex -ERROR: 0:54: 'layout' : qualifiers for matrix layout and block packing only apply to uniform or buffer blocks +ERROR: 0:54: 'layout' : cannot specify packing on a variable declaration ERROR: 0:57: 'location' : overlapping use of location 40 ERROR: 18 compilation errors. No code generated. @@ -73,7 +73,7 @@ ERROR: node is still EOpNull! 0:? '__anon__2' (out block{out highp float f}) 0:? 'badoutA' (layout(location=10 ) smooth out highp 4-component vector of float) 0:? 'compute_only' (shared highp 4-component vector of float) -0:? 'aoeuntaoeu' (layout(packed ) highp float) +0:? 'aoeuntaoeu' (layout(packed ) uniform highp float) 0:? 'cd' (layout(location=40 ) in highp float) 0:? 'ce' (layout(location=37 ) in highp 4X3 matrix of float) 0:? 'gl_VertexID' (gl_VertexId highp int) diff --git a/Test/baseResults/440.frag.out b/Test/baseResults/440.frag.out index 771715f..b81870c 100644 --- a/Test/baseResults/440.frag.out +++ b/Test/baseResults/440.frag.out @@ -3,7 +3,44 @@ Warning, version 440 is not yet complete; some version-specific features are pre ERROR: 0:11: 'location' : overlapping use of location 4 ERROR: 0:13: 'component' : type overflows the available 4 components ERROR: 0:22: 'location' : fragment outputs sharing the same location must be the same basic type 30 -ERROR: 3 compilation errors. No code generated. +ERROR: 0:24: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) +ERROR: 0:25: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) +ERROR: 0:26: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) +ERROR: 0:29: 'layout qualifier' : cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type) +ERROR: 0:30: 'layout qualifier' : cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type) +ERROR: 0:30: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:31: 'layout qualifier' : cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type) +ERROR: 0:31: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:33: 'layout qualifier' : cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type) +ERROR: 0:34: 'layout qualifier' : cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type) +ERROR: 0:34: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:35: 'layout qualifier' : cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type) +ERROR: 0:35: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:37: 'offset' : only applies to block members, not blocks +ERROR: 0:38: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:38: 'offset' : only applies to block members, not blocks +ERROR: 0:39: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:39: 'offset' : only applies to block members, not blocks +ERROR: 0:42: 'offset/align' : can only be used with std140 or std430 layout packing +ERROR: 0:43: 'offset/align' : can only be used with std140 or std430 layout packing +ERROR: 0:43: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:44: 'offset/align' : can only be used with std140 or std430 layout packing +ERROR: 0:44: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:46: 'offset' : cannot specify on a variable declaration +ERROR: 0:47: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:48: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:50: 'align' : cannot specify on a variable declaration +ERROR: 0:51: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:52: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:54: 'layout' : matrix or packing qualifiers can only be used on a uniform or buffer +ERROR: 0:55: 'layout' : cannot specify packing on a variable declaration +ERROR: 0:57: 'align' : must be a power of 2 +ERROR: 0:58: 'align' : can only be used with std140 or std430 layout packing +ERROR: 0:63: 'align' : can only be used with std140 or std430 layout packing +ERROR: 0:62: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:63: 'layout' : offset/align can only be used on a uniform or buffer +ERROR: 0:87: 'align' : must be a power of 2 +ERROR: 40 compilation errors. No code generated. ERROR: node is still EOpNull! @@ -16,6 +53,25 @@ ERROR: node is still EOpNull! 0:? 'f' (layout(location=20 component=3 ) smooth in 6-element array of float) 0:? 'be' (layout(location=30 component=3 ) out int) 0:? 'bf' (layout(location=30 component=0 ) out 3-component vector of float) +0:? 'inst1' (layout(column_major shared offset=12 ) uniform block{layout(column_major shared ) uniform int a}) +0:? 'inst2' (layout(offset=12 ) in block{in int a}) +0:? 'inst3' (layout(offset=12 ) out block{out int a}) +0:? 'inst4' (layout(column_major std140 align=16 ) uniform block{layout(column_major std140 align=16 ) uniform int a}) +0:? 'inst8' (layout(column_major shared align=16 ) uniform block{layout(column_major shared ) uniform int a}) +0:? 'inst5' (layout(align=16 ) in block{in int a}) +0:? 'inst6' (layout(align=16 ) out block{out int a}) +0:? 'v1' (layout(offset=12 ) uniform 4-component vector of float) +0:? 'v2' (layout(offset=12 ) smooth in 4-component vector of float) +0:? 'v3' (layout(offset=12 ) out 4-component vector of float) +0:? 'v4' (layout(align=16 ) uniform 4-component vector of float) +0:? 'v5' (layout(align=16 ) smooth in 4-component vector of float) +0:? 'v6' (layout(align=16 ) out 4-component vector of float) +0:? 'v7' (layout(std140 ) uniform 4-component vector of float) +0:? 'inst7' (layout(column_major shared ) uniform block{layout(column_major shared offset=12 align=4 ) uniform float f}) +0:? 'inst10' (in block{layout(offset=12 ) in float f, layout(align=4 ) in float g}) +0:? 'inst9' (layout(column_major std430 align=32 ) uniform block{layout(column_major std430 align=32 ) uniform float e, layout(column_major std430 offset=12 align=4 ) uniform float f, layout(column_major std430 offset=20 align=32 ) uniform float g, layout(column_major std430 align=32 ) uniform float h}) +0:? 'inst11' (layout(column_major std430 ) uniform block{layout(column_major std430 offset=12 align=4 ) uniform float f, layout(column_major std430 ) uniform float g}) +0:? 'specExample' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float a, layout(column_major std140 offset=20 ) uniform 3-component vector of float b, layout(column_major std140 offset=40 ) uniform 2-component vector of float c, layout(column_major std140 offset=48 ) uniform 2-component vector of float d, layout(column_major std140 align=16 ) uniform float e, layout(column_major std140 align=2 ) uniform double f, layout(column_major std140 ) uniform double g, layout(column_major std140 offset=80 ) uniform float h, layout(column_major std140 align=64 ) uniform 3-component vector of double i, layout(column_major std140 offset=153 align=8 ) uniform float j}) Linked fragment stage: diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out index c9ce162..b69695a 100644 --- a/Test/baseResults/specExamples.vert.out +++ b/Test/baseResults/specExamples.vert.out @@ -19,6 +19,7 @@ ERROR: 0:55: 'stream' : there is no such layout identifier for this stage taking ERROR: 0:80: 's17' : redefinition ERROR: 0:85: 'uniform buffer-member offset' : not supported for this version or the enabled extensions ERROR: 0:85: 'binding' : requires block, or sampler/image, or atomic-counter type +ERROR: 0:85: 'offset' : cannot specify on a variable declaration ERROR: 0:87: 'binding' : requires block, or sampler/image, or atomic-counter type ERROR: 0:89: 'uniform buffer-member offset' : not supported for this version or the enabled extensions WARNING: 0:89: 'layout' : useless application of layout qualifier @@ -42,7 +43,7 @@ ERROR: 0:153: '' : function does not return a value: func3 ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array ERROR: 0:194: 'constructor' : constructing from a non-dereferenced array -ERROR: 41 compilation errors. No code generated. +ERROR: 42 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/glslang/Include/Common.h b/glslang/Include/Common.h index e4c14ff..305b534 100644 --- a/glslang/Include/Common.h +++ b/glslang/Include/Common.h @@ -186,17 +186,22 @@ typedef TMap::tAllocator TPragmaTableAllocator; const int GlslangMaxTokenLength = 1024; +template bool IsPow2(T powerOf2) +{ + return (powerOf2 & (powerOf2 - 1)) == 0; +} + // Round number up to a multiple of the given powerOf2, which is not // a power, just a number that must be a power of 2. template void RoundToPow2(T& number, int powerOf2) { - assert((powerOf2 & (powerOf2 - 1)) == 0); + assert(IsPow2(powerOf2)); number = (number + powerOf2 - 1) & ~(powerOf2 - 1); } template bool IsMultipleOfPow2(T number, int powerOf2) { - assert((powerOf2 & (powerOf2 - 1)) == 0); + assert(IsPow2(powerOf2)); return ! (number & (powerOf2 - 1)); } diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 08ffd99..a7435d0 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -401,10 +401,26 @@ public: bool hasUniformLayout() const { - return layoutMatrix != ElmNone || - layoutPacking != ElpNone || - layoutOffset != -1 || - layoutAlign != -1; + return hasMatrix() || + hasPacking() || + hasOffset() || + hasAlign(); + } + bool hasMatrix() const + { + return layoutMatrix != ElmNone; + } + bool hasPacking() const + { + return layoutPacking != ElpNone; + } + bool hasOffset() const + { + return layoutOffset != -1; + } + bool hasAlign() const + { + return layoutAlign != -1; } bool hasLocation() const { @@ -904,13 +920,13 @@ public: p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding); if (qualifier.hasStream()) p += snprintf(p, end - p, "stream=%d ", qualifier.layoutStream); - if (qualifier.layoutMatrix != ElmNone) + if (qualifier.hasMatrix()) p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); - if (qualifier.layoutPacking != ElpNone) + if (qualifier.hasPacking()) p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking)); - if (qualifier.layoutOffset != -1) + if (qualifier.hasOffset()) p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset); - if (qualifier.layoutAlign != -1) + if (qualifier.hasAlign()) p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign); if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 2b295b5..1a2b8fe 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -9,5 +9,5 @@ // source have to figure out how to create revision.h just to get a build // going. However, if it is not updated, it can be a version behind. -#define GLSLANG_REVISION "25018" -#define GLSLANG_DATE "2014/01/26 00:56:43" +#define GLSLANG_REVISION "25043" +#define GLSLANG_DATE "2014/01/27 13:02:12" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 911da93..34699c5 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2852,7 +2852,11 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, const char* feature = "uniform buffer-member align"; requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature); - publicType.qualifier.layoutAlign = value; + // "The specified alignment must be a power of 2, or a compile-time error results." + if (! IsPow2(value)) + error(loc, "must be a power of 2", "align", ""); + else + publicType.qualifier.layoutAlign = value; return; } else if (id == "location") { requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "location"); @@ -2965,9 +2969,9 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, // Merge any layout qualifier information from src into dst, leaving everything else in dst alone void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst, const TQualifier& src, bool inheritOnly) { - if (src.layoutMatrix != ElmNone) + if (src.hasMatrix()) dst.layoutMatrix = src.layoutMatrix; - if (src.layoutPacking != ElpNone) + if (src.hasPacking()) dst.layoutPacking = src.layoutPacking; if (src.hasStream()) @@ -2976,16 +2980,17 @@ void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst, if (src.hasXfbBuffer()) dst.layoutXfbBuffer = src.layoutXfbBuffer; + if (src.hasAlign()) + dst.layoutAlign = src.layoutAlign; + if (! inheritOnly) { if (src.layoutLocation != TQualifier::layoutLocationEnd) dst.layoutLocation = src.layoutLocation; if (src.layoutComponent != TQualifier::layoutComponentEnd) dst.layoutComponent = src.layoutComponent; - if (src.layoutOffset != -1) + if (src.hasOffset()) dst.layoutOffset = src.layoutOffset; - if (src.layoutAlign != -1) - dst.layoutAlign = src.layoutAlign; if (src.layoutBinding != TQualifier::layoutBindingEnd) dst.layoutBinding = src.layoutBinding; @@ -3021,24 +3026,26 @@ void TParseContext::layoutObjectCheck(TSourceLoc loc, const TSymbol& symbol) } // Check packing and matrix - // TODO: 4.4 enhanced layouts: generalize to include offset/align - if (qualifier.layoutMatrix || qualifier.layoutPacking) { + if (qualifier.hasUniformLayout()) { switch (qualifier.storage) { case EvqBuffer: case EvqUniform: if (type.getBasicType() != EbtBlock) { - if (qualifier.layoutMatrix != ElmNone) + if (qualifier.hasMatrix()) error(loc, "cannot specify matrix layout on a variable declaration", "layout", ""); - if (qualifier.layoutPacking != ElpNone) + if (qualifier.hasPacking()) error(loc, "cannot specify packing on a variable declaration", "layout", ""); + // "The offset qualifier can only be used on block members of blocks..." + if (qualifier.hasOffset()) + error(loc, "cannot specify on a variable declaration", "offset", ""); + // "The align qualifier can only be used on blocks or block members..." + if (qualifier.hasAlign()) + error(loc, "cannot specify on a variable declaration", "align", ""); } break; default: - if (type.getBasicType() != EbtBlock && symbol.getAsVariable()) { - if (qualifier.layoutMatrix != ElmNone || - qualifier.layoutPacking != ElpNone) - error(loc, "qualifiers for matrix layout and block packing only apply to uniform or buffer blocks", "layout", ""); - } + // these were already filtered by layoutTypeCheck() (or its callees) + break; } } } @@ -3127,6 +3134,12 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type) error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); } } + + // "The offset qualifier can only be used on block members of blocks..." + if (qualifier.hasOffset()) { + if (type.getBasicType() == EbtBlock) + error(loc, "only applies to block members, not blocks", "offset", ""); + } } // Do layout error checking that can be done within a qualifier proper, not needing to know @@ -3185,7 +3198,6 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali if (qualifier.storage != EvqUniform && qualifier.storage != EvqBuffer) error(loc, "requires uniform or buffer storage qualifier", "binding", ""); } - if (qualifier.hasStream()) { if (qualifier.storage != EvqVaryingOut) error(loc, "can only be used on an output", "stream", ""); @@ -3194,6 +3206,14 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali if (qualifier.storage != EvqVaryingOut) error(loc, "can only be used on an output", "xfb layout qualifier", ""); } + if (qualifier.hasUniformLayout()) { + if (! (qualifier.storage == EvqUniform || qualifier.storage == EvqBuffer)) { + if (qualifier.hasMatrix() || qualifier.hasPacking()) + error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); + if (qualifier.hasOffset() || qualifier.hasAlign()) + error(loc, "offset/align can only be used on a uniform or buffer", "layout", ""); + } + } } // For places that can't have shader-level layout qualifiers @@ -3871,8 +3891,18 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr } // fix and check for member layout qualifiers - // TODO: 4.4 enhanced layouts: generalize to include offset/align + mergeObjectLayoutQualifiers(loc, defaultQualification, currentBlockQualifier, true); + + // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts." + // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." + if (currentBlockQualifier.hasAlign() || currentBlockQualifier.hasAlign()) { + if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) { + error(loc, "can only be used with std140 or std430 layout packing", "offset/align", ""); + defaultQualification.layoutAlign = -1; + } + } + bool memberWithLocation = false; bool memberWithoutLocation = false; for (unsigned int member = 0; member < typeList.size(); ++member) { @@ -3892,7 +3922,7 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); } - if (memberQualifier.layoutPacking != ElpNone) + if (memberQualifier.hasPacking()) error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), ""); if (memberQualifier.hasLocation()) { const char* feature = "location on block member"; @@ -3909,6 +3939,11 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr } } else memberWithoutLocation = true; + if (memberQualifier.hasAlign()) { + if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) + error(memberLoc, "can only be used with std140 or std430 layout packing", "align", ""); + } + TQualifier newMemberQualification = defaultQualification; mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false); memberQualifier = newMemberQualification; @@ -3917,6 +3952,7 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr // Process the members fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); fixBlockXfbOffsets(loc, currentBlockQualifier, typeList); + fixBlockUniformOffsets(loc, currentBlockQualifier, typeList); for (unsigned int member = 0; member < typeList.size(); ++member) layoutTypeCheck(typeList[member].loc, *typeList[member].type); @@ -4037,10 +4073,10 @@ void TParseContext::fixBlockXfbOffsets(TSourceLoc loc, TQualifier& qualifier, TT // members of that block not qualified with an xfb_offsetwill not be assigned transform feedback buffer // offsets." - if (! currentBlockQualifier.hasXfbBuffer() || ! currentBlockQualifier.hasXfbOffset()) + if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) return; - int nextOffset = currentBlockQualifier.layoutXfbOffset; + int nextOffset = qualifier.layoutXfbOffset; for (unsigned int member = 0; member < typeList.size(); ++member) { TQualifier& memberQualifier = typeList[member].type->getQualifier(); bool containsDouble = false; @@ -4061,6 +4097,12 @@ void TParseContext::fixBlockXfbOffsets(TSourceLoc loc, TQualifier& qualifier, TT qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; } +void TParseContext::fixBlockUniformOffsets(TSourceLoc loc, TQualifier& qualifier, TTypeList& typeList) +{ + if (qualifier.storage != EvqUniform || qualifier.storage != EvqBuffer) + return; +} + // For an identifier that is already declared, add more qualification to it. void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, const TString& identifier) { @@ -4203,22 +4245,26 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub qualifier.isMemory() || qualifier.isInterpolation() || qualifier.precision != EpqNone) - error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "", ""); + error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", ""); + // "The offset qualifier can only be used on block members of blocks..." + // "The align qualifier can only be used on blocks or block members..." + if (qualifier.hasOffset() || + qualifier.hasAlign()) + error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", ""); layoutQualifierCheck(loc, qualifier); - // TODO: 4.4 enhanced layouts: generalize to include all new ones switch (qualifier.storage) { case EvqUniform: - if (qualifier.layoutMatrix != ElmNone) + if (qualifier.hasMatrix()) globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.layoutPacking != ElpNone) + if (qualifier.hasPacking()) globalUniformDefaults.layoutPacking = qualifier.layoutPacking; break; case EvqBuffer: - if (qualifier.layoutMatrix != ElmNone) + if (qualifier.hasMatrix()) globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.layoutPacking != ElpNone) + if (qualifier.hasPacking()) globalBufferDefaults.layoutPacking = qualifier.layoutPacking; break; case EvqVaryingIn: diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 813f323..cf8abd4 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -166,6 +166,7 @@ public: void declareBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); void fixBlockLocations(TSourceLoc, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); void fixBlockXfbOffsets(TSourceLoc, TQualifier&, TTypeList&); + void fixBlockUniformOffsets(TSourceLoc, TQualifier&, TTypeList&); void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier); void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&); void invariantCheck(TSourceLoc, const TType&, const TString& identifier); -- 2.7.4