pan/texture: Don't mix image and buffer views

Specialize the texture emission logic for buffer views, which are much
simpler to deal with than image views.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com>
Acked-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34767>
This commit is contained in:
Boris Brezillon
2025-05-19 12:53:28 +02:00
parent a6157e8dd5
commit 7164208efb
6 changed files with 201 additions and 129 deletions
+46 -11
View File
@@ -1725,16 +1725,53 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
enum mali_texture_dimension type =
panfrost_translate_texture_dimension(so->base.target);
bool is_buffer = (so->base.target == PIPE_BUFFER);
if (so->base.target == PIPE_BUFFER) {
const struct util_format_description *desc =
util_format_description(format);
struct pan_buffer_view bview = {
.format = format,
.astc.narrow =
desc->layout == UTIL_FORMAT_LAYOUT_ASTC &&
so->base.astc_decode_format == PIPE_ASTC_DECODE_FORMAT_UNORM8,
.width_el =
MIN2(so->base.u.buf.size / util_format_get_blocksize(format),
PAN_MAX_TEXEL_BUFFER_ELEMENTS),
.base = prsrc->image.data.base + so->base.u.buf.offset,
};
#if PAN_ARCH >= 9
unsigned payload_size = pan_size(PLANE);
#elif PAN_ARCH >= 6
unsigned payload_size = pan_size(SURFACE_WITH_STRIDE);
#else
unsigned payload_size = pan_size(TEXTURE) + pan_size(SURFACE_WITH_STRIDE);
#endif
unsigned first_level = is_buffer ? 0 : so->base.u.tex.first_level;
unsigned last_level = is_buffer ? 0 : so->base.u.tex.last_level;
unsigned first_layer = is_buffer ? 0 : so->base.u.tex.first_layer;
unsigned last_layer = is_buffer ? 0 : so->base.u.tex.last_layer;
unsigned buf_offset = is_buffer ? so->base.u.buf.offset : 0;
unsigned buf_size =
(is_buffer ? so->base.u.buf.size : 0) / util_format_get_blocksize(format);
buf_size = MIN2(buf_size, PAN_MAX_TEXEL_BUFFER_ELEMENTS);
struct panfrost_pool *pool = so->pool ?: &ctx->descs;
struct pan_ptr payload =
pan_pool_alloc_aligned(&pool->base, payload_size, 64);
if (!payload.cpu) {
mesa_loge("panfrost_create_sampler_view_bo failed");
return;
}
so->state = panfrost_pool_take_ref(&ctx->descs, payload.gpu);
void *tex = (PAN_ARCH >= 6) ? &so->bifrost_descriptor : payload.cpu;
if (PAN_ARCH <= 5) {
payload.cpu += pan_size(TEXTURE);
payload.gpu += pan_size(TEXTURE);
}
GENX(pan_buffer_texture_emit)(&bview, tex, &payload);
return;
}
unsigned first_level = so->base.u.tex.first_level;
unsigned last_level = so->base.u.tex.last_level;
unsigned first_layer = so->base.u.tex.first_layer;
unsigned last_layer = so->base.u.tex.last_layer;
if (so->base.target == PIPE_TEXTURE_3D) {
first_layer /= prsrc->image.props.extent_px.depth;
@@ -1757,8 +1794,6 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
so->base.swizzle_a,
},
.planes = {NULL},
.buf.offset = buf_offset,
.buf.size = buf_size,
};
#if PAN_ARCH >= 7
+9
View File
@@ -33,6 +33,15 @@
#include "pan_image.h"
#include "pan_pool.h"
struct pan_buffer_view {
enum pipe_format format;
struct {
unsigned narrow;
} astc;
unsigned width_el;
uint64_t base;
};
struct pan_compute_dim {
uint32_t x, y, z;
};
-6
View File
@@ -58,12 +58,6 @@ struct pan_image_view {
* greater than image->layout.nr_samples. */
unsigned nr_samples;
/* Only valid if dim == 1D, needed to implement buffer views */
struct {
unsigned offset;
unsigned size;
} buf;
struct {
unsigned narrow;
} astc;
+130 -58
View File
@@ -31,6 +31,7 @@
#include "util/u_math.h"
#include "pan_afbc.h"
#include "pan_afrc.h"
#include "pan_desc.h"
#include "pan_format.h"
#include "pan_image.h"
#include "pan_pool.h"
@@ -234,11 +235,6 @@ get_image_section_info(const struct pan_image_view *iview,
uint64_t base = plane->data.base;
struct pan_image_section_info info = {0};
if (iview->buf.size) {
assert(iview->dim == MALI_TEXTURE_DIMENSION_1D);
base += iview->buf.offset;
}
/* v4 does not support compression */
assert(PAN_ARCH >= 5 || !drm_is_afbc(plane->props.modifier));
assert(PAN_ARCH >= 5 || desc->layout != UTIL_FORMAT_LAYOUT_ASTC);
@@ -260,8 +256,24 @@ get_image_section_info(const struct pan_image_view *iview,
#if PAN_ARCH <= 7
static void
pan_emit_surface_with_stride(const struct pan_image_section_info *section,
void **payload)
pan_emit_bview_surface_with_stride(const struct pan_buffer_view *bview,
void *payload)
{
const struct util_format_description *desc =
util_format_description(bview->format);
unsigned tag = pan_compression_tag(desc, MALI_TEXTURE_DIMENSION_1D,
DRM_FORMAT_MOD_LINEAR);
pan_cast_and_pack(payload, SURFACE_WITH_STRIDE, cfg) {
cfg.pointer = bview->base | tag;
cfg.row_stride = 0;
cfg.surface_stride = 0;
}
}
static void
pan_emit_iview_surface_with_stride(const struct pan_image_section_info *section,
void **payload)
{
pan_cast_and_pack(*payload, SURFACE_WITH_STRIDE, cfg) {
cfg.pointer = section->pointer;
@@ -274,8 +286,8 @@ pan_emit_surface_with_stride(const struct pan_image_section_info *section,
#if PAN_ARCH == 7
static void
pan_emit_multiplanar_surface(const struct pan_image_section_info *sections,
void **payload)
pan_emit_iview_multiplanar_surface(
const struct pan_image_section_info *sections, void **payload)
{
assert(sections[2].row_stride == 0 ||
sections[1].row_stride == sections[2].row_stride);
@@ -291,28 +303,6 @@ pan_emit_multiplanar_surface(const struct pan_image_section_info *sections,
}
#endif
/* Special case for iview->buf.size as the passed layout->width is incorrect */
static struct pan_image_extent
pan_texture_buf_get_extent(const struct pan_image_view *iview,
const struct pan_image_props *iprops)
{
assert(iview->buf.size);
struct pan_image_extent extent_px;
assert(iview->dim == MALI_TEXTURE_DIMENSION_1D);
assert(!iview->first_level && !iview->last_level);
assert(!iview->first_layer && !iview->last_layer);
assert(iprops->nr_samples == 1);
assert(iprops->extent_px.height == 1 && iprops->extent_px.depth == 1);
assert(iview->buf.offset + iview->buf.size <= iprops->extent_px.width);
extent_px.width = iview->buf.size;
extent_px.height = 1;
extent_px.depth = 1;
return extent_px;
}
#if PAN_ARCH >= 9
/* clang-format off */
@@ -435,9 +425,54 @@ translate_superblock_size(uint64_t modifier)
}
static void
pan_emit_plane(const struct pan_image_view *iview,
const struct pan_image_section_info *sections, int plane_index,
unsigned level, void **payload)
pan_emit_bview_plane(const struct pan_buffer_view *bview, void *payload)
{
const struct util_format_description *desc =
util_format_description(bview->format);
pan_cast_and_pack(payload, PLANE, cfg) {
cfg.pointer = bview->base;
cfg.size = util_format_get_blocksize(bview->format) * bview->width_el;
cfg.clump_ordering = MALI_CLUMP_ORDERING_LINEAR;
#if PAN_ARCH >= 10
cfg.width = bview->width_el;
cfg.height = 1;
#endif
if (desc->layout == UTIL_FORMAT_LAYOUT_ASTC) {
if (desc->block.depth > 1) {
cfg.plane_type = MALI_PLANE_TYPE_ASTC_3D;
cfg.astc._3d.block_width = pan_astc_dim_3d(desc->block.width);
cfg.astc._3d.block_height = pan_astc_dim_3d(desc->block.height);
cfg.astc._3d.block_depth = pan_astc_dim_3d(desc->block.depth);
} else {
cfg.plane_type = MALI_PLANE_TYPE_ASTC_2D;
cfg.astc._2d.block_width = pan_astc_dim_2d(desc->block.width);
cfg.astc._2d.block_height = pan_astc_dim_2d(desc->block.height);
}
bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
/* Mesa does not advertise _HDR formats yet */
cfg.astc.decode_hdr = false;
/* sRGB formats decode to RGBA8 sRGB, which is narrow.
*
* Non-sRGB formats decode to RGBA16F which is wide except if decode
* precision is set to GL_RGBA8 for that texture.
*/
cfg.astc.decode_wide = !srgb && !bview->astc.narrow;
} else {
cfg.plane_type = MALI_PLANE_TYPE_GENERIC;
cfg.clump_format = pan_clump_format(bview->format);
}
}
}
static void
pan_emit_iview_plane(const struct pan_image_view *iview,
const struct pan_image_section_info *sections,
int plane_index, unsigned level, void **payload)
{
const struct util_format_description *desc =
util_format_description(iview->format);
@@ -464,13 +499,10 @@ pan_emit_plane(const struct pan_image_view *iview,
cfg.row_stride = row_stride;
cfg.size = layout->slices[level].size_B;
#if PAN_ARCH >= 10
struct pan_image_extent extent;
if (iview->buf.size)
extent = pan_texture_buf_get_extent(iview, props);
else {
extent.width = u_minify(props->extent_px.width, level);
extent.height = u_minify(props->extent_px.height, level);
}
struct pan_image_extent extent = {
.width = u_minify(props->extent_px.width, level),
.height = u_minify(props->extent_px.height, level),
};
if (is_chroma_2p) {
cfg.two_plane_yuv_chroma.width = extent.width;
@@ -554,8 +586,8 @@ pan_emit_plane(const struct pan_image_view *iview,
#endif
static void
pan_emit_surface(const struct pan_image_view *iview, unsigned level,
unsigned index, unsigned sample, void **payload)
pan_emit_iview_surface(const struct pan_image_view *iview, unsigned level,
unsigned index, unsigned sample, void **payload)
{
#if PAN_ARCH == 7 || PAN_ARCH >= 9
if (pan_format_is_yuv(iview->format)) {
@@ -576,19 +608,19 @@ pan_emit_surface(const struct pan_image_view *iview, unsigned level,
#if PAN_ARCH >= 9
/* 3-plane YUV is submitted using two PLANE descriptors, where the
* second one is of type CHROMA_2P */
pan_emit_plane(iview, sections, 0, level, payload);
pan_emit_iview_plane(iview, sections, 0, level, payload);
if (plane_count > 1) {
/* 3-plane YUV requires equal stride for both chroma planes */
assert(plane_count == 2 ||
sections[1].row_stride == sections[2].row_stride);
pan_emit_plane(iview, sections, 1, level, payload);
pan_emit_iview_plane(iview, sections, 1, level, payload);
}
#else
if (plane_count > 1)
pan_emit_multiplanar_surface(sections, payload);
pan_emit_iview_multiplanar_surface(sections, payload);
else
pan_emit_surface_with_stride(sections, payload);
pan_emit_iview_surface_with_stride(sections, payload);
#endif
return;
}
@@ -611,14 +643,15 @@ pan_emit_surface(const struct pan_image_view *iview, unsigned level,
};
#if PAN_ARCH >= 9
pan_emit_plane(iview, section, 0, level, payload);
pan_emit_iview_plane(iview, section, 0, level, payload);
#else
pan_emit_surface_with_stride(section, payload);
pan_emit_iview_surface_with_stride(section, payload);
#endif
}
static void
pan_emit_texture_payload(const struct pan_image_view *iview, void *payload)
pan_emit_iview_texture_payload(const struct pan_image_view *iview,
void *payload)
{
unsigned nr_samples =
PAN_ARCH <= 7 ? pan_image_view_get_nr_samples(iview) : 1;
@@ -635,7 +668,7 @@ pan_emit_texture_payload(const struct pan_image_view *iview, void *payload)
for (int sample = 0; sample < nr_samples; ++sample) {
for (int level = iview->first_level; level <= iview->last_level;
++level) {
pan_emit_surface(iview, level, layer, sample, &payload);
pan_emit_iview_surface(iview, level, layer, sample, &payload);
}
}
}
@@ -658,8 +691,8 @@ pan_emit_texture_payload(const struct pan_image_view *iview, void *payload)
*/
for (int face = 0; face < face_count; ++face) {
for (int sample = 0; sample < nr_samples; ++sample) {
pan_emit_surface(iview, level, (face_count * layer) + face,
sample, &payload);
pan_emit_iview_surface(iview, level, (face_count * layer) + face,
sample, &payload);
}
}
}
@@ -761,9 +794,6 @@ static struct pan_image_extent
pan_texture_get_extent(const struct pan_image_view *iview,
const struct pan_image_props *iprops)
{
if (iview->buf.size)
return pan_texture_buf_get_extent(iview, iprops);
struct pan_image_extent extent_px = {
.width = u_minify(iprops->extent_px.width, iview->first_level),
.height = u_minify(iprops->extent_px.height, iview->first_level),
@@ -812,7 +842,7 @@ GENX(pan_sampled_texture_emit)(const struct pan_image_view *iview,
mali_format = MALI_PACK_FMT(RGBA8_UNORM, RGBA, L);
}
pan_emit_texture_payload(iview, payload->cpu);
pan_emit_iview_texture_payload(iview, payload->cpu);
unsigned array_size = pan_texture_get_array_size(iview);
@@ -872,7 +902,7 @@ GENX(pan_storage_texture_emit)(const struct pan_image_view *iview,
mali_format = MALI_PACK_FMT(RGBA8_UNORM, RGBA, L);
}
pan_emit_texture_payload(iview, payload->cpu);
pan_emit_iview_texture_payload(iview, payload->cpu);
unsigned array_size = pan_texture_get_array_size(iview);
@@ -910,3 +940,45 @@ GENX(pan_storage_texture_emit)(const struct pan_image_view *iview,
}
}
#endif
void
GENX(pan_buffer_texture_emit)(const struct pan_buffer_view *bview,
struct mali_texture_packed *out,
const struct pan_ptr *payload)
{
uint32_t mali_format = GENX(pan_format_from_pipe_format)(bview->format)->hw;
static const unsigned char rgba_swizzle[4] = {
PIPE_SWIZZLE_X,
PIPE_SWIZZLE_Y,
PIPE_SWIZZLE_Z,
PIPE_SWIZZLE_W,
};
#if PAN_ARCH >= 9
pan_emit_bview_plane(bview, payload->cpu);
#else
pan_emit_bview_surface_with_stride(bview, payload->cpu);
#endif
pan_pack(out, TEXTURE, cfg) {
cfg.dimension = MALI_TEXTURE_DIMENSION_1D;
cfg.format = mali_format;
cfg.width = bview->width_el;
cfg.height = 1;
cfg.sample_count = 1;
cfg.swizzle = pan_translate_swizzle_4(rgba_swizzle);
#if PAN_ARCH >= 9
cfg.texel_interleave = false;
#else
cfg.texel_ordering = MALI_TEXTURE_LAYOUT_LINEAR;
#endif
cfg.levels = 1;
cfg.array_size = 1;
#if PAN_ARCH >= 6
cfg.surfaces = payload->gpu;
cfg.minimum_lod = 0;
cfg.maximum_lod = 0;
#endif
}
}
+6
View File
@@ -36,6 +36,7 @@
struct pan_ptr;
struct mali_texture_packed;
struct pan_buffer_view;
#if PAN_ARCH >= 7
void GENX(pan_texture_swizzle_replicate_x)(struct pan_image_view *iview);
@@ -58,4 +59,9 @@ void GENX(pan_storage_texture_emit)(const struct pan_image_view *iview,
const struct pan_ptr *payload);
#endif
void
GENX(pan_buffer_texture_emit)(const struct pan_buffer_view *bview,
struct mali_texture_packed *out,
const struct pan_ptr *payload);
#endif
+10 -54
View File
@@ -18,6 +18,7 @@
#include "panvk_priv_bo.h"
#include "pan_afbc.h"
#include "pan_desc.h"
#include "pan_props.h"
#include "pan_texture.h"
@@ -54,70 +55,25 @@ panvk_per_arch(CreateBufferView)(VkDevice _device,
assert(!(address & 63));
if (buffer->vk.usage & tex_usage_mask) {
struct panvk_physical_device *physical_device =
to_panvk_physical_device(device->vk.physical);
unsigned arch = pan_arch(physical_device->kmod.props.gpu_prod_id);
struct pan_image plane = {
.data = {
.base = address,
},
.props = {
.modifier = DRM_FORMAT_MOD_LINEAR,
.format = pfmt,
.dim = MALI_TEXTURE_DIMENSION_1D,
.extent_px = {
.width = view->vk.elements,
.height = 1,
.depth = 1,
},
.array_size = 1,
.nr_samples = 1,
.nr_slices = 1,
},
};
struct pan_image_view pview = {
.planes[0] = &plane,
struct pan_buffer_view bview = {
.format = pfmt,
.dim = MALI_TEXTURE_DIMENSION_1D,
.nr_samples = 1,
.first_level = 0,
.last_level = 0,
.first_layer = 0,
.last_layer = 0,
.swizzle =
{
PIPE_SWIZZLE_X,
PIPE_SWIZZLE_Y,
PIPE_SWIZZLE_Z,
PIPE_SWIZZLE_W,
},
.width_el = view->vk.elements,
.base = address,
};
#if PAN_ARCH == 7
/* v7 requires AFBC reswizzle. */
if (!util_format_is_depth_or_stencil(pfmt) &&
!pan_format_is_yuv(pfmt) &&
pan_format_supports_afbc(PAN_ARCH, pfmt))
GENX(pan_texture_afbc_reswizzle)(&pview);
#if PAN_ARCH >= 9
view->mem = panvk_pool_alloc_desc(&device->mempools.rw, PLANE);
#else
view->mem =
panvk_pool_alloc_desc(&device->mempools.rw, SURFACE_WITH_STRIDE);
#endif
pan_image_layout_init(arch, &plane.props, NULL, &plane.layout);
struct panvk_pool_alloc_info alloc_info = {
.alignment = pan_alignment(TEXTURE),
.size = GENX(pan_texture_estimate_payload_size)(&pview),
};
view->mem = panvk_pool_alloc_mem(&device->mempools.rw, alloc_info);
struct pan_ptr ptr = {
.gpu = panvk_priv_mem_dev_addr(view->mem),
.cpu = panvk_priv_mem_host_addr(view->mem),
};
GENX(pan_sampled_texture_emit)(&pview, &view->descs.tex, &ptr);
GENX(pan_buffer_texture_emit)(&bview, &view->descs.tex, &ptr);
}
#if PAN_ARCH <= 7