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:
John Kessenich 2018-03-28 18:01:20 -06:00
parent 2316924b09
commit ead8622484
25 changed files with 563 additions and 583 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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