Add interface blocks as a basic type and handle uniform blocks that have an instance...
authorJohn Kessenich <cepheus@frii.com>
Wed, 10 Apr 2013 02:06:46 +0000 (02:06 +0000)
committerJohn Kessenich <cepheus@frii.com>
Wed, 10 Apr 2013 02:06:46 +0000 (02:06 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21093 e7fa87d3-cd2b-0410-9028-fcbf551c1848

Test/300layout.vert
Test/specExamples.vert
glslang/Include/BaseTypes.h
glslang/Include/Types.h
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/glslang.y

index fd177ddb24bda939bdcf1d5e3cca72a0cabbb580..89fb17b6b42f8cbec2792e5bdf2a7250ce78d549 100644 (file)
@@ -1,30 +1,30 @@
 #version 300 es
 
-layout(location = 7) in vec4 c;
+layout(location = 7) in vec3 c;
 layout(LocatioN = 3) in vec4 p;
 out vec4 pos;
-out vec4 color;
+out vec3 color;
 
 layout(shared, column_major, row_major) uniform mat4 m4; // default is now shared and row_major
 
-//layout(std140) uniform Transform { // layout of this block is std140
-//    mat4 M1; // row_major
-//    layout(column_major) mat4 M2; // column major
-//    mat3 N1; // row_major
-//};
-//
+layout(std140) uniform Transform { // layout of this block is std140
+    mat4 M1; // row_major
+    layout(column_major) mat4 M2; // column major
+    mat3 N1; // row_major
+} tblock;
+
 //uniform T2 { // layout of this block is shared
 //...
 //};
 //
-//layout(column_major) uniform T3 { // shared and column_major
-//    mat4 M3; // column_major
-//    layout(row_major) mat4 m4; // row major
-//    mat3 N2; // column_major
-//};
+layout(column_major) uniform T3 { // shared and column_major
+    mat4 M3; // column_major
+    layout(row_major) mat4 m4; // row major
+    mat3 N2; // column_major
+};
 
 void main()
 {
-    pos = p * m4;
-    color = c;
+    pos = p * (m4 + tblock.M1 + tblock.M2);
+    color = c * tblock.N1;
 }
index ab51872d23693fa509e74490a6f9b6b88b95bf4d..bc406a9b4470c488e544b73b1685ca7e411c914e 100644 (file)
@@ -61,7 +61,7 @@ layout(row_major, column_major)
 \r
 layout(shared, row_major) uniform; // default is now shared and row_major\r
 \r
-layout(std140) uniform Transform { // layout of this block is std140\r
+layout(std140) uniform Transform2 { // layout of this block is std140\r
     mat4 M1;                       // row_major\r
     layout(column_major) mat4 M2;  // column major\r
     mat3 N1;                       // row_major\r
@@ -124,7 +124,7 @@ coherent buffer Block {
     vec4 member2;\r
 };\r
 \r
-buffer Block {\r
+buffer Block2 {\r
     coherent readonly vec4 member1;\r
     coherent vec4 member2;\r
 };\r
index 367ce36e7b519c09b8ce00ccb3ac084954716cdd..b3f592a0208aaaaeb1518d5279ae0629a54123d7 100644 (file)
@@ -49,6 +49,7 @@ enum TBasicType {
     EbtBool,
     EbtSampler,
     EbtStruct,
+    EbtBlock,
     EbtNumTypes
 };
 
index b13f331489ed5d6a53ea195ad0123c0514be8a9c..2785e50451b838245b025a146550cfde969bdd6f 100644 (file)
@@ -351,7 +351,7 @@ typedef std::map<TTypeList*, TTypeList*>::const_iterator TStructureMapIterator;
 class TType {
 public:
     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-    explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
+    TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
                             type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
                             structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
                             fieldName(0), mangled(0), typeName(0)
@@ -360,7 +360,7 @@ public:
                                 qualifier.clear();
                                 qualifier.storage = q;
                             }
-             TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0) :
+    TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0) :
                             type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
                             structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
                             fieldName(0), mangled(0), typeName(0)
@@ -382,15 +382,20 @@ public:
                                     typeName = NewPoolTString(p.userDef->getTypeName().c_str());
                                 }
                             }
