gallium/radeon: don't discard DCC if an external user can write to it
authorMarek Olšák <marek.olsak@amd.com>
Thu, 2 Jun 2016 21:30:01 +0000 (23:30 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 7 Jun 2016 09:12:26 +0000 (11:12 +0200)
We don't import textures with DCC now, but soon we will.

v2: if we can't disable DCC for image writes, at least decompress DCC
    at bind time

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

index 8072833204a81b3a89dd7c2f470eacd9153aaf46..2d60da49b728c6a40a6107eafd25162569a92ecd 100644 (file)
@@ -676,7 +676,7 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
                                   struct r600_atom *fb_state,
                                   unsigned *buffers, unsigned *dirty_cbufs,
                                   const union pipe_color_union *color);
-void r600_texture_disable_dcc(struct r600_common_screen *rscreen,
+bool r600_texture_disable_dcc(struct r600_common_screen *rscreen,
                              struct r600_texture *rtex);
 void r600_init_screen_texture_functions(struct r600_common_screen *rscreen);
 void r600_init_context_texture_functions(struct r600_common_context *rctx);
index 71758c42093870755265148f8bceca9cae3622ff..0f5c08f281a494a6805f0ed87cff06cbbce6256a 100644 (file)
@@ -32,7 +32,7 @@
 #include <errno.h>
 #include <inttypes.h>
 
-static void r600_texture_discard_dcc(struct r600_common_screen *rscreen,
+static bool r600_texture_discard_dcc(struct r600_common_screen *rscreen,
                                     struct r600_texture *rtex);
 static void r600_texture_discard_cmask(struct r600_common_screen *rscreen,
                                       struct r600_texture *rtex);
@@ -86,7 +86,8 @@ bool r600_prepare_for_dma_blit(struct r600_common_context *rctx,
                                                      src_box->height, src_box->depth))
                        return false;
 
-               r600_texture_discard_dcc(rctx->screen, rdst);
+               if (!r600_texture_discard_dcc(rctx->screen, rdst))
+                       return false;
        }
 
        /* CMASK as:
@@ -376,25 +377,37 @@ static void r600_texture_discard_cmask(struct r600_common_screen *rscreen,
        p_atomic_inc(&rscreen->compressed_colortex_counter);
 }
 
-static void r600_texture_discard_dcc(struct r600_common_screen *rscreen,
+static bool r600_can_disable_dcc(struct r600_texture *rtex)
+{
+       /* We can't disable DCC if it can be written by another process. */
+       return rtex->dcc_offset &&
+              (!rtex->resource.is_shared ||
+               !(rtex->resource.external_usage & PIPE_HANDLE_USAGE_WRITE));
+}
+
+static bool r600_texture_discard_dcc(struct r600_common_screen *rscreen,
                                     struct r600_texture *rtex)
 {
+       if (!r600_can_disable_dcc(rtex))
+               return false;
+
        /* Disable DCC. */
        rtex->dcc_offset = 0;
        rtex->cb_color_info &= ~VI_S_028C70_DCC_ENABLE(1);
 
        /* Notify all contexts about the change. */
        r600_dirty_all_framebuffer_states(rscreen);
+       return true;
 }
 
-void r600_texture_disable_dcc(struct r600_common_screen *rscreen,
+bool r600_texture_disable_dcc(struct r600_common_screen *rscreen,
                              struct r600_texture *rtex)
 {
        struct r600_common_context *rctx =
                (struct r600_common_context *)rscreen->aux_context;
 
-       if (!rtex->dcc_offset)
-               return;
+       if (!r600_can_disable_dcc(rtex))
+               return false;
 
        /* Decompress DCC. */
        pipe_mutex_lock(rscreen->aux_context_lock);
@@ -402,7 +415,7 @@ void r600_texture_disable_dcc(struct r600_common_screen *rscreen,
        rctx->b.flush(&rctx->b, NULL, 0);
        pipe_mutex_unlock(rscreen->aux_context_lock);
 
-       r600_texture_discard_dcc(rscreen, rtex);
+       return r600_texture_discard_dcc(rscreen, rtex);
 }
 
 static void r600_degrade_tile_mode_to_linear(struct r600_common_context *rctx,
@@ -497,8 +510,8 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
                 * access.
                 */
                if (usage & PIPE_HANDLE_USAGE_WRITE && rtex->dcc_offset) {
-                       r600_texture_disable_dcc(rscreen, rtex);
-                       update_metadata = true;
+                       if (r600_texture_disable_dcc(rscreen, rtex))
+                               update_metadata = true;
                }
 
                if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) &&
index f48ddb77aabe672ec38796983be4c61c6bc120a0..9ddb142602dd1295c076d3d321c699f629c89905 100644 (file)
@@ -570,8 +570,14 @@ static void si_set_shader_image(struct si_context *ctx,
                assert(tex->fmask.size == 0);
 
                if (tex->dcc_offset &&
-                   view->access & PIPE_IMAGE_ACCESS_WRITE)
-                       r600_texture_disable_dcc(&screen->b, tex);
+                   view->access & PIPE_IMAGE_ACCESS_WRITE) {
+                       /* If DCC can't be disabled, at least decompress it.
+                        * The decompression is relatively cheap if the surface
+                        * has been decompressed already.
+                        */
+                       if (!r600_texture_disable_dcc(&screen->b, tex))
+                               ctx->b.decompress_dcc(&ctx->b.b, tex);
+               }
 
                if (is_compressed_colortex(tex)) {
                        images->compressed_colortex_mask |= 1 << slot;