From 7b8fc77bb974fbd4fbc697405a8b6aec748bb7f2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Jun 2013 23:28:47 -0700 Subject: [PATCH] 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 Reviewed-by: Chris Wilson --- src/cairo-gl-composite.c | 2 +- src/cairo-gl-operand.c | 30 ++++++------------ src/cairo-gl-private.h | 19 ++++++++---- src/cairo-gl-shaders.c | 67 +++++++++++++++++++++++++++------------- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index 1dcc6a134..68c9b80ca 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 7b5b404de..401574717 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 d49e3d93f..8379abc95 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 d8de71252..cc22cea41 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); }