mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 02:28:10 +02:00
pan/mod: Allow testing if a modifier is optimal
Testing if a modifier is supported for a set of image properties is not enough when we're supposed to pick the best modifier among a selection of modifiers. Extend the image/mod logic to report if a modifier is optimal when supported. This forces us to pass extra usage information through a new pan_image_usage object. When this usage info is missing (NULL), the mod layer assumes a set of usage that would make the modifier optimal. Note that the usage info also allows us to reject a few more cases that would otherwise need to be checked by the frontend. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Eric R. Smith <eric.smith@collabora.com> Reviewed-by: Christoph Pillmayer <christoph.pillmayer@arm.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37158>
This commit is contained in:
parent
a4547fd4b1
commit
bff39c4f25
4 changed files with 148 additions and 36 deletions
|
|
@ -252,9 +252,24 @@ bool pan_image_layout_init(
|
|||
unsigned arch, struct pan_image *image, unsigned plane_idx,
|
||||
const struct pan_image_layout_constraints *explicit_layout_constraints);
|
||||
|
||||
static inline bool
|
||||
struct pan_image_usage {
|
||||
/* PAN_BIND_xxx flags. */
|
||||
uint32_t bind;
|
||||
|
||||
/* Image filled directly from the CPU. */
|
||||
bool host_copy;
|
||||
|
||||
/* Image frequently updated with host data. */
|
||||
bool frequent_host_updates;
|
||||
|
||||
/* Scanout image. */
|
||||
bool scanout;
|
||||
};
|
||||
|
||||
static inline enum pan_mod_support
|
||||
pan_image_test_props(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops)
|
||||
const struct pan_image_props *iprops,
|
||||
const struct pan_image_usage *iusage)
|
||||
{
|
||||
const unsigned arch = pan_arch(dprops->gpu_id);
|
||||
struct pan_image image = {
|
||||
|
|
@ -263,10 +278,12 @@ pan_image_test_props(const struct pan_kmod_dev_props *dprops,
|
|||
};
|
||||
|
||||
if (!image.mod_handler)
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
if (!image.mod_handler->test_props(dprops, &image.props))
|
||||
return false;
|
||||
enum pan_mod_support ret =
|
||||
image.mod_handler->test_props(dprops, &image.props, iusage);
|
||||
if (ret == PAN_MOD_NOT_SUPPORTED)
|
||||
return ret;
|
||||
|
||||
/* Now make sure the layout can be properly initialized on all planes. */
|
||||
uint32_t plane_count = util_format_get_num_planes(image.props.format);
|
||||
|
|
@ -277,10 +294,10 @@ pan_image_test_props(const struct pan_kmod_dev_props *dprops,
|
|||
image.planes[p] = &plane;
|
||||
|
||||
if (!pan_image_layout_init(arch, &image, p, NULL))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
@ -304,10 +321,9 @@ pan_image_test_modifier_with_format(const struct pan_kmod_dev_props *dprops,
|
|||
.array_size = 1,
|
||||
};
|
||||
|
||||
return pan_image_test_props(dprops, &iprops);
|
||||
return pan_image_test_props(dprops, &iprops, NULL) != PAN_MOD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -171,50 +171,99 @@ pan_mod_afbc_init_slice_layout(
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
static enum pan_mod_support
|
||||
pan_mod_afbc_test_props(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops)
|
||||
const struct pan_image_props *iprops,
|
||||
const struct pan_image_usage *iusage)
|
||||
{
|
||||
/* No image store. */
|
||||
if (iusage && iusage->bind & PAN_BIND_STORAGE_IMAGE)
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* AFBC not supported. */
|
||||
if (!pan_query_afbc(dprops))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* Check if the format is supported first. */
|
||||
if (!pan_afbc_supports_format(PAN_ARCH, iprops->format))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* AFBC can't do multisampling. */
|
||||
if (iprops->nr_samples > 1)
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* AFBC(2D) or AFBC(3D) on v7+ only. */
|
||||
if ((iprops->dim == MALI_TEXTURE_DIMENSION_3D && PAN_ARCH < 7) ||
|
||||
iprops->dim != MALI_TEXTURE_DIMENSION_2D)
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
unsigned plane_count = util_format_get_num_planes(iprops->format);
|
||||
const struct util_format_description *fdesc =
|
||||
util_format_description(iprops->format);
|
||||
|
||||
/* ZS buffer descriptors can't pass split/wide/YTR modifiers. */
|
||||
if (iusage && (iusage->bind & PAN_BIND_DEPTH_STENCIL) &&
|
||||
(pan_afbc_superblock_width(iprops->modifier) != 16 ||
|
||||
(iprops->modifier & (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_YTR))))
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* YTR is only useful on RGB formats. */
|
||||
if ((iprops->modifier & AFBC_FORMAT_MOD_YTR) &&
|
||||
(pan_format_is_yuv(iprops->format) || fdesc->nr_channels < 3))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* Make sure all planes support split mode. */
|
||||
if ((iprops->modifier & AFBC_FORMAT_MOD_SPLIT)) {
|
||||
for (unsigned p = 0; p < plane_count; p++) {
|
||||
if (!pan_afbc_can_split(PAN_ARCH, iprops->format, iprops->modifier, p))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure tiled mode is supported. */
|
||||
if ((iprops->modifier & AFBC_FORMAT_MOD_TILED) &&
|
||||
!pan_afbc_can_tile(PAN_ARCH))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
return true;
|
||||
/* For one tile, AFBC is a loss compared to u-interleaved */
|
||||
if (iprops->extent_px.width <= 16 && iprops->extent_px.height <= 16)
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
/* Reserve 32x8 tiles for scanout buffers. */
|
||||
if (iusage && !iusage->scanout &&
|
||||
pan_afbc_superblock_width(iprops->modifier) != 16)
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
/* Prefer YTR when available. */
|
||||
if (pan_afbc_can_ytr(iprops->format) &&
|
||||
!(iprops->modifier & AFBC_FORMAT_MOD_YTR))
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
if (iprops->modifier & (AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SC))
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
bool is_tiled = iprops->modifier & AFBC_FORMAT_MOD_TILED;
|
||||
bool can_tile = pan_afbc_can_tile(PAN_ARCH);
|
||||
|
||||
if (is_tiled && !can_tile)
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* Prefer tiled headers when the image is big enough. */
|
||||
bool should_tile =
|
||||
iprops->extent_px.width >= 128 && iprops->extent_px.height >= 128;
|
||||
|
||||
if (is_tiled != should_tile)
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
/* Packing/unpacking AFBC payload requires a COMPUTE job which we'd rather
|
||||
* avoid.
|
||||
*/
|
||||
if (iusage &&
|
||||
(iusage->bind & (PAN_BIND_DEPTH_STENCIL | PAN_BIND_RENDER_TARGET)) &&
|
||||
!(iprops->modifier & AFBC_FORMAT_MOD_SPARSE))
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
return PAN_MOD_OPTIMAL;
|
||||
}
|
||||
|
||||
#define pan_mod_afbc_emit_tex_payload_entry \
|
||||
|
|
@ -230,19 +279,40 @@ pan_mod_afrc_match(uint64_t mod)
|
|||
return drm_is_afrc(mod);
|
||||
}
|
||||
|
||||
static bool
|
||||
static enum pan_mod_support
|
||||
pan_mod_afrc_test_props(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops)
|
||||
const struct pan_image_props *iprops,
|
||||
const struct pan_image_usage *iusage)
|
||||
{
|
||||
/* AFRC not supported. */
|
||||
if (!pan_query_afrc(dprops))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* Format not AFRC-able. */
|
||||
if (!pan_afrc_supports_format(iprops->format))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
return true;
|
||||
/* AFRC does not support layered multisampling. */
|
||||
if (iprops->nr_samples > 1)
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* No image store. */
|
||||
if (iusage && iusage->bind & PAN_BIND_STORAGE_IMAGE)
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* We can't write to an AFRC resource directly. */
|
||||
if (iusage && iusage->host_copy)
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
/* Host updates require an extra blit which we would rather avoid. */
|
||||
if (iusage && iusage->frequent_host_updates)
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
/* There's nothing preventing 1D AFRC, but it's pointless. */
|
||||
if (iprops->dim == MALI_TEXTURE_DIMENSION_1D)
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
return PAN_MOD_OPTIMAL;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
@ -350,17 +420,26 @@ pan_mod_u_tiled_match(uint64_t mod)
|
|||
return mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
}
|
||||
|
||||
static bool
|
||||
static enum pan_mod_support
|
||||
pan_mod_u_tiled_test_props(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops)
|
||||
const struct pan_image_props *iprops,
|
||||
const struct pan_image_usage *iusage)
|
||||
{
|
||||
assert(GENX(pan_format_from_pipe_format)(iprops->format)->hw);
|
||||
|
||||
/* YUV not supported. */
|
||||
if (pan_format_is_yuv(iprops->format))
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
return true;
|
||||
/* The purpose of tiling is improving locality in both X- and
|
||||
* Y-directions. If there is only a single pixel in either direction,
|
||||
* tiling does not make sense; using a linear layout instead is optimal
|
||||
* for both memory usage and performance.
|
||||
*/
|
||||
if (MIN2(iprops->extent_px.width, iprops->extent_px.height) < 2)
|
||||
return PAN_MOD_NOT_OPTIMAL;
|
||||
|
||||
return PAN_MOD_OPTIMAL;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
@ -479,9 +558,10 @@ pan_mod_linear_match(uint64_t mod)
|
|||
return mod == DRM_FORMAT_MOD_LINEAR;
|
||||
}
|
||||
|
||||
static bool
|
||||
static enum pan_mod_support
|
||||
pan_mod_linear_test_props(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops)
|
||||
const struct pan_image_props *iprops,
|
||||
const struct pan_image_usage *iusage)
|
||||
{
|
||||
assert(GENX(pan_format_from_pipe_format)(iprops->format)->hw);
|
||||
|
||||
|
|
@ -489,10 +569,14 @@ pan_mod_linear_test_props(const struct pan_kmod_dev_props *dprops,
|
|||
/* AFBC-only formats. */
|
||||
case PIPE_FORMAT_R8G8B8_420_UNORM_PACKED:
|
||||
case PIPE_FORMAT_R10G10B10_420_UNORM_PACKED:
|
||||
return false;
|
||||
return PAN_MOD_NOT_SUPPORTED;
|
||||
|
||||
default:
|
||||
return true;
|
||||
/* We assume that all "better" mods have been tested before linear, and
|
||||
* declare it as optimal so it's always picked when tested, unless it's
|
||||
* not supported.
|
||||
*/
|
||||
return PAN_MOD_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,27 @@ extern "C" {
|
|||
struct pan_fb_info;
|
||||
struct pan_image;
|
||||
struct pan_image_view;
|
||||
struct pan_image_usage;
|
||||
struct pan_kmod_dev_props;
|
||||
struct pan_mod_handler;
|
||||
|
||||
enum pan_mod_support {
|
||||
PAN_MOD_NOT_SUPPORTED = 0,
|
||||
PAN_MOD_NOT_OPTIMAL,
|
||||
PAN_MOD_OPTIMAL,
|
||||
};
|
||||
|
||||
struct pan_mod_handler {
|
||||
bool (*match)(uint64_t mod);
|
||||
|
||||
/* Used to check if a set of image properties is valid. */
|
||||
bool (*test_props)(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops);
|
||||
/* Used to check if a set of image properties is valid. Passing a NULL iusage
|
||||
* is valid and means "optimal set of usage for this mod". This implies
|
||||
* that some non-supported cases can't be detected or can be reported as
|
||||
* optimal when specific usage flags would report it non-optimal.
|
||||
*/
|
||||
enum pan_mod_support (*test_props)(const struct pan_kmod_dev_props *dprops,
|
||||
const struct pan_image_props *iprops,
|
||||
const struct pan_image_usage *iusage);
|
||||
|
||||
bool (*init_slice_layout)(
|
||||
const struct pan_image_props *props, unsigned plane_idx,
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
|
|||
.depth = image->vk.extent.depth,
|
||||
};
|
||||
|
||||
if (!pan_image_test_props(&phys_dev->kmod.props, &iprops))
|
||||
if (!pan_image_test_props(&phys_dev->kmod.props, &iprops, NULL))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue