Implement default layout qualifiers at global and block levels with proper inheritance. Also add more error checking of qualifiers.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21107 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-04-10 22:26:56 +00:00
Родитель ba04210097
Коммит bcd79fe5a3
5 изменённых файлов: 84 добавлений и 21 удалений

Просмотреть файл

@ -12,6 +12,8 @@ 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
centroid float badf; // ERROR
in float badg; // ERROR
} tblock;
uniform T2 { // layout of this block is shared
@ -26,6 +28,10 @@ layout(column_major) uniform T3 { // shared and column_major
int b; // ERROR, redefinition (needs to be last member of block for testing, following members are skipped)
};
out badout { // ERROR
float f;
};
void main()
{
pos = p * (tblock.M1 + tblock.M2 + M4 + M3 + t2m);

Просмотреть файл

@ -70,6 +70,11 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
error(1, "INTERNAL ERROR", "unexpected language", "");
}
}
defaultGlobalQualification.clear();
defaultGlobalQualification.layoutMatrix = ElmColumnMajor;
defaultGlobalQualification.layoutPacking = ElpShared;
defaultGlobalQualification.layoutSlotLocation = 0;
}
///////////////////////////////////////////////////////////////////////
@ -750,7 +755,7 @@ bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const
dst.qualifier.precision = src.qualifier.precision;
// Layout qualifiers
mergeLayoutQualifiers(line, dst, src);
mergeLayoutQualifiers(line, dst.qualifier, src.qualifier);
// other qualifiers
#define MERGE_SINGLETON(field) bad |= dst.qualifier.field && src.qualifier.field; dst.qualifier.field |= src.qualifier.field;
@ -1133,16 +1138,16 @@ void TParseContext::setLayoutQualifier(int line, TPublicType& publicType, TStrin
}
// Merge any layout qualifier information from src into dst, leaving everything else in dst alone
void TParseContext::mergeLayoutQualifiers(int line, TPublicType& dst, const TPublicType& src)
void TParseContext::mergeLayoutQualifiers(int line, TQualifier& dst, const TQualifier& src)
{
if (src.qualifier.layoutMatrix != ElmNone)
dst.qualifier.layoutMatrix = src.qualifier.layoutMatrix;
if (src.layoutMatrix != ElmNone)
dst.layoutMatrix = src.layoutMatrix;
if (src.qualifier.layoutPacking != ElpNone)
dst.qualifier.layoutPacking = src.qualifier.layoutPacking;
if (src.layoutPacking != ElpNone)
dst.layoutPacking = src.layoutPacking;
if (src.qualifier.hasLocation())
dst.qualifier.layoutSlotLocation = src.qualifier.layoutSlotLocation;
if (src.hasLocation())
dst.layoutSlotLocation = src.layoutSlotLocation;
}
/////////////////////////////////////////////////////////////////////////////////
@ -1464,7 +1469,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
//
// 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)
void TParseContext::addBlock(int line, TPublicType& publicType, const TString& blockName, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes)
{
// First, error checks
@ -1478,13 +1483,13 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl
return;
}
if (qualifier.basicType != EbtVoid) {
if (publicType.basicType != EbtVoid) {
error(line, "interface blocks cannot be declared with a type", blockName.c_str(), "");
recover();
return;
}
if (qualifier.qualifier.storage == EvqUniform) {
if (publicType.qualifier.storage == EvqUniform) {
requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block");
profileRequires(line, EEsProfile, 300, 0, "uniform block");
} else {
@ -1494,9 +1499,36 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl
return;
}
// check for qualifiers that don't belong within a block
for (unsigned int member = 0; member < typeList.size(); ++member) {
TQualifier memberQualifier = typeList[member].type->getQualifier();
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal &&
memberQualifier.storage != publicType.qualifier.storage) {
error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
recover();
}
if (publicType.qualifier.storage == EvqUniform) {
if (memberQualifier.isInterpolation() || memberQualifier.isAuxillary()) {
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
recover();
}
}
}
// Make default block qualification, and adjust the member qualifications
TQualifier defaultQualification = defaultGlobalQualification;
mergeLayoutQualifiers(line, defaultQualification, publicType.qualifier);
for (unsigned int member = 0; member < typeList.size(); ++member) {
TQualifier memberQualification = defaultQualification;
mergeLayoutQualifiers(line, memberQualification, typeList[member].type->getQualifier());
typeList[member].type->getQualifier() = memberQualification;
}
// Build and add the interface block as a new type named blockName
TType blockType(&typeList, blockName, qualifier.qualifier.storage);
TType blockType(&typeList, blockName, publicType.qualifier.storage);
blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking;
TVariable* userTypeDef = new TVariable(&blockName, blockType, true);
if (! symbolTable.insert(*userTypeDef)) {
error(line, "redefinition", blockName.c_str(), "block name");
@ -1505,11 +1537,6 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl
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
@ -1528,6 +1555,28 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl
}
}
void TParseContext::updateDefaults(int line, const TPublicType& publicType, const TString* id)
{
bool cantHaveId = false;
TQualifier qualifier = publicType.qualifier;
if (qualifier.storage == EvqUniform) {
if (qualifier.layoutMatrix != ElmNone) {
cantHaveId = true;
defaultGlobalQualification.layoutMatrix = qualifier.layoutMatrix;
}
if (qualifier.layoutPacking != ElpNone) {
cantHaveId = true;
defaultGlobalQualification.layoutPacking = qualifier.layoutPacking;
}
}
if (cantHaveId && id) {
error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), "");
recover();
}
}
//
// 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

Просмотреть файл

@ -91,6 +91,7 @@ struct TParseContext {
struct TPragma contextPragma;
TPrecisionQualifier defaultPrecision[EbtNumTypes];
TQualifier defaultGlobalQualification;
TString HashErrMsg;
bool AfterEOF;
@ -132,7 +133,7 @@ struct TParseContext {
void setLayoutQualifier(int line, TPublicType&, TString&);
void setLayoutQualifier(int line, TPublicType&, TString&, int);
void mergeLayoutQualifiers(int line, TPublicType& dest, const TPublicType& src);
void mergeLayoutQualifiers(int line, TQualifier& dest, const TQualifier& src);
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
@ -141,6 +142,7 @@ struct TParseContext {
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);
void updateDefaults(int line, const TPublicType&, const TString* id);
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);

Просмотреть файл

@ -234,7 +234,7 @@ variable_identifier
unionArray->setUConst(anon->getMemberNumber());
TIntermTyped* constNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.line);
$$ = parseContext.intermediate.addIndex(EOpIndexDirect, container, constNode, $1.line);
$$ = parseContext.intermediate.addIndex(EOpIndexDirectStruct, container, constNode, $1.line);
$$->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);
} else {
const TVariable* variable = symbol ? symbol->getAsVariable() : 0;
@ -1494,6 +1494,7 @@ single_declaration
: fully_specified_type {
$$.type = $1;
$$.intermAggregate = 0;
parseContext.updateDefaults($1.line, $$.type, 0);
}
| fully_specified_type IDENTIFIER {
$$.intermAggregate = 0;
@ -1504,6 +1505,8 @@ single_declaration
if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type))
parseContext.recover();
parseContext.updateDefaults($2.line, $$.type, $2.string);
}
| fully_specified_type IDENTIFIER array_specifier {
$$.intermAggregate = 0;
@ -1520,6 +1523,7 @@ single_declaration
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
parseContext.recover();
}
parseContext.updateDefaults($2.line, $$.type, $2.string);
}
| fully_specified_type IDENTIFIER array_specifier EQUAL initializer {
$$.intermAggregate = 0;
@ -1647,7 +1651,7 @@ layout_qualifier_id_list
}
| layout_qualifier_id_list COMMA layout_qualifier_id {
$$ = $1;
parseContext.mergeLayoutQualifiers($2.line, $$, $3);
parseContext.mergeLayoutQualifiers($2.line, $$.qualifier, $3.qualifier);
}
layout_qualifier_id

Просмотреть файл

@ -119,7 +119,9 @@ bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it
case EOpIndexDirect: out.debug << "direct index"; break;
case EOpIndexIndirect: out.debug << "indirect index"; break;
case EOpIndexDirectStruct: out.debug << "direct index for structure"; break;
case EOpIndexDirectStruct:
out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getUnionArrayPointer()->getIConst()].type->getFieldName();
out.debug << ": direct index for structure"; break;
case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
case EOpAdd: out.debug << "add"; break;