Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 86d9c93

Browse files
ShabbyXCommit Bot
authored andcommitted
Use TSpan for TType's array sizes
Until C++20, std::vector doesn't have a constexpr constructor, which means TType cannot use a `TVector` for `mArraySizes` if an arrayed type needs to be created constexpr. This is needed for the upcoming textureGatherOffsets implementation. A new TSpan class is introduced, based on std::span (from C++20) that holds the pointer/size allocated from a TVector without owning it. Since TVector's allocation are made from a pool, the allocated memory will live beyond the vector's destruction. `TType::mArraySizes` is changed to this type. This change will allow a new constexpr constructor to be added to TType that takes a TSpan as array directly, a value which is constexpr initialized from a static array (instead of TVector). Bug: angleproject:3569 Change-Id: I78793b0f4c64519e0ebe30cf6e0de995ba70035d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1968260 Reviewed-by: Jiajia Qin <[email protected]> Reviewed-by: Shahbaz Youssefi <[email protected]> Commit-Queue: Shahbaz Youssefi <[email protected]>
1 parent c713abf commit 86d9c93

15 files changed

+431
-135
lines changed

src/compiler/translator/CollectVariables.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,10 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
653653
variableOut->fields.push_back(fieldVariable);
654654
}
655655
}
656-
if (auto *arraySizes = type.getArraySizes())
656+
const TSpan<const unsigned int> &arraySizes = type.getArraySizes();
657+
if (!arraySizes.empty())
657658
{
658-
variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
659+
variableOut->arraySizes.assign(arraySizes.begin(), arraySizes.end());
659660
}
660661
}
661662

src/compiler/translator/Common.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,105 @@ class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
108108
{}
109109
};
110110

111+
// Basic implementation of C++20's span for use with pool-allocated containers (TVector) or static
112+
// arrays. This is used by the array sizes member of TType to allow arrayed types to be
113+
// constexpr-constructed.
114+
// See the reference for std::span here: https://en.cppreference.com/w/cpp/container/span
115+
template <typename T>
116+
class TSpan
117+
{
118+
public:
119+
typedef size_t size_type;
120+
121+
constexpr TSpan() {}
122+
constexpr TSpan(T *ptr, size_type size) : mData(ptr), mSize(size) {}
123+
124+
constexpr TSpan(const TSpan &that) : mData(that.mData), mSize(that.mSize) {}
125+
constexpr TSpan &operator=(const TSpan &that)
126+
{
127+
mData = that.mData;
128+
mSize = that.mSize;
129+
return *this;
130+
}
131+
132+
// Note: the pointer is taken out of the TVector because TVector's memory is pool allocated,
133+
// so the memory will live on even if the TVector is destroyed.
134+
template <typename S>
135+
TSpan(const TVector<S> &vec) : mData(vec.data()), mSize(vec.size())
136+
{}
137+
template <typename S>
138+
TSpan &operator=(const TVector<S> &vec)
139+
{
140+
mData = vec.data();
141+
mSize = vec.size();
142+
return *this;
143+
}
144+
145+
constexpr bool operator==(const TSpan &that) const
146+
{
147+
if (mSize != that.mSize)
148+
{
149+
return false;
150+
}
151+
152+
if (mData == that.mData)
153+
{
154+
return true;
155+
}
156+
157+
for (size_type index = 0; index < mSize; ++index)
158+
{
159+
if (mData[index] != that.mData[index])
160+
{
161+
return false;
162+
}
163+
}
164+
165+
return true;
166+
}
167+
constexpr bool operator!=(const TSpan &that) const { return !(*this == that); }
168+
169+
constexpr T *data() const { return mData; }
170+
constexpr size_type size() const { return mSize; }
171+
constexpr bool empty() const { return mSize == 0; }
172+
173+
constexpr T &operator[](size_type index) const { return mData[index]; }
174+
constexpr T &front() const { return mData[0]; }
175+
constexpr T &back() const { return mData[mSize - 1]; }
176+
177+
constexpr T *begin() const { return mData; }
178+
constexpr T *end() const { return mData + mSize; }
179+
180+
constexpr std::reverse_iterator<T *> rbegin() const
181+
{
182+
return std::make_reverse_iterator(end());
183+
}
184+
constexpr std::reverse_iterator<T *> rend() const
185+
{
186+
return std::make_reverse_iterator(begin());
187+
}
188+
189+
constexpr TSpan first(size_type count) const
190+
{
191+
ASSERT(count <= mSize);
192+
return count == 0 ? TSpan() : TSpan(mData, count);
193+
}
194+
constexpr TSpan last(size_type count) const
195+
{
196+
ASSERT(count <= mSize);
197+
return count == 0 ? TSpan() : TSpan(mData + mSize - count, count);
198+
}
199+
constexpr TSpan subspan(size_type offset, size_type count) const
200+
{
201+
ASSERT(offset + count <= mSize);
202+
return count == 0 ? TSpan() : TSpan(mData + offset, count);
203+
}
204+
205+
private:
206+
T *mData = nullptr;
207+
size_t mSize = 0;
208+
};
209+
111210
// Integer to TString conversion
112211
template <typename T>
113212
inline TString str(T i)

src/compiler/translator/InfoSink.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ TInfoSinkBase &TInfoSinkBase::operator<<(const TType &type)
7373

7474
if (type.isArray())
7575
{
76-
for (auto arraySizeIter = type.getArraySizes()->rbegin();
77-
arraySizeIter != type.getArraySizes()->rend(); ++arraySizeIter)
76+
for (auto arraySizeIter = type.getArraySizes().rbegin();
77+
arraySizeIter != type.getArraySizes().rend(); ++arraySizeIter)
7878
{
7979
*this << "array[" << (*arraySizeIter) << "] of ";
8080
}

src/compiler/translator/OutputHLSL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ TString ArrayHelperFunctionName(const char *prefix, const TType &type)
4343
fnName << prefix << "_";
4444
if (type.isArray())
4545
{
46-
for (unsigned int arraySize : *type.getArraySizes())
46+
for (unsigned int arraySize : type.getArraySizes())
4747
{
4848
fnName << arraySize << "_";
4949
}

src/compiler/translator/ParseContext.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,8 +1961,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
19611961
// will default to setting array sizes to 1. We have not checked yet whether the initializer
19621962
// actually is an array or not. Having a non-array initializer for an unsized array will
19631963
// result in an error later, so we don't generate an error message here.
1964-
auto *arraySizes = initializer->getType().getArraySizes();
1965-
type->sizeUnsizedArrays(arraySizes);
1964+
type->sizeUnsizedArrays(initializer->getType().getArraySizes());
19661965
}
19671966

19681967
const TQualifier qualifier = type->getQualifier();
@@ -3531,7 +3530,7 @@ void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
35313530
if (arrayType->isUnsizedArray())
35323531
{
35333532
error(line, errorMessage, token);
3534-
arrayType->sizeUnsizedArrays(nullptr);
3533+
arrayType->sizeUnsizedArrays(TSpan<const unsigned int>());
35353534
}
35363535
}
35373536

@@ -3623,7 +3622,7 @@ TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSour
36233622
{
36243623
if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
36253624
{
3626-
type.sizeUnsizedArrays(nullptr);
3625+
type.sizeUnsizedArrays(TSpan<const unsigned int>());
36273626
return CreateZeroNode(type);
36283627
}
36293628
TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
@@ -3634,9 +3633,9 @@ TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSour
36343633
}
36353634
for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
36363635
{
3637-
if ((*type.getArraySizes())[i] == 0u)
3636+
if (type.getArraySizes()[i] == 0u)
36383637
{
3639-
type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]);
3638+
type.setArraySize(i, firstElement->getType().getArraySizes()[i]);
36403639
}
36413640
}
36423641
ASSERT(!type.isUnsizedArray());
@@ -5227,7 +5226,7 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
52275226
return false;
52285227
}
52295228
// At this point, size of implicitly sized arrays should be resolved.
5230-
if (*left->getType().getArraySizes() != *right->getType().getArraySizes())
5229+
if (left->getType().getArraySizes() != right->getType().getArraySizes())
52315230
{
52325231
error(loc, "array size mismatch", GetOperatorString(op));
52335232
return false;

src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ const BlockMemberInfo GetBlockMemberInfoByType(const TType &type,
111111
}
112112

113113
std::vector<unsigned int> arraySizes;
114-
auto *typeArraySizes = type.getArraySizes();
115-
if (typeArraySizes != nullptr)
114+
const TSpan<const unsigned int> &typeArraySizes = type.getArraySizes();
115+
if (!typeArraySizes.empty())
116116
{
117-
arraySizes.assign(typeArraySizes->begin(), typeArraySizes->end());
117+
arraySizes.assign(typeArraySizes.begin(), typeArraySizes.end());
118118
}
119119
return encoder->encodeType(GLVariableType(type), arraySizes, rowMajor);
120120
}
@@ -677,7 +677,7 @@ void ShaderStorageBlockOutputHLSL::writeEOpIndexDirectOrIndirectOutput(TInfoSink
677677
{
678678
if (type.isArrayOfArrays())
679679
{
680-
const TVector<unsigned int> &arraySizes = *type.getArraySizes();
680+
const TSpan<const unsigned int> &arraySizes = type.getArraySizes();
681681
// Don't need to concern the tail comma which will be used to multiply the index.
682682
for (unsigned int i = 0; i < (arraySizes.size() - 1); i++)
683683
{

0 commit comments

Comments
 (0)