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