-    explicit TType(TTypeList* userDef, const TString& n) :
+    TType(TTypeList* userDef, const TString& n, TStorageQualifier blockQualifier = EvqGlobal) :
                             type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), arraySizes(0),
                             structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0)
                             {
                                 sampler.clear();
                                 qualifier.clear();
+                                // is it an interface block?
+                                if (blockQualifier != EvqGlobal) {
+                                    qualifier.storage = blockQualifier;
+                                    type = EbtBlock;
+                                }
                                                                typeName = NewPoolTString(n.c_str());
                             }
-       explicit TType() {}
+       TType() {}
     virtual ~TType() {}
 
        TType(const TType& type) { *this = type; }
@@ -513,6 +518,9 @@ public:
     void setArrayInformationType(TType* t) { arrayInformationType = t; }
     TType* getArrayInformationType() { return arrayInformationType; }
     virtual bool isVector() const { return vectorSize > 1; }
+    const char* getBasicString() const {
+        return TType::getBasicString(type);
+    }
     static const char* getBasicString(TBasicType t) {
         switch (t) {
         case EbtVoid:              return "void";
@@ -523,6 +531,7 @@ public:
         case EbtBool:              return "bool";
         case EbtSampler:           return "sampler/image";
         case EbtStruct:            return "structure";
+        case EbtBlock:             return "block";
         default:                   return "unknown type";
         }
     }
@@ -598,10 +607,9 @@ public:
         if (type == EbtSampler)
             return sampler.getString();
         else
-            return getBasicString(type);
+            return getBasicString();
     }
 
-    const char* getBasicString() const { return TType::getBasicString(type); }
     const char* getStorageQualifierString() const { return ::getStorageQualifierString(qualifier.storage); }
     const char* getPrecisionQualifierString() const { return ::getPrecisionQualifierString(qualifier.precision); }
     TTypeList* getStruct() { return structure; }
@@ -610,7 +618,7 @@ public:
     {
         int totalSize;
 
-        if (getBasicType() == EbtStruct)
+        if (getBasicType() == EbtStruct || getBasicType() == EbtBlock)
             totalSize = getStructSize();
         else if (matrixCols)
             totalSize = matrixCols * matrixRows;
index 117fe3c39625ebfe2535ff929f656c43b05c5f04..5e6bb03f4e0c044a7906ae56e97f29caf5c31efa 100644 (file)
@@ -71,6 +71,9 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
 //
 TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
 {
+    if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
+        return 0;
+
     switch (op) {
     case EOpLessThan:
     case EOpGreaterThan:
@@ -199,6 +202,9 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
 {
     TIntermTyped* child = childNode->getAsTyped();
 
+    if (child->getType().getBasicType() == EbtBlock)
+        return 0;
+
     if (child == 0) {
         infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
         return 0;
index 363af6016525fcf28b5dfc5a713adaae4ff97192..7c0de79557d2c311221695f954eb4f59df3e6f4c 100644 (file)
@@ -717,43 +717,43 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
 }
 
 //
-// Merge characteristics of the 'right' qualifier into the 'left'.
-// If there is duplication, issue error messages.
+// Merge characteristics of the 'src' qualifier into the 'dst'.
+// If there is duplication, issue error messages, unless 'force'
+// is specified, which means to just override default settings.
 // 
 // Return true if there was an error.
 //
-bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right)
+bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force)
 {
     bool bad = false;
 
     // Storage qualification
-    if (left.qualifier.storage == EvqTemporary)
-        left.qualifier.storage = right.qualifier.storage;
-    else if (left.qualifier.storage == EvqIn  && right.qualifier.storage == EvqOut ||
-             left.qualifier.storage == EvqOut && right.qualifier.storage == EvqIn)
-        left.qualifier.storage = EvqInOut;
-    else if (left.qualifier.storage == EvqIn    && right.qualifier.storage == EvqConst ||
-             left.qualifier.storage == EvqConst && right.qualifier.storage == EvqIn)
-        left.qualifier.storage = EvqConstReadOnly;
-    else if ( left.qualifier.storage != EvqTemporary &&
-             right.qualifier.storage != EvqTemporary) {
-        error(line, "too many storage qualifiers", getStorageQualifierString(right.qualifier.storage), "");
+    if (dst.qualifier.storage == EvqTemporary || dst.qualifier.storage == EvqGlobal)
+        dst.qualifier.storage = src.qualifier.storage;
+    else if (dst.qualifier.storage == EvqIn  && src.qualifier.storage == EvqOut ||
+             dst.qualifier.storage == EvqOut && src.qualifier.storage == EvqIn)
+        dst.qualifier.storage = EvqInOut;
+    else if (dst.qualifier.storage == EvqIn    && src.qualifier.storage == EvqConst ||
+             dst.qualifier.storage == EvqConst && src.qualifier.storage == EvqIn)
+        dst.qualifier.storage = EvqConstReadOnly;
+    else if (src.qualifier.storage != EvqTemporary) {
+        error(line, "too many storage qualifiers", getStorageQualifierString(src.qualifier.storage), "");
         bad = true;
     }
 
     // Precision qualifiers
-    if (left.qualifier.precision == EpqNone)
-        left.qualifier.precision = right.qualifier.precision;
-    else if (right.qualifier.precision) {
-        error(line, "only one precision qualifier allowed", getPrecisionQualifierString(right.qualifier.precision), "");
+    if (! force && src.qualifier.precision != EpqNone && dst.qualifier.precision != EpqNone) {
+        error(line, "only one precision qualifier allowed", getPrecisionQualifierString(src.qualifier.precision), "");
         bad = true;
     }
+    if (dst.qualifier.precision == EpqNone || force && src.qualifier.precision != EpqNone)
+        dst.qualifier.precision = src.qualifier.precision;
 
     // Layout qualifiers
-    mergeLayoutQualifiers(line, left, right);
+    mergeLayoutQualifiers(line, dst, src);
 
     // other qualifiers
-    #define MERGE_SINGLETON(field) bad |= left.qualifier.field && right.qualifier.field; left.qualifier.field |= right.qualifier.field;
+    #define MERGE_SINGLETON(field) bad |= dst.qualifier.field && src.qualifier.field; dst.qualifier.field |= src.qualifier.field;
     MERGE_SINGLETON(invariant);
     MERGE_SINGLETON(centroid);
     MERGE_SINGLETON(smooth);
@@ -1461,6 +1461,72 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
     return converted;
 }
 
+//
+// Do everything needed to add an interface block.
+//
+void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes)
+{
+    // First, error checks
+
+    if (reservedErrorCheck(line, blockName)) {
+        recover();
+
+        return;
+    }
+    if (instanceName && reservedErrorCheck(line, *instanceName)) {
+        recover();
+
+        return;
+    }
+    if (qualifier.type != EbtVoid) {
+        error(line, "interface blocks cannot be declared with a type", blockName.c_str(), "");
+        recover();
+
+        return;
+    }
+    if (qualifier.qualifier.storage == EvqUniform) {
+        requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block");
+        profileRequires(line, EEsProfile, 300, 0, "uniform block");
+    } else {
+        error(line, "only uniform interface blocks are supported", blockName.c_str(), "");
+        recover();
+
+        return;
+    }
+
+    // Build and add the interface block as a new type named blockName
+
+    TType* blockType = new TType(&typeList, blockName, qualifier.qualifier.storage);
+    TVariable* userTypeDef = new TVariable(&blockName, *blockType, true);
+    if (! symbolTable.insert(*userTypeDef)) {
+        error(line, "redefinition", blockName.c_str(), "block name");
+        recover();
+
+        return;
+    }
+
+    // TODO: semantics: check for qualifiers that don't belong within a block
+    for (unsigned int member = 0; member < typeList.size(); ++member) {
+        //printf("%s: %s\n", typeList[member].type->getFieldName().c_str(), typeList[member].type->getCompleteString().c_str());
+    }
+
+    // Add the variable, as anonymous or named instanceName
+
+    // make an anonymous variable if no name was provided
+    if (! instanceName)
+        instanceName = new TString("");
+
+    TVariable* variable = new TVariable(instanceName, *blockType);
+
+    if (! symbolTable.insert(*variable)) {
+        error(line, "redefinition", variable->getName().c_str(), "");
+        delete variable;
+        recover();
+
+        return;
+    }
+}
+
 //
 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
index 13e334513d3537a9037935f09c0d9416f51ce0b5..d0d189e56e0558ec40f8ee73f0088c3844ea9d33 100644 (file)
@@ -122,7 +122,7 @@ struct TParseContext {
     bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
     bool globalQualifierFixAndErrorCheck(int line, TQualifier&, const TPublicType&);
     bool structQualifierErrorCheck(int line, const TPublicType& pType);
-    bool mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right);
+    bool mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force);
     void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);
     bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
     bool containsSampler(const TType& type);
@@ -140,10 +140,12 @@ struct TParseContext {
     TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
     TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
+    void addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
     TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
     TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
     TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
     TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+
     bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
     void requireProfile(int line, EProfileMask profileMask, const char *featureDesc);
     void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc);
index 6c84725ff882b29f7886d46f6a4917187864a50a..25da7d74e05111b1e2f06b9e1e56718b3b4fd929 100644 (file)
@@ -406,7 +406,7 @@ postfix_expression
         } else if ($1->isMatrix()) {\r
             parseContext.error($2.line, "field selection not allowed on matrix", ".", "");\r
             parseContext.recover();\r
-        } else if ($1->getBasicType() == EbtStruct) {\r
+        } else if ($1->getBasicType() == EbtStruct || $1->getBasicType() == EbtBlock) {\r
             bool fieldFound = false;\r
             TTypeList* fields = $1->getType().getStruct();\r
             if (fields == 0) {\r
@@ -1184,15 +1184,15 @@ declaration
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON {\r
-        // block\r
+        parseContext.addBlock($2.line, $1, *$2.string, *$4);\r
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {\r
-        // block\r
+        parseContext.addBlock($2.line, $1, *$2.string, *$4, $6.string);\r
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON {\r
-        // block\r
+        parseContext.addBlock($2.line, $1, *$2.string, *$4, $6.string, $7.arraySizes);\r
         $$ = 0;\r
     }\r
     | type_qualifier SEMICOLON {\r
@@ -1665,7 +1665,7 @@ type_qualifier
         if ($$.type == EbtVoid)\r
             $$.type = $2.type;\r
 \r
-        if (parseContext.mergeQualifiersErrorCheck($$.line, $$, $2))\r
+        if (parseContext.mergeQualifiersErrorCheck($$.line, $$, $2, false))\r
             parseContext.recover();\r
     }\r
     ;\r
@@ -2530,6 +2530,7 @@ precision_qualifier
 \r
 struct_specifier\r
     : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {\r
+        // TODO: semantics: check for qualifiers that don't belong in a struct\r
         TType* structure = new TType($4, *$2.string);\r
         TVariable* userTypeDef = new TVariable($2.string, *structure, true);\r
         if (! parseContext.symbolTable.insert(*userTypeDef)) {\r
@@ -2557,7 +2558,7 @@ struct_declaration_list
         for (unsigned int i = 0; i < $2->size(); ++i) {\r
             for (unsigned int j = 0; j < $$->size(); ++j) {\r
                 if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {\r
-                    parseContext.error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());\r
+                    parseContext.error((*$2)[i].line, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());\r
                     parseContext.recover();\r
                 }\r
             }\r
@@ -2598,15 +2599,16 @@ struct_declaration
 \r
         $$ = $3;\r
 \r
-        if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2)) {\r
+        if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2))\r
+            parseContext.recover();\r
+        if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))\r
             parseContext.recover();\r
-        }\r
         for (unsigned int i = 0; i < $$->size(); ++i) {\r
             //\r
             // Careful not to replace already know aspects of type, like array-ness\r
             //\r
             (*$$)[i].type->setElementType($2.type, $2.vectorSize, $2.matrixCols, $2.matrixRows, $2.userDef);\r
-\r
+            (*$$)[i].type->getQualifier() = $2.qualifier;\r
             if ($2.arraySizes)\r
                 (*$$)[i].type->setArraySizes($2.arraySizes);\r
             if ($2.userDef)\r