diff options
author | Dave Airlie <airlied@redhat.com> | 2016-03-08 10:12:52 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-03-08 10:12:52 +1000 |
commit | 51e483830addb1ae870b30f4ebd2d0595ad404bf (patch) | |
tree | f203f7ecd42cd53b67feb5eb762ce8541b7c0a25 | |
parent | 8aa342721d3f996dd1c31ec9e0802c58ea0ddfa0 (diff) |
renderer: avoid looking up the same shader on every draw.
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.
-rw-r--r-- | src/vrend_renderer.c | 33 |
1 files 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; } } |