radeonsi: decompress DCC in set_framebuffer_state instead of create_surface (v2)
authorMarek Olšák <marek.olsak@amd.com>
Fri, 24 Mar 2017 02:02:53 +0000 (03:02 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 31 Mar 2017 18:57:53 +0000 (20:57 +0200)
for threaded gallium, which can't use pipe_context in create_surface

v2: don't add a new decompress helper function

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_state.c

index 2feca0172faf37b89b8ba0915d28004467983e05..6a52247d45879760d163f94b58a5e7312f504638 100644 (file)
@@ -287,6 +287,7 @@ struct r600_surface {
        bool export_16bpc;
        bool color_is_int8;
        bool color_is_int10;
+       bool dcc_incompatible;
 
        /* Color registers. */
        unsigned cb_color_info;
@@ -801,6 +802,9 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
                                        const struct pipe_resource *templ);
 bool vi_dcc_formats_compatible(enum pipe_format format1,
                               enum pipe_format format2);
+bool vi_dcc_formats_are_incompatible(struct pipe_resource *tex,
+                                    unsigned level,
+                                    enum pipe_format view_format);
 void vi_disable_dcc_if_incompatible_format(struct r600_common_context *rctx,
                                           struct pipe_resource *tex,
                                           unsigned level,
index 0daa5ea53e2b4f7abf3c73117af7757ea0d50b54..877f5552bd549cdc3ac1363146e0ffaa6672b47c 100644 (file)
@@ -1903,6 +1903,18 @@ bool vi_dcc_formats_compatible(enum pipe_format format1,
               type1 == type2;
 }
 
+bool vi_dcc_formats_are_incompatible(struct pipe_resource *tex,
+                                    unsigned level,
+                                    enum pipe_format view_format)
+{
+       struct r600_texture *rtex = (struct r600_texture *)tex;
+
+       return vi_dcc_enabled(rtex, level) &&
+              !vi_dcc_formats_compatible(tex->format, view_format);
+}
+
+/* This can't be merged with the above function, because
+ * vi_dcc_formats_compatible should be called only when DCC is enabled. */
 void vi_disable_dcc_if_incompatible_format(struct r600_common_context *rctx,
                                           struct pipe_resource *tex,
                                           unsigned level,
@@ -1922,7 +1934,6 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
                                                unsigned width0, unsigned height0,
                                                unsigned width, unsigned height)
 {
-       struct r600_common_context *rctx = (struct r600_common_context*)pipe;
        struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
 
        if (!surface)
@@ -1942,11 +1953,10 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
        surface->width0 = width0;
        surface->height0 = height0;
 
-       if (texture->target != PIPE_BUFFER)
-               vi_disable_dcc_if_incompatible_format(rctx, texture,
-                                                     templ->u.tex.level,
-                                                     templ->format);
-
+       surface->dcc_incompatible =
+               texture->target != PIPE_BUFFER &&
+               vi_dcc_formats_are_incompatible(texture, templ->u.tex.level,
+                                               templ->format);
        return &surface->base;
 }
 
index 866c20639945196b011b9da7abfc6587db993a5e..2c2e3c77f6e1697f580e5bc7ecf78ddf35748b4a 100644 (file)
@@ -2439,6 +2439,7 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
        struct r600_texture *rtex;
        bool old_any_dst_linear = sctx->framebuffer.any_dst_linear;
        unsigned old_nr_samples = sctx->framebuffer.nr_samples;
+       bool unbound = false;
        int i;
 
        for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) {
@@ -2450,6 +2451,34 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
                        vi_separate_dcc_stop_query(ctx, rtex);
        }
 
+       /* Disable DCC if the formats are incompatible. */
+       for (i = 0; i < state->nr_cbufs; i++) {
+               if (!state->cbufs[i])
+                       continue;
+
+               surf = (struct r600_surface*)state->cbufs[i];
+               rtex = (struct r600_texture*)surf->base.texture;
+
+               if (!surf->dcc_incompatible)
+                       continue;
+
+               /* Since the DCC decompression calls back into set_framebuffer-
+                * _state, we need to unbind the framebuffer, so that
+                * vi_separate_dcc_stop_query isn't called twice with the same
+                * color buffer.
+                */
+               if (!unbound) {
+                       util_copy_framebuffer_state(&sctx->framebuffer.state, NULL);
+                       unbound = true;
+               }
+
+               if (vi_dcc_enabled(rtex, surf->base.u.tex.level))
+                       if (!r600_texture_disable_dcc(&sctx->b, rtex))
+                               sctx->b.decompress_dcc(ctx, rtex);
+
+               surf->dcc_incompatible = false;
+       }
+
        /* Only flush TC when changing the framebuffer state, because
         * the only client not using TC that can change textures is
         * the framebuffer.