GL_ARB_enhanced_layouts, part 3: Semantics for xfb_*: where they can go, inheritance...
authorJohn Kessenich <cepheus@frii.com>
Tue, 21 Jan 2014 04:43:23 +0000 (04:43 +0000)
committerJohn Kessenich <cepheus@frii.com>
Tue, 21 Jan 2014 04:43:23 +0000 (04:43 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24916 e7fa87d3-cd2b-0410-9028-fcbf551c1848

Test/440.vert
Test/baseResults/440.vert.out
glslang/Include/Types.h
glslang/Include/revision.h
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/intermOut.cpp
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/localintermediate.h

index 3aeebaa..d02e7d3 100644 (file)
@@ -62,3 +62,37 @@ layout(location = 1, component = 1) out;                 // ERROR, no global set
 \r
 layout(location = 50, component = 3) out int be;\r
 layout(location = 50, component = 0) out vec3 bf;\r
+\r
+out bblck1 {\r
+    vec4 bbv;\r
+} bbinst1;\r
+\r
+out bblck2 {\r
+    layout(xfb_offset=16) vec4 bbv;\r
+} bbinst2;\r
+\r
+layout(xfb_buffer = 3, xfb_stride = 16) out;\r
+\r
+out bblck3 {\r
+    layout(xfb_offset=16) vec4 bbv;\r
+} bbinst3;\r
+\r
+uniform ubblck3 {\r
+    layout(xfb_offset=16) vec4 bbv;  // ERROR\r
+} ubbinst3;\r
+\r
+layout(xfb_buffer=2, xfb_offset=32, xfb_stride=64) out vec4 bg;\r
+layout(              xfb_offset=32, xfb_stride=64) out vec4 bh;\r
+\r
+layout(xfb_offset=48) out; // ERROR\r
+\r
+layout(xfb_stride=32, xfb_buffer=2, xfb_offset=16) out bblck4 {\r
+    vec4 bbv1;\r
+    vec4 bbv2;\r
+} bbinst4;\r
+\r
+out bblck5 {\r
+    layout(xfb_offset=0) vec4 bbv1;\r
+    layout(xfb_stride=32, xfb_buffer=3, xfb_offset=16) vec4 bbv2;\r
+    layout(xfb_buffer=2) vec4 bbv3;                               // ERROR, wrong buffer\r
+} bbinst5;\r
index ed94e05..6eef4ab 100644 (file)
@@ -19,9 +19,13 @@ ERROR: 0:55: 'component' : type overflows the available 4 components
 ERROR: 0:57: 'component' : cannot apply to a matrix, structure, or block \r
 ERROR: 0:58: 'component' : cannot apply to a matrix, structure, or block \r
 ERROR: 0:61: 'location' : cannot declare a default, use a full declaration \r
-ERROR: 19 compilation errors.  No code generated.\r
+ERROR: 0:81: 'xfb layout qualifier' : can only be used on an output \r
+ERROR: 0:87: 'xfb_offset' : cannot declare a default, use a full declaration \r
+ERROR: 0:97: 'xfb_buffer' : member cannot contradict block (or what block inherited from global) \r
+ERROR: 22 compilation errors.  No code generated.\r
 \r
 \r
+in xfb mode\r
 ERROR: node is still EOpNull!\r
 0:?   Linker Objects\r
 0:?     'a' (layout(location=2 component=2 ) in 2-component vector of float)\r
@@ -55,6 +59,14 @@ ERROR: node is still EOpNull!
 0:?     'bd' (out block{layout(location=40 component=2 ) out float u, layout(location=40 component=0 ) out float v, layout(location=40 component=3 ) out float w, layout(location=40 component=1 ) out 2-component vector of float x, layout(location=41 component=3 ) out 2-component vector of float y, layout(location=42 component=1 ) out 4-component vector of float z, layout(location=42 component=1 ) out 4X4 matrix of float ba, layout(location=43 component=1 ) out structure{int a} Ss})\r
 0:?     'be' (layout(location=50 component=3 ) smooth out int)\r
 0:?     'bf' (layout(location=50 component=0 ) smooth out 3-component vector of float)\r
+0:?     'bbinst1' (out block{out 4-component vector of float bbv})\r
+0:?     'bbinst2' (out block{layout(xfb_buffer=0 xfb_offset=16 ) out 4-component vector of float bbv})\r
+0:?     'bbinst3' (out block{layout(xfb_buffer=3 xfb_offset=16 ) out 4-component vector of float bbv})\r
+0:?     'ubbinst3' (layout(column_major shared ) uniform block{layout(column_major shared xfb_offset=16 ) uniform 4-component vector of float bbv})\r
+0:?     'bg' (layout(xfb_buffer=2 xfb_offset=32 xfb_stride=64 ) smooth out 4-component vector of float)\r
+0:?     'bh' (layout(xfb_buffer=3 xfb_offset=32 xfb_stride=64 ) smooth out 4-component vector of float)\r
+0:?     'bbinst4' (layout(xfb_buffer=2 xfb_offset=16 xfb_stride=32 ) out block{layout(xfb_buffer=2 xfb_offset=16 ) out 4-component vector of float bbv1, layout(xfb_buffer=2 xfb_offset=16 ) out 4-component vector of float bbv2})\r
+0:?     'bbinst5' (out block{layout(xfb_buffer=3 xfb_offset=0 ) out 4-component vector of float bbv1, layout(xfb_buffer=3 xfb_offset=16 xfb_stride=32 ) out 4-component vector of float bbv2, out 4-component vector of float bbv3})\r
 0:?     'gl_VertexID' (gl_VertexId int)\r
 0:?     'gl_InstanceID' (gl_InstanceId int)\r
 \r
@@ -63,4 +75,5 @@ Linked vertex stage:
 \r
 ERROR: Linking vertex stage: Missing entry point: Each stage requires one "void main()" entry point\r
 \r
+in xfb mode\r
 \r
index 8424126..56d70e4 100644 (file)
@@ -255,7 +255,7 @@ public:
         writeonly = false;
         clearLayout();
     }
