tu: Add support for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 color attachments

Supported on A7XX+.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39592>
This commit is contained in:
Emma Anholt 2025-07-04 12:40:55 -07:00 committed by Marge Bot
parent f472bbf017
commit 9dc3410512
8 changed files with 63 additions and 23 deletions

View file

@ -221,7 +221,7 @@ static const struct fd6_format formats[PIPE_FORMAT_COUNT] = {
V__(B10G10R10A2_SSCALED, 10_10_10_2_SINT, WXYZ),
VTC(R11G11B10_FLOAT, 11_11_10_FLOAT, WZYX),
_T_(R9G9B9E5_FLOAT, 9_9_9_E5_FLOAT, WZYX),
_TC(R9G9B9E5_FLOAT, 9_9_9_E5_FLOAT, WZYX),
_TC(Z24X8_UNORM, Z24_UNORM_S8_UINT, WZYX),
_TC(X24S8_UINT, 8_8_8_8_UINT, WZYX),
@ -527,6 +527,15 @@ fd6_color_format(enum pipe_format format, enum a6xx_tile_mode tile_mode)
return formats[format].rb;
}
bool
fd6_color_format_supported(const struct fd_dev_info *info, enum pipe_format format,
enum a6xx_tile_mode tile_mode)
{
if (info->chip < 7 && format == PIPE_FORMAT_R9G9B9E5_FLOAT)
return false;
return fd6_color_format(format, tile_mode) != FMT6_NONE;
}
enum a3xx_color_swap
fd6_color_swap(enum pipe_format format, enum a6xx_tile_mode tile_mode,
bool is_mutable)

View file

@ -62,6 +62,9 @@ enum a3xx_color_swap fd6_texture_swap(enum pipe_format format,
bool is_mutable) ATTRIBUTE_CONST;
enum a6xx_format fd6_color_format(enum pipe_format format,
enum a6xx_tile_mode tile_mode) ATTRIBUTE_CONST;
bool fd6_color_format_supported(const struct fd_dev_info *info, enum pipe_format format,
enum a6xx_tile_mode tile_mode)
ATTRIBUTE_CONST;
enum a3xx_color_swap fd6_color_swap(enum pipe_format format,
enum a6xx_tile_mode tile_mode,
bool is_mutable) ATTRIBUTE_CONST;

View file

