Add grammar productions for the syntax "layout(...) uniform;" for setting global defaults.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22112 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
60d9f7a881
commit
211cba242b
@ -9,7 +9,7 @@ layout(LocatioN = 10) in s r[4]; // ERROR, no struct
|
|||||||
out vec4 pos;
|
out vec4 pos;
|
||||||
out vec3 color;
|
out vec3 color;
|
||||||
|
|
||||||
layout(shared, column_major, row_major) uniform mat4 badm4; // ERROR
|
layout(shared, column_major) uniform mat4 badm4; // ERROR
|
||||||
layout(shared, column_major, row_major) uniform; // default is now shared and row_major
|
layout(shared, column_major, row_major) uniform; // default is now shared and row_major
|
||||||
|
|
||||||
layout(std140) uniform Transform { // layout of this block is std140
|
layout(std140) uniform Transform { // layout of this block is std140
|
||||||
|
|||||||
@ -81,10 +81,16 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultGlobalQualification.clear();
|
globalUniformDefaults.clear();
|
||||||
defaultGlobalQualification.layoutMatrix = ElmColumnMajor;
|
globalUniformDefaults.layoutMatrix = ElmColumnMajor;
|
||||||
defaultGlobalQualification.layoutPacking = ElpShared;
|
globalUniformDefaults.layoutPacking = ElpShared;
|
||||||
defaultGlobalQualification.layoutSlotLocation = 0;
|
globalUniformDefaults.layoutSlotLocation = 0;
|
||||||
|
|
||||||
|
globalInputDefaults.clear();
|
||||||
|
globalInputDefaults.layoutSlotLocation = 0;
|
||||||
|
|
||||||
|
globalOutputDefaults.clear();
|
||||||
|
globalOutputDefaults.layoutSlotLocation = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get code that is not part of a shared symbol table, specific to this shader
|
// Get code that is not part of a shared symbol table, specific to this shader
|
||||||
@ -1541,12 +1547,7 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
|
|||||||
if (profile == EEsProfile && arraySizes)
|
if (profile == EEsProfile && arraySizes)
|
||||||
arraySizeRequiredCheck(line, arraySizes->front());
|
arraySizeRequiredCheck(line, arraySizes->front());
|
||||||
|
|
||||||
if (publicBlockType.basicType != EbtVoid) {
|
if (currentBlockDefaults.storage == EvqUniform) {
|
||||||
error(line, "interface blocks cannot be declared with a type", blockName->c_str(), "");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (publicBlockType.qualifier.storage == EvqUniform) {
|
|
||||||
requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block");
|
requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block");
|
||||||
profileRequires(line, EEsProfile, 300, 0, "uniform block");
|
profileRequires(line, EEsProfile, 300, 0, "uniform block");
|
||||||
} else {
|
} else {
|
||||||
@ -1558,9 +1559,9 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
|
|||||||
// check for qualifiers and types that don't belong within a block
|
// check for qualifiers and types that don't belong within a block
|
||||||
for (unsigned int member = 0; member < typeList.size(); ++member) {
|
for (unsigned int member = 0; member < typeList.size(); ++member) {
|
||||||
TQualifier memberQualifier = typeList[member].type->getQualifier();
|
TQualifier memberQualifier = typeList[member].type->getQualifier();
|
||||||
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != publicBlockType.qualifier.storage)
|
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockDefaults.storage)
|
||||||
error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
|
error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||||
if (publicBlockType.qualifier.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
|
if (currentBlockDefaults.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
|
||||||
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
|
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||||
|
|
||||||
TBasicType basicType = typeList[member].type->getBasicType();
|
TBasicType basicType = typeList[member].type->getBasicType();
|
||||||
@ -1570,8 +1571,15 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
|
|||||||
|
|
||||||
// Make default block qualification, and adjust the member qualifications
|
// Make default block qualification, and adjust the member qualifications
|
||||||
|
|
||||||
TQualifier defaultQualification = defaultGlobalQualification;
|
TQualifier defaultQualification;
|
||||||
mergeLayoutQualifiers(line, defaultQualification, publicBlockType.qualifier);
|
switch (currentBlockDefaults.storage) {
|
||||||
|
case EvqUniform: defaultQualification = globalUniformDefaults; break;
|
||||||
|
case EvqIn: defaultQualification = globalInputDefaults; break;
|
||||||
|
case EvqOut: defaultQualification = globalOutputDefaults; break;
|
||||||
|
default: defaultQualification.clear(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeLayoutQualifiers(line, defaultQualification, currentBlockDefaults);
|
||||||
for (unsigned int member = 0; member < typeList.size(); ++member) {
|
for (unsigned int member = 0; member < typeList.size(); ++member) {
|
||||||
TQualifier memberQualification = defaultQualification;
|
TQualifier memberQualification = defaultQualification;
|
||||||
mergeLayoutQualifiers(line, memberQualification, typeList[member].type->getQualifier());
|
mergeLayoutQualifiers(line, memberQualification, typeList[member].type->getQualifier());
|
||||||
@ -1580,7 +1588,7 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
|
|||||||
|
|
||||||
// Build and add the interface block as a new type named blockName
|
// Build and add the interface block as a new type named blockName
|
||||||
|
|
||||||
TType blockType(&typeList, *blockName, publicBlockType.qualifier.storage);
|
TType blockType(&typeList, *blockName, currentBlockDefaults.storage);
|
||||||
if (arraySizes)
|
if (arraySizes)
|
||||||
blockType.setArraySizes(arraySizes);
|
blockType.setArraySizes(arraySizes);
|
||||||
blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking;
|
blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking;
|
||||||
@ -1624,11 +1632,12 @@ void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, const
|
|||||||
qualifier.isInterpolation() ||
|
qualifier.isInterpolation() ||
|
||||||
qualifier.storage != EvqTemporary ||
|
qualifier.storage != EvqTemporary ||
|
||||||
qualifier.precision != EpqNone) {
|
qualifier.precision != EpqNone) {
|
||||||
error(line, "cannot add this qualifier to an existing variable", identifier.c_str(), "");
|
error(line, "cannot add storage, auxillary, memory, interpolation, or precision qualifier to an existing variable", identifier.c_str(), "");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qualifier.invariant)
|
||||||
variable->getType().getQualifier().invariant = true;
|
variable->getType().getQualifier().invariant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1638,6 +1647,88 @@ void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, TIden
|
|||||||
addQualifierToExisting(line, qualifier, *identifiers[i]);
|
addQualifierToExisting(line, qualifier, *identifiers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TParseContext::updateQualifierDefaults(TQualifier qualifier)
|
||||||
|
{
|
||||||
|
switch (qualifier.storage) {
|
||||||
|
case EvqUniform:
|
||||||
|
if (qualifier.layoutMatrix != ElmNone)
|
||||||
|
globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix;
|
||||||
|
if (qualifier.layoutPacking != ElpNone)
|
||||||
|
globalUniformDefaults.layoutPacking = qualifier.layoutPacking;
|
||||||
|
break;
|
||||||
|
case EvqIn:
|
||||||
|
if (qualifier.hasLocation())
|
||||||
|
globalInputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation;
|
||||||
|
break;
|
||||||
|
case EvqOut:
|
||||||
|
if (qualifier.hasLocation())
|
||||||
|
globalOutputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// error handling should be done by callers of this function
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TParseContext::updateQualifierDefaults(int line, TQualifier qualifier)
|
||||||
|
{
|
||||||
|
if (qualifier.isAuxillary() ||
|
||||||
|
qualifier.isMemory() ||
|
||||||
|
qualifier.isInterpolation() ||
|
||||||
|
qualifier.precision != EpqNone)
|
||||||
|
error(line, "cannot use auxillary, memory, interpolation, or precision qualifier in a standalone qualifier", "", "");
|
||||||
|
|
||||||
|
switch (qualifier.storage) {
|
||||||
|
case EvqUniform:
|
||||||
|
case EvqIn:
|
||||||
|
case EvqOut:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error(line, "standalone qualifier requires 'uniform', 'in', or 'out' storage qualification", "", "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateQualifierDefaults(qualifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TParseContext::updateTypedDefaults(int line, TQualifier qualifier, const TString* id)
|
||||||
|
{
|
||||||
|
bool cantHaveId = false;
|
||||||
|
|
||||||
|
if (! id) {
|
||||||
|
if (qualifier.hasLayout())
|
||||||
|
warn(line, "cannot set qualifier defaults when using a type and no identifier", "", "");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualifier.storage == EvqUniform) {
|
||||||
|
if (qualifier.layoutMatrix != ElmNone)
|
||||||
|
error(line, "cannot specify matrix layout on a variable declaration", id->c_str(), "");
|
||||||
|
if (qualifier.layoutPacking != ElpNone)
|
||||||
|
error(line, "cannot specify packing on a variable declaration", id->c_str(), "");
|
||||||
|
} else if (qualifier.storage == EvqVaryingIn) {
|
||||||
|
if (qualifier.hasLayout() && language != EShLangVertex) {
|
||||||
|
error(line, "can only use location layout qualifier on a vertex input or fragment output", id->c_str(), "");
|
||||||
|
}
|
||||||
|
} else if (qualifier.storage == EvqVaryingOut) {
|
||||||
|
if (qualifier.hasLayout() && language != EShLangFragment) {
|
||||||
|
error(line, "can only use location layout qualifier on a vertex input or fragment output", id->c_str(), "");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (qualifier.layoutMatrix != ElmNone ||
|
||||||
|
qualifier.layoutPacking != ElpNone)
|
||||||
|
error(line, "layout qualifiers for matrix layout and packing only apply to uniform blocks", id->c_str(), "");
|
||||||
|
else if (qualifier.hasLocation())
|
||||||
|
error(line, "location qualifiers only appy to uniform, in, or out storage qualifiers", id->c_str(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cantHaveId)
|
||||||
|
error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), "");
|
||||||
|
|
||||||
|
updateQualifierDefaults(qualifier);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Take the sequence of statements that has been built up since the last case/default,
|
// Take the sequence of statements that has been built up since the last case/default,
|
||||||
// put it on the list of top-level nodes for the current (inner-most) switch statement,
|
// put it on the list of top-level nodes for the current (inner-most) switch statement,
|
||||||
@ -1697,34 +1788,6 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter
|
|||||||
return switchNode;
|
return switchNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else if (qualifier.storage == EvqVaryingIn) {
|
|
||||||
if (qualifier.hasLayout() && language != EShLangVertex) {
|
|
||||||
error(line, "can only use location layout qualifier on a vertex input or fragment output", id->c_str(), "");
|
|
||||||
}
|
|
||||||
} else if (qualifier.storage == EvqVaryingOut) {
|
|
||||||
if (qualifier.hasLayout() && language != EShLangFragment) {
|
|
||||||
error(line, "can only use location layout qualifier on a vertex input or fragment output", id->c_str(), "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cantHaveId && id)
|
|
||||||
error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
|
// 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
|
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
|
||||||
|
|||||||
@ -93,11 +93,13 @@ struct TParseContext {
|
|||||||
TPrecisionQualifier defaultPrecision[EbtNumTypes];
|
TPrecisionQualifier defaultPrecision[EbtNumTypes];
|
||||||
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex()
|
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex()
|
||||||
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
|
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
|
||||||
TQualifier defaultGlobalQualification;
|
|
||||||
TString HashErrMsg;
|
TString HashErrMsg;
|
||||||
bool AfterEOF;
|
bool AfterEOF;
|
||||||
const TString* blockName;
|
const TString* blockName;
|
||||||
TPublicType publicBlockType;
|
TQualifier globalUniformDefaults;
|
||||||
|
TQualifier globalInputDefaults;
|
||||||
|
TQualifier globalOutputDefaults;
|
||||||
|
TQualifier currentBlockDefaults;
|
||||||
|
|
||||||
void initializeExtensionBehavior();
|
void initializeExtensionBehavior();
|
||||||
const char* getPreamble();
|
const char* getPreamble();
|
||||||
@ -156,9 +158,11 @@ struct TParseContext {
|
|||||||
void addBlock(int line, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
|
void addBlock(int line, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
|
||||||
void addQualifierToExisting(int line, TQualifier, const TString& identifier);
|
void addQualifierToExisting(int line, TQualifier, const TString& identifier);
|
||||||
void addQualifierToExisting(int line, TQualifier, TIdentifierList&);
|
void addQualifierToExisting(int line, TQualifier, TIdentifierList&);
|
||||||
|
void updateQualifierDefaults(TQualifier);
|
||||||
|
void updateQualifierDefaults(int line, TQualifier);
|
||||||
|
void updateTypedDefaults(int line, TQualifier, const TString* id);
|
||||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
||||||
TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body);
|
TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body);
|
||||||
void updateDefaults(int line, const TPublicType&, const TString* id);
|
|
||||||
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
|
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
|
||||||
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
|
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
|
||||||
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
||||||
|
|||||||
@ -1119,7 +1119,7 @@ declaration
|
|||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
| type_qualifier SEMICOLON {
|
| type_qualifier SEMICOLON {
|
||||||
// setting defaults
|
parseContext.updateQualifierDefaults($1.line, $1.qualifier);
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
| type_qualifier IDENTIFIER SEMICOLON {
|
| type_qualifier IDENTIFIER SEMICOLON {
|
||||||
@ -1137,7 +1137,7 @@ block_structure
|
|||||||
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.line); } struct_declaration_list RIGHT_BRACE {
|
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.line); } struct_declaration_list RIGHT_BRACE {
|
||||||
--parseContext.structNestingLevel;
|
--parseContext.structNestingLevel;
|
||||||
parseContext.blockName = $2.string;
|
parseContext.blockName = $2.string;
|
||||||
parseContext.publicBlockType = $1;
|
parseContext.currentBlockDefaults = $1.qualifier;
|
||||||
$$.line = $1.line;
|
$$.line = $1.line;
|
||||||
$$.typeList = $5;
|
$$.typeList = $5;
|
||||||
}
|
}
|
||||||
@ -1395,7 +1395,7 @@ single_declaration
|
|||||||
: fully_specified_type {
|
: fully_specified_type {
|
||||||
$$.type = $1;
|
$$.type = $1;
|
||||||
$$.intermAggregate = 0;
|
$$.intermAggregate = 0;
|
||||||
parseContext.updateDefaults($1.line, $$.type, 0);
|
parseContext.updateTypedDefaults($1.line, $$.type.qualifier, 0);
|
||||||
}
|
}
|
||||||
| fully_specified_type IDENTIFIER {
|
| fully_specified_type IDENTIFIER {
|
||||||
$$.intermAggregate = 0;
|
$$.intermAggregate = 0;
|
||||||
@ -1404,7 +1404,7 @@ single_declaration
|
|||||||
parseContext.nonInitConstCheck($2.line, *$2.string, $$.type);
|
parseContext.nonInitConstCheck($2.line, *$2.string, $$.type);
|
||||||
parseContext.nonInitCheck($2.line, *$2.string, $$.type);
|
parseContext.nonInitCheck($2.line, *$2.string, $$.type);
|
||||||
|
|
||||||
parseContext.updateDefaults($2.line, $$.type, $2.string);
|
parseContext.updateTypedDefaults($2.line, $$.type.qualifier, $2.string);
|
||||||
}
|
}
|
||||||
| fully_specified_type IDENTIFIER array_specifier {
|
| fully_specified_type IDENTIFIER array_specifier {
|
||||||
$$.intermAggregate = 0;
|
$$.intermAggregate = 0;
|
||||||
@ -1419,7 +1419,7 @@ single_declaration
|
|||||||
TVariable* variable;
|
TVariable* variable;
|
||||||
parseContext.arrayCheck($3.line, *$2.string, $1, variable);
|
parseContext.arrayCheck($3.line, *$2.string, $1, variable);
|
||||||
}
|
}
|
||||||
parseContext.updateDefaults($2.line, $$.type, $2.string);
|
parseContext.updateTypedDefaults($2.line, $$.type.qualifier, $2.string);
|
||||||
}
|
}
|
||||||
| fully_specified_type IDENTIFIER array_specifier EQUAL initializer {
|
| fully_specified_type IDENTIFIER array_specifier EQUAL initializer {
|
||||||
$$.intermAggregate = 0;
|
$$.intermAggregate = 0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user