summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2013-06-25 06:28:47 (GMT)
committerChris Wilson <chris@chris-wilson.co.uk>2013-06-28 10:53:04 (GMT)
commit7b8fc77bb974fbd4fbc697405a8b6aec748bb7f2 (patch)
tree6bd8a8016e2f9116e375c02fe3f91c8dfcc3b1fb
parent4d9439132de85c0f0f4d5b5a474ea7164910251e (diff)
downloadcairo-7b8fc77bb974fbd4fbc697405a8b6aec748bb7f2.tar.gz
cairo-7b8fc77bb974fbd4fbc697405a8b6aec748bb7f2.tar.xz
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>
-rw-r--r--src/cairo-gl-composite.c2
-rw-r--r--src/cairo-gl-operand.c30
-rw-r--r--src/cairo-gl-private.h19
-rw-r--r--src/cairo-gl-shaders.c67
4 files changed, 70 insertions, 48 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 1dcc6a1..68c9b80 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -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);
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 7b5b404..4015747 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -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);
}
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index d49e3d9..8379abc 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -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
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index d8de712..cc22cea 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -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);
}