[cairo] [PATCH] gl: Move glGetUniformLocation to shader compile time.

Eric Anholt eric at anholt.net
Mon Jun 24 23:28:47 PDT 2013


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 at anholt.net>
---
 src/cairo-gl-composite.c |  2 +-
 src/cairo-gl-operand.c   | 30 ++++++++---------------
 src/cairo-gl-private.h   | 19 ++++++++++-----
 src/cairo-gl-shaders.c   | 62 ++++++++++++++++++++++++++++++++++--------------
 4 files changed, 68 insertions(+), 45 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..54c2d0e 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -805,6 +805,23 @@ 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 +830,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);
 
@@ -843,6 +862,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 +925,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 +984,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);
 }
-- 
1.8.3.rc0



More information about the cairo mailing list