From 7164208efb83439bf2f3452e8721fd28d05b6d57 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 19 May 2025 12:53:28 +0200 Subject: [PATCH] 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 Reviewed-by: Mary Guillemard Reviewed-by: Lars-Ivar Hesselberg Simonsen Acked-by: Eric R. Smith Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 57 ++++-- src/panfrost/lib/pan_desc.h | 9 + src/panfrost/lib/pan_image.h | 6 - src/panfrost/lib/pan_texture.c | 188 +++++++++++++------ src/panfrost/lib/pan_texture.h | 6 + src/panfrost/vulkan/panvk_vX_buffer_view.c | 64 +------ 6 files changed, 201 insertions(+), 129 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 82558bc285c..6acf82fdcbe 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -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 diff --git a/src/panfrost/lib/pan_desc.h b/src/panfrost/lib/pan_desc.h index 6b66dfc9da0..c87d5f82361 100644 --- a/src/panfrost/lib/pan_desc.h +++ b/src/panfrost/lib/pan_desc.h @@ -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; }; diff --git a/src/panfrost/lib/pan_image.h b/src/panfrost/lib/pan_image.h index 85d47095123..b6407ee6a91 100644 --- a/src/panfrost/lib/pan_image.h +++ b/src/panfrost/lib/pan_image.h @@ -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; diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index 841cb95a9bd..e46c5457b7c 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -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 + } +} diff --git a/src/panfrost/lib/pan_texture.h b/src/panfrost/lib/pan_texture.h index 5f44fa31caf..ad0e168d747 100644 --- a/src/panfrost/lib/pan_texture.h +++ b/src/panfrost/lib/pan_texture.h @@ -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 diff --git a/src/panfrost/vulkan/panvk_vX_buffer_view.c b/src/panfrost/vulkan/panvk_vX_buffer_view.c index 34ad49987d0..cc71ba05bc4 100644 --- a/src/panfrost/vulkan/panvk_vX_buffer_view.c +++ b/src/panfrost/vulkan/panvk_vX_buffer_view.c @@ -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