GLSL/SPV: Implement SPV_EXT_descriptor_indexing and GL_EXT_nonuniform_qualifier
This commit is contained in:
parent
0b5e5da7e7
commit
5611c6d27b
31 changed files with 5887 additions and 4668 deletions
|
|
@ -381,6 +381,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||
if (index->getQualifier().isFrontEndConstant()) {
|
||||
if (base->getType().isUnsizedArray())
|
||||
base->getWritableType().updateImplicitArraySize(indexValue + 1);
|
||||
else
|
||||
checkIndex(loc, base->getType(), indexValue);
|
||||
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
||||
} else {
|
||||
if (base->getType().isUnsizedArray()) {
|
||||
|
|
@ -390,8 +392,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||
error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
|
||||
else {
|
||||
// it is okay for a run-time sized array
|
||||
if (!isRuntimeSizable(*base))
|
||||
error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
|
||||
checkRuntimeSizable(loc, *base);
|
||||
}
|
||||
base->getWritableType().setArrayVariablyIndexed();
|
||||
}
|
||||
|
|
@ -434,6 +435,10 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||
}
|
||||
result->setType(newType);
|
||||
|
||||
// Propagate nonuniform
|
||||
if (base->getQualifier().isNonUniform() || index->getQualifier().isNonUniform())
|
||||
result->getWritableType().getQualifier().nonUniform = true;
|
||||
|
||||
if (anyIndexLimits)
|
||||
handleIndexLimits(loc, base, index);
|
||||
}
|
||||
|
|
@ -742,6 +747,10 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||
if (base->getQualifier().noContraction)
|
||||
result->getWritableType().getQualifier().noContraction = true;
|
||||
|
||||
// Propagate nonuniform
|
||||
if (base->getQualifier().isNonUniform())
|
||||
result->getWritableType().getQualifier().nonUniform = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -2622,6 +2631,10 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
|
|||
{
|
||||
globalQualifierFixCheck(publicType.loc, publicType.qualifier);
|
||||
checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
|
||||
if (publicType.qualifier.isNonUniform()) {
|
||||
error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
|
||||
publicType.qualifier.nonUniform = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -2629,12 +2642,15 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
|
|||
//
|
||||
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
|
||||
{
|
||||
bool nonuniformOkay = false;
|
||||
|
||||
// move from parameter/unknown qualifiers to pipeline in/out qualifiers
|
||||
switch (qualifier.storage) {
|
||||
case EvqIn:
|
||||
profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs");
|
||||
profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs");
|
||||
qualifier.storage = EvqVaryingIn;
|
||||
nonuniformOkay = true;
|
||||
break;
|
||||
case EvqOut:
|
||||
profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs");
|
||||
|
|
@ -2645,10 +2661,17 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
|
|||
qualifier.storage = EvqVaryingIn;
|
||||
error(loc, "cannot use 'inout' at global scope", "", "");
|
||||
break;
|
||||
case EvqGlobal:
|
||||
case EvqTemporary:
|
||||
nonuniformOkay = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nonuniformOkay && qualifier.nonUniform)
|
||||
error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
|
||||
|
||||
invariantCheck(loc, qualifier);
|
||||
}
|
||||
|
||||
|
|
@ -2897,6 +2920,7 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
|
|||
MERGE_SINGLETON(readonly);
|
||||
MERGE_SINGLETON(writeonly);
|
||||
MERGE_SINGLETON(specConstant);
|
||||
MERGE_SINGLETON(nonUniform);
|
||||
|
||||
if (repeated)
|
||||
error(loc, "replicated qualifiers", "", "");
|
||||
|
|
@ -3268,11 +3292,25 @@ void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifie
|
|||
checkIoArraysConsistency(loc);
|
||||
}
|
||||
|
||||
// Policy decision for whether a node could potentially be sized at runtime.
|
||||
bool TParseContext::isRuntimeSizable(const TIntermTyped& base) const
|
||||
// Policy and error check for needing a runtime sized array.
|
||||
void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermTyped& base)
|
||||
{
|
||||
const TType& type = base.getType();
|
||||
if (type.getQualifier().storage == EvqBuffer) {
|
||||
// runtime length implies runtime sizeable, so no problem
|
||||
if (isRuntimeLength(base))
|
||||
return;
|
||||
|
||||
// check for additional things allowed by GL_EXT_nonuniform_qualifier
|
||||
if (base.getBasicType() == EbtSampler ||
|
||||
(base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
|
||||
requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index");
|
||||
else
|
||||
error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
|
||||
}
|
||||
|
||||
// Policy decision for whether a run-time .length() is allowed.
|
||||
bool TParseContext::isRuntimeLength(const TIntermTyped& base) const
|
||||
{
|
||||
if (base.getType().getQualifier().storage == EvqBuffer) {
|
||||
// in a buffer block
|
||||
const TIntermBinary* binary = base.getAsBinaryNode();
|
||||
if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) {
|
||||
|
|
@ -3287,12 +3325,6 @@ bool TParseContext::isRuntimeSizable(const TIntermTyped& base) const
|
|||
return false;
|
||||
}
|
||||
|
||||
// Policy decision for whether a run-time .length() is allowed.
|
||||
bool TParseContext::isRuntimeLength(const TIntermTyped& base) const
|
||||
{
|
||||
return isRuntimeSizable(base);
|
||||
}
|
||||
|
||||
// Returns true if the first argument to the #line directive is the line number for the next line.
|
||||
//
|
||||
// Desktop, pre-version 3.30: "After processing this directive
|
||||
|
|
@ -3703,6 +3735,8 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
|
|||
else
|
||||
warn(loc, "qualifier has no effect on non-output parameters", "precise", "");
|
||||
}
|
||||
if (qualifier.isNonUniform())
|
||||
type.getQualifier().nonUniform = qualifier.nonUniform;
|
||||
|
||||
paramCheckFixStorage(loc, qualifier.storage, type);
|
||||
}
|
||||
|
|
@ -4680,11 +4714,16 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
|||
if (type.getBasicType() == EbtSampler) {
|
||||
int lastBinding = qualifier.layoutBinding;
|
||||
if (type.isArray()) {
|
||||
if (type.isSizedArray())
|
||||
lastBinding += type.getCumulativeArraySize();
|
||||
else {
|
||||
if (spvVersion.vulkan > 0)
|
||||
lastBinding += 1;
|
||||
warn(loc, "assuming array size of one for compile-time checking of binding numbers for unsized array", "[]", "");
|
||||
else {
|
||||
if (type.isSizedArray())
|
||||
lastBinding += type.getCumulativeArraySize();
|
||||
else {
|
||||
lastBinding += 1;
|
||||
if (spvVersion.vulkan == 0)
|
||||
warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits)
|
||||
|
|
@ -5852,6 +5891,11 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||
basicOp = EOpConstructBool;
|
||||
break;
|
||||
|
||||
case EOpConstructNonuniform:
|
||||
node->getWritableType().getQualifier().nonUniform = true;
|
||||
return node;
|
||||
break;
|
||||
|
||||
default:
|
||||
error(loc, "unsupported construction", "", "");
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue