SPV: Add auto location mapping of non-opaque non-block uniform variables.
Fix #1019.
This commit is contained in:
parent
8268a35504
commit
82e95a3aa5
9 changed files with 93 additions and 12 deletions
|
|
@ -2493,8 +2493,8 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
|
|||
// Vulkan doesn't allow transparent uniforms outside of blocks
|
||||
if (spvVersion.vulkan > 0)
|
||||
vulkanRemoved(loc, "non-opaque uniforms outside a block");
|
||||
// OpenGL wants locations on these
|
||||
if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation())
|
||||
// OpenGL wants locations on these (unless they are getting automapped)
|
||||
if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
|
||||
error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,10 +253,14 @@ struct TResolverUniformAdaptor
|
|||
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) {
|
||||
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);
|
||||
ent.newSet = resolver.resolveSet(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
|
||||
ent.newLocation = resolver.resolveUniformLocation(stage, ent.symbol->getName().c_str(),
|
||||
ent.symbol->getType(), ent.live);
|
||||
|
||||
if (ent.newBinding != -1) {
|
||||
if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
|
||||
|
|
@ -356,6 +360,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
|
|||
std::vector<std::string> baseResourceSetBinding;
|
||||
bool doAutoBindingMapping;
|
||||
bool doAutoLocationMapping;
|
||||
int nextUniformLocation;
|
||||
typedef std::vector<int> TSlotSet;
|
||||
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
|
||||
TSlotSetMap slots;
|
||||
|
|
@ -411,7 +416,27 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
|
|||
|
||||
return 0;
|
||||
}
|
||||
int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
|
||||
{
|
||||
// kick out of not doing this
|
||||
if (!doAutoLocationMapping)
|
||||
return -1;
|
||||
|
||||
// no locations added if already present, a built-in variable, a block, or an opaque
|
||||
if (type.getQualifier().hasLocation() || type.isBuiltIn() ||
|
||||
type.getBasicType() == EbtBlock || type.containsOpaque())
|
||||
return -1;
|
||||
|
||||
// no locations on blocks of built-in variables
|
||||
if (type.isStruct()) {
|
||||
if (type.getStruct()->size() < 1)
|
||||
return -1;
|
||||
if ((*type.getStruct())[0].type->isBuiltIn())
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nextUniformLocation++;
|
||||
}
|
||||
bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
|
||||
{
|
||||
return true;
|
||||
|
|
@ -700,6 +725,7 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
|
|||
resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
|
||||
resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
|
||||
resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
|
||||
resolverBase->nextUniformLocation = 0;
|
||||
|
||||
resolver = resolverBase;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -533,9 +533,10 @@ class TIoMapper;
|
|||
|
||||
// Allows to customize the binding layout after linking.
|
||||
// All used uniform variables will invoke at least validateBinding.
|
||||
// If validateBinding returned true then the other resolveBinding
|
||||
// and resolveSet are invoked to resolve the binding and descriptor
|
||||
// set index respectively.
|
||||
// If validateBinding returned true then the other resolveBinding,
|
||||
// resolveSet, and resolveLocation are invoked to resolve the binding
|
||||
// and descriptor set index respectively.
|
||||
//
|
||||
// Invocations happen in a particular order:
|
||||
// 1) all shader inputs
|
||||
// 2) all shader outputs
|
||||
|
|
@ -567,6 +568,9 @@ public:
|
|||
// Should return a value >= 0 if the current set should be overridden.
|
||||
// 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;
|
||||
// Should return a value >= 0 if the current location should be overridden.
|
||||
// Return -1 if the current location (including no location) should be kept.
|
||||
virtual int resolveUniformLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
|
||||
// Should return true if the resulting/current setup would be okay.
|
||||
// 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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue