Add redeclarations of built-in blocks.
Note: lots of test results changed due to listing the members of a block when printing types. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23682 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
94fdd1117b
commit
ab41fe5df6
44 changed files with 528 additions and 324 deletions
|
|
@ -755,6 +755,17 @@ public:
|
|||
TString s(buf);
|
||||
s.append(getCompleteTypeString());
|
||||
|
||||
// Add struct/block members
|
||||
if (structure) {
|
||||
s.append("{");
|
||||
for (size_t i = 0; i < structure->size(); ++i) {
|
||||
s.append((*structure)[i].type->getFieldName());
|
||||
if (i < structure->size()-1)
|
||||
s.append(",");
|
||||
}
|
||||
s.append("}");
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1328,7 +1328,7 @@ void TBuiltIns::initialize(int version, EProfile profile)
|
|||
);
|
||||
|
||||
if (IncludeLegacy(version, profile)) {
|
||||
if (version < 410)
|
||||
if (version < 150)
|
||||
stageBuiltins[EShLangFragment].append(
|
||||
"in float gl_FogFragCoord;"
|
||||
"in vec4 gl_TexCoord[];"
|
||||
|
|
|
|||
|
|
@ -1881,7 +1881,7 @@ void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TType
|
|||
//
|
||||
// Returns a redeclared and type-modified variable if a redeclarated occurred.
|
||||
//
|
||||
TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifier, bool& newDeclaration)
|
||||
TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString& identifier, bool& newDeclaration)
|
||||
{
|
||||
if (profile == EEsProfile || identifier.compare(0, 3, "gl_") != 0 || symbolTable.atBuiltInLevel())
|
||||
return 0;
|
||||
|
|
@ -1889,8 +1889,6 @@ TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifi
|
|||
// Potentially redeclaring a built-in variable...
|
||||
|
||||
if ((identifier == "gl_FragDepth" && version >= 420) ||
|
||||
(identifier == "gl_PerVertex" && version >= 410) ||
|
||||
(identifier == "gl_PerFragment" && version >= 410) ||
|
||||
(identifier == "gl_FragCoord" && version >= 150) ||
|
||||
(identifier == "gl_ClipDistance" && version >= 130) ||
|
||||
(identifier == "gl_FrontColor" && version >= 130) ||
|
||||
|
|
@ -1928,6 +1926,90 @@ TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifi
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
|
||||
{
|
||||
// just a quick out, not everything that must be checked:
|
||||
if (symbolTable.atBuiltInLevel() || profile == EEsProfile || blockName.compare(0, 3, "gl_") != 0)
|
||||
return false;
|
||||
|
||||
if (instanceName && instanceName->compare(0, 3, "gl_") != 0) {
|
||||
error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, "built-in block redeclaration");
|
||||
|
||||
// Potentially redeclaring a built-in block...
|
||||
|
||||
if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment")
|
||||
return false;
|
||||
|
||||
|
||||
// Blocks with instance names are easy to find, lookup the instance name,
|
||||
// Anonymous blocks need to be found via a member. copyUp()?? will work
|
||||
// just fine for either find.
|
||||
|
||||
bool builtIn;
|
||||
TSymbol* block;
|
||||
if (instanceName)
|
||||
block = symbolTable.find(*instanceName, &builtIn);
|
||||
else
|
||||
block = symbolTable.find(typeList.front().type->getFieldName(), &builtIn);
|
||||
|
||||
// If the block was not found, this must be a version/profile/stage
|
||||
// that doesn't have it.
|
||||
if (! block)
|
||||
return false;
|
||||
|
||||
// Built-in blocks cannot be redeclared more than once, which if happened,
|
||||
// we'd be finding the already redeclared one here, rather than the built in.
|
||||
if (! builtIn) {
|
||||
error(loc, "can only redeclare a built-in block once", blockName.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the to make a writable version, to insert into the block table after editing
|
||||
block = symbolTable.copyUpDeferredInsert(block);
|
||||
|
||||
if (block->getType().getBasicType() != EbtBlock) {
|
||||
error(loc, "cannot redeclare a non block as a block", blockName.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: semantics: block redeclaration: instance array size matching?
|
||||
|
||||
// Edit and error check the container against the redeclaration
|
||||
// - remove unused members
|
||||
// - ensure remaining qualifiers match
|
||||
TType& type = block->getWritableType();
|
||||
TTypeList::iterator member = type.getStruct()->begin();
|
||||
while (member != type.getStruct()->end()) {
|
||||
// look for match
|
||||
bool found = false;
|
||||
for (TTypeList::iterator newMember = typeList.begin(); newMember != typeList.end(); ++newMember) {
|
||||
if (member->type->getFieldName() == newMember->type->getFieldName()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remove non-redeclared members
|
||||
if (found)
|
||||
++member;
|
||||
else
|
||||
member = type.getStruct()->erase(member);
|
||||
|
||||
// TODO: semantics: block redeclaration: member type/qualifier matching
|
||||
}
|
||||
|
||||
symbolTable.insert(*block);
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *block);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TParseContext::paramCheck(TSourceLoc loc, const TStorageQualifier& qualifier, TType* type)
|
||||
{
|
||||
switch (qualifier) {
|
||||
|
|
@ -2418,12 +2500,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
|
|||
if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut)
|
||||
type.getQualifier().layoutStream = globalOutputDefaults.layoutStream;
|
||||
|
||||
if (publicType.geometry != ElgNone)
|
||||
error(loc, "geometry primitive qualifier cannot be applied to a variable declaration", TQualifier::getGeometryString(publicType.geometry), "");
|
||||
|
||||
// Check for redeclaration of built-ins and/or attempting to declare a reserved name
|
||||
bool newDeclaration = false; // true if a new entry gets added to the symbol table
|
||||
TSymbol* symbol = redeclareBuiltin(loc, identifier, newDeclaration);
|
||||
TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, newDeclaration);
|
||||
if (! symbol)
|
||||
reservedErrorCheck(loc, identifier);
|
||||
|
||||
|
|
@ -2848,10 +2927,14 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
|
|||
//
|
||||
// Do everything needed to add an interface block.
|
||||
//
|
||||
void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
|
||||
void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
|
||||
{
|
||||
// First, error checks
|
||||
// This might be a redeclaration of a built-in block, find out, and get
|
||||
// a modifiable copy if so.
|
||||
if (redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes))
|
||||
return;
|
||||
|
||||
// Basic error checks
|
||||
if (reservedErrorCheck(loc, *blockName))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ public:
|
|||
void precisionQualifierCheck(TSourceLoc, TPublicType&);
|
||||
void parameterSamplerCheck(TSourceLoc, TStorageQualifier qualifier, const TType& type);
|
||||
bool containsSampler(const TType& type);
|
||||
TSymbol* redeclareBuiltin(TSourceLoc, const TString&, bool& newDeclaration);
|
||||
TSymbol* redeclareBuiltinVariable(TSourceLoc, const TString&, bool& newDeclaration);
|
||||
bool redeclareBuiltinBlock(TSourceLoc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
|
||||
void paramCheck(TSourceLoc, const TStorageQualifier&, TType* type);
|
||||
void nestedBlockCheck(TSourceLoc);
|
||||
void nestedStructCheck(TSourceLoc);
|
||||
|
|
@ -137,7 +138,7 @@ public:
|
|||
TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator);
|
||||
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
|
||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
|
||||
void addBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||
void declareBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||
void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier);
|
||||
void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&);
|
||||
void updateStandaloneQualifierDefaults(TSourceLoc, const TPublicType&);
|
||||
|
|
|
|||
|
|
@ -463,13 +463,11 @@ public:
|
|||
// to the current level, so it can be modified without impacting other users
|
||||
// of the shared table.
|
||||
//
|
||||
TSymbol* copyUp(TSymbol* shared)
|
||||
TSymbol* copyUpDeferredInsert(TSymbol* shared)
|
||||
{
|
||||
TSymbol* copy;
|
||||
if (shared->getAsVariable()) {
|
||||
copy = shared->clone();
|
||||
TSymbol* copy = shared->clone();
|
||||
copy->setUniqueId(shared->getUniqueId());
|
||||
table[currentLevel()]->insert(*copy);
|
||||
return copy;
|
||||
} else {
|
||||
const TAnonMember* anon = shared->getAsAnonMember();
|
||||
|
|
@ -477,7 +475,20 @@ public:
|
|||
TVariable* container = anon->getAnonContainer().clone();
|
||||
container->changeName(NewPoolTString(""));
|
||||
container->setUniqueId(anon->getAnonContainer().getUniqueId());
|
||||
table[currentLevel()]->insert(*container);
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
TSymbol* copyUp(TSymbol* shared)
|
||||
{
|
||||
TSymbol* copy = copyUpDeferredInsert(shared);
|
||||
table[currentLevel()]->insert(*copy);
|
||||
if (shared->getAsVariable())
|
||||
return copy;
|
||||
else {
|
||||
// get copy of an anonymous member's container
|
||||
table[currentLevel()]->insert(*copy);
|
||||
// return the copy of the anonymous member
|
||||
return table[currentLevel()]->find(shared->getName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -761,15 +761,15 @@ declaration
|
|||
$$ = 0;
|
||||
}
|
||||
| block_structure SEMICOLON {
|
||||
parseContext.addBlock($1.loc, *$1.typeList);
|
||||
parseContext.declareBlock($1.loc, *$1.typeList);
|
||||
$$ = 0;
|
||||
}
|
||||
| block_structure IDENTIFIER SEMICOLON {
|
||||
parseContext.addBlock($1.loc, *$1.typeList, $2.string);
|
||||
parseContext.declareBlock($1.loc, *$1.typeList, $2.string);
|
||||
$$ = 0;
|
||||
}
|
||||
| block_structure IDENTIFIER array_specifier SEMICOLON {
|
||||
parseContext.addBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes);
|
||||
parseContext.declareBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes);
|
||||
$$ = 0;
|
||||
}
|
||||
| type_qualifier SEMICOLON {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue