Subject: [virglrenderer-devel] [PATCH 1/2] renderer: add program to end of list.

From: Dave Airlie <[email-masked]>
Date: Tue, 8 Mar 2016 10:47:38 +1000

From: Dave Airlie <[email-masked]>

This seems to do better in xonotic traces, we at least don't
traverse as much of the list to pick up the shaders.

I think we should be using a hash table here really.
---
 src/vrend_renderer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 64a2d78..ee45c23 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -905,7 +905,7 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
 
    sprog->id = prog_id;
 
-   list_add(&sprog->head, &ctx->sub->programs);
+   list_addtail(&sprog->head, &ctx->sub->programs);
 
    if (fs->key.pstipple_tex)
       sprog->fs_stipple_loc = glGetUniformLocation(prog_id, "pstipple_sampler");
-- 
2.5.0

_______________________________________________
virglrenderer-devel mailing list
[email-masked]
https://lists.freedesktop.org/mailman/listinfo/virglrenderer-devel

---

From: Dave Airlie <[email-masked]>
Date: Tue, 8 Mar 2016 10:47:39 +1000

If we have a lot of draws we end up traversing the linked list
looking for the same shader on each draw call even if the
shader is the same one we used the last time.

This removes a chunk of CPU overhead in the draw path.
---
 src/vrend_renderer.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index ee45c23..247acd5 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -311,6 +311,7 @@ struct vrend_sub_context {
    struct vrend_shader_selector *shaders[PIPE_SHADER_TYPES];
    struct vrend_linked_shader_program *prog;
 
+   int prog_ids[PIPE_SHADER_TYPES];
    struct vrend_shader_view views[PIPE_SHADER_TYPES];
 
    struct vrend_constants consts[PIPE_SHADER_TYPES];
@@ -2733,6 +2734,7 @@ void vrend_draw_vbo(struct vrend_context *ctx,
       struct vrend_linked_shader_program *prog;
       bool fs_dirty, vs_dirty, gs_dirty;
       bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0);
+      bool same_prog;
       if (!ctx->sub->shaders[PIPE_SHADER_VERTEX] || !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]) {
          fprintf(stderr,"dropping rendering due to missing shaders: %s\n", ctx->debug_name);
          return;
@@ -2747,16 +2749,31 @@ void vrend_draw_vbo(struct vrend_context *ctx,
          fprintf(stderr, "failure to compile shader variants: %s\n", ctx->debug_name);
          return;
       }
-      prog = lookup_shader_program(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id, ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id, ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id : 0, dual_src);
-      if (!prog) {
-         prog = add_shader_program(ctx,
-                                   ctx->sub->shaders[PIPE_SHADER_VERTEX]->current,
-                                   ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current, ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL);
-         if (!prog)
-            return;
-      }
+      same_prog = true;
+      if (ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id != ctx->sub->prog_ids[PIPE_SHADER_VERTEX])
+         same_prog = false;
+      if (ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id != ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT])
+         same_prog = false;
+      if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id != ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT])
+         same_prog = false;
+
+      if (!same_prog) {
+         prog = lookup_shader_program(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id, ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id, ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id : 0, dual_src);
+         if (!prog) {
+            prog = add_shader_program(ctx,
+                                      ctx->sub->shaders[PIPE_SHADER_VERTEX]->current,
+                                      ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current, ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL);
+            if (!prog)
+               return;
+         }
+      } else
+         prog = ctx->sub->prog;
       if (ctx->sub->prog != prog) {
          new_program = true;
+         ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id;
+         ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT] = ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id;
+         if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY])
+            ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY] = ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id;
          ctx->sub->prog = prog;
       }
    }
-- 
2.5.0