Non-functional. Rationalizations enabling future generalizations:
- Use much simpler method to update implicit array sizes. The previous overly complicated method was error prone. - Rationalize all use of unsized arrays. - Combine decorations when generating SPIR-V, to simplify adding extensions.
This commit is contained in:
parent
2316924b09
commit
ead8622484
25 changed files with 563 additions and 583 deletions
|
|
@ -470,7 +470,7 @@ public:
|
|||
// Drop just the storage qualification, which perhaps should
|
||||
// never be done, as it is fundamentally inconsistent, but need to
|
||||
// explore what downstream consumers need.
|
||||
// E.g., in a deference, it is an inconsistency between:
|
||||
// E.g., in a dereference, it is an inconsistency between:
|
||||
// A) partially dereferenced resource is still in the storage class it started in
|
||||
// B) partially dereferenced resource is a new temporary object
|
||||
// If A, then nothing should change, if B, then everything should change, but this is half way.
|
||||
|
|
@ -1354,9 +1354,11 @@ public:
|
|||
virtual bool isVector() const { return vectorSize > 1 || vector1; }
|
||||
virtual bool isMatrix() const { return matrixCols ? true : false; }
|
||||
virtual bool isArray() const { return arraySizes != nullptr; }
|
||||
virtual bool isExplicitlySizedArray() const { return isArray() && getOuterArraySize() != UnsizedArraySize; }
|
||||
virtual bool isImplicitlySizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; }
|
||||
virtual bool isRuntimeSizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; }
|
||||
virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
|
||||
virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
|
||||
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 bool isStruct() const { return structure != nullptr; }
|
||||
virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
|
||||
virtual bool isIntegerDomain() const
|
||||
|
|
@ -1414,10 +1416,10 @@ public:
|
|||
return contains([this](const TType* t) { return t != this && t->isStruct(); } );
|
||||
}
|
||||
|
||||
// Recursively check the structure for any implicitly-sized arrays, needed for triggering a copyUp().
|
||||
virtual bool containsImplicitlySizedArray() const
|
||||
// Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
|
||||
virtual bool containsUnsizedArray() const
|
||||
{
|
||||
return contains([](const TType* t) { return t->isImplicitlySizedArray(); } );
|
||||
return contains([](const TType* t) { return t->isUnsizedArray(); } );
|
||||
}
|
||||
|
||||
virtual bool containsOpaque() const
|
||||
|
|
@ -1510,16 +1512,22 @@ public:
|
|||
}
|
||||
}
|
||||
void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
|
||||
void setImplicitArraySize(int s) { arraySizes->setImplicitSize(s); }
|
||||
|
||||
// Recursively make the implicit array size the explicit array size, through the type tree.
|
||||
void adoptImplicitArraySizes()
|
||||
// Recursively make the implicit array size the explicit array size.
|
||||
// Expicit arrays are compile-time or link-time sized, never run-time sized.
|
||||
// Sometimes, policy calls for an array to be run-time sized even if it was
|
||||
// never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
|
||||
// an explicit array.
|
||||
void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
|
||||
{
|
||||
if (isImplicitlySizedArray())
|
||||
if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
|
||||
changeOuterArraySize(getImplicitArraySize());
|
||||
if (isStruct()) {
|
||||
for (int i = 0; i < (int)structure->size(); ++i)
|
||||
(*structure)[i].type->adoptImplicitArraySizes();
|
||||
if (isStruct() && structure->size() > 0) {
|
||||
int lastMember = (int)structure->size() - 1;
|
||||
for (int i = 0; i < lastMember; ++i)
|
||||
(*structure)[i].type->adoptImplicitArraySizes(false);
|
||||
// implement the "last member of an SSBO" policy
|
||||
(*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1686,17 +1694,21 @@ public:
|
|||
if (isArray()) {
|
||||
for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
|
||||
int size = arraySizes->getDimSize(i);
|
||||
if (size == UnsizedArraySize) {
|
||||
appendStr(" unsized");
|
||||
if (i == 0) {
|
||||
if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
|
||||
appendStr(" runtime-sized array of");
|
||||
else {
|
||||
if (size == UnsizedArraySize) {
|
||||
appendStr(" unsized");
|
||||
if (i == 0) {
|
||||
appendStr(" ");
|
||||
appendInt(arraySizes->getImplicitSize());
|
||||
}
|
||||
} else {
|
||||
appendStr(" ");
|
||||
appendInt(arraySizes->getImplicitSize());
|
||||
appendInt(arraySizes->getDimSize(i));
|
||||
}
|
||||
} else {
|
||||
appendStr(" ");
|
||||
appendInt(arraySizes->getDimSize(i));
|
||||
appendStr("-element array of");
|
||||
}
|
||||
appendStr("-element array of");
|
||||
}
|
||||
}
|
||||
if (qualifier.precision != EpqNone) {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#ifndef _ARRAYS_INCLUDED
|
||||
#define _ARRAYS_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
|
||||
|
|
@ -220,12 +222,13 @@ protected:
|
|||
struct TArraySizes {
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
TArraySizes() : implicitArraySize(1) { }
|
||||
TArraySizes() : implicitArraySize(1), variablyIndexed(false) { }
|
||||
|
||||
// For breaking into two non-shared copies, independently modifiable.
|
||||
TArraySizes& operator=(const TArraySizes& from)
|
||||
{
|
||||
implicitArraySize = from.implicitArraySize;
|
||||
variablyIndexed = from.variablyIndexed;
|
||||
sizes = from.sizes;
|
||||
|
||||
return *this;
|
||||
|
|
@ -254,9 +257,9 @@ struct TArraySizes {
|
|||
void addInnerSize(TArraySize pair) { sizes.push_back(pair.size, pair.node); }
|
||||
void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
|
||||
void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
|
||||
int getImplicitSize() const { return (int)implicitArraySize; }
|
||||
void setImplicitSize(int s) { implicitArraySize = s; }
|
||||
bool isInnerImplicit() const
|
||||
int getImplicitSize() const { return implicitArraySize; }
|
||||
void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); }
|
||||
bool isInnerUnsized() const
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
|
||||
|
|
@ -265,7 +268,7 @@ struct TArraySizes {
|
|||
|
||||
return false;
|
||||
}
|
||||
bool clearInnerImplicit()
|
||||
bool clearInnerUnsized()
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
|
||||
|
|
@ -288,7 +291,8 @@ struct TArraySizes {
|
|||
return sizes.getDimNode(0) != nullptr;
|
||||
}
|
||||
|
||||
bool isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); }
|
||||
bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
|
||||
bool isSized() const { return getOuterSize() != UnsizedArraySize; }
|
||||
void dereference() { sizes.pop_front(); }
|
||||
void copyDereferenced(const TArraySizes& rhs)
|
||||
{
|
||||
|
|
@ -311,6 +315,9 @@ struct TArraySizes {
|
|||
return true;
|
||||
}
|
||||
|
||||
void setVariablyIndexed() { variablyIndexed = true; }
|
||||
bool isVariablyIndexed() const { return variablyIndexed; }
|
||||
|
||||
bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
|
||||
bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
|
||||
|
||||
|
|
@ -319,9 +326,12 @@ protected:
|
|||
|
||||
TArraySizes(const TArraySizes&);
|
||||
|
||||
// for tracking maximum referenced index, before an explicit size is given
|
||||
// applies only to the outer-most dimension
|
||||
// For tracking maximum referenced compile-time constant index.
|
||||
// Applies only to the outer-most dimension. Potentially becomes
|
||||
// the implicit size of the array, if not variably indexed and
|
||||
// otherwise legal.
|
||||
int implicitArraySize;
|
||||
bool variablyIndexed; // true if array is indexed with a non compile-time constant
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
|
|
@ -729,7 +729,11 @@ enum TOperator {
|
|||
// Array operators
|
||||
//
|
||||
|
||||
EOpArrayLength, // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well.
|
||||
// Can apply to arrays, vectors, or matrices.
|
||||
// Can be decomposed to a constant at compile time, but this does not always happen,
|
||||
// due to link-time effects. So, consumer can expect either a link-time sized or
|
||||
// run-time sized array.
|
||||
EOpArrayLength,
|
||||
|
||||
//
|
||||
// Image operations
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue