diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c index 43ecfa8f015..dc9079c0593 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c @@ -127,6 +127,18 @@ valid_format_cast(struct fd_resource *rsc, enum pipe_format format) return true; } +/** + * R8G8 have a different block width/height and height alignment from other + * formats that would normally be compatible (like R16), and so if we are + * trying to, for example, sample R16 as R8G8 we need to demote to linear. + */ +static bool +is_r8g8(enum pipe_format format) +{ + return (util_format_get_blocksize(format) == 2) && + (util_format_get_nr_components(format) == 2); +} + /** * Ensure the rsc is in an ok state to be used with the specified format. * This handles the case of UBWC buffers used with non-UBWC compatible @@ -136,8 +148,22 @@ void fd6_validate_format(struct fd_context *ctx, struct fd_resource *rsc, enum pipe_format format) { + enum pipe_format orig_format = rsc->b.b.format; + tc_assert_driver_thread(ctx->tc); + if (orig_format == format) + return; + + if (rsc->layout.tile_mode && (is_r8g8(orig_format) != is_r8g8(format))) { + perf_debug_ctx(ctx, + "%" PRSC_FMT ": demoted to linear+uncompressed due to use as %s", + PRSC_ARGS(&rsc->b.b), util_format_short_name(format)); + + fd_resource_uncompress(ctx, rsc, true); + return; + } + if (!rsc->layout.ubwc) return; @@ -148,7 +174,7 @@ fd6_validate_format(struct fd_context *ctx, struct fd_resource *rsc, "%" PRSC_FMT ": demoted to uncompressed due to use as %s", PRSC_ARGS(&rsc->b.b), util_format_short_name(format)); - fd_resource_uncompress(ctx, rsc); + fd_resource_uncompress(ctx, rsc, false); } static void diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 4d1c96c3e91..54c520f1b1a 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -531,12 +531,13 @@ fd_try_shadow_resource(struct fd_context *ctx, struct fd_resource *rsc, * appears to the gallium frontends as if nothing changed. */ void -fd_resource_uncompress(struct fd_context *ctx, struct fd_resource *rsc) +fd_resource_uncompress(struct fd_context *ctx, struct fd_resource *rsc, bool linear) { tc_assert_driver_thread(ctx->tc); - bool success = - fd_try_shadow_resource(ctx, rsc, 0, NULL, FD_FORMAT_MOD_QCOM_TILED); + uint64_t modifier = linear ? DRM_FORMAT_MOD_LINEAR : FD_FORMAT_MOD_QCOM_TILED; + + bool success = fd_try_shadow_resource(ctx, rsc, 0, NULL, modifier); /* shadow should not fail in any cases where we need to uncompress: */ debug_assert(success); diff --git a/src/gallium/drivers/freedreno/freedreno_resource.h b/src/gallium/drivers/freedreno/freedreno_resource.h index e4939d199f1..d4666b06e10 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.h +++ b/src/gallium/drivers/freedreno/freedreno_resource.h @@ -352,7 +352,8 @@ bool fd_resource_busy(struct pipe_screen *pscreen, struct pipe_resource *prsc, unsigned usage); void fd_resource_uncompress(struct fd_context *ctx, - struct fd_resource *rsc) assert_dt; + struct fd_resource *rsc, + bool linear) assert_dt; void fd_resource_dump(struct fd_resource *rsc, const char *name); bool fd_render_condition_check(struct pipe_context *pctx) assert_dt;