panfrost: Adjust the format for AFBC textures on Bifrost v7
On Bifrost v7, AFBC textures can't be used with a non-identity component order. Let's patch the format so the component order is always RGB[A]. That means we're lying about the internal format, but that shouldn't be a problem as long as we don't share the resource. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8125>
This commit is contained in:
parent
256d4a3eee
commit
44217be921
|
@ -83,13 +83,20 @@ panfrost_mfbd_raw_format(unsigned bits)
|
|||
}
|
||||
|
||||
static void
|
||||
panfrost_mfbd_rt_init_format(struct pipe_surface *surf,
|
||||
panfrost_mfbd_rt_init_format(const struct panfrost_device *dev,
|
||||
struct pipe_surface *surf,
|
||||
struct MALI_RENDER_TARGET *rt)
|
||||
{
|
||||
struct panfrost_resource *rsrc = pan_resource(surf->texture);
|
||||
enum pipe_format format =
|
||||
drm_is_afbc(rsrc->layout.modifier) ?
|
||||
panfrost_afbc_format_fixup(dev, surf->format) :
|
||||
surf->format;
|
||||
|
||||
/* Explode details on the format */
|
||||
|
||||
const struct util_format_description *desc =
|
||||
util_format_description(surf->format);
|
||||
util_format_description(format);
|
||||
|
||||
/* The swizzle for rendering is inverted from texturing */
|
||||
|
||||
|
@ -149,7 +156,7 @@ panfrost_mfbd_rt_set_buf(struct pipe_surface *surf,
|
|||
else
|
||||
rt->writeback_msaa = MALI_MSAA_SINGLE;
|
||||
|
||||
panfrost_mfbd_rt_init_format(surf, rt);
|
||||
panfrost_mfbd_rt_init_format(dev, surf, rt);
|
||||
|
||||
if (rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR) {
|
||||
if (version >= 7)
|
||||
|
|
|
@ -127,7 +127,18 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
|
|||
rsc->checksummed = true;
|
||||
}
|
||||
|
||||
/* If we import an AFBC resource, it should be in a format that's
|
||||
* supported, otherwise we don't know if the fixup is expected to be
|
||||
* applied or not. In practice that's not a problem if the buffer has
|
||||
* been exported by the GPU because the same constraint applies to both
|
||||
* ends, but we might have issues if the exporter is a different piece
|
||||
* of hardware (VPU?) that supports the BGR variants.
|
||||
*/
|
||||
assert(!drm_is_afbc(whandle->modifier) ||
|
||||
!panfrost_afbc_format_needs_fixup(dev, rsc->internal_format));
|
||||
|
||||
if (drm_is_afbc(whandle->modifier)) {
|
||||
|
||||
unsigned tile_w =
|
||||
panfrost_block_dim(whandle->modifier, true, 0);
|
||||
unsigned tile_h =
|
||||
|
@ -163,6 +174,16 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
|
|||
struct panfrost_resource *rsrc = (struct panfrost_resource *) pt;
|
||||
struct renderonly_scanout *scanout = rsrc->scanout;
|
||||
|
||||
/* If we export an AFBC resource, it should be in a format that's
|
||||
* supported, otherwise the importer has no clue about the format fixup
|
||||
* done internally. In practice that shouldn't be an issue for GPU
|
||||
* buffers because the same constraint applies to both ends, but we
|
||||
* might have issues if the importer is a different piece of hardware
|
||||
* that supports BGR variants.
|
||||
*/
|
||||
assert(!drm_is_afbc(rsrc->layout.modifier) ||
|
||||
!panfrost_afbc_format_needs_fixup(dev, rsrc->internal_format));
|
||||
|
||||
handle->modifier = rsrc->layout.modifier;
|
||||
rsrc->modifier_constant = true;
|
||||
|
||||
|
@ -519,6 +540,14 @@ panfrost_should_afbc(struct panfrost_device *dev, const struct panfrost_resource
|
|||
if (pres->base.width0 <= 16 && pres->base.height0 <= 16)
|
||||
return false;
|
||||
|
||||
/* AFBC(BGR) is not natively supported on Bifrost v7+. When we don't
|
||||
* share the buffer we can fake those formats since we're in control
|
||||
* of the format/swizzle we apply to the textures/RTs.
|
||||
*/
|
||||
if (panfrost_afbc_format_needs_fixup(dev, pres->internal_format) &&
|
||||
(pres->base.bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)))
|
||||
return false;
|
||||
|
||||
/* Otherwise, we'd prefer AFBC as it is dramatically more efficient
|
||||
* than linear or usually even u-interleaved */
|
||||
return true;
|
||||
|
|
|
@ -140,3 +140,51 @@ panfrost_afbc_can_ytr(enum pipe_format format)
|
|||
/* The fourth channel if it exists doesn't matter */
|
||||
return desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB;
|
||||
}
|
||||
|
||||
bool
|
||||
panfrost_afbc_format_needs_fixup(const struct panfrost_device *dev,
|
||||
enum pipe_format format)
|
||||
{
|
||||
if (dev->arch < 7)
|
||||
return false;
|
||||
|
||||
const struct util_format_description *desc =
|
||||
util_format_description(format);
|
||||
|
||||
bool identity_swizzle = true;
|
||||
for (unsigned c = 0; c < desc->nr_channels; c++) {
|
||||
if (desc->swizzle[c] != c) {
|
||||
identity_swizzle = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (identity_swizzle ||
|
||||
desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum pipe_format
|
||||
panfrost_afbc_format_fixup(const struct panfrost_device *dev,
|
||||
enum pipe_format format)
|
||||
{
|
||||
if (!panfrost_afbc_format_needs_fixup(dev, format))
|
||||
return format;
|
||||
|
||||
const struct util_format_description *desc =
|
||||
util_format_description(format);
|
||||
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_B8G8R8_UNORM:
|
||||
return PIPE_FORMAT_R8G8B8_UNORM;
|
||||
case PIPE_FORMAT_B5G6R5_UNORM:
|
||||
return PIPE_FORMAT_R5G6B5_UNORM;
|
||||
default:
|
||||
if (util_format_is_rgba8_variant(desc))
|
||||
return PIPE_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
unreachable("Invalid format");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,6 +414,10 @@ panfrost_new_texture(const struct panfrost_device *dev,
|
|||
const struct panfrost_ptr *payload)
|
||||
{
|
||||
unsigned swizzle = panfrost_translate_swizzle_4(user_swizzle);
|
||||
|
||||
if (drm_is_afbc(layout->modifier))
|
||||
format = panfrost_afbc_format_fixup(dev, format);
|
||||
|
||||
const struct util_format_description *desc =
|
||||
util_format_description(format);
|
||||
|
||||
|
|
|
@ -112,6 +112,14 @@ panfrost_afbc_header_size(unsigned width, unsigned height);
|
|||
bool
|
||||
panfrost_afbc_can_ytr(enum pipe_format format);
|
||||
|
||||
bool
|
||||
panfrost_afbc_format_needs_fixup(const struct panfrost_device *dev,
|
||||
enum pipe_format format);
|
||||
|
||||
enum pipe_format
|
||||
panfrost_afbc_format_fixup(const struct panfrost_device *dev,
|
||||
enum pipe_format format);
|
||||
|
||||
unsigned
|
||||
panfrost_block_dim(uint64_t modifier, bool width, unsigned plane);
|
||||
|
||||
|
|
Loading…
Reference in New Issue