mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-25 07:00:45 +02:00
radeonsi: fix texture format reinterpretation with DCC
DCC is limited in how texture formats can be reinterpreted using texture views. If we get a view format that is incompatible with the initial texture format with respect to DCC, disable DCC. There is a new piglit which tests all format combinations. What works and what doesn't was deduced by looking at the piglit failures. Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
parent
63da0c991d
commit
21de3be8e6
5 changed files with 116 additions and 1 deletions
|
|
@ -757,6 +757,12 @@ bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
|
|||
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);
|
||||
void vi_dcc_disable_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,
|
||||
|
|
|
|||
|
|
@ -1666,11 +1666,102 @@ static const struct u_resource_vtbl r600_texture_vtbl =
|
|||
r600_texture_transfer_unmap, /* transfer_unmap */
|
||||
};
|
||||
|
||||
/* DCC channel type categories within which formats can be reinterpreted
|
||||
* while keeping the same DCC encoding. The swizzle must also match. */
|
||||
enum dcc_channel_type {
|
||||
dcc_channel_any32,
|
||||
dcc_channel_int16,
|
||||
dcc_channel_float16,
|
||||
dcc_channel_any_10_10_10_2,
|
||||
dcc_channel_any8,
|
||||
dcc_channel_incompatible,
|
||||
};
|
||||
|
||||
/* Return the type of DCC encoding. */
|
||||
static enum dcc_channel_type
|
||||
vi_get_dcc_channel_type(const struct util_format_description *desc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Find the first non-void channel. */
|
||||
for (i = 0; i < desc->nr_channels; i++)
|
||||
if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
|
||||
break;
|
||||
if (i == desc->nr_channels)
|
||||
return dcc_channel_incompatible;
|
||||
|
||||
switch (desc->channel[i].size) {
|
||||
case 32:
|
||||
if (desc->nr_channels == 4)
|
||||
return dcc_channel_incompatible;
|
||||
else
|
||||
return dcc_channel_any32;
|
||||
case 16:
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
|
||||
return dcc_channel_float16;
|
||||
else
|
||||
return dcc_channel_int16;
|
||||
case 10:
|
||||
return dcc_channel_any_10_10_10_2;
|
||||
case 8:
|
||||
return dcc_channel_any8;
|
||||
default:
|
||||
return dcc_channel_incompatible;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return if it's allowed to reinterpret one format as another with DCC enabled. */
|
||||
bool vi_dcc_formats_compatible(enum pipe_format format1,
|
||||
enum pipe_format format2)
|
||||
{
|
||||
const struct util_format_description *desc1, *desc2;
|
||||
enum dcc_channel_type type1, type2;
|
||||
int i;
|
||||
|
||||
if (format1 == format2)
|
||||
return true;
|
||||
|
||||
desc1 = util_format_description(format1);
|
||||
desc2 = util_format_description(format2);
|
||||
|
||||
if (desc1->nr_channels != desc2->nr_channels)
|
||||
return false;
|
||||
|
||||
/* Swizzles must be the same. */
|
||||
for (i = 0; i < desc1->nr_channels; i++)
|
||||
if (desc1->swizzle[i] <= PIPE_SWIZZLE_W &&
|
||||
desc2->swizzle[i] <= PIPE_SWIZZLE_W &&
|
||||
desc1->swizzle[i] != desc2->swizzle[i])
|
||||
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;
|
||||
}
|
||||
|
||||
void vi_dcc_disable_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 (rtex->dcc_offset &&
|
||||
rtex->surface.level[level].dcc_enabled &&
|
||||
!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_texture *rtex = (struct r600_texture*)texture;
|
||||
struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
|
||||
|
||||
|
|
@ -1688,6 +1779,11 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
|
|||
surface->base.height = height;
|
||||
surface->base.u = templ->u;
|
||||
surface->level_info = &rtex->surface.level[templ->u.tex.level];
|
||||
|
||||
vi_dcc_disable_if_incompatible_format(rctx, texture,
|
||||
templ->u.tex.level,
|
||||
templ->format);
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1124,6 +1124,12 @@ static void si_blit(struct pipe_context *ctx,
|
|||
|
||||
/* The driver doesn't decompress resources automatically while
|
||||
* u_blitter is rendering. */
|
||||
vi_dcc_disable_if_incompatible_format(&sctx->b, info->src.resource,
|
||||
info->src.level,
|
||||
info->src.format);
|
||||
vi_dcc_disable_if_incompatible_format(&sctx->b, info->dst.resource,
|
||||
info->dst.level,
|
||||
info->dst.format);
|
||||
si_decompress_subresource(ctx, info->src.resource, info->mask,
|
||||
info->src.level,
|
||||
info->src.box.z,
|
||||
|
|
@ -1153,6 +1159,8 @@ static boolean si_generate_mipmap(struct pipe_context *ctx,
|
|||
|
||||
/* The driver doesn't decompress resources automatically while
|
||||
* u_blitter is rendering. */
|
||||
vi_dcc_disable_if_incompatible_format(&sctx->b, tex, base_level,
|
||||
format);
|
||||
si_decompress_subresource(ctx, tex, PIPE_MASK_RGBAZS,
|
||||
base_level, first_layer, last_layer);
|
||||
|
||||
|
|
|
|||
|
|
@ -653,7 +653,8 @@ static void si_set_shader_image(struct si_context *ctx,
|
|||
assert(tex->fmask.size == 0);
|
||||
|
||||
if (uses_dcc &&
|
||||
view->access & PIPE_IMAGE_ACCESS_WRITE) {
|
||||
(view->access & PIPE_IMAGE_ACCESS_WRITE ||
|
||||
!vi_dcc_formats_compatible(res->b.b.format, view->format))) {
|
||||
/* If DCC can't be disabled, at least decompress it.
|
||||
* The decompression is relatively cheap if the surface
|
||||
* has been decompressed already.
|
||||
|
|
|
|||
|
|
@ -3051,6 +3051,10 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
vi_dcc_disable_if_incompatible_format(&sctx->b, texture,
|
||||
state->u.tex.first_level,
|
||||
state->format);
|
||||
|
||||
si_make_texture_descriptor(sctx->screen, tmp, true,
|
||||
state->target, pipe_format, state_swizzle,
|
||||
first_level, last_level,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue