gallium/radeon: add state setup for a separate DCC buffer
authorMarek Olšák <marek.olsak@amd.com>
Tue, 21 Jun 2016 14:16:15 +0000 (16:16 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 29 Jun 2016 18:12:00 +0000 (20:12 +0200)
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/r600_texture.c
src/gallium/drivers/radeonsi/si_descriptors.c
src/gallium/drivers/radeonsi/si_state.c

index 75dc5acc2471e86f3619b627b80eda5b9fcb9202..b411b23ba8738cb4e1ae67b34bd61e8bfbd52be8 100644 (file)
@@ -265,6 +265,14 @@ struct r600_texture {
 
        bool                            non_disp_tiling; /* R600-Cayman only */
 
+       /* Whether the texture is a displayable back buffer and needs DCC
+        * decompression, which is expensive. Therefore, it's enabled only
+        * if statistics suggest that it will pay off and it's allocated
+        * separately. Limited to target == 2D and last_level == 0. If enabled,
+        * dcc_offset contains the absolute GPUVM address, not the relative one.
+        */
+       struct r600_resource            *dcc_separate_buffer;
+
        /* Counter that should be non-zero if the texture is bound to a
         * framebuffer. Implemented in radeonsi only.
         */
index 50f50257ebf317d7267e7371880e3b5a72a6a6c9..c45c5f29fb8706d9bc646476c0fa3ca22487bc89 100644 (file)
@@ -387,6 +387,8 @@ static bool r600_texture_discard_dcc(struct r600_common_screen *rscreen,
        if (!r600_can_disable_dcc(rtex))
                return false;
 
+       assert(rtex->dcc_separate_buffer == NULL);
+
        /* Disable DCC. */
        rtex->dcc_offset = 0;
 
@@ -564,6 +566,7 @@ static void r600_texture_destroy(struct pipe_screen *screen,
            r600_resource_reference(&rtex->cmask_buffer, NULL);
        }
        pb_reference(&resource->buf, NULL);
+       r600_resource_reference(&rtex->dcc_separate_buffer, NULL);
        FREE(rtex);
 }
 
@@ -1800,12 +1803,21 @@ void vi_dcc_clear_level(struct r600_common_context *rctx,
                        struct r600_texture *rtex,
                        unsigned level, unsigned clear_value)
 {
-       struct pipe_resource *dcc_buffer = &rtex->resource.b.b;
-       uint64_t dcc_offset = rtex->dcc_offset +
-                             rtex->surface.level[level].dcc_offset;
+       struct pipe_resource *dcc_buffer;
+       uint64_t dcc_offset;
 
        assert(rtex->dcc_offset && rtex->surface.level[level].dcc_enabled);
 
+       if (rtex->dcc_separate_buffer) {
+               dcc_buffer = &rtex->dcc_separate_buffer->b.b;
+               dcc_offset = 0;
+       } else {
+               dcc_buffer = &rtex->resource.b.b;
+               dcc_offset = rtex->dcc_offset;
+       }
+
+       dcc_offset += rtex->surface.level[level].dcc_offset;
+
        rctx->clear_buffer(&rctx->b, dcc_buffer, dcc_offset,
                           rtex->surface.level[level].dcc_fast_clear_size,
                           clear_value, R600_COHERENCY_CB_META);
index 78d14afe4066570afb2d6c3ba2da484f62f1b56d..d1cd3c4449a2130a641834e2b3f4d2b6932771f1 100644 (file)
@@ -304,6 +304,15 @@ static void si_sampler_view_add_buffer(struct si_context *sctx,
 
        radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, rres, usage,
                                  r600_get_sampler_view_priority(rres));
+
+       if (resource->target != PIPE_BUFFER) {
+               struct r600_texture *rtex = (struct r600_texture*)resource;
+
+               if (rtex->dcc_separate_buffer)
+                       radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
+                                                 rtex->dcc_separate_buffer, usage,
+                                                 RADEON_PRIO_DCC);
+       }
 }
 
 static void si_sampler_views_begin_new_cs(struct si_context *sctx,
@@ -352,7 +361,7 @@ void si_set_mutable_tex_desc_fields(struct r600_texture *tex,
 
        if (tex->dcc_offset && tex->surface.level[first_level].dcc_enabled) {
                state[6] |= S_008F28_COMPRESSION_EN(1);
-               state[7] = (tex->resource.gpu_address +
+               state[7] = ((!tex->dcc_separate_buffer ? tex->resource.gpu_address : 0) +
                            tex->dcc_offset +
                            base_level_info->dcc_offset) >> 8;
        }
index 6db65be382fe5e8cd970f6cc2a9d85ec519892d6..5aed352f55c82f6daa5d9a99320d297060947dc7 100644 (file)
@@ -2420,6 +2420,12 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
                                RADEON_PRIO_CMASK);
                }
 
+               if (tex->dcc_separate_buffer)
+                       radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
+                                                 tex->dcc_separate_buffer,
+                                                 RADEON_USAGE_READWRITE,
+                                                 RADEON_PRIO_DCC);
+
                /* Compute mutable surface parameters. */
                pitch_tile_max = cb->level_info->nblk_x / 8 - 1;
                slice_tile_max = cb->level_info->nblk_x *
@@ -2476,7 +2482,7 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
                radeon_emit(cs, tex->color_clear_value[1]);     /* R_028C90_CB_COLOR0_CLEAR_WORD1 */
 
                if (sctx->b.chip_class >= VI) /* R_028C94_CB_COLOR0_DCC_BASE */
-                       radeon_emit(cs, (tex->resource.gpu_address +
+                       radeon_emit(cs, ((!tex->dcc_separate_buffer ? tex->resource.gpu_address : 0) +
                                         tex->dcc_offset +
                                         tex->surface.level[cb->base.u.tex.level].dcc_offset) >> 8);
        }
@@ -3447,6 +3453,7 @@ static void si_query_opaque_metadata(struct r600_common_screen *rscreen,
        if (rscreen->info.drm_major != 3)
                return;
 
+       assert(rtex->dcc_separate_buffer == NULL);
        assert(rtex->fmask.size == 0);
 
        /* Metadata image format format version 1: