Move ProgramGL's sampler bindings to gl::Program.
This saves code duplication and makes the sampler validation a bit
simpler. In the future we might be able to use it to replace the
custom D3D logic for caching sampler info, but this relies on
some shader-specific non-merged data.
This also introduces some code duplication in Uniform1iv.
BUG=angleproject:1685
Change-Id: I258607a21886ca20766607bddf958cd511fac3f1
Reviewed-on: https://chromium-review.googlesource.com/426781
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 9252b5a..8aa6a17 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -246,6 +246,7 @@
mAttachedVertexShader(nullptr),
mAttachedComputeShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
+ mSamplerUniformRange(0, 0),
mBinaryRetrieveableHint(false)
{
mComputeShaderLocalSize.fill(1);
@@ -325,7 +326,7 @@
return -1;
}
-GLuint ProgramState::getUniformIndex(const std::string &name) const
+GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = ParseUniformName(name, &subscript);
@@ -351,6 +352,34 @@
return GL_INVALID_INDEX;
}
+GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
+{
+ ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformLocations.size());
+ return mUniformLocations[location].index;
+}
+
+Optional<GLuint> ProgramState::getSamplerIndex(GLint location) const
+{
+ GLuint index = getUniformIndexFromLocation(location);
+ if (!isSamplerUniformIndex(index))
+ {
+ return Optional<GLuint>::Invalid();
+ }
+
+ return getSamplerIndexFromUniformIndex(index);
+}
+
+bool ProgramState::isSamplerUniformIndex(GLuint index) const
+{
+ return index >= mSamplerUniformRange.start && index < mSamplerUniformRange.end;
+}
+
+GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
+{
+ ASSERT(isSamplerUniformIndex(uniformIndex));
+ return uniformIndex - mSamplerUniformRange.start;
+}
+
Program::Program(rx::GLImplFactory *factory, ResourceManager *manager, GLuint handle)
: mProgram(factory->createProgram(mState)),
mValidated(false),
@@ -358,8 +387,7 @@
mDeleteStatus(false),
mRefCount(0),
mResourceManager(manager),
- mHandle(handle),
- mSamplerUniformRange(0, 0)
+ mHandle(handle)
{
ASSERT(mProgram);
@@ -723,6 +751,7 @@
mState.mUniformBlocks.clear();
mState.mOutputVariables.clear();
mState.mComputeShaderLocalSize.fill(1);
+ mState.mSamplerBindings.clear();
mValidated = false;
@@ -877,8 +906,16 @@
mState.mOutputVariables[locationIndex] = locationData;
}
- stream.readInt(&mSamplerUniformRange.start);
- stream.readInt(&mSamplerUniformRange.end);
+ stream.readInt(&mState.mSamplerUniformRange.start);
+ stream.readInt(&mState.mSamplerUniformRange.end);
+
+ unsigned int samplerCount = stream.readInt<unsigned int>();
+ for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
+ {
+ GLenum textureType = stream.readInt<GLenum>();
+ size_t bindingCount = stream.readInt<size_t>();
+ mState.mSamplerBindings.emplace_back(SamplerBinding(textureType, bindingCount));
+ }
ANGLE_TRY_RESULT(mProgram->load(context->getImplementation(), mInfoLog, &stream), mLinked);
@@ -992,8 +1029,15 @@
stream.writeString(outputPair.second.name);
}
- stream.writeInt(mSamplerUniformRange.start);
- stream.writeInt(mSamplerUniformRange.end);
+ stream.writeInt(mState.mSamplerUniformRange.start);
+ stream.writeInt(mState.mSamplerUniformRange.end);
+
+ stream.writeInt(mState.mSamplerBindings.size());
+ for (const auto &samplerBinding : mState.mSamplerBindings)
+ {
+ stream.writeInt(samplerBinding.textureType);
+ stream.writeInt(samplerBinding.boundTextureUnits.size());
+ }
ANGLE_TRY(mProgram->save(&stream));
@@ -1373,7 +1417,7 @@
const LinkedUniform &Program::getUniformByLocation(GLint location) const
{
ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
- return mState.mUniforms[mState.mUniformLocations[location].index];
+ return mState.mUniforms[mState.getUniformIndexFromLocation(location)];
}
GLint Program::getUniformLocation(const std::string &name) const
@@ -1383,7 +1427,7 @@
GLuint Program::getUniformIndex(const std::string &name) const
{
- return mState.getUniformIndex(name);
+ return mState.getUniformIndexFromName(name);
}
void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
@@ -1572,22 +1616,12 @@
// if any two active samplers in a program are of different types, but refer to the same
// texture image unit, and this is the current program, then ValidateProgram will fail, and
// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
- for (unsigned int samplerIndex = mSamplerUniformRange.start;
- samplerIndex < mSamplerUniformRange.end; ++samplerIndex)
+ for (const auto &samplerBinding : mState.mSamplerBindings)
{
- const LinkedUniform &uniform = mState.mUniforms[samplerIndex];
- ASSERT(uniform.isSampler());
+ GLenum textureType = samplerBinding.textureType;
- if (!uniform.staticUse)
- continue;
-
- const GLuint *dataPtr = reinterpret_cast<const GLuint *>(uniform.getDataPtrToElement(0));
- GLenum textureType = SamplerTypeToTextureType(uniform.type);
-
- for (unsigned int arrayElement = 0; arrayElement < uniform.elementCount(); ++arrayElement)
+ for (GLuint textureUnit : samplerBinding.boundTextureUnits)
{
- GLuint textureUnit = dataPtr[arrayElement];
-
if (textureUnit >= caps.maxCombinedTextureImageUnits)
{
if (infoLog)
@@ -2677,12 +2711,20 @@
}
}
- mSamplerUniformRange.start = static_cast<unsigned int>(mState.mUniforms.size());
- mSamplerUniformRange.end =
- mSamplerUniformRange.start + static_cast<unsigned int>(samplerUniforms.size());
+ mState.mSamplerUniformRange.start = static_cast<unsigned int>(mState.mUniforms.size());
+ mState.mSamplerUniformRange.end =
+ mState.mSamplerUniformRange.start + static_cast<unsigned int>(samplerUniforms.size());
mState.mUniforms.insert(mState.mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
+ // If uniform is a sampler type, insert it into the mSamplerBindings array.
+ for (const auto &samplerUniform : samplerUniforms)
+ {
+ GLenum textureType = SamplerTypeToTextureType(samplerUniform.type);
+ mState.mSamplerBindings.emplace_back(
+ SamplerBinding(textureType, samplerUniform.elementCount()));
+ }
+
return true;
}
@@ -2945,6 +2987,33 @@
}
}
+template <>
+void Program::updateSamplerUniform(const VariableLocation &locationInfo,
+ const uint8_t *destPointer,
+ GLsizei clampedCount,
+ const GLint *v)
+{
+ // Invalidate the validation cache only if we modify the sampler data.
+ if (mState.isSamplerUniformIndex(locationInfo.index) &&
+ memcmp(destPointer, v, sizeof(GLint) * clampedCount) != 0)
+ {
+ GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
+ std::vector<GLuint> *boundTextureUnits =
+ &mState.mSamplerBindings[samplerIndex].boundTextureUnits;
+
+ std::copy(v, v + clampedCount, boundTextureUnits->begin() + locationInfo.element);
+ mCachedValidateSamplersResult.reset();
+ }
+}
+
+template <typename T>
+void Program::updateSamplerUniform(const VariableLocation &locationInfo,
+ const uint8_t *destPointer,
+ GLsizei clampedCount,
+ const T *v)
+{
+}
+
template <typename T>
GLsizei Program::setUniformInternal(GLint location, GLsizei countIn, int vectorSize, const T *v)
{
@@ -2978,12 +3047,7 @@
}
else
{
- // Invalide the validation cache if we modify the sampler data.
- if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * clampedCount) != 0)
- {
- mCachedValidateSamplersResult.reset();
- }
-
+ updateSamplerUniform(locationInfo, destPointer, clampedCount, v);
memcpy(destPointer, v, sizeof(T) * clampedCount);
}