From: Marek Olšák <marek.ol...@amd.com>

for threaded gallium, which can't use pipe_context in create_surface
---
 src/gallium/drivers/radeon/r600_pipe_common.h |  8 +++++++
 src/gallium/drivers/radeon/r600_texture.c     | 33 +++++++++++++++++++++++----
 src/gallium/drivers/radeonsi/si_state.c       | 26 +++++++++++++++++++++
 3 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h 
b/src/gallium/drivers/radeon/r600_pipe_common.h
index 035ab1c..c9cb586 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -276,20 +276,21 @@ struct r600_surface {
        struct pipe_surface             base;
 
        bool color_initialized;
        bool depth_initialized;
 
        /* Misc. color flags. */
        bool alphatest_bypass;
        bool export_16bpc;
        bool color_is_int8;
        bool color_is_int10;
+       bool dcc_incompatible;
 
        /* Color registers. */
        unsigned cb_color_info;
        unsigned cb_color_base;
        unsigned cb_color_view;
        unsigned cb_color_size;         /* R600 only */
        unsigned cb_color_dim;          /* EG only */
        unsigned cb_color_pitch;        /* EG and later */
        unsigned cb_color_slice;        /* EG and later */
        unsigned cb_color_attrib;       /* EG and later */
@@ -784,20 +785,27 @@ void r600_texture_get_cmask_info(struct 
r600_common_screen *rscreen,
                                 struct r600_texture *rtex,
                                 struct r600_cmask_info *out);
 bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
                                     struct pipe_resource *texture,
                                     struct r600_texture **staging);
 void r600_print_texture_info(struct r600_texture *rtex, FILE *f);
 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_flag(struct r600_common_context *rctx,
+                                        struct pipe_resource *tex,
+                                        unsigned level,
+                                        bool dcc_incompatible);
 void vi_disable_dcc_if_incompatible_format(struct r600_common_context *rctx,
                                           struct pipe_resource *tex,
                                           unsigned level,
                                           enum pipe_format view_format);
 struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
                                                struct pipe_resource *texture,
                                                const struct pipe_surface 
*templ,
                                                unsigned width, unsigned 
height);
 unsigned r600_translate_colorswap(enum pipe_format format, bool 
do_endian_swap);
 void vi_separate_dcc_start_query(struct pipe_context *ctx,
diff --git a/src/gallium/drivers/radeon/r600_texture.c 
b/src/gallium/drivers/radeon/r600_texture.c
index 783f50c..1191a74 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -1733,59 +1733,82 @@ bool vi_dcc_formats_compatible(enum pipe_format format1,
                        return false;
 
        type1 = vi_get_dcc_channel_type(desc1);
        type2 = vi_get_dcc_channel_type(desc2);
 
        return type1 != dcc_channel_incompatible &&
               type2 != dcc_channel_incompatible &&
               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);
+}
+
+void vi_disable_dcc_if_incompatible_flag(struct r600_common_context *rctx,
+                                        struct pipe_resource *tex,
+                                        unsigned level,
+                                        bool dcc_incompatible)
+{
+       struct r600_texture *rtex = (struct r600_texture *)tex;
+
+       if (vi_dcc_enabled(rtex, level) && dcc_incompatible)
+               if (!r600_texture_disable_dcc(rctx, (struct r600_texture*)tex))
+                       rctx->decompress_dcc(&rctx->b, rtex);
+}
+
+/* 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,
                                           enum pipe_format view_format)
 {
        struct r600_texture *rtex = (struct r600_texture *)tex;
 
        if (vi_dcc_enabled(rtex, level) &&
            !vi_dcc_formats_compatible(tex->format, view_format))
                if (!r600_texture_disable_dcc(rctx, (struct r600_texture*)tex))
                        rctx->decompress_dcc(&rctx->b, rtex);
 }
 
 struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
                                                struct pipe_resource *texture,
                                                const struct pipe_surface 
*templ,
                                                unsigned width, unsigned height)
 {
-       struct r600_common_context *rctx = (struct r600_common_context*)pipe;
        struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
 
        if (!surface)
                return NULL;
 
        assert(templ->u.tex.first_layer <= util_max_layer(texture, 
templ->u.tex.level));
        assert(templ->u.tex.last_layer <= util_max_layer(texture, 
templ->u.tex.level));
 
        pipe_reference_init(&surface->base.reference, 1);
        pipe_resource_reference(&surface->base.texture, texture);
        surface->base.context = pipe;
        surface->base.format = templ->format;
        surface->base.width = width;
        surface->base.height = height;
        surface->base.u = templ->u;
 
-       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;
 }
 
 static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
                                                struct pipe_resource *tex,
                                                const struct pipe_surface 
*templ)
 {
        unsigned level = templ->u.tex.level;
        unsigned width = u_minify(tex->width0, level);
diff --git a/src/gallium/drivers/radeonsi/si_state.c 
b/src/gallium/drivers/radeonsi/si_state.c
index 9461a1c..39b9152 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2362,31 +2362,57 @@ static void si_dec_framebuffer_counters(const struct 
pipe_framebuffer_state *sta
 
 static void si_set_framebuffer_state(struct pipe_context *ctx,
                                     const struct pipe_framebuffer_state *state)
 {
        struct si_context *sctx = (struct si_context *)ctx;
        struct pipe_constant_buffer constbuf = {0};
        struct r600_surface *surf = NULL;
        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++) {
                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);
        }
 
+       /* 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];
+               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;
+               }
+
+               vi_disable_dcc_if_incompatible_flag(&sctx->b, 
surf->base.texture,
+                                                   surf->base.u.tex.level,
+                                                   surf->dcc_incompatible);
+               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.
         *
         * Flush all CB and DB caches here because all buffers can be used
         * for write by both TC (with shader image stores) and CB/DB.
         */
        sctx->b.flags |= SI_CONTEXT_INV_VMEM_L1 |
                         SI_CONTEXT_INV_GLOBAL_L2 |
                         SI_CONTEXT_FLUSH_AND_INV_CB |
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to