Commit e7d8432d by Jamie Madill Committed by Commit Bot

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/426781Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 98e34077
......@@ -246,6 +246,7 @@ ProgramState::ProgramState()
mAttachedVertexShader(nullptr),
mAttachedComputeShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mSamplerUniformRange(0, 0),
mBinaryRetrieveableHint(false)
{
mComputeShaderLocalSize.fill(1);
......@@ -325,7 +326,7 @@ GLint ProgramState::getUniformLocation(const std::string &name) const
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 @@ GLuint ProgramState::getUniformIndex(const std::string &name) const
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 @@ Program::Program(rx::GLImplFactory *factory, ResourceManager *manager, GLuint ha
mDeleteStatus(false),
mRefCount(0),
mResourceManager(manager),
mHandle(handle),
mSamplerUniformRange(0, 0)
mHandle(handle)
{
ASSERT(mProgram);
......@@ -723,6 +751,7 @@ void Program::unlink(bool destroy)
mState.mUniformBlocks.clear();
mState.mOutputVariables.clear();
mState.mComputeShaderLocalSize.fill(1);
mState.mSamplerBindings.clear();
mValidated = false;
......@@ -877,8 +906,16 @@ Error Program::loadBinary(const Context *context,
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 @@ Error Program::saveBinary(const Context *context,
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 @@ bool Program::isIgnoredUniformLocation(GLint location) const
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 @@ GLint Program::getUniformLocation(const std::string &name) const
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 @@ bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
// 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 @@ bool Program::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
}
}
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 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
}
}
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 @@ GLsizei Program::setUniformInternal(GLint location, GLsizei countIn, int vectorS
}
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);
}
......
......@@ -159,6 +159,21 @@ struct BindingInfo
bool valid;
};
// This small structure encapsulates binding sampler uniforms to active GL textures.
struct SamplerBinding
{
SamplerBinding(GLenum textureTypeIn, size_t elementCount)
: textureType(textureTypeIn), boundTextureUnits(elementCount, 0)
{
}
// Necessary for retrieving active textures from the GL state.
GLenum textureType;
// List of all textures bound to this sampler, of type textureType.
std::vector<GLuint> boundTextureUnits;
};
class ProgramState final : angle::NonCopyable
{
public:
......@@ -193,10 +208,15 @@ class ProgramState final : angle::NonCopyable
const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
const LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
GLuint getUniformIndexFromName(const std::string &name) const;
GLuint getUniformIndexFromLocation(GLint location) const;
Optional<GLuint> getSamplerIndex(GLint location) const;
bool isSamplerUniformIndex(GLuint index) const;
GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
private:
friend class Program;
......@@ -227,6 +247,10 @@ class ProgramState final : angle::NonCopyable
std::vector<LinkedUniform> mUniforms;
std::vector<VariableLocation> mUniformLocations;
std::vector<UniformBlock> mUniformBlocks;
RangeUI mSamplerUniformRange;
// An array of the samplers that are used by the program
std::vector<gl::SamplerBinding> mSamplerBindings;
// TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables;
......@@ -372,6 +396,11 @@ class Program final : angle::NonCopyable, public LabeledObject
return mState.mActiveAttribLocationsMask;
}
const std::vector<SamplerBinding> &getSamplerBindings() const
{
return mState.mSamplerBindings;
}
private:
class Bindings final : angle::NonCopyable
{
......@@ -488,6 +517,11 @@ class Program final : angle::NonCopyable, public LabeledObject
GLsizei count,
GLboolean transpose,
const T *v);
template <typename T>
void updateSamplerUniform(const VariableLocation &locationInfo,
const uint8_t *destPointer,
GLsizei clampedCount,
const T *v);
template <typename DestT>
void getUniformInternal(GLint location, DestT *dataOut) const;
......@@ -516,7 +550,6 @@ class Program final : angle::NonCopyable, public LabeledObject
// Cache for sampler validation
Optional<bool> mCachedValidateSamplersResult;
std::vector<GLenum> mTextureUnitTypesCache;
RangeUI mSamplerUniformRange;
};
} // namespace gl
......
......@@ -107,6 +107,8 @@ gl::Error RendererD3D::applyTextures(GLImplFactory *implFactory,
ASSERT(!programD3D->isSamplerMappingDirty());
// TODO(jmadill): Use the Program's sampler bindings.
unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{
......
......@@ -265,18 +265,6 @@ void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
mStateManager->useProgram(mProgramID);
mFunctions->uniform1iv(uniLoc(location), count, v);
}
const gl::VariableLocation &locationEntry = mState.getUniformLocations()[location];
size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
if (samplerIndex != GL_INVALID_INDEX)
{
std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
size_t copyCount =
std::min<size_t>(count, boundTextureUnits.size() - locationEntry.element);
std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
}
}
void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
......@@ -519,11 +507,6 @@ GLuint ProgramGL::getProgramID() const
return mProgramID;
}
const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
{
return mSamplerBindings;
}
bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
{
ASSERT(mProgramID != 0u);
......@@ -595,8 +578,6 @@ void ProgramGL::preLink()
// Reset the program state
mUniformRealLocationMap.clear();
mUniformBlockRealLocationMap.clear();
mSamplerBindings.clear();
mUniformIndexToSamplerIndex.clear();
mPathRenderingFragmentInputs.clear();
}
......@@ -670,24 +651,6 @@ void ProgramGL::postLink()
mUniformRealLocationMap[uniformLocation] = realLocation;
}
mUniformIndexToSamplerIndex.resize(mState.getUniforms().size(), GL_INVALID_INDEX);
for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
{
const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
continue;
mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
// If uniform is a sampler type, insert it into the mSamplerBindings array
SamplerBindingGL samplerBinding;
samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
mSamplerBindings.push_back(samplerBinding);
}
// Discover CHROMIUM_path_rendering fragment inputs if enabled.
if (!mEnablePathRendering)
return;
......
......@@ -21,12 +21,6 @@ namespace rx
class FunctionsGL;
class StateManagerGL;
struct SamplerBindingGL
{
GLenum textureType;
std::vector<GLuint> boundTextureUnits;
};
class ProgramGL : public ProgramImpl
{
public:
......@@ -82,7 +76,6 @@ class ProgramGL : public ProgramImpl
const GLfloat *coeffs) override;
GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
private:
void preLink();
......@@ -99,12 +92,6 @@ class ProgramGL : public ProgramImpl
std::vector<GLint> mUniformRealLocationMap;
std::vector<GLuint> mUniformBlockRealLocationMap;
// An array of the samplers that are used by the program
std::vector<SamplerBindingGL> mSamplerBindings;
// A map from a mData.getUniforms() index to a mSamplerBindings index.
std::vector<size_t> mUniformIndexToSamplerIndex;
struct PathRenderingFragmentInput
{
std::string name;
......
......@@ -789,8 +789,7 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data)
}
}
const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms();
for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms)
for (const gl::SamplerBinding &samplerUniform : program->getSamplerBindings())
{
GLenum textureType = samplerUniform.textureType;
for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment