[glslang] Refine implicit array size interfaces. (#3074)
* [glslang] Refine implicit array size interfaces. Help to check builtin and other variables if across stages.
This commit is contained in:
@@ -1894,9 +1894,11 @@ public:
|
||||
virtual bool isArray() const { return arraySizes != nullptr; }
|
||||
virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
|
||||
virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
|
||||
virtual bool isImplicitlySizedArray() const { return isArray() && arraySizes->isImplicitlySized(); }
|
||||
virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
|
||||
virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
|
||||
virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
|
||||
virtual void setImplicitlySized(bool isImplicitSized) { arraySizes->setImplicitlySized(isImplicitSized); }
|
||||
virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
|
||||
virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
|
||||
virtual bool isIntegerDomain() const
|
||||
@@ -2125,8 +2127,12 @@ public:
|
||||
// an explicit array.
|
||||
void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
|
||||
{
|
||||
if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
|
||||
if (isUnsizedArray() &&
|
||||
(qualifier.builtIn == EbvSampleMask ||
|
||||
!(skipNonvariablyIndexed || isArrayVariablyIndexed()))) {
|
||||
changeOuterArraySize(getImplicitArraySize());
|
||||
setImplicitlySized(true);
|
||||
}
|
||||
// For multi-dim per-view arrays, set unsized inner dimension size to 1
|
||||
if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
|
||||
arraySizes->clearInnerUnsized();
|
||||
@@ -2758,7 +2764,10 @@ public:
|
||||
bool sameArrayness(const TType& right) const
|
||||
{
|
||||
return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
|
||||
(arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
|
||||
(arraySizes != nullptr && right.arraySizes != nullptr &&
|
||||
(*arraySizes == *right.arraySizes ||
|
||||
(arraySizes->isImplicitlySized() && right.arraySizes->isDefaultImplicitlySized()) ||
|
||||
(right.arraySizes->isImplicitlySized() && arraySizes->isDefaultImplicitlySized()))));
|
||||
}
|
||||
|
||||
// See if two type's arrayness match in everything except their outer dimension
|
||||
|
||||
@@ -222,7 +222,7 @@ protected:
|
||||
struct TArraySizes {
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
TArraySizes() : implicitArraySize(1), variablyIndexed(false) { }
|
||||
TArraySizes() : implicitArraySize(0), implicitlySized(true), variablyIndexed(false){ }
|
||||
|
||||
// For breaking into two non-shared copies, independently modifiable.
|
||||
TArraySizes& operator=(const TArraySizes& from)
|
||||
@@ -230,6 +230,7 @@ struct TArraySizes {
|
||||
implicitArraySize = from.implicitArraySize;
|
||||
variablyIndexed = from.variablyIndexed;
|
||||
sizes = from.sizes;
|
||||
implicitlySized = from.implicitlySized;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -256,11 +257,17 @@ struct TArraySizes {
|
||||
void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
|
||||
void addInnerSize(TArraySize pair) {
|
||||
sizes.push_back(pair.size, pair.node);
|
||||
implicitlySized = false;
|
||||
}
|
||||
void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
|
||||
void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
|
||||
int getImplicitSize() const { return implicitArraySize; }
|
||||
void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); }
|
||||
void changeOuterSize(int s) {
|
||||
sizes.changeFront((unsigned)s);
|
||||
implicitlySized = false;
|
||||
}
|
||||
int getImplicitSize() const { return implicitArraySize > 0 ? implicitArraySize : 1; }
|
||||
void updateImplicitSize(int s) {
|
||||
implicitArraySize = (std::max)(implicitArraySize, s);
|
||||
}
|
||||
bool isInnerUnsized() const
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
@@ -295,6 +302,9 @@ struct TArraySizes {
|
||||
|
||||
bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
|
||||
bool isSized() const { return getOuterSize() != UnsizedArraySize; }
|
||||
bool isImplicitlySized() const { return implicitlySized; }
|
||||
bool isDefaultImplicitlySized() const { return implicitlySized && implicitArraySize == 0; }
|
||||
void setImplicitlySized(bool isImplicitSizing) { implicitlySized = isImplicitSizing; }
|
||||
void dereference() { sizes.pop_front(); }
|
||||
void copyDereferenced(const TArraySizes& rhs)
|
||||
{
|
||||
@@ -333,6 +343,7 @@ protected:
|
||||
// the implicit size of the array, if not variably indexed and
|
||||
// otherwise legal.
|
||||
int implicitArraySize;
|
||||
bool implicitlySized;
|
||||
bool variablyIndexed; // true if array is indexed with a non compile-time constant
|
||||
};
|
||||
|
||||
|
||||
@@ -608,6 +608,15 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
||||
#ifndef GLSLANG_WEB
|
||||
if (base->getType().isUnsizedArray()) {
|
||||
base->getWritableType().updateImplicitArraySize(indexValue + 1);
|
||||
base->getWritableType().setImplicitlySized(true);
|
||||
if (base->getQualifier().builtIn == EbvClipDistance &&
|
||||
indexValue >= resources.maxClipDistances) {
|
||||
error(loc, "gl_ClipDistance", "[", "array index out of range '%d'", indexValue);
|
||||
}
|
||||
else if (base->getQualifier().builtIn == EbvCullDistance &&
|
||||
indexValue >= resources.maxCullDistances) {
|
||||
error(loc, "gl_CullDistance", "[", "array index out of range '%d'", indexValue);
|
||||
}
|
||||
// For 2D per-view builtin arrays, update the inner dimension size in parent type
|
||||
if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) {
|
||||
TIntermBinary* binaryNode = base->getAsBinaryNode();
|
||||
|
||||
@@ -749,6 +749,21 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
|
||||
symbol->getQualifier().layoutLocation = unitSymbol->getQualifier().layoutLocation;
|
||||
}
|
||||
|
||||
// Update implicit array sizes
|
||||
if (symbol->getWritableType().isImplicitlySizedArray() && unitSymbol->getType().isImplicitlySizedArray()) {
|
||||
if (unitSymbol->getType().getImplicitArraySize() > symbol->getType().getImplicitArraySize()){
|
||||
symbol->getWritableType().updateImplicitArraySize(unitSymbol->getType().getImplicitArraySize());
|
||||
}
|
||||
}
|
||||
else if (symbol->getWritableType().isImplicitlySizedArray() && unitSymbol->getType().isSizedArray()) {
|
||||
if (symbol->getWritableType().getImplicitArraySize() > unitSymbol->getType().getOuterArraySize())
|
||||
error(infoSink, "Implicit size of unsized array doesn't match same symbol among multiple shaders.");
|
||||
}
|
||||
else if (unitSymbol->getType().isImplicitlySizedArray() && symbol->getWritableType().isSizedArray()) {
|
||||
if (unitSymbol->getType().getImplicitArraySize() > symbol->getWritableType().getOuterArraySize())
|
||||
error(infoSink, "Implicit size of unsized array doesn't match same symbol among multiple shaders.");
|
||||
}
|
||||
|
||||
// Update implicit array sizes
|
||||
mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
|
||||
|
||||
@@ -759,6 +774,19 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
|
||||
else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage)
|
||||
error(infoSink, "Only one push_constant block is allowed per stage");
|
||||
}
|
||||
|
||||
// Check conflicts between preset primitives and sizes of I/O variables among multiple geometry shaders
|
||||
if (language == EShLangGeometry && unitStage == EShLangGeometry)
|
||||
{
|
||||
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
|
||||
if (unitSymbol->isArray() && unitSymbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().builtIn == EbvNone)
|
||||
if ((unitSymbol->getArraySizes()->isImplicitlySized() &&
|
||||
unitSymbol->getArraySizes()->getImplicitSize() != TQualifier::mapGeometryToSize(getInputPrimitive())) ||
|
||||
(! unitSymbol->getArraySizes()->isImplicitlySized() &&
|
||||
unitSymbol->getArraySizes()->getDimSize(0) != TQualifier::mapGeometryToSize(getInputPrimitive())))
|
||||
error(infoSink, "Not all array sizes match across all geometry shaders in the program");
|
||||
}
|
||||
|
||||
if (merge) {
|
||||
linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
|
||||
|
||||
@@ -863,7 +891,8 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
||||
else {
|
||||
arraysMatch = symbol.getType().sameArrayness(unitSymbol.getType()) ||
|
||||
(symbol.getType().isArray() && unitSymbol.getType().isArray() &&
|
||||
(symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
|
||||
(symbol.getType().isImplicitlySizedArray() || unitSymbol.getType().isImplicitlySizedArray() ||
|
||||
symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
|
||||
}
|
||||
|
||||
int lpidx = -1;
|
||||
|
||||
Reference in New Issue
Block a user