Merge branch 'semantic_handling' of https://github.com/TiemoJung/glslang into TiemoJung-semantic_handling
This commit is contained in:
commit
2dc50ff372
@ -394,6 +394,7 @@ public:
|
|||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
semanticName = nullptr;
|
||||||
precision = EpqNone;
|
precision = EpqNone;
|
||||||
invariant = false;
|
invariant = false;
|
||||||
noContraction = false;
|
noContraction = false;
|
||||||
@ -403,6 +404,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();
|
||||||
@ -447,10 +449,17 @@ public:
|
|||||||
// If A, then nothing should change, if B, then everything should change, but this is half way.
|
// If A, then nothing should change, if B, then everything should change, but this is half way.
|
||||||
void makePartialTemporary()
|
void makePartialTemporary()
|
||||||
{
|
{
|
||||||
|
semanticName = nullptr;
|
||||||
storage = EvqTemporary;
|
storage = EvqTemporary;
|
||||||
specConstant = false;
|
specConstant = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasSemantic() const
|
||||||
|
{
|
||||||
|
return semanticName != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* semanticName;
|
||||||
TStorageQualifier storage : 6;
|
TStorageQualifier storage : 6;
|
||||||
TBuiltInVariable builtIn : 8;
|
TBuiltInVariable builtIn : 8;
|
||||||
TPrecisionQualifier precision : 3;
|
TPrecisionQualifier precision : 3;
|
||||||
|
@ -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,110 @@ 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;
|
||||||
|
if (base->getQualifier().storage == EvqVaryingIn)
|
||||||
|
target = &inputList;
|
||||||
|
else if (base->getQualifier().storage == EvqVaryingOut)
|
||||||
|
target = &outputList;
|
||||||
|
else if (base->getType().getQualifier().isUniformOrBuffer())
|
||||||
|
target = &uniformList;
|
||||||
|
else
|
||||||
|
target = nullptr;
|
||||||
|
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().storage == EvqUniform)
|
||||||
|
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,9 +252,63 @@ 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&);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -348,6 +445,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 +500,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 +514,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -4161,6 +4161,7 @@ void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBu
|
|||||||
}
|
}
|
||||||
|
|
||||||
qualifier.builtIn = builtIn;
|
qualifier.builtIn = builtIn;
|
||||||
|
qualifier.semanticName = intermediate.addSemanticName(semanticUpperCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user