mirror of
https://github.com/love2d/love.git
synced 2026-08-12 16:40:57 +02:00
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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user