From 80f269d2526e992e665ae08a11d8b984c0139039 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 28 Dec 2016 16:24:57 -0400 Subject: [PATCH] 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 --- src/modules/graphics/opengl/Shader.cpp | 52 +++++++++++++++----------- src/modules/graphics/opengl/Shader.h | 2 + 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index ba723a14e..9648ea133 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -548,13 +548,19 @@ void Shader::attach(bool temporary) if (!temporary) { - // make sure all sent textures are properly bound to their respective texture units - // note: list potentially contains texture ids of deleted/invalid textures! + // Make sure all textures are properly bound to their respective + // texture units. for (int i = 1; i < (int) textureUnits.size(); ++i) { if (textureUnits[i].active) 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) { + if (current != this) + { + pendingUniformUpdates.push_back(std::make_pair(info, count)); + return; + } + if (!internalUpdate) flushStreamDraws(); - TemporaryAttacher attacher(this, !internalUpdate); - int location = info->location; UniformType type = info->baseType; @@ -682,7 +692,9 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count if (info->baseType != UNIFORM_SAMPLER) return; - if (!internalUpdate) + bool shaderactive = current == this; + + if (!internalUpdate && shaderactive) flushStreamDraws(); 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(); - 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; } else { - gl.bindTextureToUnit((GLuint) 0, texunit, false); + if (shaderactive) + gl.bindTextureToUnit((GLuint) 0, texunit, false); + textureUnits[texunit].texture = 0; 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. 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(Module::M_GRAPHICS); bool canvasActive = gfx->isCanvasActive(); - if (view == lastViewport && canvasWasActive == canvasActive) + if ((view == lastViewport && canvasWasActive == canvasActive) || current != this) return; // 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]; - if (location >= 0) - { - TemporaryAttacher attacher(this, true); glUniform4fv(location, 1, params); - } canvasWasActive = canvasActive; lastViewport = view; @@ -863,22 +875,21 @@ void Shader::checkSetScreenParams() void Shader::checkSetPointSize(float size) { - if (size == lastPointSize) + if (size == lastPointSize || current != this) return; GLint location = builtinUniforms[BUILTIN_POINT_SIZE]; - if (location >= 0) - { - TemporaryAttacher attacher(this, true); glUniform1f(location, size); - } lastPointSize = size; } void Shader::checkSetBuiltinUniforms() { + if (current != this) + return; + checkSetScreenParams(); // We use a more efficient method for sending transformation matrices to @@ -888,10 +899,9 @@ void Shader::checkSetBuiltinUniforms() checkSetPointSize(gl.getPointSize()); auto gfx = Module::getInstance(Module::M_GRAPHICS); - const Matrix4 &curproj = gfx->getProjection(); + const Matrix4 &curproj = gfx->getProjection(); const Matrix4 &curxform = gfx->getTransform(); - TemporaryAttacher attacher(this, true); bool tpmatrixneedsupdate = false; diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index 3ebce2c06..d74be1c42 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -243,6 +243,8 @@ private: // Texture unit pool for setting images std::vector textureUnits; + std::vector> pendingUniformUpdates; + bool canvasWasActive; Rect lastViewport;