diff options
author | Marek Olšák <[email protected]> | 2016-08-02 16:40:50 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2016-08-12 18:50:01 +0200 |
commit | c323d5b8096cec3251c7a4a4269f0f7570fb274f (patch) | |
tree | a7c4e3e70b2109b34f57c85555f746aa959e0956 /src/mesa/state_tracker/st_atom.c | |
parent | 8c1775c14caf934bf56e9511099033477853d568 (diff) |
st/mesa: when changing shaders, only dirty states that are affected by them
This reduces the amount of state processing that has no effect.
Tested-by: Edmondo Tommasina <[email protected]>
Reviewed-by: Nicolai Hähnle <[email protected]>
Diffstat (limited to 'src/mesa/state_tracker/st_atom.c')
-rw-r--r-- | src/mesa/state_tracker/st_atom.c | 78 |
1 files changed, 63 insertions, 15 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 9985168be09..dddc5ff8a8b 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -63,22 +63,58 @@ void st_destroy_atoms( struct st_context *st ) static void check_program_state( struct st_context *st ) { struct gl_context *ctx = st->ctx; + struct st_vertex_program *old_vp = st->vp; + struct st_tessctrl_program *old_tcp = st->tcp; + struct st_tesseval_program *old_tep = st->tep; + struct st_geometry_program *old_gp = st->gp; + struct st_fragment_program *old_fp = st->fp; + + struct gl_vertex_program *new_vp = ctx->VertexProgram._Current; + struct gl_tess_ctrl_program *new_tcp = ctx->TessCtrlProgram._Current; + struct gl_tess_eval_program *new_tep = ctx->TessEvalProgram._Current; + struct gl_geometry_program *new_gp = ctx->GeometryProgram._Current; + struct gl_fragment_program *new_fp = ctx->FragmentProgram._Current; + uint64_t dirty = 0; + + /* Flag states used by both new and old shaders to unbind shader resources + * properly when transitioning to shaders that don't use them. + */ + if (unlikely(new_vp != &old_vp->Base)) { + if (old_vp) + dirty |= old_vp->affected_states; + if (new_vp) + dirty |= ST_NEW_VERTEX_PROGRAM(st, st_vertex_program(new_vp)); + } - if (ctx->VertexProgram._Current != &st->vp->Base) - st->dirty |= ST_NEW_VERTEX_PROGRAM(st); - - if (ctx->FragmentProgram._Current != &st->fp->Base) - st->dirty |= ST_NEW_FRAGMENT_PROGRAM; + if (unlikely(new_tcp != &old_tcp->Base)) { + if (old_tcp) + dirty |= old_tcp->affected_states; + if (new_tcp) + dirty |= st_tessctrl_program(new_tcp)->affected_states; + } - if (ctx->GeometryProgram._Current != &st->gp->Base) - st->dirty |= ST_NEW_GEOMETRY_PROGRAM; + if (unlikely(new_tep != &old_tep->Base)) { + if (old_tep) + dirty |= old_tep->affected_states; + if (new_tep) + dirty |= st_tesseval_program(new_tep)->affected_states; + } - if (ctx->TessCtrlProgram._Current != &st->tcp->Base) - st->dirty |= ST_NEW_TESSCTRL_PROGRAM; + if (unlikely(new_gp != &old_gp->Base)) { + if (old_gp) + dirty |= old_gp->affected_states; + if (new_gp) + dirty |= st_geometry_program(new_gp)->affected_states; + } - if (ctx->TessEvalProgram._Current != &st->tep->Base) - st->dirty |= ST_NEW_TESSEVAL_PROGRAM; + if (unlikely(new_fp != &old_fp->Base)) { + if (old_fp) + dirty |= old_fp->affected_states; + if (new_fp) + dirty |= st_fragment_program(new_fp)->affected_states; + } + st->dirty |= dirty; st->gfx_shaders_may_be_dirty = false; } @@ -86,6 +122,7 @@ static void check_attrib_edgeflag(struct st_context *st) { const struct gl_client_array **arrays = st->ctx->Array._DrawArrays; GLboolean vertdata_edgeflags, edgeflag_culls_prims, edgeflags_enabled; + struct gl_vertex_program *vp = st->ctx->VertexProgram._Current; if (!arrays) return; @@ -97,7 +134,8 @@ static void check_attrib_edgeflag(struct st_context *st) arrays[VERT_ATTRIB_EDGEFLAG]->StrideB != 0; if (vertdata_edgeflags != st->vertdata_edgeflags) { st->vertdata_edgeflags = vertdata_edgeflags; - st->dirty |= ST_NEW_VERTEX_PROGRAM(st); + if (vp) + st->dirty |= ST_NEW_VERTEX_PROGRAM(st, st_vertex_program(vp)); } edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags && @@ -134,13 +172,23 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline ) pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK; break; - case ST_PIPELINE_COMPUTE: - if (ctx->ComputeProgram._Current != &st->cp->Base) - st->dirty |= ST_NEW_COMPUTE_PROGRAM; + + case ST_PIPELINE_COMPUTE: { + struct st_compute_program *old_cp = st->cp; + struct gl_compute_program *new_cp = ctx->ComputeProgram._Current; + + if (new_cp != &old_cp->Base) { + if (old_cp) + st->dirty |= old_cp->affected_states; + assert(new_cp); + st->dirty |= st_compute_program(new_cp)->affected_states; + } st->compute_shader_may_be_dirty = false; pipeline_mask = ST_PIPELINE_COMPUTE_STATE_MASK; break; + } + default: unreachable("Invalid pipeline specified"); } |