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) ...@@ -279,6 +279,39 @@ bool IsSamplerType(GLenum type)
return false; 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) bool IsMatrixType(GLenum type)
{ {
return VariableRowCount(type) > 1; return VariableRowCount(type) > 1;
......
...@@ -27,6 +27,7 @@ GLenum VariableBoolVectorType(GLenum type); ...@@ -27,6 +27,7 @@ GLenum VariableBoolVectorType(GLenum type);
int VariableRowCount(GLenum type); int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type); int VariableColumnCount(GLenum type);
bool IsSamplerType(GLenum type); bool IsSamplerType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type); bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type); GLenum TransposeMatrixType(GLenum type);
int VariableRegisterCount(GLenum type); int VariableRegisterCount(GLenum type);
......
...@@ -154,6 +154,15 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog, ...@@ -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())); 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, ...@@ -162,6 +171,15 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog,
// TODO: determine uniform precision // TODO: determine uniform precision
mUniforms.push_back(new gl::LinkedUniform(uniformType, GL_NONE, uniformName, arraySize, -1, sh::BlockMemberInfo::getDefaultBlockInfo())); 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 // Query the attribute information
...@@ -223,6 +241,16 @@ void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v) ...@@ -223,6 +241,16 @@ void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{ {
mStateManager->useProgram(mProgramID); mStateManager->useProgram(mProgramID);
mFunctions->uniform1iv(location, count, v); 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) void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
...@@ -408,6 +436,9 @@ bool ProgramGL::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBloc ...@@ -408,6 +436,9 @@ bool ProgramGL::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBloc
void ProgramGL::reset() void ProgramGL::reset()
{ {
ProgramImpl::reset(); ProgramImpl::reset();
mSamplerUniformMap.clear();
mSamplerBindings.clear();
} }
GLuint ProgramGL::getProgramID() const GLuint ProgramGL::getProgramID() const
...@@ -415,4 +446,9 @@ GLuint ProgramGL::getProgramID() const ...@@ -415,4 +446,9 @@ GLuint ProgramGL::getProgramID() const
return mProgramID; return mProgramID;
} }
const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
{
return mSamplerBindings;
}
} }
...@@ -17,6 +17,12 @@ namespace rx ...@@ -17,6 +17,12 @@ namespace rx
class FunctionsGL; class FunctionsGL;
class StateManagerGL; class StateManagerGL;
struct SamplerBindingGL
{
GLenum textureType;
std::vector<GLuint> boundTextureUnits;
};
class ProgramGL : public ProgramImpl class ProgramGL : public ProgramImpl
{ {
public: public:
...@@ -88,11 +94,23 @@ class ProgramGL : public ProgramImpl ...@@ -88,11 +94,23 @@ class ProgramGL : public ProgramImpl
void reset() override; void reset() override;
GLuint getProgramID() const; GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
private: private:
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
StateManagerGL *mStateManager; 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; GLuint mProgramID;
}; };
......
...@@ -344,7 +344,6 @@ gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data, GLsizei cou ...@@ -344,7 +344,6 @@ gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data, GLsizei cou
gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
{ {
const gl::State &state = *data.state; const gl::State &state = *data.state;
const gl::Caps &caps = *data.caps;
const gl::VertexArray *vao = state.getVertexArray(); const gl::VertexArray *vao = state.getVertexArray();
const std::vector<gl::VertexAttribute>& attribs = vao->getVertexAttributes(); const std::vector<gl::VertexAttribute>& attribs = vao->getVertexAttributes();
...@@ -361,31 +360,16 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) ...@@ -361,31 +360,16 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
const ProgramGL *programGL = GetImplAs<ProgramGL>(program); const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
useProgram(programGL->getProgramID()); useProgram(programGL->getProgramID());
// TODO: Only apply textures referenced by the program. const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms();
for (auto textureTypeIter = mTextures.begin(); textureTypeIter != mTextures.end(); textureTypeIter++) for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms)
{ {
GLenum textureType = textureTypeIter->first; GLenum textureType = samplerUniform.textureType;
for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
// 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++)
{ {
const gl::Texture *texture = nullptr; const gl::Texture *texture = state.getSamplerTexture(textureUnitIndex, textureType);
bool validTextureUnit = textureUnitIndex < caps.maxCombinedTextureImageUnits;
if (validTextureType && validTextureUnit)
{
texture = state.getSamplerTexture(textureUnitIndex, textureType);
}
if (texture != nullptr) if (texture != nullptr)
{ {
const TextureGL *textureGL = GetImplAs<TextureGL>(texture); const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
textureGL->syncSamplerState(texture->getSamplerState());
if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID()) if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID())
{ {
...@@ -393,6 +377,8 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) ...@@ -393,6 +377,8 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
bindTexture(textureType, textureGL->getTextureID()); bindTexture(textureType, textureGL->getTextureID());
} }
textureGL->syncSamplerState(texture->getSamplerState());
// TODO: apply sampler object if one is bound // TODO: apply sampler object if one is bound
} }
else 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