diff options
author | Marek Olšák <[email protected]> | 2016-06-21 18:18:46 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2016-06-29 20:12:00 +0200 |
commit | 49e3c74cdd0da5abd6cad1fb14af6cc0d85d76c9 (patch) | |
tree | 7a928269bb6fc839a7e316265c09626ac8ba3c41 /src/gallium/drivers/radeonsi | |
parent | 9124457bff70686ea804d7e35fb63bea5db5a8a2 (diff) |
gallium/radeon: add a heuristic enabling DCC for scanout surfaces (v2)
DCC for displayable surfaces is allocated in a separate buffer and is
enabled or disabled based on PS invocations from 2 frames ago (to let
queries go idle) and the number of slow clears from the current frame.
At least an equivalent of 5 fullscreen draws or slow clears must be done
to enable DCC. (PS invocations / (width * height) + num_slow_clears >= 5)
Pipeline statistic queries are always active if a color buffer that can
have separate DCC is bound, even if separate DCC is disabled. That means
the window color buffer is always monitored and DCC is enabled only when
the situation is right.
The tracking of per-texture queries in r600_common_context is quite ugly,
but I don't see a better way.
The first fast clear always enables DCC. DCC decompression can disable it.
A later fast clear can enable it again. Enable/disable typically happens
only once per frame.
The impact is expected to be negligible because games usually don't have
a high level of overdraw. DCC usually activates when too much blending
is happening (smoke rendering) or when testing glClear performance and
CMASK isn't supported (Stoney).
v2: rename stuff, add assertions
Reviewed-by: Nicolai Hähnle <[email protected]>
Diffstat (limited to 'src/gallium/drivers/radeonsi')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_blit.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state_draw.c | 5 |
3 files changed, 33 insertions, 2 deletions
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c index 46daeac4ac0..a48c5bc19e1 100644 --- a/src/gallium/drivers/radeonsi/si_blit.c +++ b/src/gallium/drivers/radeonsi/si_blit.c @@ -1055,10 +1055,23 @@ static void si_flush_resource(struct pipe_context *ctx, struct r600_texture *rtex = (struct r600_texture*)res; assert(res->target != PIPE_BUFFER); + assert(!rtex->dcc_separate_buffer || rtex->dcc_gather_statistics); + + /* st/dri calls flush twice per frame (not a bug), this prevents double + * decompression. */ + if (rtex->dcc_separate_buffer && !rtex->separate_dcc_dirty) + return; if (!rtex->is_depth && (rtex->cmask.size || rtex->dcc_offset)) { si_blit_decompress_color(ctx, rtex, 0, res->last_level, - 0, util_max_layer(res, 0), false); + 0, util_max_layer(res, 0), + rtex->dcc_separate_buffer != NULL); + } + + /* Always do the analysis even if DCC is disabled at the moment. */ + if (rtex->dcc_gather_statistics && rtex->separate_dcc_dirty) { + rtex->separate_dcc_dirty = false; + vi_separate_dcc_process_and_reset_stats(ctx, rtex); } } diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 5aed352f55c..26831faa107 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2236,6 +2236,15 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, unsigned old_nr_samples = sctx->framebuffer.nr_samples; int i; + for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) { + if (!sctx->framebuffer.state.cbufs[i]) + continue; + + rtex = (struct r600_texture*)sctx->framebuffer.state.cbufs[i]->texture; + if (rtex->dcc_gather_statistics) + vi_separate_dcc_stop_query(ctx, rtex); + } + /* Only flush TC when changing the framebuffer state, because * the only client not using TC that can change textures is * the framebuffer. @@ -2307,6 +2316,12 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, r600_context_add_resource_size(ctx, surf->base.texture); p_atomic_inc(&rtex->framebuffers_bound); + + if (rtex->dcc_gather_statistics) { + /* Dirty tracking must be enabled for DCC usage analysis. */ + sctx->framebuffer.compressed_cb_mask |= 1 << i; + vi_separate_dcc_start_query(ctx, rtex); + } } /* Set the second SPI format for possible dual-src blending. */ if (i == 1 && surf) { diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index ce8def46659..a596bd81381 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -1042,7 +1042,10 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) surf = sctx->framebuffer.state.cbufs[i]; rtex = (struct r600_texture*)surf->texture; - rtex->dirty_level_mask |= 1 << surf->u.tex.level; + if (rtex->fmask.size) + rtex->dirty_level_mask |= 1 << surf->u.tex.level; + if (rtex->dcc_gather_statistics) + rtex->separate_dcc_dirty = true; } while (mask); } |