Array of array: Implement the core functionality: types, constructors, operations.
There will be subsequent commits to refine semantics, esp. version-specific semantics, as well as I/O functionality and restrictions. Note: I'm getting white-space differences in the preprocessor test results, which I'm not checking in. I think they need to be tagged as binary or something.
This commit is contained in:
parent
b35483587f
commit
65c78a0b62
23 changed files with 1344 additions and 185 deletions
|
|
@ -896,15 +896,32 @@ public:
|
|||
// and using only shallow copy
|
||||
TType(const TType& type, int derefIndex, bool rowMajor = false)
|
||||
{
|
||||
if (! type.isArray() && (type.basicType == EbtStruct || type.basicType == EbtBlock)) {
|
||||
if (type.isArray()) {
|
||||
shallowCopy(type);
|
||||
if (type.getArraySizes()->getNumDims() == 1) {
|
||||
arraySizes = nullptr;
|
||||
} else {
|
||||
// want our own copy of the array, so we can edit it
|
||||
arraySizes = new TArraySizes;
|
||||
arraySizes->copyDereferenced(*type.arraySizes);
|
||||
}
|
||||
} else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
|
||||
// do a structure dereference
|
||||
const TTypeList& memberList = *type.getStruct();
|
||||
shallowCopy(*memberList[derefIndex].type);
|
||||
return;
|
||||
} else {
|
||||
// do an array/vector/matrix dereference
|
||||
// do a vector/matrix dereference
|
||||
shallowCopy(type);
|
||||
dereference(rowMajor);
|
||||
if (matrixCols > 0) {
|
||||
if (rowMajor)
|
||||
vectorSize = matrixCols;
|
||||
else
|
||||
vectorSize = matrixRows;
|
||||
matrixCols = 0;
|
||||
matrixRows = 0;
|
||||
} else if (vectorSize > 1)
|
||||
vectorSize = 1;
|
||||
}
|
||||
}
|
||||
// for making structures, ...
|
||||
|
|
@ -990,28 +1007,13 @@ public:
|
|||
qualifier = parentType.qualifier;
|
||||
sampler = parentType.sampler;
|
||||
if (parentType.arraySizes)
|
||||
setArraySizes(parentType.arraySizes);
|
||||
newArraySizes(*parentType.arraySizes);
|
||||
if (parentType.userDef) {
|
||||
structure = parentType.userDef->getWritableStruct();
|
||||
setTypeName(parentType.userDef->getTypeName());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void dereference(bool rowMajor = false)
|
||||
{
|
||||
if (arraySizes)
|
||||
arraySizes = nullptr;
|
||||
else if (matrixCols > 0) {
|
||||
if (rowMajor)
|
||||
vectorSize = matrixCols;
|
||||
else
|
||||
vectorSize = matrixRows;
|
||||
matrixCols = 0;
|
||||
matrixRows = 0;
|
||||
} else if (vectorSize > 1)
|
||||
vectorSize = 1;
|
||||
}
|
||||
|
||||
virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
|
||||
virtual bool hiddenMember() const { return basicType == EbtVoid; }
|
||||
|
||||
|
|
@ -1038,17 +1040,20 @@ public:
|
|||
virtual int getVectorSize() const { return vectorSize; }
|
||||
virtual int getMatrixCols() const { return matrixCols; }
|
||||
virtual int getMatrixRows() const { return matrixRows; }
|
||||
virtual int getArraySize() const { return arraySizes->getOuterSize(); }
|
||||
virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
|
||||
virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
|
||||
virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
|
||||
virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
|
||||
virtual const TArraySizes* getArraySizes() const { return arraySizes; }
|
||||
virtual TArraySizes& getArraySizes() { assert(arraySizes != nullptr); return *arraySizes; }
|
||||
|
||||
virtual bool isScalar() const { return vectorSize == 1 && ! isStruct() && ! isArray(); }
|
||||
virtual bool isVector() const { return vectorSize > 1; }
|
||||
virtual bool isMatrix() const { return matrixCols ? true : false; }
|
||||
virtual bool isArray() const { return arraySizes != nullptr; }
|
||||
virtual bool isExplicitlySizedArray() const { return isArray() && getArraySize() != UnsizedArraySize; }
|
||||
virtual bool isImplicitlySizedArray() const { return isArray() && getArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; }
|
||||
virtual bool isRuntimeSizedArray() const { return isArray() && getArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; }
|
||||
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 isStruct() const { return structure != nullptr; }
|
||||
virtual bool isImage() const { return basicType == EbtSampler && getSampler().image; }
|
||||
|
||||
|
|
@ -1125,22 +1130,27 @@ public:
|
|||
assert(type.arraySizes != nullptr);
|
||||
*arraySizes = *type.arraySizes;
|
||||
}
|
||||
void setArraySizes(TArraySizes* s)
|
||||
void newArraySizes(const TArraySizes& s)
|
||||
{
|
||||
// For setting a fresh new set of array sizes, not yet worrying about sharing.
|
||||
arraySizes = new TArraySizes;
|
||||
assert(s != nullptr);
|
||||
*arraySizes = *s;
|
||||
*arraySizes = s;
|
||||
}
|
||||
void setArraySizes(const TType& type) { setArraySizes(type.arraySizes); }
|
||||
void changeArraySize(int s) { arraySizes->changeOuterSize(s); }
|
||||
void addArrayOuterSizes(const TArraySizes& s)
|
||||
{
|
||||
if (arraySizes == nullptr)
|
||||
newArraySizes(s);
|
||||
else
|
||||
arraySizes->addOuterSizes(s);
|
||||
}
|
||||
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()
|
||||
{
|
||||
if (isImplicitlySizedArray())
|
||||
changeArraySize(getImplicitArraySize());
|
||||
changeOuterArraySize(getImplicitArraySize());
|
||||
if (isStruct()) {
|
||||
for (int i = 0; i < (int)structure->size(); ++i)
|
||||
(*structure)[i].type->adoptImplicitArraySizes();
|
||||
|
|
@ -1151,7 +1161,7 @@ public:
|
|||
{
|
||||
return TType::getBasicString(basicType);
|
||||
}
|
||||
|
||||
|
||||
static const char* getBasicString(TBasicType t)
|
||||
{
|
||||
switch (t) {
|
||||
|
|
@ -1242,12 +1252,12 @@ public:
|
|||
p += snprintf(p, end - p, "writeonly ");
|
||||
p += snprintf(p, end - p, "%s ", getStorageQualifierString());
|
||||
if (arraySizes) {
|
||||
if (arraySizes->getOuterSize() == UnsizedArraySize) {
|
||||
p += snprintf(p, end - p, "implicitly-sized array of ");
|
||||
} else {
|
||||
for(int i = 0; i < (int)arraySizes->getNumDims() ; ++i) {
|
||||
p += snprintf(p, end - p, "%d-element array of ", (*arraySizes)[i]);
|
||||
}
|
||||
for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
|
||||
int size = arraySizes->getDimSize(i);
|
||||
if (size == 0)
|
||||
p += snprintf(p, end - p, "implicitly-sized array of ");
|
||||
else
|
||||
p += snprintf(p, end - p, "%d-element array of ", arraySizes->getDimSize(i));
|
||||
}
|
||||
}
|
||||
if (qualifier.precision != EpqNone)
|
||||
|
|
@ -1310,10 +1320,8 @@ public:
|
|||
else
|
||||
components = vectorSize;
|
||||
|
||||
if (isArray()) {
|
||||
// this function can only be used in paths that have a known array size
|
||||
assert(isExplicitlySizedArray());
|
||||
components *= getArraySize();
|
||||
if (arraySizes != nullptr) {
|
||||
components *= arraySizes->getCumulativeSize();
|
||||
}
|
||||
|
||||
return components;
|
||||
|
|
@ -1371,7 +1379,14 @@ public:
|
|||
bool sameArrayness(const TType& right) const
|
||||
{
|
||||
return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
|
||||
(arraySizes && right.arraySizes && *arraySizes == *right.arraySizes));
|
||||
(arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
|
||||
}
|
||||
|
||||
// See if two type's arrayness match in everything except their outer dimension
|
||||
bool sameInnerArrayness(const TType& right) const
|
||||
{
|
||||
assert(arraySizes != nullptr && right.arraySizes != nullptr);
|
||||
return arraySizes->sameInnerArrayness(*right.arraySizes);
|
||||
}
|
||||
|
||||
// See if two type's elements match in all ways except basic type
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@
|
|||
|
||||
namespace glslang {
|
||||
|
||||
// This is used to mean there is no size yet, it is waiting to get a size from somewhere else.
|
||||
// Historically, this is not fully encapsulated, trying to catch them all...
|
||||
// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
|
||||
const int UnsizedArraySize = 0;
|
||||
|
||||
//
|
||||
// TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
|
||||
// It has generic-container semantics, while TArraySizes has array-of-array semantics.
|
||||
// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
|
||||
//
|
||||
struct TSmallArrayVector {
|
||||
//
|
||||
|
|
@ -101,9 +101,43 @@ struct TSmallArrayVector {
|
|||
sizes->push_back(e);
|
||||
}
|
||||
|
||||
void push_front(const TSmallArrayVector& newDims)
|
||||
{
|
||||
alloc();
|
||||
sizes->insert(sizes->begin(), newDims.sizes->begin(), newDims.sizes->end());
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
assert(sizes != nullptr && sizes->size() > 0);
|
||||
if (sizes->size() == 1)
|
||||
dealloc();
|
||||
else
|
||||
sizes->erase(sizes->begin());
|
||||
}
|
||||
|
||||
// 'this' should currently not be holding anything, and copyNonFront
|
||||
// will make it hold a copy of all but the first element of rhs.
|
||||
// (This would be useful for making a type that is dereferenced by
|
||||
// one dimension.)
|
||||
void copyNonFront(const TSmallArrayVector& rhs)
|
||||
{
|
||||
assert(sizes == nullptr);
|
||||
if (rhs.size() > 1) {
|
||||
alloc();
|
||||
sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int operator[](int i) const
|
||||
{
|
||||
assert(sizes && (int)sizes->size() > i);
|
||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
||||
return (*sizes)[i];
|
||||
}
|
||||
|
||||
unsigned int& operator[](int i)
|
||||
{
|
||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
||||
return (*sizes)[i];
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +149,7 @@ struct TSmallArrayVector {
|
|||
return false;
|
||||
return *sizes == *rhs.sizes;
|
||||
}
|
||||
bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
|
||||
|
||||
protected:
|
||||
TSmallArrayVector(const TSmallArrayVector&);
|
||||
|
|
@ -127,6 +162,7 @@ protected:
|
|||
void dealloc()
|
||||
{
|
||||
delete sizes;
|
||||
sizes = nullptr;
|
||||
}
|
||||
|
||||
TVector<unsigned int>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
|
||||
|
|
@ -134,11 +170,17 @@ protected:
|
|||
|
||||
//
|
||||
// Represent an array, or array of arrays, to arbitrary depth. This is not
|
||||
// done through a hierarchy of types, but localized into this single cumulative object.
|
||||
// done through a hierarchy of types in a type tree, rather all contiguous arrayness
|
||||
// in the type hierarchy is localized into this single cumulative object.
|
||||
//
|
||||
// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
|
||||
// for the vast majority of types that are non-array types.
|
||||
//
|
||||
// Order Policy: these are all identical:
|
||||
// - left to right order within a contiguous set of ...[..][..][..]... in the source language
|
||||
// - index order 0, 1, 2, ... within the 'sizes' member below
|
||||
// - outer-most to inner-most
|
||||
//
|
||||
struct TArraySizes {
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
|
|
@ -155,13 +197,57 @@ struct TArraySizes {
|
|||
|
||||
// translate from array-of-array semantics to container semantics
|
||||
int getNumDims() const { return sizes.size(); }
|
||||
int getDimSize(int dim) const { return sizes[dim]; }
|
||||
void setDimSize(int dim, int size) { sizes[dim] = size; }
|
||||
int getOuterSize() const { return sizes.front(); }
|
||||
void setOuterSize(int s) { sizes.push_back((unsigned)s); }
|
||||
int getCumulativeSize() const
|
||||
{
|
||||
int size = 1;
|
||||
for (int d = 0; d < sizes.size(); ++d) {
|
||||
// this only makes sense in paths that have a known array size
|
||||
assert(sizes[d] != UnsizedArraySize);
|
||||
size *= sizes[d];
|
||||
}
|
||||
return size;
|
||||
}
|
||||
void addInnerSize() { sizes.push_back((unsigned)UnsizedArraySize); }
|
||||
void addInnerSize(int s) { sizes.push_back((unsigned)s); }
|
||||
void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
|
||||
int getImplicitSize() const { return (int)implicitArraySize; }
|
||||
void setImplicitSize(int s) { implicitArraySize = s; }
|
||||
int operator[](int i) const { return sizes[i]; }
|
||||
bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; }
|
||||
bool isInnerImplicit() const
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes[d] == (unsigned)UnsizedArraySize)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); }
|
||||
void dereference() { sizes.pop_front(); }
|
||||
void copyDereferenced(const TArraySizes& rhs)
|
||||
{
|
||||
assert(sizes.size() == 0);
|
||||
if (rhs.sizes.size() > 1)
|
||||
sizes.copyNonFront(rhs.sizes);
|
||||
}
|
||||
|
||||
bool sameInnerArrayness(const TArraySizes& rhs) const
|
||||
{
|
||||
if (sizes.size() != rhs.sizes.size())
|
||||
return false;
|
||||
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes[d] != rhs.sizes[d])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
|
||||
bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
|
||||
|
||||
protected:
|
||||
TSmallArrayVector sizes;
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
// For the date, it uses the current date (when then script is run).
|
||||
|
||||
#define GLSLANG_REVISION "2.3.706"
|
||||
#define GLSLANG_DATE "09-Aug-2015"
|
||||
#define GLSLANG_DATE "10-Aug-2015"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue