Merge branch 'TiemoJung-semantic_handling'

This commit is contained in:
John Kessenich 2017-03-14 21:50:06 -06:00
commit 2dd643ff03
11 changed files with 187 additions and 49 deletions

View File

@ -403,6 +403,7 @@ public:
// drop qualifiers that don't belong in a temporary variable // drop qualifiers that don't belong in a temporary variable
void makeTemporary() void makeTemporary()
{ {
semanticName = nullptr;
storage = EvqTemporary; storage = EvqTemporary;
builtIn = EbvNone; builtIn = EbvNone;
clearInterstage(); clearInterstage();
@ -451,6 +452,7 @@ public:
specConstant = false; specConstant = false;
} }
const char* semanticName;
TStorageQualifier storage : 6; TStorageQualifier storage : 6;
TBuiltInVariable builtIn : 8; TBuiltInVariable builtIn : 8;
TPrecisionQualifier precision : 3; TPrecisionQualifier precision : 3;

View File

@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits. // For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run). // For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "Overload400-PrecQual.1911" #define GLSLANG_REVISION "Overload400-PrecQual.1914"
#define GLSLANG_DATE "14-Mar-2017" #define GLSLANG_DATE "14-Mar-2017"

View File

@ -66,11 +66,14 @@ namespace glslang {
struct TVarEntryInfo struct TVarEntryInfo
{ {
int id; int id;
TIntermSymbol* symbol; TIntermSymbol* symbol;
bool live; bool live;
int newBinding; int newBinding;
int newSet; int newSet;
int newLocation;
int newComponent;
int newIndex;
struct TOrderById struct TOrderById
{ {
@ -113,70 +116,109 @@ typedef std::vector<TVarEntryInfo> TVarLiveMap;
class TVarGatherTraverser : public TLiveTraverser class TVarGatherTraverser : public TLiveTraverser
{ {
public: public:
TVarGatherTraverser(const TIntermediate& i, TVarLiveMap& vars, bool traverseDeadCode) TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList)
: TLiveTraverser(i, traverseDeadCode, true, true, false) : TLiveTraverser(i, traverseDeadCode, true, true, false)
, varLiveList(vars) , inputList(inList)
, outputList(outList)
, uniformList(uniformList)
{ {
} }
virtual void visitSymbol(TIntermSymbol* base) virtual void visitSymbol(TIntermSymbol* base)
{ {
if (base->getType().getQualifier().isUniformOrBuffer()) { TVarLiveMap* target = nullptr;
if (base->getQualifier().storage == EvqVaryingIn)
target = &inputList;
else if (base->getQualifier().storage == EvqVaryingOut)
target = &outputList;
else if (base->getQualifier().isUniformOrBuffer())
target = &uniformList;
if (target) {
TVarEntryInfo ent = { base->getId(), base, !traverseAll }; TVarEntryInfo ent = { base->getId(), base, !traverseAll };
TVarLiveMap::iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById()); TVarLiveMap::iterator at = std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
if (at != varLiveList.end() && at->id == ent.id) if (at != target->end() && at->id == ent.id)
at->live = at->live || !traverseAll; // update live state at->live = at->live || !traverseAll; // update live state
else else
varLiveList.insert(at, ent); target->insert(at, ent);
} }
} }
private: private:
TVarLiveMap& varLiveList; TVarLiveMap& inputList;
TVarLiveMap& outputList;
TVarLiveMap& uniformList;
}; };
class TVarSetTraverser : public TLiveTraverser class TVarSetTraverser : public TLiveTraverser
{ {
public: public:
TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& vars) TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList)
: TLiveTraverser(i, true, true, true, false) : TLiveTraverser(i, true, true, true, false)
, varLiveList(vars) , inputList(inList)
, outputList(outList)
, uniformList(uniformList)
{ {
} }
virtual void visitSymbol(TIntermSymbol* base) virtual void visitSymbol(TIntermSymbol* base)
{ {
TVarEntryInfo ent = { base->getId() }; const TVarLiveMap* source;
TVarLiveMap::const_iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById()); if (base->getQualifier().storage == EvqVaryingIn)
if (at == varLiveList.end()) source = &inputList;
else if (base->getQualifier().storage == EvqVaryingOut)
source = &outputList;
else if (base->getQualifier().isUniformOrBuffer())
source = &uniformList;
else
return; return;
if (!(at->id == ent.id))
TVarEntryInfo ent = { base->getId() };
TVarLiveMap::const_iterator at = std::lower_bound(source->begin(), source->end(), ent, TVarEntryInfo::TOrderById());
if (at == source->end())
return;
if (at->id != ent.id)
return; return;
if (at->newBinding != -1) if (at->newBinding != -1)
base->getWritableType().getQualifier().layoutBinding = at->newBinding; base->getWritableType().getQualifier().layoutBinding = at->newBinding;
if (at->newSet != -1) if (at->newSet != -1)
base->getWritableType().getQualifier().layoutSet = at->newSet; base->getWritableType().getQualifier().layoutSet = at->newSet;
if (at->newLocation != -1)
base->getWritableType().getQualifier().layoutLocation = at->newLocation;
if (at->newComponent != -1)
base->getWritableType().getQualifier().layoutComponent = at->newComponent;
if (at->newIndex != -1)
base->getWritableType().getQualifier().layoutIndex = at->newIndex;
} }
private: private:
const TVarLiveMap& varLiveList; const TVarLiveMap& inputList;
const TVarLiveMap& outputList;
const TVarLiveMap& uniformList;
}; };
struct TResolverAdaptor struct TResolverUniformAdaptor
{ {
TResolverAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e) TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm)
: stage(s) : resolver(r)
, resolver(r) , stage(s)
, infoSink(i) , infoSink(i)
, error(e) , error(e)
, intermediate(interm)
{ {
} }
inline void operator()(TVarEntryInfo& ent) inline void operator()(TVarEntryInfo& ent)
{ {
ent.newLocation = -1;
ent.newComponent = -1;
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
if (isValid) { if (isValid) {
ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
@ -209,15 +251,69 @@ struct TResolverAdaptor
TIoMapResolver& resolver; TIoMapResolver& resolver;
TInfoSink& infoSink; TInfoSink& infoSink;
bool& error; bool& error;
TIntermediate& intermediate;
private: private:
TResolverAdaptor& operator=(TResolverAdaptor&); TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&);
};
struct TResolverInOutAdaptor
{
TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm)
: resolver(r)
, stage(s)
, infoSink(i)
, error(e)
, intermediate(interm)
{
}
inline void operator()(TVarEntryInfo& ent)
{
ent.newLocation = -1;
ent.newComponent = -1;
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateInOut(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
if (isValid) {
ent.newLocation = resolver.resolveInOutLocation(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
ent.newComponent = resolver.resolveInOutComponent(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
ent.newIndex = resolver.resolveInOutIndex(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
} else {
TString errorMsg = "Invalid shader In/Out variable semantic: ";
errorMsg += ent.symbol->getType().getQualifier().semanticName;
infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
error = true;
}
}
EShLanguage stage;
TIoMapResolver& resolver;
TInfoSink& infoSink;
bool& error;
TIntermediate& intermediate;
private:
TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&);
}; };
/* /*
* Basic implementation of glslang::TIoMapResolver that replaces the * Basic implementation of glslang::TIoMapResolver that replaces the
* previous offset behaviour. * previous offset behavior.
* It does the same, uses the offsets for th corresponding uniform * It does the same, uses the offsets for the corresponding uniform
* types. Also respects the EOptionAutoMapBindings flag and binds * types. Also respects the EOptionAutoMapBindings flag and binds
* them if needed. * them if needed.
*/ */
@ -348,6 +444,23 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver
return type.getQualifier().layoutSet; return type.getQualifier().layoutSet;
return 0; return 0;
} }
bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) override
{
return true;
}
int resolveInOutLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) override
{
return -1;
}
int resolveInOutComponent(EShLanguage stage, const char* name, const TType& type, bool is_live) override
{
return -1;
}
int resolveInOutIndex(EShLanguage stage, const char* name, const TType& type, bool is_live) override
{
return -1;
}
}; };
// Map I/O variables to provided offsets, and make bindings for // Map I/O variables to provided offsets, and make bindings for
@ -386,9 +499,9 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
resolver = &defaultResolver; resolver = &defaultResolver;
} }
TVarLiveMap varMap; TVarLiveMap inVarMap, outVarMap, uniformVarMap;
TVarGatherTraverser iter_binding_all(intermediate, varMap, true); TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap);
TVarGatherTraverser iter_binding_live(intermediate, varMap, false); TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
root->traverse(&iter_binding_all); root->traverse(&iter_binding_all);
iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
@ -400,16 +513,19 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
} }
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info. // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
std::sort(varMap.begin(), varMap.end(), TVarEntryInfo::TOrderByPriority()); std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderByPriority());
bool hadError = false; bool hadError = false;
TResolverAdaptor doResolve(stage, *resolver, infoSink, hadError); TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate);
std::for_each(varMap.begin(), varMap.end(), doResolve); TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate);
std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve);
std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve);
std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve);
if (!hadError) { if (!hadError) {
// sort by id again, so we can use lower bound to find entries // sort by id again, so we can use lower bound to find entries
std::sort(varMap.begin(), varMap.end(), TVarEntryInfo::TOrderById()); std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderById());
TVarSetTraverser iter_iomap(intermediate, varMap); TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap);
root->traverse(&iter_iomap); root->traverse(&iter_iomap);
} }

View File

@ -423,6 +423,11 @@ public:
bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
#endif #endif
const char* addSemanticName(const TString& name)
{
return semanticNameSet.insert(name).first->c_str();
}
protected: protected:
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*); void error(TInfoSink& infoSink, const char*);
@ -501,6 +506,7 @@ protected:
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
std::unordered_set<int> usedConstantId; // specialization constant ids used std::unordered_set<int> usedConstantId; // specialization constant ids used
std::set<TString> semanticNameSet;
private: private:
void operator=(TIntermediate&); // prevent assignments void operator=(TIntermediate&); // prevent assignments

View File

@ -452,10 +452,12 @@ class TIoMapper;
// and resolveSet are invoked to resolve the binding and descriptor // and resolveSet are invoked to resolve the binding and descriptor
// set index respectively. // set index respectively.
// Invocations happen in a particular order: // Invocations happen in a particular order:
// 1) var with binding and set already defined // 1) all shader inputs
// 2) var with binding but no set defined // 2) all shader outputs
// 3) var with set but no binding defined // 3) all uniforms with binding and set already defined
// 4) var with no binding and no set defined // 4) all uniforms with binding but no set defined
// 5) all uniforms with set but no binding defined
// 6) all uniforms with no binding and no set defined
// //
// NOTE: that still limit checks are applied to bindings and sets // NOTE: that still limit checks are applied to bindings and sets
// and may result in an error. // and may result in an error.
@ -473,6 +475,18 @@ public:
// Should return a value >= 0 if the current set should be overriden. // Should return a value >= 0 if the current set should be overriden.
// Return -1 if the current set (including no set) should be kept. // Return -1 if the current set (including no set) should be kept.
virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return true if the resuling/current setup would be ok.
// Basic idea is to do aliasing checks and reject invalid semantic names.
virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current location should be overriden.
// Return -1 if the current location (including no location) should be kept.
virtual int resolveInOutLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current component index should be overriden.
// Return -1 if the current component index (including no index) should be kept.
virtual int resolveInOutComponent(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current color index should be overriden.
// Return -1 if the current color index (including no index) should be kept.
virtual int resolveInOutIndex(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
}; };
// Make one TProgram per set of shaders that will get linked together. Add all // Make one TProgram per set of shaders that will get linked together. Add all

View File

@ -3528,7 +3528,9 @@ bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string); parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
} else { } else {
// semantic, in idToken.string // semantic, in idToken.string
parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(*idToken.string)); TString semanticUpperCase = *idToken.string;
std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
} }
} else if (peekTokenClass(EHTokLeftAngle)) { } else if (peekTokenClass(EHTokLeftAngle)) {
found = true; found = true;

View File

@ -4144,7 +4144,7 @@ TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const
// Handle seeing a "COLON semantic" at the end of a type declaration, // Handle seeing a "COLON semantic" at the end of a type declaration,
// by updating the type according to the semantic. // by updating the type according to the semantic.
// //
void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn) void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn, const TString& upperCase)
{ {
// adjust for stage in/out // adjust for stage in/out
@ -4161,6 +4161,7 @@ void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBu
} }
qualifier.builtIn = builtIn; qualifier.builtIn = builtIn;
qualifier.semanticName = intermediate.addSemanticName(upperCase);
} }
// //

View File

@ -91,7 +91,7 @@ public:
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&); TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
TFunction* handleConstructorCall(const TSourceLoc&, const TType&); TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable); void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase);
void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location, void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location,
const glslang::TString* component); const glslang::TString* component);
void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc, void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc,

View File

@ -467,12 +467,9 @@ void HlslScanContext::tokenize(HlslToken& token)
token.tokenClass = tokenClass; token.tokenClass = tokenClass;
} }
glslang::TBuiltInVariable HlslScanContext::mapSemantic(const TString& semantic) glslang::TBuiltInVariable HlslScanContext::mapSemantic(const char* upperCase)
{ {
TString semanticUpperCase = semantic; auto it = SemanticMap->find(upperCase);
std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
auto it = SemanticMap->find(semanticUpperCase.c_str());
if (it != SemanticMap->end()) if (it != SemanticMap->end())
return it->second; return it->second;
else else

View File

@ -82,7 +82,7 @@ public:
static void deleteKeywordMap(); static void deleteKeywordMap();
void tokenize(HlslToken&); void tokenize(HlslToken&);
glslang::TBuiltInVariable mapSemantic(const TString& semantic); glslang::TBuiltInVariable mapSemantic(const char*);
protected: protected:
HlslScanContext(HlslScanContext&); HlslScanContext(HlslScanContext&);

View File

@ -52,7 +52,7 @@ namespace glslang {
bool acceptTokenClass(EHlslTokenClass); bool acceptTokenClass(EHlslTokenClass);
EHlslTokenClass peek() const; EHlslTokenClass peek() const;
bool peekTokenClass(EHlslTokenClass) const; bool peekTokenClass(EHlslTokenClass) const;
glslang::TBuiltInVariable mapSemantic(const TString& semantic) { return scanner.mapSemantic(semantic); } glslang::TBuiltInVariable mapSemantic(const char* upperCase) { return scanner.mapSemantic(upperCase); }
void pushTokenStream(const TVector<HlslToken>* tokens); void pushTokenStream(const TVector<HlslToken>* tokens);
void popTokenStream(); void popTokenStream();