Revert "Revert "GL_ext_vulkan_glsl_relaxed extension support, and cross stage aware IO mapper""
This commit is contained in:
parent
a36d91e5ac
commit
4e064eef46
43 changed files with 6707 additions and 111 deletions
|
|
@ -210,8 +210,8 @@ struct TResolverUniformAdaptor {
|
|||
ent.newIndex = -1;
|
||||
const bool isValid = resolver.validateBinding(stage, ent);
|
||||
if (isValid) {
|
||||
resolver.resolveBinding(ent.stage, ent);
|
||||
resolver.resolveSet(ent.stage, ent);
|
||||
resolver.resolveBinding(ent.stage, ent);
|
||||
resolver.resolveUniformLocation(ent.stage, ent);
|
||||
|
||||
if (ent.newBinding != -1) {
|
||||
|
|
@ -317,15 +317,13 @@ private:
|
|||
};
|
||||
|
||||
// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
|
||||
// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform"
|
||||
|
||||
struct TSymbolValidater
|
||||
{
|
||||
TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
|
||||
TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version)
|
||||
: preStage(EShLangCount)
|
||||
, currentStage(EShLangCount)
|
||||
, nextStage(EShLangCount)
|
||||
, resolver(r)
|
||||
: resolver(r)
|
||||
, infoSink(i)
|
||||
, hadError(hadError)
|
||||
, profile(profile)
|
||||
|
|
@ -438,17 +436,23 @@ struct TSymbolValidater
|
|||
TIntermSymbol* base = ent1.symbol;
|
||||
const TType& type = ent1.symbol->getType();
|
||||
const TString& name = entKey.first;
|
||||
EShLanguage stage = ent1.stage;
|
||||
TString mangleName1, mangleName2;
|
||||
if (currentStage != stage) {
|
||||
preStage = currentStage;
|
||||
currentStage = stage;
|
||||
nextStage = EShLangCount;
|
||||
for (int i = currentStage + 1; i < EShLangCount; i++) {
|
||||
if (inVarMaps[i] != nullptr) {
|
||||
nextStage = static_cast<EShLanguage>(i);
|
||||
break;
|
||||
}
|
||||
EShLanguage stage = ent1.stage;
|
||||
EShLanguage preStage, currentStage, nextStage;
|
||||
|
||||
preStage = EShLangCount;
|
||||
for (int i = stage - 1; i >= 0; i--) {
|
||||
if (inVarMaps[i] != nullptr) {
|
||||
preStage = static_cast<EShLanguage>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentStage = stage;
|
||||
nextStage = EShLangCount;
|
||||
for (int i = stage + 1; i < EShLangCount; i++) {
|
||||
if (inVarMaps[i] != nullptr) {
|
||||
nextStage = static_cast<EShLanguage>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -459,6 +463,9 @@ struct TSymbolValidater
|
|||
type.appendMangledName(mangleName1);
|
||||
}
|
||||
|
||||
|
||||
// basic checking that symbols match
|
||||
// more extensive checking in the link stage
|
||||
if (base->getQualifier().storage == EvqVaryingIn) {
|
||||
// validate stage in;
|
||||
if (preStage == EShLangCount)
|
||||
|
|
@ -484,8 +491,7 @@ struct TSymbolValidater
|
|||
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
|
||||
TType subType(ent2->second.symbol->getType(), 0);
|
||||
subType.appendMangledName(mangleName2);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
||||
}
|
||||
|
||||
|
|
@ -536,8 +542,7 @@ struct TSymbolValidater
|
|||
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
|
||||
TType subType(ent2->second.symbol->getType(), 0);
|
||||
subType.appendMangledName(mangleName2);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
||||
}
|
||||
if (mangleName1 == mangleName2)
|
||||
|
|
@ -550,7 +555,7 @@ struct TSymbolValidater
|
|||
}
|
||||
return;
|
||||
}
|
||||
} else if (base->getQualifier().isUniformOrBuffer() && ! base->getQualifier().isPushConstant()) {
|
||||
} else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) {
|
||||
// validate uniform type;
|
||||
for (int i = 0; i < EShLangCount; i++) {
|
||||
if (i != currentStage && outVarMaps[i] != nullptr) {
|
||||
|
|
@ -558,6 +563,7 @@ struct TSymbolValidater
|
|||
if (ent2 != uniformVarMap[i]->end()) {
|
||||
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
||||
if (mangleName1 != mangleName2) {
|
||||
ent2->second.symbol->getType().sameElementType(type);
|
||||
TString err = "Invalid Uniform variable type : " + entKey.first;
|
||||
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||
hadError = true;
|
||||
|
|
@ -608,8 +614,7 @@ struct TSymbolValidater
|
|||
}
|
||||
|
||||
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
|
||||
// Use for mark pre stage, to get more interface symbol information.
|
||||
EShLanguage preStage, currentStage, nextStage;
|
||||
|
||||
// Use for mark current shader stage for resolver
|
||||
TIoMapResolver& resolver;
|
||||
TInfoSink& infoSink;
|
||||
|
|
@ -749,14 +754,18 @@ TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate
|
|||
, nextOutputLocation(0)
|
||||
{
|
||||
memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
|
||||
memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount));
|
||||
stageIntermediates[intermediate.getStage()] = &intermediate;
|
||||
}
|
||||
|
||||
int TDefaultIoResolverBase::getBaseBinding(TResourceType res, unsigned int set) const {
|
||||
return selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
|
||||
int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const {
|
||||
return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set))
|
||||
: selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
|
||||
}
|
||||
|
||||
const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding() const {
|
||||
return intermediate.getResourceSetBinding();
|
||||
const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const {
|
||||
return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding()
|
||||
: intermediate.getResourceSetBinding();
|
||||
}
|
||||
|
||||
bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
|
||||
|
|
@ -797,14 +806,14 @@ int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) {
|
|||
return reserveSlot(set, base, size);
|
||||
}
|
||||
|
||||
int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
||||
int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) {
|
||||
const TType& type = ent.symbol->getType();
|
||||
if (type.getQualifier().hasSet()) {
|
||||
return ent.newSet = type.getQualifier().layoutSet;
|
||||
}
|
||||
// If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
|
||||
if (getResourceSetBinding().size() == 1) {
|
||||
return ent.newSet = atoi(getResourceSetBinding()[0].c_str());
|
||||
if (getResourceSetBinding(stage).size() == 1) {
|
||||
return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str());
|
||||
}
|
||||
return ent.newSet = 0;
|
||||
}
|
||||
|
|
@ -925,7 +934,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
|
|||
preStage = currentStage;
|
||||
currentStage = stage;
|
||||
}
|
||||
// kick out of not doing this
|
||||
// kick out if not doing this
|
||||
if (! doAutoLocationMapping()) {
|
||||
return ent.newLocation = -1;
|
||||
}
|
||||
|
|
@ -1073,7 +1082,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
|
|||
return ent.newLocation = location;
|
||||
}
|
||||
|
||||
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
||||
int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) {
|
||||
const TType& type = ent.symbol->getType();
|
||||
const TString& name = ent.symbol->getAccessName();
|
||||
// On OpenGL arrays of opaque types take a separate binding for each element
|
||||
|
|
@ -1086,30 +1095,32 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo&
|
|||
// There is no 'set' qualifier in OpenGL shading language, each resource has its own
|
||||
// binding name space, so remap the 'set' to resource type which make each resource
|
||||
// binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
|
||||
int set = resource;
|
||||
int set = intermediate.getSpv().openGl != 0 ? resource : ent.newSet;
|
||||
int resourceKey = set;
|
||||
if (resource < EResCount) {
|
||||
if (type.getQualifier().hasBinding()) {
|
||||
ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
|
||||
return ent.newBinding;
|
||||
} else if (ent.live && doAutoBindingMapping()) {
|
||||
int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
|
||||
return ent.newBinding = newBinding;
|
||||
|
||||
} else {
|
||||
// The resource in current stage is not declared with binding, but it is possible declared
|
||||
// with explicit binding in other stages, find the resourceSlotMap firstly to check whether
|
||||
// the resource has binding, don't need to allocate if it already has a binding
|
||||
bool hasBinding = false;
|
||||
if (! resourceSlotMap[resource].empty()) {
|
||||
TVarSlotMap::iterator iter = resourceSlotMap[resource].find(name);
|
||||
if (iter != resourceSlotMap[resource].end()) {
|
||||
ent.newBinding = -1; // leave as -1 if it isn't set below
|
||||
|
||||
if (! resourceSlotMap[resourceKey].empty()) {
|
||||
TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name);
|
||||
if (iter != resourceSlotMap[resourceKey].end()) {
|
||||
hasBinding = true;
|
||||
ent.newBinding = iter->second;
|
||||
}
|
||||
}
|
||||
if (! hasBinding) {
|
||||
TVarSlotMap varSlotMap;
|
||||
if (!hasBinding && (ent.live && doAutoBindingMapping())) {
|
||||
// find free slot, the caller did make sure it passes all vars with binding
|
||||
// first and now all are passed that do not have a binding and needs one
|
||||
int binding = getFreeSlot(resource, getBaseBinding(resource, set), numBindings);
|
||||
varSlotMap[name] = binding;
|
||||
resourceSlotMap[resource] = varSlotMap;
|
||||
int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings);
|
||||
resourceSlotMap[resourceKey][name] = binding;
|
||||
ent.newBinding = binding;
|
||||
}
|
||||
return ent.newBinding;
|
||||
|
|
@ -1211,16 +1222,20 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
|
|||
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||
const TType& type = ent.symbol->getType();
|
||||
const TString& name = ent.symbol->getAccessName();
|
||||
int resource = getResourceType(type);
|
||||
TResourceType resource = getResourceType(type);
|
||||
int set = intermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent);
|
||||
int resourceKey = set;
|
||||
|
||||
if (type.getQualifier().hasBinding()) {
|
||||
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
|
||||
TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey];
|
||||
TVarSlotMap::iterator iter = varSlotMap.find(name);
|
||||
int binding = type.getQualifier().layoutBinding;
|
||||
int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set);
|
||||
|
||||
if (iter == varSlotMap.end()) {
|
||||
// Reserve the slots for the ubo, ssbo and opaques who has explicit binding
|
||||
int numBindings = type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
||||
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
||||
varSlotMap[name] = binding;
|
||||
reserveSlot(resource, binding, numBindings);
|
||||
reserveSlot(resourceKey, binding, numBindings);
|
||||
} else {
|
||||
// Allocate binding by name for OpenGL driver, so the resource in different
|
||||
// stages should be declared with the same binding
|
||||
|
|
@ -1269,7 +1284,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
|
|||
return EResCount;
|
||||
}
|
||||
|
||||
int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
|
||||
int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
|
||||
const TType& type = ent.symbol->getType();
|
||||
const int set = getLayoutSet(type);
|
||||
// On OpenGL arrays of opaque types take a seperate binding for each element
|
||||
|
|
@ -1278,11 +1293,11 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
|
|||
if (resource < EResCount) {
|
||||
if (type.getQualifier().hasBinding()) {
|
||||
return ent.newBinding = reserveSlot(
|
||||
set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
|
||||
set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
|
||||
} else if (ent.live && doAutoBindingMapping()) {
|
||||
// find free slot, the caller did make sure it passes all vars with binding
|
||||
// first and now all are passed that do not have a binding and needs one
|
||||
return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set), numBindings);
|
||||
return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings);
|
||||
}
|
||||
}
|
||||
return ent.newBinding = -1;
|
||||
|
|
@ -1354,17 +1369,17 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
|
|||
return EResCount;
|
||||
}
|
||||
|
||||
int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
|
||||
int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
|
||||
const TType& type = ent.symbol->getType();
|
||||
const int set = getLayoutSet(type);
|
||||
TResourceType resource = getResourceType(type);
|
||||
if (resource < EResCount) {
|
||||
if (type.getQualifier().hasBinding()) {
|
||||
return ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding);
|
||||
return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding);
|
||||
} else if (ent.live && doAutoBindingMapping()) {
|
||||
// find free slot, the caller did make sure it passes all vars with binding
|
||||
// first and now all are passed that do not have a binding and needs one
|
||||
return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set));
|
||||
return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set));
|
||||
}
|
||||
}
|
||||
return ent.newBinding = -1;
|
||||
|
|
@ -1403,10 +1418,10 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
|
|||
else
|
||||
resolver = &defaultResolver;
|
||||
}
|
||||
resolver->addStage(stage);
|
||||
#else
|
||||
resolver = &defaultResolver;
|
||||
#endif
|
||||
resolver->addStage(stage, intermediate);
|
||||
|
||||
TVarLiveMap inVarMap, outVarMap, uniformVarMap;
|
||||
TVarLiveVector inVector, outVector, uniformVector;
|
||||
|
|
@ -1502,10 +1517,21 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn
|
|||
}
|
||||
// if no resolver is provided, use the default resolver with the given shifts and auto map settings
|
||||
TDefaultGlslIoResolver defaultResolver(intermediate);
|
||||
#ifdef ENABLE_HLSL
|
||||
TDefaultHlslIoResolver defaultHlslResolver(intermediate);
|
||||
if (resolver == nullptr) {
|
||||
// TODO: use a passed in IO mapper for this
|
||||
if (intermediate.usingHlslIoMapping())
|
||||
resolver = &defaultHlslResolver;
|
||||
else
|
||||
resolver = &defaultResolver;
|
||||
}
|
||||
#else
|
||||
if (resolver == nullptr) {
|
||||
resolver = &defaultResolver;
|
||||
}
|
||||
resolver->addStage(stage);
|
||||
#endif
|
||||
resolver->addStage(stage, intermediate);
|
||||
inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
|
||||
TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
|
||||
*uniformVarMap[stage]);
|
||||
|
|
@ -1547,15 +1573,51 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
|
|||
TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
|
||||
TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps,
|
||||
outVarMaps, uniformVarMap, hadError, profile, version);
|
||||
|
||||
TVarLiveVector inVectors[EShLangCount];
|
||||
TVarLiveVector outVectors[EShLangCount];
|
||||
TVarLiveVector uniformVector;
|
||||
|
||||
resolver->beginResolve(EShLangCount);
|
||||
for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
|
||||
if (inVarMaps[stage] != nullptr) {
|
||||
inOutResolve.setStage(EShLanguage(stage));
|
||||
for (auto& var : *(inVarMaps[stage])) { symbolValidater(var); }
|
||||
for (auto& var : *(inVarMaps[stage])) { inOutResolve(var); }
|
||||
for (auto& var : *(outVarMaps[stage])) { symbolValidater(var); }
|
||||
for (auto& var : *(outVarMaps[stage])) { inOutResolve(var); }
|
||||
|
||||
// copy vars into a sorted list
|
||||
std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(),
|
||||
[&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); });
|
||||
std::sort(inVectors[stage].begin(), inVectors[stage].end(),
|
||||
[](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||
});
|
||||
|
||||
std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(),
|
||||
[&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); });
|
||||
std::sort(outVectors[stage].begin(), outVectors[stage].end(),
|
||||
[](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||
});
|
||||
|
||||
for (auto& var : inVectors[stage]) { symbolValidater(var); }
|
||||
for (auto& var : inVectors[stage]) { inOutResolve(var); }
|
||||
for (auto& var : outVectors[stage]) { symbolValidater(var); }
|
||||
for (auto& var : outVectors[stage]) { inOutResolve(var); }
|
||||
|
||||
// copy results back into maps
|
||||
std::for_each(inVectors[stage].begin(), inVectors[stage].end(),
|
||||
[this, stage](TVarLivePair p) {
|
||||
auto at = inVarMaps[stage]->find(p.first);
|
||||
if (at != inVarMaps[stage]->end())
|
||||
at->second = p.second;
|
||||
});
|
||||
|
||||
std::for_each(outVectors[stage].begin(), outVectors[stage].end(),
|
||||
[this, stage](TVarLivePair p) {
|
||||
auto at = outVarMaps[stage]->find(p.first);
|
||||
if (at != outVarMaps[stage]->end())
|
||||
at->second = p.second;
|
||||
});
|
||||
|
||||
}
|
||||
if (uniformVarMap[stage] != nullptr) {
|
||||
uniformResolve.setStage(EShLanguage(stage));
|
||||
|
|
@ -1563,7 +1625,7 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
|
|||
}
|
||||
}
|
||||
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||
return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second);
|
||||
});
|
||||
for (auto& var : uniformVector) { symbolValidater(var); }
|
||||
for (auto& var : uniformVector) { uniformResolve(var); }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue