[Mesa-dev] [PATCH 17/26] gallium/radeon: disable CMASK on handle export if sharing doesn't allow it
Marek Olšák
maraeo at gmail.com
Wed Mar 2 16:36:26 UTC 2016
From: Marek Olšák <marek.olsak at amd.com>
The disabling of CMASK is simple, but notifying all contexts about it is not:
- The screen must have a list of all contexts.
- Each context must have a monotonic counter that is incremented only when
the screen wants to re-emit framebuffer states.
- Each context must check in draw_vbo if the counter has been changed and
re-emit the framebuffer state accordingly.
---
src/gallium/drivers/r600/r600_state_common.c | 9 +++++-
src/gallium/drivers/radeon/r600_pipe_common.c | 15 ++++++++++
src/gallium/drivers/radeon/r600_pipe_common.h | 13 +++++++++
src/gallium/drivers/radeon/r600_texture.c | 41 +++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_state_draw.c | 12 +++++++-
5 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index aa3a085..a1645ee 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.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.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index ea02827..88e8e8e 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -322,11 +322,23 @@ bool r600_common_context_init(struct r600_common_context *rctx,
rctx->dma.flush = r600_flush_dma_ring;
}
+ /* Add the new context the the global list. */
+ pipe_mutex_lock(rscreen->context_list_lock);
+ LIST_ADD(&rctx->list_item, &rscreen->context_list);
+ pipe_mutex_unlock(rscreen->context_list_lock);
+
return true;
}
void r600_common_context_cleanup(struct r600_common_context *rctx)
{
+ struct r600_common_screen *rscreen = rctx->screen;
+
+ /* Remove the context from the global list. */
+ pipe_mutex_lock(rscreen->context_list_lock);
+ LIST_DEL(&rctx->list_item);
+ pipe_mutex_unlock(rscreen->context_list_lock);
+
if (rctx->gfx.cs)
rctx->ws->cs_destroy(rctx->gfx.cs);
if (rctx->dma.cs)
@@ -892,6 +904,8 @@ bool r600_common_screen_init(struct r600_common_screen *rscreen,
util_format_s3tc_init();
pipe_mutex_init(rscreen->aux_context_lock);
pipe_mutex_init(rscreen->gpu_load_mutex);
+ pipe_mutex_init(rscreen->context_list_lock);
+ LIST_INITHEAD(&rscreen->context_list);
if (((rscreen->info.drm_major == 2 && rscreen->info.drm_minor >= 28) ||
rscreen->info.drm_major == 3) &&
@@ -949,6 +963,7 @@ void r600_destroy_common_screen(struct r600_common_screen *rscreen)
pipe_mutex_destroy(rscreen->gpu_load_mutex);
pipe_mutex_destroy(rscreen->aux_context_lock);
+ pipe_mutex_destroy(rscreen->context_list_lock);
rscreen->aux_context->destroy(rscreen->aux_context);
if (rscreen->trace_bo)
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index 3bbbfbb..daf8798 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -325,6 +325,10 @@ struct r600_common_screen {
/* Performance counters. */
struct r600_perfcounters *perfcounters;
+
+ /* All contexts. */
+ pipe_mutex context_list_lock;
+ struct list_head context_list;
};
/* This encapsulates a state or an operation which can emitted into the GPU
@@ -382,6 +386,7 @@ struct r600_ring {
struct r600_common_context {
struct pipe_context b; /* base class */
+ struct list_head list_item; /* part of the context list */
struct r600_common_screen *screen;
struct radeon_winsys *ws;
struct radeon_winsys_ctx *ctx;
@@ -393,6 +398,14 @@ struct r600_common_context {
unsigned initial_gfx_cs_size;
unsigned gpu_reset_counter;
+ /* If pipe_screen wants to re-emit the framebuffer state of all
+ * contexts, it should atomically increment dirty_fb_counter.
+ * Each context will compare the current and last counter before draw
+ * and re-emit the framebuffer state accordingly.
+ */
+ unsigned dirty_fb_counter;
+ unsigned last_dirty_fb_counter;
+
struct u_upload_mgr *uploader;
struct u_suballocator *allocator_so_filled_size;
struct util_slab_mempool pool_transfers;
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index ec2f245..395607b 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -249,6 +249,17 @@ 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)
+{
+ struct r600_common_context *iter;
+
+ pipe_mutex_lock(rscreen->context_list_lock);
+ LIST_FOR_EACH_ENTRY(iter, &rscreen->context_list, list_item) {
+ p_atomic_inc(&iter->dirty_fb_counter);
+ }
+ pipe_mutex_unlock(rscreen->context_list_lock);
+}
+
static void r600_eliminate_fast_color_clear(struct r600_common_screen *rscreen,
struct r600_texture *rtex)
{
@@ -260,6 +271,31 @@ 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 +321,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 91ccd07..e901bdc 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.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.
--
2.5.0
More information about the mesa-dev
mailing list