[Mesa-dev] [PATCH 8/9] radeonsi: decompress DCC in set_framebuffer_state instead of create_surface
Marek Olšák
maraeo at gmail.com
Wed Mar 29 17:58:53 UTC 2017
From: Marek Olšák <marek.olsak at 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
More information about the mesa-dev
mailing list