* The DB->CB copy uses CB for the final writes.
*/
if (copy_planes && tex->resource.b.b.nr_samples > 1)
- si_make_CB_shader_coherent(sctx, tex->resource.b.b.nr_samples);
+ si_make_CB_shader_coherent(sctx, tex->resource.b.b.nr_samples,
+ false);
}
static void
}
sctx->decompression_enabled = false;
- si_make_CB_shader_coherent(sctx, rtex->resource.b.b.nr_samples);
+ si_make_CB_shader_coherent(sctx, rtex->resource.b.b.nr_samples,
+ vi_dcc_enabled(rtex, first_level));
}
static void
si_blitter_end(&sctx->b.b);
/* Flush caches for possible texturing. */
- si_make_CB_shader_coherent(sctx, 1);
+ si_make_CB_shader_coherent(sctx, 1, false);
}
static bool do_hardware_msaa_resolve(struct pipe_context *ctx,
/* Write dirty L2 lines back to memory (shader and CP DMA stores), but don't
* invalidate L2. SI-CIK can't do it, so they will do complete invalidation. */
#define SI_CONTEXT_WRITEBACK_GLOBAL_L2 (R600_CONTEXT_PRIVATE_FLAG << 4)
-/* gaps */
+/* Writeback & invalidate the L2 metadata cache. It can only be coupled with
+ * a CB or DB flush. */
+#define SI_CONTEXT_INV_L2_METADATA (R600_CONTEXT_PRIVATE_FLAG << 5)
+/* gap */
/* Framebuffer caches. */
#define SI_CONTEXT_FLUSH_AND_INV_DB (R600_CONTEXT_PRIVATE_FLAG << 7)
#define SI_CONTEXT_FLUSH_AND_INV_CB (R600_CONTEXT_PRIVATE_FLAG << 8)
ubyte dirty_cbufs;
bool dirty_zsbuf;
bool any_dst_linear;
+ bool CB_has_shader_readable_metadata;
};
struct si_clip_state {
}
static inline void
-si_make_CB_shader_coherent(struct si_context *sctx, unsigned num_samples)
+si_make_CB_shader_coherent(struct si_context *sctx, unsigned num_samples,
+ bool shaders_read_metadata)
{
sctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_CB |
SI_CONTEXT_INV_VMEM_L1;
- /* Single-sample color is coherent with shaders on GFX9. */
- if (sctx->b.chip_class <= VI || num_samples >= 2)
+ if (sctx->b.chip_class >= GFX9) {
+ /* Single-sample color is coherent with shaders on GFX9, but
+ * L2 metadata must be flushed if shaders read metadata.
+ * (DCC, CMASK).
+ */
+ if (num_samples >= 2)
+ sctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2;
+ else if (shaders_read_metadata)
+ sctx->b.flags |= SI_CONTEXT_INV_L2_METADATA;
+ } else {
+ /* SI-CI-VI */
sctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2;
+ }
}
static inline void
*/
if (sctx->framebuffer.nr_samples <= 1 &&
sctx->framebuffer.state.nr_cbufs)
- si_make_CB_shader_coherent(sctx, sctx->framebuffer.nr_samples);
+ si_make_CB_shader_coherent(sctx, sctx->framebuffer.nr_samples,
+ sctx->framebuffer.CB_has_shader_readable_metadata);
sctx->b.flags |= SI_CONTEXT_CS_PARTIAL_FLUSH;
sctx->framebuffer.nr_samples = util_framebuffer_get_num_samples(state);
sctx->framebuffer.log_samples = util_logbase2(sctx->framebuffer.nr_samples);
sctx->framebuffer.any_dst_linear = false;
+ sctx->framebuffer.CB_has_shader_readable_metadata = false;
for (i = 0; i < state->nr_cbufs; i++) {
if (!state->cbufs[i])
if (rtex->surface.is_linear)
sctx->framebuffer.any_dst_linear = true;
+ if (vi_dcc_enabled(rtex, surf->base.u.tex.level))
+ sctx->framebuffer.CB_has_shader_readable_metadata = true;
+
r600_context_add_resource_size(ctx, surf->base.texture);
p_atomic_inc(&rtex->framebuffers_bound);
/* Multisample surfaces are flushed in si_decompress_textures. */
if (sctx->framebuffer.nr_samples <= 1 &&
sctx->framebuffer.state.nr_cbufs)
- si_make_CB_shader_coherent(sctx, sctx->framebuffer.nr_samples);
+ si_make_CB_shader_coherent(sctx, sctx->framebuffer.nr_samples,
+ sctx->framebuffer.CB_has_shader_readable_metadata);
}
/* This only ensures coherency for shader image/buffer stores. */
sctx->framebuffer.state.nr_cbufs) {
sctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_CB;
- /* Single-sample color is coherent with TC on GFX9. */
- if (sctx->screen->b.chip_class <= VI)
+ if (sctx->b.chip_class <= VI)
sctx->b.flags |= SI_CONTEXT_WRITEBACK_GLOBAL_L2;
}
* TC | TC_MD = writeback & invalidate L2 metadata (DCC, etc.)
* TCL1 = invalidate L1
*/
+ tc_flags = 0;
- /* When flushing CB or DB, L2 metadata should always be invali-
- * dated before texturing. Invalidating L2 data is not needed
- * in some cases.
- */
- tc_flags = EVENT_TC_ACTION_ENA |
- EVENT_TC_MD_ACTION_ENA;
+ if (rctx->flags & SI_CONTEXT_INV_L2_METADATA) {
+ tc_flags = EVENT_TC_ACTION_ENA |
+ EVENT_TC_MD_ACTION_ENA;
+ }
/* Ideally flush TC together with CB/DB. */
if (rctx->flags & SI_CONTEXT_INV_GLOBAL_L2) {