diff options
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 9 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/r600_pipe_common.h | 8 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/r600_texture.c | 34 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state_draw.c | 12 |
4 files changed, 61 insertions, 2 deletions
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index aa3a085c6d2..e3314bbf426 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -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 diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index 3bbbfbbd528..7763ea30777 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -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; diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index ec2f2454b1c..65b17a01dc3 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -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); diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index 91ccd073267..5d094c71734 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -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. |