Commit f51bc795 by Geoff Lang

Optimize Texture binding by only applying referenced textures.

Update ProgramGL to track which the current values of sampler uniforms so that only the currently applied texture units have to be bound for the draw call. BUG=angleproject:882 Change-Id: I280aa106172b13a5fbb31cdefba27b6691c0a0e4 Reviewed-on: https://chromium-review.googlesource.com/264803Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 9477dc94
......@@ -279,6 +279,39 @@ bool IsSamplerType(GLenum type)
return false;
}
GLenum SamplerTypeToTextureType(GLenum samplerType)
{
switch (samplerType)
{
case GL_SAMPLER_2D:
case GL_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_SAMPLER_2D_SHADOW:
return GL_TEXTURE_2D;
case GL_SAMPLER_CUBE:
case GL_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_SAMPLER_CUBE_SHADOW:
return GL_TEXTURE_CUBE_MAP;
case GL_SAMPLER_2D_ARRAY:
case GL_INT_SAMPLER_2D_ARRAY:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
case GL_SAMPLER_2D_ARRAY_SHADOW:
return GL_TEXTURE_2D_ARRAY;
case GL_SAMPLER_3D:
case GL_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_3D:
return GL_TEXTURE_3D;
default:
UNREACHABLE();
return 0;
}
}
bool IsMatrixType(GLenum type)
{
return VariableRowCount(type) > 1;
......
......@@ -27,6 +27,7 @@ GLenum VariableBoolVectorType(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
bool IsSamplerType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type);
int VariableRegisterCount(GLenum type);
......
......@@ -154,6 +154,15 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog,
}
mUniformIndex[location] = gl::VariableLocation(uniformName, arrayIndex, static_cast<unsigned int>(mUniforms.size()));
// If the uniform is a sampler, track it in the sampler bindings array
if (gl::IsSamplerType(uniformType))
{
SamplerLocation samplerLoc;
samplerLoc.samplerIndex = mSamplerBindings.size();
samplerLoc.arrayIndex = arrayIndex;
mSamplerUniformMap[location] = samplerLoc;
}
}
}
......@@ -162,6 +171,15 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog,
// TODO: determine uniform precision
mUniforms.push_back(new gl::LinkedUniform(uniformType, GL_NONE, uniformName, arraySize, -1, sh::BlockMemberInfo::getDefaultBlockInfo()));
// If uniform is a sampler type, insert it into the mSamplerBindings array
if (gl::IsSamplerType(uniformType))
{
SamplerBindingGL samplerBinding;
samplerBinding.textureType = gl::SamplerTypeToTextureType(uniformType);
samplerBinding.boundTextureUnits.resize(uniformSize, 0);
mSamplerBindings.push_back(samplerBinding);
}
}
// Query the attribute information
......@@ -223,6 +241,16 @@ void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform1iv(location, count, v);
auto iter = mSamplerUniformMap.find(location);
if (iter != mSamplerUniformMap.end())
{
const SamplerLocation &samplerLoc = iter->second;
std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerLoc.samplerIndex].boundTextureUnits;
size_t copyCount = std::max<size_t>(count, boundTextureUnits.size() - samplerLoc.arrayIndex);
std::copy(v, v + copyCount, boundTextureUnits.begin() + samplerLoc.arrayIndex);
}
}
void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
......@@ -408,6 +436,9 @@ bool ProgramGL::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBloc
void ProgramGL::reset()
{
ProgramImpl::reset();
mSamplerUniformMap.clear();
mSamplerBindings.clear();
}
GLuint ProgramGL::getProgramID() const
......@@ -415,4 +446,9 @@ GLuint ProgramGL::getProgramID() const
return mProgramID;
}
const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
{
return mSamplerBindings;
}
}
......@@ -17,6 +17,12 @@ namespace rx
class FunctionsGL;
class StateManagerGL;
struct SamplerBindingGL
{
GLenum textureType;
std::vector<GLuint> boundTextureUnits;
};
class ProgramGL : public ProgramImpl
{
public:
......@@ -88,11 +94,23 @@ class ProgramGL : public ProgramImpl
void reset() override;
GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
private:
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
// A map from uniform location to index of mSamplerBindings and array index of the uniform
struct SamplerLocation
{
size_t samplerIndex;
size_t arrayIndex;
};
std::map<GLint, SamplerLocation> mSamplerUniformMap;
// An array of the samplers that are used by the program
std::vector<SamplerBindingGL> mSamplerBindings;
GLuint mProgramID;
};
......
......@@ -344,7 +344,6 @@ gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data, GLsizei cou
gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
{
const gl::State &state = *data.state;
const gl::Caps &caps = *data.caps;
const gl::VertexArray *vao = state.getVertexArray();
const std::vector<gl::VertexAttribute>& attribs = vao->getVertexAttributes();
......@@ -361,31 +360,16 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
useProgram(programGL->getProgramID());
// TODO: Only apply textures referenced by the program.
for (auto textureTypeIter = mTextures.begin(); textureTypeIter != mTextures.end(); textureTypeIter++)
const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms();
for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms)
{
GLenum textureType = textureTypeIter->first;
// Determine if this texture type can exist in the source context
bool validTextureType = (textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP ||
(textureType == GL_TEXTURE_2D_ARRAY && data.clientVersion >= 3) ||
(textureType == GL_TEXTURE_3D && data.clientVersion >= 3));
const std::vector<GLuint> &textureVector = textureTypeIter->second;
for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size(); textureUnitIndex++)
GLenum textureType = samplerUniform.textureType;
for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
{
const gl::Texture *texture = nullptr;
bool validTextureUnit = textureUnitIndex < caps.maxCombinedTextureImageUnits;
if (validTextureType && validTextureUnit)
{
texture = state.getSamplerTexture(textureUnitIndex, textureType);
}
const gl::Texture *texture = state.getSamplerTexture(textureUnitIndex, textureType);
if (texture != nullptr)
{
const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
textureGL->syncSamplerState(texture->getSamplerState());
if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID())
{
......@@ -393,6 +377,8 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
bindTexture(textureType, textureGL->getTextureID());
}
textureGL->syncSamplerState(texture->getSamplerState());
// TODO: apply sampler object if one is bound
}
else
......
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