-       TStorageQualifier   storage   : 6;
+    TStorageQualifier   storage   : 6;
     TPrecisionQualifier precision : 3;
     bool invariant : 1;
     bool centroid  : 1;
@@ -413,9 +413,21 @@ public:
     }
     bool hasXfb() const
     {
-        return layoutXfbBuffer != layoutXfbBufferEnd ||
-               layoutXfbStride != layoutXfbStrideEnd ||
-               layoutXfbOffset != layoutXfbOffsetEnd;
+        return hasXfbBuffer() ||
+               hasXfbStride() ||
+               hasXfbOffset();
+    }
+    bool hasXfbBuffer() const
+    {
+        return layoutXfbBuffer != layoutXfbBufferEnd;
+    }
+    bool hasXfbStride() const
+    {
+        return layoutXfbStride != layoutXfbStrideEnd;
+    }
+    bool hasXfbOffset() const
+    {
+        return layoutXfbOffset != layoutXfbOffsetEnd;
     }
     static const char* getLayoutPackingString(TLayoutPacking packing)
     {
@@ -662,7 +674,7 @@ public:
                             {
                                 sampler.clear();
                                 qualifier.clear();
-                                                               typeName = NewPoolTString(n.c_str());
+                                typeName = NewPoolTString(n.c_str());
                             }
     // For interface blocks
     TType(TTypeList* userDef, const TString& n, const TQualifier& q) : 
@@ -670,7 +682,7 @@ public:
                             qualifier(q), arraySizes(0), structure(userDef), fieldName(0)
                             {
                                 sampler.clear();
-                                                               typeName = NewPoolTString(n.c_str());
+                                typeName = NewPoolTString(n.c_str());
                             }
     virtual ~TType() {}
     
@@ -679,21 +691,21 @@ public:
     // the instances are sharing the same pool. 
     void shallowCopy(const TType& copyOf)
     {
-               basicType = copyOf.basicType;
+        basicType = copyOf.basicType;
         sampler = copyOf.sampler;
-               qualifier = copyOf.qualifier;
-               vectorSize = copyOf.vectorSize;
-               matrixCols = copyOf.matrixCols;
-               matrixRows = copyOf.matrixRows;
+        qualifier = copyOf.qualifier;
+        vectorSize = copyOf.vectorSize;
+        matrixCols = copyOf.matrixCols;
+        matrixRows = copyOf.matrixRows;
         arraySizes = copyOf.arraySizes;
         structure = copyOf.structure;
         structureSize = copyOf.structureSize;
-           fieldName = copyOf.fieldName;
-           typeName = copyOf.typeName;
+        fieldName = copyOf.fieldName;
+        typeName = copyOf.typeName;
     }
 
-       void deepCopy(const TType& copyOf)
-       {
+    void deepCopy(const TType& copyOf)
+    {
         shallowCopy(copyOf);
 
         if (arraySizes) {
@@ -701,31 +713,31 @@ public:
             *arraySizes = *copyOf.arraySizes;
         }
 
-               if (structure) {
-                       structure = new TTypeList;
-               TStructureMapIterator iter;
-                       for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
-                               TTypeLoc typeLoc;
-                               typeLoc.loc = (*copyOf.structure)[i].loc;
-                               typeLoc.type = new TType();
-                       typeLoc.type->deepCopy(*(*copyOf.structure)[i].type);
-                               structure->push_back(typeLoc);
-                       }
-               }
-
-               if (fieldName)
-                       fieldName = NewPoolTString(copyOf.fieldName->c_str());
-               if (typeName)
-                       typeName = NewPoolTString(copyOf.typeName->c_str());
-       }
+        if (structure) {
+            structure = new TTypeList;
+            TStructureMapIterator iter;
+            for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
+                TTypeLoc typeLoc;
+                typeLoc.loc = (*copyOf.structure)[i].loc;
+                typeLoc.type = new TType();
+                typeLoc.type->deepCopy(*(*copyOf.structure)[i].type);
+                structure->push_back(typeLoc);
+            }
+        }
+
+        if (fieldName)
+            fieldName = NewPoolTString(copyOf.fieldName->c_str());
+        if (typeName)
+            typeName = NewPoolTString(copyOf.typeName->c_str());
+    }
     
     TType* clone()
-       {
-               TType *newType = new TType();
-               newType->deepCopy(*this);
+    {
+        TType *newType = new TType();
+        newType->deepCopy(*this);
 
-               return newType;
-       }
+        return newType;
+    }
 
     // Merge type from parent, where a parentType is at the beginning of a declaration,
     // establishing some charastics for all subsequent names, while this type
@@ -768,14 +780,14 @@ public:
     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
     virtual const TString& getTypeName() const
     {
-               assert(typeName);               
-       return *typeName;
+        assert(typeName);              
+        return *typeName;
     }
 
     virtual const TString& getFieldName() const
     {
-       assert(fieldName);
-               return *fieldName;
+        assert(fieldName);
+        return *fieldName;
     }
 
     virtual TBasicType getBasicType() const { return basicType; }
@@ -789,7 +801,7 @@ public:
 
     virtual bool isScalar() const { return vectorSize == 1 && ! isStruct() && ! isArray(); }
     virtual bool isVector() const { return vectorSize > 1; }
-       virtual bool isMatrix() const { return matrixCols ? true : false; }
+    virtual bool isMatrix() const { return matrixCols ? true : false; }
     virtual bool isArray()  const { return arraySizes != 0; }
     virtual bool isStruct() const { return structure != 0; }
 
@@ -798,9 +810,9 @@ public:
     {
         if (isArray())
             return true;
-               if (! structure)
+        if (! structure)
             return false;
-               for (unsigned int i = 0; i < structure->size(); ++i) {
+        for (unsigned int i = 0; i < structure->size(); ++i) {
             if ((*structure)[i].type->containsArray())
                 return true;
         }
@@ -852,35 +864,41 @@ public:
         const int maxSize = GlslangMaxTypeLength;
         char buf[maxSize];
         char *p = &buf[0];
-           char *end = &buf[maxSize];
+        char *end = &buf[maxSize];
 
         if (qualifier.hasLayout()) {
-            p += snprintf(p, end - p, "layout(");
-            if (qualifier.hasLocation()) {
-                p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
-                if (qualifier.layoutComponent != qualifier.layoutComponentEnd)
-                    p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
+            // To reduce noise, skip this if the only layout is an xfb_buffer
+            // with no triggering xfb_offset.
+            TQualifier noXfbBuffer = qualifier;
+            noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
+            if (noXfbBuffer.hasLayout()) {
+                p += snprintf(p, end - p, "layout(");
+                if (qualifier.hasLocation()) {
+                    p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
+                    if (qualifier.layoutComponent != qualifier.layoutComponentEnd)
+                        p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
+                }
+                if (qualifier.hasBinding())
+                    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)
+                    p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
+                if (qualifier.layoutPacking != ElpNone)
+                    p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
+                if (qualifier.layoutOffset != -1)
+                    p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
+                if (qualifier.layoutAlign != -1)
+                    p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
+
+                if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset())
+                    p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
+                if (qualifier.hasXfbOffset())
+                    p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
+                if (qualifier.hasXfbStride())
+                    p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
+                p += snprintf(p, end - p, ") ");
             }
-            if (qualifier.hasBinding())
-                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)
-                p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
-            if (qualifier.layoutPacking != ElpNone)
-                p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
-            if (qualifier.layoutOffset != -1)
-                p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
-            if (qualifier.layoutAlign != -1)
-                p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
-
-            if (qualifier.layoutXfbBuffer != qualifier.layoutXfbBufferEnd)
-                p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
-            if (qualifier.layoutXfbOffset != qualifier.layoutXfbOffsetEnd)
-                p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
-            if (qualifier.layoutXfbStride != qualifier.layoutXfbStrideEnd)
-                p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
-            p += snprintf(p, end - p, ") ");
         }
 
         if (qualifier.invariant)
@@ -1063,7 +1081,7 @@ protected:
     void buildMangledName(TString&);
     int getStructSize() const;
 
-       TBasicType basicType : 8;
+    TBasicType basicType : 8;
     int vectorSize       : 4;
     int matrixCols       : 4;
     int matrixRows       : 4;
@@ -1074,8 +1092,8 @@ protected:
 
     TTypeList* structure;       // 0 unless this is a struct
     mutable int structureSize;  // a cache, updated on first access
-       TString *fieldName;         // for structure field names
-       TString *typeName;          // for structure type name
+    TString *fieldName;         // for structure field names
+    TString *typeName;          // for structure type name
 };
 
 } // end namespace glslang
index 6165430..dbaa25c 100644 (file)
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build\r
 // going.  However, if it is not updated, it can be a version behind.\r
 \r
-#define GLSLANG_REVISION "24740"\r
-#define GLSLANG_DATE     "2014/01/11 12:29:55"\r
+#define GLSLANG_REVISION "24741"\r
+#define GLSLANG_DATE     "2014/01/11 13:35:26"\r
index 632a17f..ce4c885 100644 (file)
@@ -101,11 +101,14 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb,
     globalBufferDefaults.layoutMatrix = ElmColumnMajor;
     globalBufferDefaults.layoutPacking = ElpShared;
 
-    // TODO: 4.4 enhanced layouts: defaults for xfb?
-
     globalInputDefaults.clear();
 
     globalOutputDefaults.clear();
+    if (language == EShLangVertex ||
+        language == EShLangTessControl ||
+        language == EShLangTessEvaluation ||
+        language == EShLangGeometry)
+        globalOutputDefaults.layoutXfbBuffer = 0;
     if (language == EShLangGeometry)
         globalOutputDefaults.layoutStream = 0;
 }
@@ -1791,7 +1794,7 @@ void TParseContext::globalQualifierCheck(TSourceLoc loc, const TQualifier& quali
         case EShLangCompute:
             break;
 
-           default:
+        default:
             break;
         }
     } else {
@@ -1827,7 +1830,7 @@ void TParseContext::globalQualifierCheck(TSourceLoc loc, const TQualifier& quali
         case EShLangCompute:
             break;
 
-           default:
+        default:
             break;
         }
     }
@@ -2869,6 +2872,7 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
             publicType.qualifier.layoutComponent = value;
         return;
     } else if (id.compare(0, 4, "xfb_") == 0) {
+        intermediate.setXfbMode();
         const char* feature = "transform feedback qualifier";
         requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature);
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
@@ -2878,16 +2882,19 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
                 error(loc, "buffer is too large", id.c_str(), "");
             else
                 publicType.qualifier.layoutXfbBuffer = value;
+            return;
         } else if (id == "xfb_offset") {
             if (value >= TQualifier::layoutXfbOffsetEnd)   // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackInterleavedComponents
                 error(loc, "offset is too large", id.c_str(), "");
             else
                 publicType.qualifier.layoutXfbOffset = value;
+            return;
         } else if (id == "xfb_stride") {
-            if (value >= TQualifier::layoutXfbStrideEnd)    // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackInterleavedComponents
+            if (value >= TQualifier::layoutXfbStrideEnd)    // TODO: 4.4 enhanced layouts: also check against 4*gl_MaxTransformFeedbackInterleavedComponents
                 error(loc, "stride is too large", id.c_str(), "");
             else
                 publicType.qualifier.layoutXfbStride = value;
+            return;
         }
     }
 
@@ -2929,7 +2936,7 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
     case EShLangCompute:
         break;
 
-       default:
+    default:
         break;
     }
 
@@ -2947,8 +2954,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst,
     if (src.hasStream())
         dst.layoutStream = src.layoutStream;
 
-    if (src.layoutXfbBuffer != TQualifier::layoutXfbBufferEnd)
+    if (src.hasXfbBuffer())
         dst.layoutXfbBuffer = src.layoutXfbBuffer;
+    if (src.hasXfbOffset())
+        dst.layoutXfbOffset = src.layoutXfbOffset;
 
     if (! inheritOnly) {
         if (src.layoutLocation != TQualifier::layoutLocationEnd)
@@ -2964,10 +2973,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst,
         if (src.layoutBinding != TQualifier::layoutBindingEnd)
             dst.layoutBinding = src.layoutBinding;
 
-        if (src.layoutXfbStride != TQualifier::layoutXfbStrideEnd)
+        if (src.hasXfbStride())
             dst.layoutXfbStride = src.layoutXfbStride;
-        if (src.layoutXfbOffset != TQualifier::layoutXfbOffsetEnd)
-            dst.layoutXfbOffset = src.layoutXfbOffset;
     }
 }
 
@@ -3145,6 +3152,10 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali
         if (qualifier.storage != EvqVaryingOut)
             error(loc, "can only be used on an output", "stream", "");
     }
+    if (qualifier.hasXfb()) {
+        if (qualifier.storage != EvqVaryingOut)
+            error(loc, "can only be used on an output", "xfb layout qualifier", "");
+    }
 }
 
 // For places that can't have shader-level layout qualifiers
@@ -3303,10 +3314,6 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
     invariantCheck(loc, type, identifier);
     samplerCheck(loc, type, identifier);
 
-    // Pick up defaults
-    if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut)
-        type.getQualifier().layoutStream = globalOutputDefaults.layoutStream;
-
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
 
@@ -3316,6 +3323,8 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
     if (! symbol)
         reservedErrorCheck(loc, identifier);
 
+    inheritGlobalDefaults(type.getQualifier());
+
     // Declare the variable
     if (arraySizes || type.isArray()) {
         // Arrayness is potentially coming both from the type and from the 
@@ -3369,6 +3378,17 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
     return initNode;
 }
 
+// Pick up global defaults from the provide global defaults into dst.
+void TParseContext::inheritGlobalDefaults(TQualifier& dst) const
+{
+    if (dst.storage == EvqVaryingOut) {
+        if (! dst.hasStream() && language == EShLangGeometry)
+            dst.layoutStream = globalOutputDefaults.layoutStream;
+        if (! dst.hasXfbBuffer())
+            dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+    }
+}
+
 //
 // Declare a non-array variable, the main point being there is no redeclaration
 // for resizing allowed.
@@ -3824,6 +3844,10 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
             if (defaultQualification.layoutStream != memberQualifier.layoutStream)
                 error(memberLoc, "member cannot contradict block", "stream", "");
         }
+        if (memberQualifier.hasXfbBuffer()) {
+            if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer)
+                error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
+        }
         if (memberQualifier.layoutPacking != ElpNone)
             error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), "");
         if (memberQualifier.hasLocation()) {
@@ -4124,6 +4148,8 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
     case EvqVaryingOut:
         if (qualifier.hasStream())
             globalOutputDefaults.layoutStream = qualifier.layoutStream;
+        if (qualifier.hasXfbBuffer())
+            globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer;
         break;
     default:
         error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
@@ -4134,6 +4160,8 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
         error(loc, "cannot declare a default, include a type or full declaration", "binding", "");
     if (qualifier.hasLocation())
         error(loc, "cannot declare a default, use a full declaration", "location", "");
+    if (qualifier.hasXfbOffset())
+        error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
 }
 
 //
index 7a7763e..4eeb2d3 100644 (file)
@@ -202,6 +202,7 @@ public:
 
 protected:
     void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
+       void inheritGlobalDefaults(TQualifier& dst) const;
     TVariable* declareNonArray(TSourceLoc, TString& identifier, TType&, bool& newDeclaration);
     void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
     TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable);
index 64febdb..f510353 100644 (file)
@@ -579,6 +579,9 @@ bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
 //
 void TIntermediate::output(TInfoSink& infoSink, bool tree)
 {
+    if (xfbMode)
+        infoSink.debug << "in xfb mode\n";
+
     switch (language) {
     case EShLangVertex:
         break;
index 0b9b50b..cec1729 100644 (file)
@@ -110,6 +110,9 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
     if (unit.pointMode)\r
         pointMode = true;\r
 \r
+    if (unit.xfbMode)\r
+        xfbMode = true;\r
+\r
     if (unit.treeRoot == 0)\r
         return;\r
 \r
index 2ffda5d..939950a 100644 (file)
@@ -62,7 +62,7 @@ public:
     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), 
         numMains(0), numErrors(0), recursive(false),
         invocations(0), vertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),
-        vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false) { }
+        vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), xfbMode(false) { }
     bool postProcess(TIntermNode*, EShLanguage);
     void output(TInfoSink&, bool tree);
        void removeTree();
@@ -153,6 +153,7 @@ public:
         return true;
     }
     void setPointMode() { pointMode = true; }
+    void setXfbMode() { xfbMode = true; }
     bool setOutputPrimitive(TLayoutGeometry p)
     {
         if (outputPrimitive != ElgNone)
@@ -202,6 +203,7 @@ protected:
     TVertexSpacing vertexSpacing;
     TVertexOrder vertexOrder;
     bool pointMode;
+    bool xfbMode;
 
     // for detecting recursion:  pair is <caller, callee>
     struct TCall {