Improvements to the gl::Range class.
Make this a proper class, fix the extends method (previously did not
work as expected), add a contains method, and add tests. Also add an
iterator helper class so we can iterate over the range with range-for
loops.
This also fixes the shader resource unsetting code, which was not
actually unsetting all the possible applied textures.
BUG=angleproject:2052
Change-Id: I2a6fa97f96ccb612ad01a5e3f24dc869c54c967b
Reviewed-on: https://chromium-review.googlesource.com/527318
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/common/mathutil.h b/src/common/mathutil.h
index 5b1dd99..ccfab21 100644
--- a/src/common/mathutil.h
+++ b/src/common/mathutil.h
@@ -557,38 +557,65 @@
}
template <typename T>
-struct Range
+class Range
{
+ public:
Range() {}
- Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
+ Range(T lo, T hi) : mLow(lo), mHigh(hi) {}
- T start;
- T end;
-
- T length() const { return end - start; }
+ T length() const { return (empty() ? 0 : (mHigh - mLow)); }
bool intersects(Range<T> other)
{
- if (start <= other.start)
+ if (mLow <= other.mLow)
{
- return other.start < end;
+ return other.mLow < mHigh;
}
else
{
- return start < other.end;
+ return mLow < other.mHigh;
}
}
+ // Assumes that end is non-inclusive.. for example, extending to 5 will make "end" 6.
void extend(T value)
{
- start = value > start ? value : start;
- end = value < end ? value : end;
+ mLow = value < mLow ? value : mLow;
+ mHigh = value >= mHigh ? (value + 1) : mHigh;
}
- bool empty() const
+ bool empty() const { return mHigh <= mLow; }
+
+ bool contains(T value) const { return value >= mLow && value < mHigh; }
+
+ class Iterator final
{
- return end <= start;
- }
+ public:
+ Iterator(T value) : mCurrent(value) {}
+
+ Iterator &operator++()
+ {
+ mCurrent++;
+ return *this;
+ }
+ bool operator==(const Iterator &other) const { return mCurrent == other.mCurrent; }
+ bool operator!=(const Iterator &other) const { return mCurrent != other.mCurrent; }
+ T operator*() const { return mCurrent; }
+
+ private:
+ T mCurrent;
+ };
+
+ Iterator begin() const { return Iterator(mLow); }
+
+ Iterator end() const { return Iterator(mHigh); }
+
+ T low() const { return mLow; }
+ T high() const { return mHigh; }
+
+ private:
+ T mLow;
+ T mHigh;
};
typedef Range<int> RangeI;
diff --git a/src/common/mathutil_unittest.cpp b/src/common/mathutil_unittest.cpp
index ad39b38..1949ad1 100644
--- a/src/common/mathutil_unittest.cpp
+++ b/src/common/mathutil_unittest.cpp
@@ -331,4 +331,38 @@
EXPECT_EQ(0.0f, Ldexp(1.0f, -129));
}
+// Test that Range::extend works as expected.
+TEST(MathUtilTest, RangeExtend)
+{
+ RangeI range(0, 0);
+
+ range.extend(5);
+ EXPECT_EQ(0, range.low());
+ EXPECT_EQ(6, range.high());
+ EXPECT_EQ(6, range.length());
+
+ range.extend(-1);
+ EXPECT_EQ(-1, range.low());
+ EXPECT_EQ(6, range.high());
+ EXPECT_EQ(7, range.length());
+
+ range.extend(10);
+ EXPECT_EQ(-1, range.low());
+ EXPECT_EQ(11, range.high());
+ EXPECT_EQ(12, range.length());
+}
+
+// Test that Range iteration works as expected.
+TEST(MathUtilTest, RangeIteration)
+{
+ RangeI range(0, 10);
+ int expected = 0;
+ for (int value : range)
+ {
+ EXPECT_EQ(expected, value);
+ expected++;
+ }
+ EXPECT_EQ(range.length(), expected);
+}
+
} // anonymous namespace
diff --git a/src/libANGLE/ImageIndex.cpp b/src/libANGLE/ImageIndex.cpp
index 2318541..657e3ad 100644
--- a/src/libANGLE/ImageIndex.cpp
+++ b/src/libANGLE/ImageIndex.cpp
@@ -139,14 +139,16 @@
nullptr);
}
-ImageIndexIterator::ImageIndexIterator(GLenum type, const Range<GLint> &mipRange,
- const Range<GLint> &layerRange, const GLsizei *layerCounts)
+ImageIndexIterator::ImageIndexIterator(GLenum type,
+ const Range<GLint> &mipRange,
+ const Range<GLint> &layerRange,
+ const GLsizei *layerCounts)
: mType(type),
mMipRange(mipRange),
mLayerRange(layerRange),
mLayerCounts(layerCounts),
- mCurrentMip(mipRange.start),
- mCurrentLayer(layerRange.start)
+ mCurrentMip(mipRange.low()),
+ mCurrentLayer(layerRange.low())
{}
GLint ImageIndexIterator::maxLayer() const
@@ -154,9 +156,9 @@
if (mLayerCounts)
{
ASSERT(mCurrentMip >= 0);
- return (mCurrentMip < mMipRange.end) ? mLayerCounts[mCurrentMip] : 0;
+ return (mCurrentMip < mMipRange.high()) ? mLayerCounts[mCurrentMip] : 0;
}
- return mLayerRange.end;
+ return mLayerRange.high();
}
ImageIndex ImageIndexIterator::next()
@@ -174,20 +176,20 @@
{
mCurrentLayer++;
}
- else if (mCurrentMip < mMipRange.end - 1)
+ else if (mCurrentMip < mMipRange.high() - 1)
{
mCurrentMip++;
- mCurrentLayer = mLayerRange.start;
+ mCurrentLayer = mLayerRange.low();
}
else
{
done();
}
}
- else if (mCurrentMip < mMipRange.end - 1)
+ else if (mCurrentMip < mMipRange.high() - 1)
{
mCurrentMip++;
- mCurrentLayer = mLayerRange.start;
+ mCurrentLayer = mLayerRange.low();
}
else
{
@@ -211,12 +213,12 @@
bool ImageIndexIterator::hasNext() const
{
- return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
+ return (mCurrentMip < mMipRange.high() || mCurrentLayer < maxLayer());
}
void ImageIndexIterator::done()
{
- mCurrentMip = mMipRange.end;
+ mCurrentMip = mMipRange.high();
mCurrentLayer = maxLayer();
}
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 2a45df2..6d18f2a 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -396,13 +396,13 @@
bool ProgramState::isSamplerUniformIndex(GLuint index) const
{
- return index >= mSamplerUniformRange.start && index < mSamplerUniformRange.end;
+ return mSamplerUniformRange.contains(index);
}
GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
{
ASSERT(isSamplerUniformIndex(uniformIndex));
- return uniformIndex - mSamplerUniformRange.start;
+ return uniformIndex - mSamplerUniformRange.low();
}
Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
@@ -949,8 +949,11 @@
"All bits of DrawBufferMask can be contained in an uint32_t");
mState.mActiveOutputVariables = stream.readInt<uint32_t>();
- stream.readInt(&mState.mSamplerUniformRange.start);
- stream.readInt(&mState.mSamplerUniformRange.end);
+ unsigned int start = 0;
+ unsigned int end = 0;
+ stream.readInt(&start);
+ stream.readInt(&end);
+ mState.mSamplerUniformRange = RangeUI(start, end);
unsigned int samplerCount = stream.readInt<unsigned int>();
for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
@@ -1091,8 +1094,8 @@
"All bits of DrawBufferMask can be contained in an uint32_t");
stream.writeInt(static_cast<uint32_t>(mState.mActiveOutputVariables.to_ulong()));
- stream.writeInt(mState.mSamplerUniformRange.start);
- stream.writeInt(mState.mSamplerUniformRange.end);
+ stream.writeInt(mState.mSamplerUniformRange.low());
+ stream.writeInt(mState.mSamplerUniformRange.high());
stream.writeInt(mState.mSamplerBindings.size());
for (const auto &samplerBinding : mState.mSamplerBindings)
@@ -2048,17 +2051,19 @@
void Program::linkSamplerBindings()
{
- mState.mSamplerUniformRange.end = static_cast<unsigned int>(mState.mUniforms.size());
- mState.mSamplerUniformRange.start = mState.mSamplerUniformRange.end;
- auto samplerIter = mState.mUniforms.rbegin();
- while (samplerIter != mState.mUniforms.rend() && samplerIter->isSampler())
+ unsigned int high = static_cast<unsigned int>(mState.mUniforms.size());
+ unsigned int low = high;
+
+ for (auto samplerIter = mState.mUniforms.rbegin();
+ samplerIter != mState.mUniforms.rend() && samplerIter->isSampler(); ++samplerIter)
{
- --mState.mSamplerUniformRange.start;
- ++samplerIter;
+ --low;
}
+
+ mState.mSamplerUniformRange = RangeUI(low, high);
+
// If uniform is a sampler type, insert it into the mSamplerBindings array.
- for (unsigned int samplerIndex = mState.mSamplerUniformRange.start;
- samplerIndex < mState.mUniforms.size(); ++samplerIndex)
+ for (unsigned int samplerIndex : mState.mSamplerUniformRange)
{
const auto &samplerUniform = mState.mUniforms[samplerIndex];
GLenum textureType = SamplerTypeToTextureType(samplerUniform.type);
@@ -2763,8 +2768,7 @@
void Program::setUniformValuesFromBindingQualifiers()
{
- for (unsigned int samplerIndex = mState.mSamplerUniformRange.start;
- samplerIndex < mState.mSamplerUniformRange.end; ++samplerIndex)
+ for (unsigned int samplerIndex : mState.mSamplerUniformRange)
{
const auto &samplerUniform = mState.mUniforms[samplerIndex];
if (samplerUniform.binding != -1)
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index fd6173c..992454a 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -910,9 +910,7 @@
auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
- gl::Range<size_t> clearRange(rangeStart, rangeStart);
- clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
-
+ gl::Range<size_t> clearRange(rangeStart, std::min(rangeEnd, currentSRVs.highestUsed()));
if (clearRange.empty())
{
return gl::NoError();
@@ -921,18 +919,18 @@
auto deviceContext = mRenderer->getDeviceContext();
if (samplerType == gl::SAMPLER_VERTEX)
{
- deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
- static_cast<unsigned int>(rangeEnd - rangeStart),
+ deviceContext->VSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
+ static_cast<unsigned int>(clearRange.length()),
&mNullSRVs[0]);
}
else
{
- deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
- static_cast<unsigned int>(rangeEnd - rangeStart),
+ deviceContext->PSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
+ static_cast<unsigned int>(clearRange.length()),
&mNullSRVs[0]);
}
- for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
+ for (size_t samplerIndex : clearRange)
{
currentSRVs.update(samplerIndex, nullptr);
}