gallium/radeon: disable CMASK on handle export if sharing doesn't allow it (v2)
authorMarek Olšák <marek.olsak@amd.com>
Wed, 24 Feb 2016 21:04:47 +0000 (22:04 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 9 Mar 2016 14:02:27 +0000 (15:02 +0100)
v2: remove the list of all contexts

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/r600/r600_state_common.c
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/r600_texture.c
src/gallium/drivers/radeonsi/si_state_draw.c

index aa3a085c6d226a3f801551f613fe076f3f882f52..e3314bbf42668bdb84d3fafeab69933260220176 100644 (file)
@@ -1672,7 +1672,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
        struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
        bool render_cond_bit = rctx->b.render_cond && !rctx->b.render_cond_force_off;
        uint64_t mask;
-       unsigned num_patches;
+       unsigned num_patches, dirty_fb_counter;
 
        if (!info.indirect && !info.count && (info.indexed || !info.count_from_stream_output)) {
                return;
@@ -1688,6 +1688,13 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                rctx->b.dma.flush(rctx, RADEON_FLUSH_ASYNC, NULL);
        }
 
+       /* Re-emit the framebuffer state if needed. */
+       dirty_fb_counter = p_atomic_read(&rctx->b.screen->dirty_fb_counter);
+       if (dirty_fb_counter != rctx->b.last_dirty_fb_counter) {
+               rctx->b.last_dirty_fb_counter = dirty_fb_counter;
+               r600_mark_atom_dirty(rctx, &rctx->framebuffer.atom);
+       }
+
        if (!r600_update_derived_state(rctx)) {
                /* useless to render because current rendering command
                 * can't be achieved
index 3bbbfbbd528e3f5d65c37a9b283fd7086c8901eb..7763ea307776b4733119f52b0fe1e38566725960 100644 (file)
@@ -325,6 +325,13 @@ struct r600_common_screen {
 
        /* Performance counters. */
        struct r600_perfcounters        *perfcounters;
+
+       /* If pipe_screen wants to re-emit the framebuffer state of all
+        * contexts, it should atomically increment this. Each context will
+        * compare this with its own last known value of the counter before
+        * drawing and re-emit the framebuffer state accordingly.
+        */
+       unsigned                        dirty_fb_counter;
 };
 
 /* This encapsulates a state or an operation which can emitted into the GPU
@@ -392,6 +399,7 @@ struct r600_common_context {
        struct pipe_fence_handle        *last_sdma_fence;
        unsigned                        initial_gfx_cs_size;
        unsigned                        gpu_reset_counter;
+       unsigned                        last_dirty_fb_counter;
 
        struct u_upload_mgr             *uploader;
        struct u_suballocator           *allocator_so_filled_size;
index ec2f2454b1cf7591b165a4b24085774d6e8aac87..65b17a01dc3ce685cfc268213e073dfa7b1346cb 100644 (file)
@@ -249,6 +249,11 @@ static void r600_texture_init_metadata(struct r600_texture *rtex,
        metadata->scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;
 }
 
+static void r600_dirty_all_framebuffer_states(struct r600_common_screen *rscreen)
+{
+       p_atomic_inc(&rscreen->dirty_fb_counter);
+}
+
 static void r600_eliminate_fast_color_clear(struct r600_common_screen *rscreen,
                                      struct r600_texture *rtex)
 {
@@ -260,6 +265,30 @@ static void r600_eliminate_fast_color_clear(struct r600_common_screen *rscreen,
        pipe_mutex_unlock(rscreen->aux_context_lock);
 }
 
+static void r600_texture_disable_cmask(struct r600_common_screen *rscreen,
+                                      struct r600_texture *rtex)
+{
+       if (!rtex->cmask.size)
+               return;
+
+       assert(rtex->resource.b.b.nr_samples <= 1);
+
+       /* Disable CMASK. */
+       memset(&rtex->cmask, 0, sizeof(rtex->cmask));
+       rtex->cmask.base_address_reg = rtex->resource.gpu_address >> 8;
+
+       if (rscreen->chip_class >= SI)
+               rtex->cb_color_info &= ~SI_S_028C70_FAST_CLEAR(1);
+       else
+               rtex->cb_color_info &= ~EG_S_028C70_FAST_CLEAR(1);
+
+       if (rtex->cmask_buffer != &rtex->resource)
+           pipe_resource_reference((struct pipe_resource**)&rtex->cmask_buffer, NULL);
+
+       /* Notify all contexts about the change. */
+       r600_dirty_all_framebuffer_states(rscreen);
+}
+
 static boolean r600_texture_get_handle(struct pipe_screen* screen,
                                       struct pipe_resource *resource,
                                       struct winsys_handle *whandle,
@@ -285,6 +314,11 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
                        if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)) {
                                /* Eliminate fast clear (both CMASK and DCC) */
                                r600_eliminate_fast_color_clear(rscreen, rtex);
+
+                               /* Disable CMASK if flush_resource isn't going
+                                * to be called.
+                                */
+                               r600_texture_disable_cmask(rscreen, rtex);
                        }
 
                        r600_texture_init_metadata(rtex, &metadata);
index 91ccd07326774d23ac7d0a9a89de0b3e3f4db39b..5d094c71734da59dc3a86183b4a517b0b7956dab 100644 (file)
@@ -763,7 +763,7 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
        struct si_context *sctx = (struct si_context *)ctx;
        struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
        struct pipe_index_buffer ib = {};
-       unsigned mask;
+       unsigned mask, dirty_fb_counter;
 
        if (!info->count && !info->indirect &&
            (info->indexed || !info->count_from_stream_output))
@@ -782,6 +782,16 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
                return;
        }
 
+       /* Re-emit the framebuffer state if needed. */
+       dirty_fb_counter = p_atomic_read(&sctx->b.screen->dirty_fb_counter);
+       if (dirty_fb_counter != sctx->b.last_dirty_fb_counter) {
+               sctx->b.last_dirty_fb_counter = dirty_fb_counter;
+               sctx->framebuffer.dirty_cbufs |=
+                       ((1 << sctx->framebuffer.state.nr_cbufs) - 1);
+               sctx->framebuffer.dirty_zsbuf = true;
+               si_mark_atom_dirty(sctx, &sctx->framebuffer.atom);
+       }
+
        si_decompress_textures(sctx);
 
        /* Set the rasterization primitive type.