Prevent redundant shader uniform uploads for built-in uniforms when OpenGL ES 2 is used.

As a result, the graphics primitive drawing functions (e.g. love.graphics.rectangle) are now more efficient on mobile devices.
This commit is contained in:
Alex Szpakowski
2015-06-24 22:04:19 -03:00
parent 88c8e0c071
commit 4c571e8fd7
3 changed files with 82 additions and 92 deletions
+6 -22
View File
@@ -321,31 +321,15 @@ void OpenGL::prepareDraw()
{
TempDebugGroup debuggroup("Prepare OpenGL draw");
Shader *shader = Shader::current;
// Make sure the active shader's love-provided uniforms are up to date.
if (Shader::current != nullptr)
Shader::current->checkSetBuiltinUniforms();
if (shader != nullptr)
if (GLAD_VERSION_1_0)
{
// Make sure the active shader has the correct values for its love-
// provided uniforms.
shader->checkSetScreenParams();
}
const Matrix &curproj = matrices.projection.back();
const Matrix &curxform = matrices.transform.back();
const Matrix &curproj = matrices.projection.back();
const Matrix &curxform = matrices.transform.back();
if (GLAD_ES_VERSION_2_0 && shader)
{
// Send built-in uniforms to the current shader.
shader->sendBuiltinMatrix(Shader::BUILTIN_TRANSFORM_MATRIX, 4, curxform.getElements(), 1);
shader->sendBuiltinMatrix(Shader::BUILTIN_PROJECTION_MATRIX, 4, curproj.getElements(), 1);
Matrix tp_matrix(curproj * curxform);
shader->sendBuiltinMatrix(Shader::BUILTIN_TRANSFORM_PROJECTION_MATRIX, 4, tp_matrix.getElements(), 1);
shader->checkSetPointSize(state.pointSize);
}
else if (GLAD_VERSION_1_0)
{
const Matrix &lastproj = state.lastProjectionMatrix;
const Matrix &lastxform = state.lastTransformMatrix;
+71 -67
View File
@@ -26,6 +26,7 @@
// C++
#include <algorithm>
#include <limits>
namespace love
{
@@ -50,7 +51,7 @@ namespace
~TemporaryAttacher()
{
if (prevShader != nullptr)
prevShader->attach();
prevShader->attach(true);
else
curShader->detach();
}
@@ -217,7 +218,12 @@ bool Shader::loadVolatile()
lastCanvas = (Canvas *) -1;
lastViewport = OpenGL::Viewport();
lastPointSize = 0.0f;
lastPointSize = -1.0f;
// Invalidate the cached matrices by setting some elements to NaN.
float nan = std::numeric_limits<float>::quiet_NaN();
lastProjectionMatrix.setTranslation(nan, nan);
lastTransformMatrix.setTranslation(nan, nan);
// zero out active texture list
activeTexUnits.clear();
@@ -299,7 +305,7 @@ bool Shader::loadVolatile()
// make sure glUseProgram gets called.
current = nullptr;
attach();
checkSetScreenParams();
checkSetBuiltinUniforms();
}
return true;
@@ -629,68 +635,6 @@ bool Shader::hasVertexAttrib(VertexAttribID attrib) const
return builtinAttributes[int(attrib)] != -1;
}
bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
{
return builtinUniforms[int(builtin)] != -1;
}
bool Shader::sendBuiltinMatrix(BuiltinUniform builtin, int size, const GLfloat *m, int count)
{
if (!hasBuiltinUniform(builtin))
return false;
GLint location = builtinUniforms[GLint(builtin)];
TemporaryAttacher attacher(this);
switch (size)
{
case 2:
glUniformMatrix2fv(location, count, GL_FALSE, m);
break;
case 3:
glUniformMatrix3fv(location, count, GL_FALSE, m);
break;
case 4:
glUniformMatrix4fv(location, count, GL_FALSE, m);
break;
default:
return false;
}
return true;
}
bool Shader::sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *vec, int count)
{
if (!hasBuiltinUniform(builtin))
return false;
GLint location = builtinUniforms[int(builtin)];
TemporaryAttacher attacher(this);
switch (size)
{
case 1:
glUniform1fv(location, count, vec);
break;
case 2:
glUniform2fv(location, count, vec);
break;
case 3:
glUniform3fv(location, count, vec);
break;
case 4:
glUniform4fv(location, count, vec);
break;
default:
return false;
}
return true;
}
void Shader::checkSetScreenParams()
{
OpenGL::Viewport view = gl.getViewport();
@@ -720,7 +664,13 @@ void Shader::checkSetScreenParams()
params[3] = (GLfloat) view.h;
}
sendBuiltinFloat(BUILTIN_SCREEN_SIZE, 4, params, 1);
GLint location = builtinUniforms[BUILTIN_SCREEN_SIZE];
if (location >= 0)
{
TemporaryAttacher attacher(this);
glUniform4fv(location, 1, params);
}
lastCanvas = Canvas::current;
lastViewport = view;
@@ -731,11 +681,65 @@ void Shader::checkSetPointSize(float size)
if (size == lastPointSize)
return;
sendBuiltinFloat(BUILTIN_POINT_SIZE, 1, &size, 1);
GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
if (location >= 0)
{
TemporaryAttacher attacher(this);
glUniform1f(location, size);
}
lastPointSize = size;
}
void Shader::checkSetBuiltinUniforms()
{
checkSetScreenParams();
if (GLAD_ES_VERSION_2_0)
{
checkSetPointSize(gl.getPointSize());
const Matrix &curxform = gl.matrices.transform.back();
const Matrix &curproj = gl.matrices.projection.back();
TemporaryAttacher attacher(this);
bool tpmatrixneedsupdate = false;
// Only upload the matrices if they've changed.
if (memcmp(curxform.getElements(), lastTransformMatrix.getElements(), sizeof(float) * 16) != 0)
{
GLint location = builtinUniforms[BUILTIN_TRANSFORM_MATRIX];
if (location >= 0)
glUniformMatrix4fv(location, 1, GL_FALSE, curxform.getElements());
tpmatrixneedsupdate = true;
lastTransformMatrix = curxform;
}
if (memcmp(curproj.getElements(), lastProjectionMatrix.getElements(), sizeof(float) * 16) != 0)
{
GLint location = builtinUniforms[BUILTIN_PROJECTION_MATRIX];
if (location >= 0)
glUniformMatrix4fv(location, 1, GL_FALSE, curproj.getElements());
tpmatrixneedsupdate = true;
lastProjectionMatrix = curproj;
}
if (tpmatrixneedsupdate)
{
GLint location = builtinUniforms[BUILTIN_TRANSFORM_PROJECTION_MATRIX];
if (location >= 0)
{
Matrix tp_matrix(curproj * curxform);
glUniformMatrix4fv(location, 1, GL_FALSE, tp_matrix.getElements());
}
}
}
}
const std::map<std::string, Object *> &Shader::getBoundRetainables() const
{
return boundRetainables;
+5 -3
View File
@@ -180,11 +180,10 @@ public:
* Internal use only.
**/
bool hasVertexAttrib(VertexAttribID attrib) const;
bool hasBuiltinUniform(BuiltinUniform builtin) const;
bool sendBuiltinMatrix(BuiltinUniform builtin, int size, const GLfloat *m, int count);
bool sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *m, int count);
void checkSetScreenParams();
void checkSetPointSize(float size);
void checkSetBuiltinUniforms();
const std::map<std::string, Object *> &getBoundRetainables() const;
@@ -260,6 +259,9 @@ private:
float lastPointSize;
Matrix lastTransformMatrix;
Matrix lastProjectionMatrix;
// Counts total number of textures bound to each texture unit in all shaders
static std::vector<int> textureCounters;