Improve performance of Shader:send when the Shader is not active.

It now defers uploading the uniforms to the program object until the shader becomes active again, instead of activating the shader program and deactivating it each time Shader:send is called.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2016-12-28 16:24:57 -04:00
parent a78fa39113
commit 80f269d252
2 changed files with 33 additions and 21 deletions
+31 -21
View File
@@ -548,13 +548,19 @@ void Shader::attach(bool temporary)
if (!temporary) if (!temporary)
{ {
// make sure all sent textures are properly bound to their respective texture units // Make sure all textures are properly bound to their respective
// note: list potentially contains texture ids of deleted/invalid textures! // texture units.
for (int i = 1; i < (int) textureUnits.size(); ++i) for (int i = 1; i < (int) textureUnits.size(); ++i)
{ {
if (textureUnits[i].active) if (textureUnits[i].active)
gl.bindTextureToUnit(textureUnits[i].texture, i, false); gl.bindTextureToUnit(textureUnits[i].texture, i, false);
} }
// send any pending uniforms to the shader program.
for (const auto &p : pendingUniformUpdates)
updateUniform(p.first, p.second);
pendingUniformUpdates.clear();
} }
} }
} }
@@ -587,11 +593,15 @@ const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const
void Shader::updateUniform(const UniformInfo *info, int count, bool internalUpdate) void Shader::updateUniform(const UniformInfo *info, int count, bool internalUpdate)
{ {
if (current != this)
{
pendingUniformUpdates.push_back(std::make_pair(info, count));
return;
}
if (!internalUpdate) if (!internalUpdate)
flushStreamDraws(); flushStreamDraws();
TemporaryAttacher attacher(this, !internalUpdate);
int location = info->location; int location = info->location;
UniformType type = info->baseType; UniformType type = info->baseType;
@@ -682,7 +692,9 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
if (info->baseType != UNIFORM_SAMPLER) if (info->baseType != UNIFORM_SAMPLER)
return; return;
if (!internalUpdate) bool shaderactive = current == this;
if (!internalUpdate && shaderactive)
flushStreamDraws(); flushStreamDraws();
count = std::min(count, info->count); count = std::min(count, info->count);
@@ -721,14 +733,17 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
{ {
GLuint gltex = (GLuint) textures[i]->getHandle(); GLuint gltex = (GLuint) textures[i]->getHandle();
gl.bindTextureToUnit(gltex, texunit, false); if (shaderactive)
gl.bindTextureToUnit(gltex, texunit, false);
// store texture id so it can be re-bound to the proper texture unit later // Store texture id so it can be re-bound to the texture unit later.
textureUnits[texunit].texture = gltex; textureUnits[texunit].texture = gltex;
} }
else else
{ {
gl.bindTextureToUnit((GLuint) 0, texunit, false); if (shaderactive)
gl.bindTextureToUnit((GLuint) 0, texunit, false);
textureUnits[texunit].texture = 0; textureUnits[texunit].texture = 0;
textureUnits[texunit].active = false; textureUnits[texunit].active = false;
} }
@@ -812,7 +827,8 @@ void Shader::setVideoTextures(GLuint ytexture, GLuint cbtexture, GLuint crtextur
{ {
// Store texture id so it can be re-bound later. // Store texture id so it can be re-bound later.
textureUnits[videoTextureUnits[i]].texture = textures[i]; textureUnits[videoTextureUnits[i]].texture = textures[i];
gl.bindTextureToUnit(textures[i], videoTextureUnits[i], false); if (current == this)
gl.bindTextureToUnit(textures[i], videoTextureUnits[i], false);
} }
} }
} }
@@ -824,7 +840,7 @@ void Shader::checkSetScreenParams()
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS); auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
bool canvasActive = gfx->isCanvasActive(); bool canvasActive = gfx->isCanvasActive();
if (view == lastViewport && canvasWasActive == canvasActive) if ((view == lastViewport && canvasWasActive == canvasActive) || current != this)
return; return;
// In the shader, we do pixcoord.y = gl_FragCoord.y * params.z + params.w. // In the shader, we do pixcoord.y = gl_FragCoord.y * params.z + params.w.
@@ -850,12 +866,8 @@ void Shader::checkSetScreenParams()
} }
GLint location = builtinUniforms[BUILTIN_SCREEN_SIZE]; GLint location = builtinUniforms[BUILTIN_SCREEN_SIZE];
if (location >= 0) if (location >= 0)
{
TemporaryAttacher attacher(this, true);
glUniform4fv(location, 1, params); glUniform4fv(location, 1, params);
}
canvasWasActive = canvasActive; canvasWasActive = canvasActive;
lastViewport = view; lastViewport = view;
@@ -863,22 +875,21 @@ void Shader::checkSetScreenParams()
void Shader::checkSetPointSize(float size) void Shader::checkSetPointSize(float size)
{ {
if (size == lastPointSize) if (size == lastPointSize || current != this)
return; return;
GLint location = builtinUniforms[BUILTIN_POINT_SIZE]; GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
if (location >= 0) if (location >= 0)
{
TemporaryAttacher attacher(this, true);
glUniform1f(location, size); glUniform1f(location, size);
}
lastPointSize = size; lastPointSize = size;
} }
void Shader::checkSetBuiltinUniforms() void Shader::checkSetBuiltinUniforms()
{ {
if (current != this)
return;
checkSetScreenParams(); checkSetScreenParams();
// We use a more efficient method for sending transformation matrices to // We use a more efficient method for sending transformation matrices to
@@ -888,10 +899,9 @@ void Shader::checkSetBuiltinUniforms()
checkSetPointSize(gl.getPointSize()); checkSetPointSize(gl.getPointSize());
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS); auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
const Matrix4 &curproj = gfx->getProjection();
const Matrix4 &curproj = gfx->getProjection();
const Matrix4 &curxform = gfx->getTransform(); const Matrix4 &curxform = gfx->getTransform();
TemporaryAttacher attacher(this, true);
bool tpmatrixneedsupdate = false; bool tpmatrixneedsupdate = false;
+2
View File
@@ -243,6 +243,8 @@ private:
// Texture unit pool for setting images // Texture unit pool for setting images
std::vector<TextureUnit> textureUnits; std::vector<TextureUnit> textureUnits;
std::vector<std::pair<const UniformInfo *, int>> pendingUniformUpdates;
bool canvasWasActive; bool canvasWasActive;
Rect lastViewport; Rect lastViewport;