diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 11 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 19 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 39 |
4 files changed, 52 insertions, 22 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 3b6cb8f7a11..550d3a75d27 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -447,6 +447,13 @@ enum r300_hiz_func { HIZ_FUNC_MIN, }; +/* For deferred fragment shader state validation. */ +enum r300_fs_validity_status { + FRAGMENT_SHADER_VALID, /* No need to change/validate the FS. */ + FRAGMENT_SHADER_MAYBE_DIRTY,/* Validate the FS if external state was changed. */ + FRAGMENT_SHADER_DIRTY /* Always validate the FS (if the FS was changed) */ +}; + struct r300_context { /* Parent class */ struct pipe_context context; @@ -598,6 +605,10 @@ struct r300_context { enum r300_hiz_func hiz_func; /* HiZ clear value. */ uint32_t hiz_clear_value; + /* Whether fragment shader needs to be validated. */ + enum r300_fs_validity_status fs_status; + /* Framebuffer multi-write. */ + boolean fb_multiwrite; void *dsa_decompress_zmask; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 3b79b36221d..6b91f93e6d6 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -387,8 +387,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) if (r300->screen->caps.is_r500) { rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE; } - if (fb->nr_cbufs && - r300_fragment_shader_writes_all(r300_fs(r300))) { + if (fb->nr_cbufs && r300->fb_multiwrite) { rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs); } @@ -483,7 +482,7 @@ void r300_emit_fb_state_pipelined(struct r300_context *r300, /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be * marked as UNUSED in the US block. */ - if (r300_fragment_shader_writes_all(r300_fs(r300))) { + if (r300->fb_multiwrite) { num_cbufs = MIN2(num_cbufs, 1); } diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 890e3961b18..61d6751e5d3 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -969,24 +969,14 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; - struct pipe_framebuffer_state *fb = r300->fb_state.state; - boolean last_multi_write; if (fs == NULL) { r300->fs.state = NULL; return; } - last_multi_write = r300_fragment_shader_writes_all(r300_fs(r300)); - r300->fs.state = fs; - r300_pick_fragment_shader(r300); - r300_mark_fs_code_dirty(r300); - - if (fb->nr_cbufs > 1 && - last_multi_write != r300_fragment_shader_writes_all(fs)) { - r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE); - } + r300->fs_status = FRAGMENT_SHADER_DIRTY; r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */ } @@ -1256,8 +1246,8 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) } if (last_frag_clamp != r300->frag_clamp && - r300->fs.state && r300_pick_fragment_shader(r300)) { - r300_mark_fs_code_dirty(r300); + r300->fs_status == FRAGMENT_SHADER_VALID) { + r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY; } } @@ -1555,7 +1545,8 @@ static void r300_set_viewport_state(struct pipe_context* pipe, } r300_mark_atom_dirty(r300, &r300->viewport_state); - if (r300->fs.state && r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) { + if (r300->fs.state && r300_fs(r300)->shader && + r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) { r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state); } } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 02fc1219e95..e943f1a715f 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -961,11 +961,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) r300->textures_state.size = size; /* Pick a fragment shader based on either the texture compare state - * or the uses_pitch flag. */ - if (r300->fs.state && count) { - if (r300_pick_fragment_shader(r300)) { - r300_mark_fs_code_dirty(r300); - } + * or the uses_pitch flag or some other external state. */ + if (count && + r300->fs_status == FRAGMENT_SHADER_VALID) { + r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY; } } @@ -994,6 +993,34 @@ static void r300_decompress_depth_textures(struct r300_context *r300) } } +static void r300_validate_fragment_shader(struct r300_context *r300) +{ + struct pipe_framebuffer_state *fb = r300->fb_state.state; + + if (r300->fs.state && r300->fs_status != FRAGMENT_SHADER_VALID) { + /* Pick the fragment shader based on external states. + * Then mark the state dirty if the fragment shader is either dirty + * or the function r300_pick_fragment_shader changed the shader. */ + if (r300_pick_fragment_shader(r300) || + r300->fs_status == FRAGMENT_SHADER_DIRTY) { + /* Mark the state atom as dirty. */ + r300_mark_fs_code_dirty(r300); + + /* Does Multiwrite need to be changed? */ + if (fb->nr_cbufs > 1) { + boolean new_multiwrite = + r300_fragment_shader_writes_all(r300_fs(r300)); + + if (r300->fb_multiwrite != new_multiwrite) { + r300->fb_multiwrite = new_multiwrite; + r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE); + } + } + } + r300->fs_status = FRAGMENT_SHADER_VALID; + } +} + void r300_update_derived_state(struct r300_context* r300) { if (r300->textures_state.dirty) { @@ -1001,6 +1028,8 @@ void r300_update_derived_state(struct r300_context* r300) r300_merge_textures_and_samplers(r300); } + r300_validate_fragment_shader(r300); + if (r300->rs_block_state.dirty) { r300_update_rs_block(r300); |