@ -52,6 +52,8 @@ format_to_ifmt(enum pipe_format format)
return R2D_INT8;
if (format == PIPE_FORMAT_A8_UNORM)
return R2D_UNORM8;
if (format == PIPE_FORMAT_R9G9B9E5_FLOAT)
return R2D_FLOAT16;
/* use the size of the red channel to find the corresponding "ifmt" */
bool is_int = util_format_is_pure_integer(format);
@ -1928,6 +1930,10 @@ pack_blit_event_clear_value(const VkClearValue *val, enum pipe_format format, ui
else
pack_int8(clear_value, val->color.uint32);
break;
case 9:
assert(format == PIPE_FORMAT_R9G9B9E5_FLOAT);
clear_value[0] = float3_to_rgb9e5(val->color.float32);
break;
case 10:
if (util_format_is_pure_integer(format))
pack_int10_2(clear_value, val->color.uint32);
@ -3922,11 +3928,6 @@ use_generic_clear_for_image_clear(struct tu_cmd_buffer *cmd,
{
const struct fd_dev_info *info = cmd->device->physical_device->info;
return info->props.has_generic_clear &&
/* A7XX supports R9G9B9E5_FLOAT as color attachment and supports
* generic clears for it. A7XX TODO: allow R9G9B9E5_FLOAT
* attachments.
*/
image->vk.format != VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 &&
/* Clearing VK_FORMAT_R8G8_* with fast-clear value, certain
* dimensions (e.g. 960x540), and having GMEM renderpass afterwards
* may lead to a GPU fault on A7XX.
@ -4785,10 +4786,16 @@ clear_sysmem_attachment(struct tu_cmd_buffer *cmd,
const VkClearValue *value = &cmd->state.clear_values[a];
if (cmd->state.pass->attachments[a].samples > 1)
ops = &r3d_ops<CHIP>;
bool e5b9g9r9_as_u32 =
vk_format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 && ops == &r2d_ops<CHIP>;
trace_start_sysmem_clear(&cmd->rp_trace, cs, cmd, vk_format, ops == &r3d_ops<CHIP>,
cmd->state.pass->attachments[a].samples);
if (e5b9g9r9_as_u32) {
format = PIPE_FORMAT_R32_UINT;
}
ops->setup(cmd, cs, format, format, clear_mask, 0, true, iview->view.ubwc_enabled,
cmd->state.pass->attachments[a].samples,
cmd->state.pass->attachments[a].samples);
@ -4796,7 +4803,12 @@ clear_sysmem_attachment(struct tu_cmd_buffer *cmd,
ops->coords(cmd, cs, cmd->state.render_areas[0].offset, (VkOffset2D) {},
cmd->state.render_areas[0].extent);
}
ops->clear_value(cmd, cs, format, value);
if (e5b9g9r9_as_u32) {
ops->clear_value(cmd, cs, PIPE_FORMAT_R9G9B9E5_FLOAT, value);
} else {
ops->clear_value(cmd, cs, format, value);
}
for_each_layer(i, clear_views, fb->layers) {
if (cmd->state.per_layer_render_area) {
@ -4810,7 +4822,15 @@ clear_sysmem_attachment(struct tu_cmd_buffer *cmd,
ops->dst_stencil(cs, iview, i);
}
} else {
ops->dst(cs, &iview->view, i, format);
if (e5b9g9r9_as_u32) {
struct fdl6_view view = iview->view;
view.RB_A2D_DEST_BUFFER_INFO =
pkt_field_set(A6XX_RB_A2D_DEST_BUFFER_INFO_COLOR_FORMAT,
view.RB_A2D_DEST_BUFFER_INFO, FMT6_32_UINT);
ops->dst(cs, &view, i, format);
} else {
ops->dst(cs, &iview->view, i, format);
}
}
ops->run(cmd, cs);
}

View file

@ -36,9 +36,9 @@ tu6_format_vtx(enum pipe_format format)
}
static bool
tu6_format_color_supported(enum pipe_format format)
tu6_format_color_supported(const struct fd_dev_info *info, enum pipe_format format)
{
return fd6_color_format(format, TILE6_LINEAR) != FMT6_NONE;
return fd6_color_format_supported(info, format, TILE6_LINEAR);
}
struct tu_native_format
@ -136,7 +136,7 @@ tu_physical_device_get_format_properties(
const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(vk_format);
bool supported_vtx = tu6_format_vtx_supported(format);
bool supported_color = tu6_format_color_supported(format);
bool supported_color = tu6_format_color_supported(physical_device->info, format);
bool supported_tex = fd6_texture_format_supported(physical_device->info, format,
TILE6_LINEAR, false);
bool is_npot = !util_is_power_of_two_or_zero(desc->block.bits);

View file

@ -111,8 +111,11 @@ ok_dims(const struct pipe_resource *r, const struct pipe_box *b, int lvl)
}
static bool
ok_format(enum pipe_format pfmt)
ok_format(const struct fd_dev_info *info, enum pipe_format pfmt)
{
if (!fd6_color_format_supported(info, pfmt, TILE6_LINEAR))
return false;
enum a6xx_format fmt = fd6_color_format(pfmt, TILE6_LINEAR);
if (util_format_is_compressed(pfmt))
@ -173,7 +176,7 @@ dump_blit_info(const struct pipe_blit_info *info)
}
static bool
can_do_blit(const struct pipe_blit_info *info)
can_do_blit(const struct fd_dev_info *dev_info, const struct pipe_blit_info *info)
{
/* I think we can do scaling, but not in z dimension since that would
* require blending..
@ -181,8 +184,8 @@ can_do_blit(const struct pipe_blit_info *info)
fail_if(info->dst.box.depth != info->src.box.depth);
/* Fail if unsupported format: */
fail_if(!ok_format(info->src.format));
fail_if(!ok_format(info->dst.format));
fail_if(!ok_format(dev_info, info->src.format));
fail_if(!ok_format(dev_info, info->dst.format));
/* using the 2d path seems to canonicalize NaNs when the source format
* is a 16-bit floating point format, likely because it implicitly
@ -248,7 +251,9 @@ static bool
can_do_clear(const struct pipe_resource *prsc, unsigned level,
const struct pipe_box *box)
{
return ok_format(prsc->format) &&
struct fd_screen *screen = fd_screen(prsc->screen);
return ok_format(screen->info, prsc->format) &&
ok_dims(prsc, box, level) &&
(fd_resource_nr_samples(prsc) == 1);
@ -1244,7 +1249,7 @@ handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
assert(!(info->mask & PIPE_MASK_ZS));
if (!can_do_blit(info))
if (!can_do_blit(ctx->screen->info, info))
return false;
struct fd_resource *src = fd_resource(info->src.resource);
@ -1539,7 +1544,7 @@ fd6_blitter_init(struct pipe_context *pctx)
FD_GENX(fd6_blitter_init);
unsigned
fd6_tile_mode_for_format(enum pipe_format pfmt)
fd6_tile_mode_for_format(const struct fd_dev_info *info, enum pipe_format pfmt)
{
if (!util_is_power_of_two_nonzero(util_format_get_blocksize(pfmt)))
return TILE6_LINEAR;
@ -1547,7 +1552,7 @@ fd6_tile_mode_for_format(enum pipe_format pfmt)
/* basically just has to be a format we can blit, so uploads/downloads
* via linear staging buffer works:
*/
if (ok_format(pfmt))
if (ok_format(info, pfmt))
return TILE6_3;
return TILE6_LINEAR;
@ -1556,5 +1561,6 @@ fd6_tile_mode_for_format(enum pipe_format pfmt)
unsigned
fd6_tile_mode(const struct pipe_resource *tmpl)
{
return fd6_tile_mode_for_format(tmpl->format);
struct fd_screen *screen = fd_screen(tmpl->screen);
return fd6_tile_mode_for_format(screen->info, tmpl->format);
}

View file

@ -18,7 +18,7 @@
template <chip CHIP>
void fd6_blitter_init(struct pipe_context *pctx);
unsigned fd6_tile_mode_for_format(enum pipe_format pfmt);
unsigned fd6_tile_mode_for_format(const struct fd_dev_info *info, enum pipe_format pfmt);
unsigned fd6_tile_mode(const struct pipe_resource *tmpl);
/*

View file

@ -342,6 +342,8 @@ fd6_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format fmt,
uint64_t modifier)
{
struct fd_screen *screen = fd_screen(pscreen);
switch (modifier) {
case DRM_FORMAT_MOD_LINEAR:
return true;
@ -351,7 +353,7 @@ fd6_is_format_supported(struct pipe_screen *pscreen,
*/
return ok_ubwc_format(pscreen, fmt, 0);
case DRM_FORMAT_MOD_QCOM_TILED3:
return fd6_tile_mode_for_format(fmt) == TILE6_3;
return fd6_tile_mode_for_format(screen->info, fmt) == TILE6_3;
default:
return false;
}

View file

@ -70,7 +70,7 @@ fd6_screen_is_format_supported(struct pipe_screen *pscreen,
retval |= PIPE_BIND_VERTEX_BUFFER;
}
bool has_color = fd6_color_format(format, TILE6_LINEAR) != FMT6_NONE;
bool has_color = fd6_color_format_supported(screen->info, format, TILE6_LINEAR);
bool has_tex = fd6_texture_format_supported(screen->info, format, TILE6_LINEAR, false);
if ((usage & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_SHADER_IMAGE)) &&