gl: Move glGetUniformLocation to shader compile time.

The lookup of the string names has significant overhead, which is why GL
gives you glGetUniformLocation so that you reference uniforms by
constant integers in your high performance path.

Reduces cairo-perf-trace runtime of firefox-planet-gnome by 1.06767% +/-
0.289265% (n=72) on my IVB macbook air.

Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Eric Anholt 2013-06-24 23:28:47 -07:00 committed by Chris Wilson
parent 4d9439132d
commit 7b8fc77bb9
4 changed files with 70 additions and 48 deletions

View file

@ -134,7 +134,7 @@ static void
_cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
_cairo_gl_shader_bind_matrix4f(ctx, "ModelViewProjectionMatrix",
_cairo_gl_shader_bind_matrix4f(ctx, ctx->current_shader->mvp_location,
ctx->modelviewprojection_matrix);
_cairo_gl_operand_bind_to_shader (ctx, &setup->src, CAIRO_GL_TEX_SOURCE);
_cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK);

View file

@ -613,14 +613,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
cairo_gl_operand_t *operand,
cairo_gl_tex_t tex_unit)
{
char uniform_name[50];
char *custom_part;
static const char *names[] = { "source", "mask" };
const cairo_matrix_t *texgen = NULL;
strcpy (uniform_name, names[tex_unit]);
custom_part = uniform_name + strlen (names[tex_unit]);
switch (operand->type) {
default:
case CAIRO_GL_OPERAND_COUNT:
@ -629,9 +623,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
return;
case CAIRO_GL_OPERAND_CONSTANT:
strcpy (custom_part, "_constant");
_cairo_gl_shader_bind_vec4 (ctx,
uniform_name,
ctx->current_shader->constant_location[tex_unit],
operand->constant.color[0],
operand->constant.color[1],
operand->constant.color[2],
@ -640,21 +633,18 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
strcpy (custom_part, "_a");
_cairo_gl_shader_bind_float (ctx,
uniform_name,
ctx->current_shader->a_location[tex_unit],
operand->gradient.a);
/* fall through */
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
strcpy (custom_part, "_circle_d");
_cairo_gl_shader_bind_vec3 (ctx,
uniform_name,
ctx->current_shader->circle_d_location[tex_unit],
operand->gradient.circle_d.center.x,
operand->gradient.circle_d.center.y,
operand->gradient.circle_d.radius);
strcpy (custom_part, "_radius_0");
_cairo_gl_shader_bind_float (ctx,
uniform_name,
ctx->current_shader->radius_0_location[tex_unit],
operand->gradient.radius_0);
/* fall through */
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
@ -677,8 +667,9 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
width = operand->gradient.gradient->cache_entry.size,
height = 1;
}
strcpy (custom_part, "_texdims");
_cairo_gl_shader_bind_vec2 (ctx, uniform_name, width, height);
_cairo_gl_shader_bind_vec2 (ctx,
ctx->current_shader->texdims_location[tex_unit],
width, height);
}
break;
}
@ -691,10 +682,9 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
texgen = &operand->gradient.m;
}
if (texgen) {
char name[20];
sprintf (name, "%s_texgen", names[tex_unit]);
_cairo_gl_shader_bind_matrix(ctx, name, texgen);
_cairo_gl_shader_bind_matrix(ctx,
ctx->current_shader->texgen_location[tex_unit],
texgen);
}
}

View file

@ -201,6 +201,13 @@ typedef enum cairo_gl_tex {
typedef struct cairo_gl_shader {
GLuint fragment_shader;
GLuint program;
GLint mvp_location;
GLint constant_location[2];
GLint a_location[2];
GLint circle_d_location[2];
GLint radius_0_location[2];
GLint texdims_location[2];
GLint texgen_location[2];
} cairo_gl_shader_t;
typedef enum cairo_gl_shader_in {
@ -651,35 +658,35 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
cairo_private void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value);
cairo_private void
_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0, float value1);
cairo_private void
_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0,
float value1,
float value2);
cairo_private void
_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0, float value1,
float value2, float value3);
cairo_private void
_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
const char *name,
GLint location,
const cairo_matrix_t* m);
cairo_private void
_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
const char *name,
GLint location,
GLfloat* gl_m);
cairo_private void

View file

@ -805,6 +805,22 @@ link_shader_program (cairo_gl_context_t *ctx,
ASSERT_NOT_REACHED;
}
static GLint
_cairo_gl_get_op_uniform_location(cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader,
cairo_gl_tex_t tex_unit,
const char *suffix)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
char uniform_name[100];
const char *unit_name[2] = { "source", "mask" };
snprintf (uniform_name, sizeof (uniform_name), "%s_%s",
unit_name[tex_unit], suffix);
return dispatch->GetUniformLocation (shader->program, uniform_name);
}
static cairo_status_t
_cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader,
@ -813,8 +829,10 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
cairo_bool_t use_coverage,
const char *fragment_text)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
unsigned int vertex_shader;
cairo_status_t status;
int i;
assert (shader->program == 0);
@ -828,12 +846,12 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
use_coverage,
CAIRO_GL_VAR_NONE,
&source);
if (unlikely (status))
goto FAILURE;
if (unlikely (status))
goto FAILURE;
compile_shader (ctx, &ctx->vertex_shaders[vertex_shader],
GL_VERTEX_SHADER, source);
free (source);
free (source);
}
compile_shader (ctx, &shader->fragment_shader,
@ -843,6 +861,25 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
ctx->vertex_shaders[vertex_shader],
shader->fragment_shader);
shader->mvp_location =
dispatch->GetUniformLocation (shader->program,
"ModelViewProjectionMatrix");
for (i = 0; i < 2; i++) {
shader->constant_location[i] =
_cairo_gl_get_op_uniform_location (ctx, shader, i, "constant");
shader->a_location[i] =
_cairo_gl_get_op_uniform_location (ctx, shader, i, "a");
shader->circle_d_location[i] =
_cairo_gl_get_op_uniform_location (ctx, shader, i, "circle_d");
shader->radius_0_location[i] =
_cairo_gl_get_op_uniform_location (ctx, shader, i, "radius_0");
shader->texdims_location[i] =
_cairo_gl_get_op_uniform_location (ctx, shader, i, "texdims");
shader->texgen_location[i] =
_cairo_gl_get_op_uniform_location (ctx, shader, i, "texgen");
}
return CAIRO_STATUS_SUCCESS;
FAILURE:
@ -887,64 +924,54 @@ _cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx,
void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
name);
assert (location != -1);
dispatch->Uniform1f (location, value);
}
void
_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0,
float value1)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
name);
assert (location != -1);
dispatch->Uniform2f (location, value0, value1);
}
void
_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0,
float value1,
float value2)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
name);
assert (location != -1);
dispatch->Uniform3f (location, value0, value1, value2);
}
void
_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0, float value1,
float value2, float value3)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
name);
assert (location != -1);
dispatch->Uniform4f (location, value0, value1, value2, value3);
}
void
_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
const char *name,
GLint location,
const cairo_matrix_t* m)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
name);
float gl_m[9] = {
m->xx, m->xy, m->x0,
m->yx, m->yy, m->y0,
@ -956,11 +983,9 @@ _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
void
_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
const char *name, GLfloat* gl_m)
GLint location, GLfloat* gl_m)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
name);
assert (location != -1);
dispatch->UniformMatrix4fv (location, 1, GL_FALSE, gl_m);
}