From a794ea6f9f9756e4f51efe13d7c485998beed460 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 30 Apr 2025 13:39:42 +0200 Subject: [PATCH] pan: Consolidate AFRC helpers in a single source file Create a pan_afrc.h header gathering all AFRC-related helpers spread across pan_layout.c, pan_texture.{c,h} and pan_afbc.c. By making them inline functions, we also allow for extra compile-time optimizations. While at it, we pick a consistent pan_ prefix instead of the pan_/panfrost_ mix we currently have. Signed-off-by: Boris Brezillon Reviewed-by: Eric R. Smith Reviewed-by: Mary Guillemard Acked-by: Daniel Stone Reviewed-by: Ryan Mckeever Reviewed-by: Olivia Lee Reviewed-by: Lars-Ivar Hesselberg Simonsen Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/panfrost/pan_resource.c | 13 +- src/gallium/drivers/panfrost/pan_screen.c | 7 +- src/panfrost/lib/meson.build | 1 - src/panfrost/lib/pan_afrc.c | 218 ---------- src/panfrost/lib/pan_afrc.h | 437 ++++++++++++++++++++ src/panfrost/lib/pan_desc.c | 9 +- src/panfrost/lib/pan_layout.c | 101 +---- src/panfrost/lib/pan_texture.c | 100 +---- src/panfrost/lib/pan_texture.h | 69 ---- 9 files changed, 461 insertions(+), 494 deletions(-) delete mode 100644 src/panfrost/lib/pan_afrc.c create mode 100644 src/panfrost/lib/pan_afrc.h diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index b9be8407bf6..a632f8dd204 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -50,6 +50,7 @@ #include "decode.h" #include "pan_afbc.h" +#include "pan_afrc.h" #include "pan_bo.h" #include "pan_context.h" #include "pan_resource.h" @@ -435,7 +436,7 @@ panfrost_should_afrc(struct panfrost_device *dev, return false; /* Only a small selection of formats are AFRC'able */ - if (!panfrost_format_supports_afrc(fmt)) + if (!pan_format_supports_afrc(fmt)) return false; /* AFRC does not support layered (GLES3 style) multisampling. Use @@ -482,7 +483,7 @@ panfrost_best_modifier(struct pipe_screen *pscreen, * for the next valid one. */ for (int i = afrc_rate; i < 12; ++i) { - if (panfrost_afrc_get_modifiers(fmt, i, 0, NULL)) { + if (pan_afrc_get_modifiers(fmt, i, 0, NULL)) { afrc_rate = i; break; } @@ -495,7 +496,7 @@ panfrost_best_modifier(struct pipe_screen *pscreen, unsigned num_mods = 0; STATIC_ASSERT(PIPE_COMPRESSION_FIXED_RATE_DEFAULT == PAN_AFRC_RATE_DEFAULT); - num_mods = panfrost_afrc_get_modifiers(fmt, afrc_rate, 1, &mod); + num_mods = pan_afrc_get_modifiers(fmt, afrc_rate, 1, &mod); if (num_mods > 0) { return mod; } @@ -573,7 +574,7 @@ panfrost_resource_setup(struct pipe_screen *screen, /* Update the compression rate with the correct value as we * want the real bitrate and not DEFAULT */ - pres->base.compression_rate = panfrost_afrc_get_rate(fmt, chosen_mod); + pres->base.compression_rate = pan_afrc_get_rate(fmt, chosen_mod); ASSERTED bool valid = pan_image_layout_init(dev->arch, &pres->image.layout, NULL); @@ -1592,9 +1593,9 @@ pan_legalize_format(struct panfrost_context *ctx, pan_afbc_format(dev->arch, new_format)); } else if (drm_is_afrc(rsrc->image.layout.modifier)) { struct pan_afrc_format_info old_info = - panfrost_afrc_get_format_info(old_format); + pan_afrc_get_format_info(old_format); struct pan_afrc_format_info new_info = - panfrost_afrc_get_format_info(new_format); + pan_afrc_get_format_info(new_format); compatible = !memcmp(&old_info, &new_info, sizeof(old_info)); } else if (drm_is_mtk_tiled(rsrc->image.layout.modifier)) { compatible = false; diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index b60711bda98..45cf02100e3 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -47,6 +47,7 @@ #include "decode.h" #include "pan_afbc.h" +#include "pan_afrc.h" #include "pan_bo.h" #include "pan_fence.h" #include "pan_public.h" @@ -233,7 +234,7 @@ panfrost_query_compression_rates(struct pipe_screen *screen, return; } - *count = panfrost_afrc_query_rates(format, max, rates); + *count = pan_afrc_query_rates(format, max, rates); } /* We always support linear and tiled operations, both external and internal. @@ -252,7 +253,7 @@ panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen, dev->has_afbc && pan_format_supports_afbc(dev->arch, format); bool ytr = pan_afbc_can_ytr(format); bool tiled_afbc = pan_afbc_can_tile(dev->arch); - bool afrc = allow_afrc && dev->has_afrc && panfrost_format_supports_afrc(format); + bool afrc = allow_afrc && dev->has_afrc && pan_format_supports_afrc(format); PAN_SUPPORTED_MODIFIERS(supported_mods); unsigned count = 0; @@ -321,7 +322,7 @@ panfrost_query_compression_modifiers(struct pipe_screen *screen, DRM_FORMAT_MOD_INVALID, false /* disallow afrc */); else if (dev->has_afrc) - *count = panfrost_afrc_get_modifiers(format, rate, max, modifiers); + *count = pan_afrc_get_modifiers(format, rate, max, modifiers); else *count = 0; /* compression requested but not supported */ } diff --git a/src/panfrost/lib/meson.build b/src/panfrost/lib/meson.build index a817d8de630..84101a8063b 100644 --- a/src/panfrost/lib/meson.build +++ b/src/panfrost/lib/meson.build @@ -51,7 +51,6 @@ endforeach libpanfrost_lib_files = files( 'pan_encoder.h', - 'pan_afrc.c', 'pan_attributes.c', 'pan_blend.c', 'pan_clear.c', diff --git a/src/panfrost/lib/pan_afrc.c b/src/panfrost/lib/pan_afrc.c deleted file mode 100644 index 4b87ccd47f8..00000000000 --- a/src/panfrost/lib/pan_afrc.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2023 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Louis-Francis Ratté-Boulianne - */ - -#include "pan_texture.h" - -/* Arm Fixed-Rate Compression (AFRC) is a lossy compression scheme natively - * implemented in Mali GPUs. AFRC images can only be rendered or textured - * from. It is currently not possible to do image reads or writes to such - * resources. - * - * AFRC divides the image into an array of fixed-size coding units which are - * grouped into paging tiles. The size of the coding units (clump size) - * depends on the image format and the pixel layout (whether it is optimized - * for 2D locality and rotation, or for scan line order access). The last - * parameter is the size of the compressed block that can be either 16, 24, - * or 32 bytes. - * - * The compression rate can be calculated by dividing the compressed block - * size by the uncompressed block size (clump size multiplied by the component - * size and the number of components). - */ - -struct pan_afrc_format_info -panfrost_afrc_get_format_info(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - struct pan_afrc_format_info info = {0}; - - /* No AFRC(ZS). */ - if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) - return info; - - unsigned bpc = 0; - for (unsigned c = 0; c < desc->nr_channels; c++) { - if (bpc && bpc != desc->channel[c].size) - return info; - - bpc = desc->channel[0].size; - } - - info.bpc = bpc; - - if (desc->colorspace == UTIL_FORMAT_COLORSPACE_YUV) { - if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) - info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_YUV444; - else if (util_format_is_subsampled_422(format)) - info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_YUV422; - else - info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_YUV420; - } else { - assert(desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || - desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); - info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_RAW; - } - - info.num_planes = util_format_get_num_planes(format); - info.num_comps = util_format_get_nr_components(format); - return info; -} - -bool -panfrost_format_supports_afrc(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - int c = util_format_get_first_non_void_channel(desc->format); - - if (c == -1) - return false; - - return desc->is_array && desc->channel[c].size == 8; -} - -struct panfrost_afrc_block_size { - unsigned size; /* Block size in bytes */ - unsigned alignment; /* Buffer alignment */ - uint64_t modifier_flag; /* Part of the modifier for CU size */ -}; - -#define BLOCK_SIZE(block_size, buffer_alignment) \ - { \ - .size = block_size, .alignment = buffer_alignment, \ - .modifier_flag = AFRC_FORMAT_MOD_CU_SIZE_##block_size, \ - } - -/* clang-format off */ -const struct panfrost_afrc_block_size panfrost_afrc_block_sizes[] = { - BLOCK_SIZE(16, 1024), - BLOCK_SIZE(24, 512), - BLOCK_SIZE(32, 2048), -}; -/* clang-format on */ - -/* Total number of components in a AFRC coding unit */ -static unsigned -panfrost_afrc_clump_get_nr_components(enum pipe_format format, bool scan) -{ - const struct util_format_description *desc = util_format_description(format); - struct pan_block_size clump_sz = panfrost_afrc_clump_size(format, scan); - return clump_sz.width * clump_sz.height * desc->nr_channels; -} - -unsigned -panfrost_afrc_query_rates(enum pipe_format format, unsigned max, - uint32_t *rates) -{ - if (!panfrost_format_supports_afrc(format)) - return 0; - - unsigned clump_comps = panfrost_afrc_clump_get_nr_components(format, false); - unsigned nr_rates = 0; - - /** - * From EGL_EXT_surface_compression: - * - * "For pixel formats with different number of bits per component, the - * specified fixed-rate compression rate applies to the component with - * the highest number of bits." - * - * We only support formats where all components have the same size for now. - * Let's just use the first component size for calculation. - */ - unsigned uncompressed_rate = - util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0); - - for (unsigned i = 0; i < ARRAY_SIZE(panfrost_afrc_block_sizes); ++i) { - unsigned clump_sz = panfrost_afrc_block_sizes[i].size * 8; - unsigned rate = clump_sz / clump_comps; - - if (rate >= uncompressed_rate) - continue; - - if (nr_rates < max) - rates[nr_rates] = rate; - nr_rates++; - - if (max > 0 && nr_rates == max) - break; - } - - return nr_rates; -} - -unsigned -panfrost_afrc_get_modifiers(enum pipe_format format, uint32_t rate, - unsigned max, uint64_t *modifiers) -{ - if (!panfrost_format_supports_afrc(format)) - return 0; - - /* For now, the number of components in a clump is always the same no - * matter the layout for all supported formats */ - unsigned clump_comps = panfrost_afrc_clump_get_nr_components(format, false); - unsigned count = 0; - - /* FIXME Choose a more sensitive default compression rate? */ - if (rate == PAN_AFRC_RATE_DEFAULT) { - if (max > 0) - modifiers[0] = DRM_FORMAT_MOD_ARM_AFRC(AFRC_FORMAT_MOD_CU_SIZE_24); - - if (max > 1) - modifiers[1] = DRM_FORMAT_MOD_ARM_AFRC(AFRC_FORMAT_MOD_CU_SIZE_24 | - AFRC_FORMAT_MOD_LAYOUT_SCAN); - - return 2; - } - - for (unsigned i = 0; i < ARRAY_SIZE(panfrost_afrc_block_sizes); ++i) { - unsigned clump_sz = panfrost_afrc_block_sizes[i].size * 8; - if (rate == clump_sz / clump_comps) { - for (unsigned scan = 0; scan < 2; ++scan) { - if (count < max) { - modifiers[count] = DRM_FORMAT_MOD_ARM_AFRC( - panfrost_afrc_block_sizes[i].modifier_flag | - (scan ? AFRC_FORMAT_MOD_LAYOUT_SCAN : 0)); - } - count++; - } - } - } - - return count; -} - -uint32_t -panfrost_afrc_get_rate(enum pipe_format format, uint64_t modifier) -{ - if (!drm_is_afrc(modifier) || !panfrost_format_supports_afrc(format)) - return PAN_AFRC_RATE_NONE; - - bool scan = panfrost_afrc_is_scan(modifier); - unsigned block_comps = panfrost_afrc_clump_get_nr_components(format, scan); - uint32_t block_sz = panfrost_afrc_block_size_from_modifier(modifier) * 8; - - return block_sz / block_comps; -} diff --git a/src/panfrost/lib/pan_afrc.h b/src/panfrost/lib/pan_afrc.h new file mode 100644 index 00000000000..0a84670f340 --- /dev/null +++ b/src/panfrost/lib/pan_afrc.h @@ -0,0 +1,437 @@ +/* + * Copyright (C) 2023 Collabora, Ltd. + * + * SPDX-License-Identifier: MIT + * + * Authors: + * Louis-Francis Ratté-Boulianne + */ + +#ifndef __PAN_AFRC_H +#define __PAN_AFRC_H + +#include "pan_format.h" +#include "pan_texture.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Arm Fixed-Rate Compression (AFRC) is a lossy compression scheme natively + * implemented in Mali GPUs. AFRC images can only be rendered or textured + * from. It is currently not possible to do image reads or writes to such + * resources. + * + * AFRC divides the image into an array of fixed-size coding units which are + * grouped into paging tiles. The size of the coding units (clump size) + * depends on the image format and the pixel layout (whether it is optimized + * for 2D locality and rotation, or for scan line order access). The last + * parameter is the size of the compressed block that can be either 16, 24, + * or 32 bytes. + * + * The compression rate can be calculated by dividing the compressed block + * size by the uncompressed block size (clump size multiplied by the component + * size and the number of components). + */ + +#define AFRC_CLUMPS_PER_TILE 64 + +enum pan_afrc_rate { + PAN_AFRC_RATE_NONE, + PAN_AFRC_RATE_1BPC, + PAN_AFRC_RATE_2BPC, + PAN_AFRC_RATE_3BPC, + PAN_AFRC_RATE_4BPC, + PAN_AFRC_RATE_5BPC, + PAN_AFRC_RATE_6BPC, + PAN_AFRC_RATE_7BPC, + PAN_AFRC_RATE_8BPC, + PAN_AFRC_RATE_9BPC, + PAN_AFRC_RATE_10BPC, + PAN_AFRC_RATE_11BPC, + PAN_AFRC_RATE_12BPC, + PAN_AFRC_RATE_DEFAULT = 0xF +}; + +enum pan_afrc_interchange_format { + PAN_AFRC_ICHANGE_FORMAT_RAW, + PAN_AFRC_ICHANGE_FORMAT_YUV444, + PAN_AFRC_ICHANGE_FORMAT_YUV422, + PAN_AFRC_ICHANGE_FORMAT_YUV420, +}; + +struct pan_afrc_format_info { + unsigned bpc : 4; + unsigned num_comps : 3; + unsigned ichange_fmt : 2; + unsigned num_planes : 2; +}; + +/* + * Given an AFRC modifier, return whether the layout is optimized for scan + * order (vs rotation order). + */ +static inline bool +pan_afrc_is_scan(uint64_t modifier) +{ + return modifier & AFRC_FORMAT_MOD_LAYOUT_SCAN; +} + +static inline struct pan_afrc_format_info +pan_afrc_get_format_info(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + struct pan_afrc_format_info info = {0}; + + /* No AFRC(ZS). */ + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) + return info; + + unsigned bpc = 0; + for (unsigned c = 0; c < desc->nr_channels; c++) { + if (bpc && bpc != desc->channel[c].size) + return info; + + bpc = desc->channel[0].size; + } + + info.bpc = bpc; + + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_YUV) { + if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) + info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_YUV444; + else if (util_format_is_subsampled_422(format)) + info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_YUV422; + else + info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_YUV420; + } else { + assert(desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || + desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); + info.ichange_fmt = PAN_AFRC_ICHANGE_FORMAT_RAW; + } + + info.num_planes = util_format_get_num_planes(format); + info.num_comps = util_format_get_nr_components(format); + return info; +} + +struct pan_afrc_block_size { + unsigned size; /* Block size in bytes */ + unsigned alignment; /* Buffer alignment */ + uint64_t modifier_flag; /* Part of the modifier for CU size */ +}; + +#define BLOCK_SIZE(block_size, buffer_alignment) \ + { \ + .size = block_size, \ + .alignment = buffer_alignment, \ + .modifier_flag = AFRC_FORMAT_MOD_CU_SIZE_##block_size, \ + } + +#define AFRC_BLOCK_SIZES(__name) \ + static const struct pan_afrc_block_size __name[] = { \ + BLOCK_SIZE(16, 1024), \ + BLOCK_SIZE(24, 512), \ + BLOCK_SIZE(32, 2048), \ + } + +static inline struct pan_block_size +pan_afrc_clump_size(enum pipe_format format, bool scan) +{ + struct pan_afrc_format_info finfo = pan_afrc_get_format_info(format); + + switch (finfo.num_comps) { + case 1: + return scan ? (struct pan_block_size){16, 4} + : (struct pan_block_size){8, 8}; + case 2: + return (struct pan_block_size){8, 4}; + case 3: + case 4: + return (struct pan_block_size){4, 4}; + default: + assert(0); + return (struct pan_block_size){0, 0}; + } +} + +/* Total number of components in a AFRC coding unit */ +static inline unsigned +pan_afrc_clump_get_nr_components(enum pipe_format format, bool scan) +{ + const struct util_format_description *desc = util_format_description(format); + struct pan_block_size clump_sz = pan_afrc_clump_size(format, scan); + return clump_sz.width * clump_sz.height * desc->nr_channels; +} + +static inline bool +pan_format_supports_afrc(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + int c = util_format_get_first_non_void_channel(desc->format); + + if (c == -1) + return false; + + return desc->is_array && desc->channel[c].size == 8; +} + +static inline unsigned +pan_afrc_query_rates(enum pipe_format format, unsigned max, uint32_t *rates) +{ + if (!pan_format_supports_afrc(format)) + return 0; + + unsigned clump_comps = pan_afrc_clump_get_nr_components(format, false); + unsigned nr_rates = 0; + + /** + * From EGL_EXT_surface_compression: + * + * "For pixel formats with different number of bits per component, the + * specified fixed-rate compression rate applies to the component with + * the highest number of bits." + * + * We only support formats where all components have the same size for now. + * Let's just use the first component size for calculation. + */ + unsigned uncompressed_rate = + util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0); + + AFRC_BLOCK_SIZES(block_sizes); + + for (unsigned i = 0; i < ARRAY_SIZE(block_sizes); ++i) { + unsigned clump_sz = block_sizes[i].size * 8; + unsigned rate = clump_sz / clump_comps; + + if (rate >= uncompressed_rate) + continue; + + if (nr_rates < max) + rates[nr_rates] = rate; + nr_rates++; + + if (max > 0 && nr_rates == max) + break; + } + + return nr_rates; +} + +static inline unsigned +pan_afrc_get_modifiers(enum pipe_format format, uint32_t rate, unsigned max, + uint64_t *modifiers) +{ + if (!pan_format_supports_afrc(format)) + return 0; + + /* For now, the number of components in a clump is always the same no + * matter the layout for all supported formats */ + unsigned clump_comps = pan_afrc_clump_get_nr_components(format, false); + unsigned count = 0; + + /* FIXME Choose a more sensitive default compression rate? */ + if (rate == PAN_AFRC_RATE_DEFAULT) { + if (max > 0) + modifiers[0] = DRM_FORMAT_MOD_ARM_AFRC(AFRC_FORMAT_MOD_CU_SIZE_24); + + if (max > 1) + modifiers[1] = DRM_FORMAT_MOD_ARM_AFRC(AFRC_FORMAT_MOD_CU_SIZE_24 | + AFRC_FORMAT_MOD_LAYOUT_SCAN); + + return 2; + } + + AFRC_BLOCK_SIZES(block_sizes); + for (unsigned i = 0; i < ARRAY_SIZE(block_sizes); ++i) { + unsigned clump_sz = block_sizes[i].size * 8; + if (rate == clump_sz / clump_comps) { + for (unsigned scan = 0; scan < 2; ++scan) { + if (count < max) { + modifiers[count] = DRM_FORMAT_MOD_ARM_AFRC( + block_sizes[i].modifier_flag | + (scan ? AFRC_FORMAT_MOD_LAYOUT_SCAN : 0)); + } + count++; + } + } + } + + return count; +} + +static inline unsigned +pan_afrc_block_size_from_modifier(uint64_t modifier) +{ + switch (modifier & AFRC_FORMAT_MOD_CU_SIZE_MASK) { + case AFRC_FORMAT_MOD_CU_SIZE_16: + return 16; + case AFRC_FORMAT_MOD_CU_SIZE_24: + return 24; + case AFRC_FORMAT_MOD_CU_SIZE_32: + return 32; + default: + unreachable("invalid coding unit size flag in modifier"); + }; +} + +static inline uint32_t +pan_afrc_get_rate(enum pipe_format format, uint64_t modifier) +{ + if (!drm_is_afrc(modifier) || !pan_format_supports_afrc(format)) + return PAN_AFRC_RATE_NONE; + + bool scan = pan_afrc_is_scan(modifier); + unsigned block_comps = pan_afrc_clump_get_nr_components(format, scan); + uint32_t block_sz = pan_afrc_block_size_from_modifier(modifier) * 8; + + return block_sz / block_comps; +} + +static inline struct pan_block_size +pan_afrc_layout_size(uint64_t modifier) +{ + if (pan_afrc_is_scan(modifier)) + return (struct pan_block_size){16, 4}; + else + return (struct pan_block_size){8, 8}; +} + +static inline struct pan_block_size +pan_afrc_tile_size(enum pipe_format format, uint64_t modifier) +{ + bool scan = pan_afrc_is_scan(modifier); + struct pan_block_size clump_sz = pan_afrc_clump_size(format, scan); + struct pan_block_size layout_sz = pan_afrc_layout_size(modifier); + + return (struct pan_block_size){clump_sz.width * layout_sz.width, + clump_sz.height * layout_sz.height}; +} + +static inline unsigned +pan_afrc_buffer_alignment_from_modifier(uint64_t modifier) +{ + switch (modifier & AFRC_FORMAT_MOD_CU_SIZE_MASK) { + case AFRC_FORMAT_MOD_CU_SIZE_16: + return 1024; + case AFRC_FORMAT_MOD_CU_SIZE_24: + return 512; + case AFRC_FORMAT_MOD_CU_SIZE_32: + return 2048; + default: + unreachable("invalid coding unit size flag in modifier"); + }; +} + +/* + * Determine the number of bytes between rows of paging tiles in an AFRC image + */ +static inline uint32_t +pan_afrc_row_stride(enum pipe_format format, uint64_t modifier, uint32_t width) +{ + struct pan_block_size tile_size = pan_afrc_tile_size(format, modifier); + unsigned block_size = pan_afrc_block_size_from_modifier(modifier); + + return (width / tile_size.width) * block_size * AFRC_CLUMPS_PER_TILE; +} + +#if PAN_ARCH >= 10 +static inline enum mali_afrc_format +pan_afrc_format(struct pan_afrc_format_info info, uint64_t modifier, + unsigned plane) +{ + bool scan = pan_afrc_is_scan(modifier); + + assert(info.bpc == 8 || info.bpc == 10); + assert(info.num_comps > 0 && info.num_comps <= 4); + + switch (info.ichange_fmt) { + case PAN_AFRC_ICHANGE_FORMAT_RAW: + assert(plane == 0); + + if (info.bpc == 8) + return (scan ? MALI_AFRC_FORMAT_R8_SCAN : MALI_AFRC_FORMAT_R8_ROT) + + (info.num_comps - 1); + + assert(info.num_comps == 4); + return (scan ? MALI_AFRC_FORMAT_R10G10B10A10_SCAN + : MALI_AFRC_FORMAT_R10G10B10A10_ROT); + + case PAN_AFRC_ICHANGE_FORMAT_YUV444: + if (info.bpc == 8) { + if (plane == 0 || info.num_planes == 3) + return (scan ? MALI_AFRC_FORMAT_R8_444_SCAN + : MALI_AFRC_FORMAT_R8_444_ROT); + + return (scan ? MALI_AFRC_FORMAT_R8G8_444_SCAN + : MALI_AFRC_FORMAT_R8G8_444_ROT); + } + + assert(info.num_planes == 3); + return (scan ? MALI_AFRC_FORMAT_R10_444_SCAN + : MALI_AFRC_FORMAT_R10_444_ROT); + + case PAN_AFRC_ICHANGE_FORMAT_YUV422: + if (info.bpc == 8) { + if (plane == 0 || info.num_planes == 3) + return (scan ? MALI_AFRC_FORMAT_R8_422_SCAN + : MALI_AFRC_FORMAT_R8_422_ROT); + + return (scan ? MALI_AFRC_FORMAT_R8G8_422_SCAN + : MALI_AFRC_FORMAT_R8G8_422_ROT); + } + + if (plane == 0 || info.num_planes == 3) + return (scan ? MALI_AFRC_FORMAT_R10_422_SCAN + : MALI_AFRC_FORMAT_R10_422_ROT); + + return (scan ? MALI_AFRC_FORMAT_R10G10_422_SCAN + : MALI_AFRC_FORMAT_R10G10_422_ROT); + + case PAN_AFRC_ICHANGE_FORMAT_YUV420: + if (info.bpc == 8) { + if (plane == 0 || info.num_planes == 3) + return (scan ? MALI_AFRC_FORMAT_R8_420_SCAN + : MALI_AFRC_FORMAT_R8_420_ROT); + + return (scan ? MALI_AFRC_FORMAT_R8G8_420_SCAN + : MALI_AFRC_FORMAT_R8G8_420_ROT); + } + + if (plane == 0 || info.num_planes == 3) + return (scan ? MALI_AFRC_FORMAT_R10_420_SCAN + : MALI_AFRC_FORMAT_R10_420_ROT); + + return (scan ? MALI_AFRC_FORMAT_R10G10_420_SCAN + : MALI_AFRC_FORMAT_R10G10_420_ROT); + + default: + return MALI_AFRC_FORMAT_INVALID; + } +} + +static inline enum mali_afrc_block_size +pan_afrc_block_size(uint64_t modifier, unsigned index) +{ + /* Clump size flag for planes 1 and 2 is shifted by 4 bits */ + unsigned shift = index == 0 ? 0 : 4; + uint64_t flag = (modifier >> shift) & AFRC_FORMAT_MOD_CU_SIZE_MASK; + + switch (flag) { + case AFRC_FORMAT_MOD_CU_SIZE_16: + return MALI_AFRC_BLOCK_SIZE_16; + case AFRC_FORMAT_MOD_CU_SIZE_24: + return MALI_AFRC_BLOCK_SIZE_24; + case AFRC_FORMAT_MOD_CU_SIZE_32: + return MALI_AFRC_BLOCK_SIZE_32; + default: + unreachable("invalid code unit size"); + } +} +#endif + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index c205f47aee5..84f3cf624dc 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -30,6 +30,7 @@ #include "genxml/gen_macros.h" #include "pan_afbc.h" +#include "pan_afrc.h" #include "pan_desc.h" #include "pan_encoder.h" #include "pan_props.h" @@ -650,13 +651,11 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx, #if PAN_ARCH >= 10 } else if (drm_is_afrc(image->layout.modifier)) { struct pan_afrc_format_info finfo = - panfrost_afrc_get_format_info(image->layout.format); + pan_afrc_get_format_info(image->layout.format); cfg->writeback_mode = MALI_WRITEBACK_MODE_AFRC_RGB; - cfg->afrc.block_size = - GENX(pan_afrc_block_size)(image->layout.modifier, 0); - cfg->afrc.format = - GENX(pan_afrc_format)(finfo, image->layout.modifier, 0); + cfg->afrc.block_size = pan_afrc_block_size(image->layout.modifier, 0); + cfg->afrc.format = pan_afrc_format(finfo, image->layout.modifier, 0); cfg->rgb.base = surf.data; cfg->rgb.row_stride = row_stride; diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index b399ea9baa1..90bd0175b91 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -27,101 +27,10 @@ #include "util/macros.h" #include "util/u_math.h" #include "pan_afbc.h" +#include "pan_afrc.h" #include "pan_props.h" #include "pan_texture.h" -/* - * Given an AFRC modifier, return whether the layout is optimized for scan - * order (vs rotation order). - */ -bool -panfrost_afrc_is_scan(uint64_t modifier) -{ - return modifier & AFRC_FORMAT_MOD_LAYOUT_SCAN; -} - -struct pan_block_size -panfrost_afrc_clump_size(enum pipe_format format, bool scan) -{ - struct pan_afrc_format_info finfo = panfrost_afrc_get_format_info(format); - - switch (finfo.num_comps) { - case 1: - return scan ? (struct pan_block_size){16, 4} - : (struct pan_block_size){8, 8}; - case 2: - return (struct pan_block_size){8, 4}; - case 3: - case 4: - return (struct pan_block_size){4, 4}; - default: - assert(0); - return (struct pan_block_size){0, 0}; - } -} - -static struct pan_block_size -panfrost_afrc_layout_size(uint64_t modifier) -{ - if (panfrost_afrc_is_scan(modifier)) - return (struct pan_block_size){16, 4}; - else - return (struct pan_block_size){8, 8}; -} - -struct pan_block_size -panfrost_afrc_tile_size(enum pipe_format format, uint64_t modifier) -{ - bool scan = panfrost_afrc_is_scan(modifier); - struct pan_block_size clump_sz = panfrost_afrc_clump_size(format, scan); - struct pan_block_size layout_sz = panfrost_afrc_layout_size(modifier); - - return (struct pan_block_size){clump_sz.width * layout_sz.width, - clump_sz.height * layout_sz.height}; -} - -unsigned -panfrost_afrc_block_size_from_modifier(uint64_t modifier) -{ - switch (modifier & AFRC_FORMAT_MOD_CU_SIZE_MASK) { - case AFRC_FORMAT_MOD_CU_SIZE_16: - return 16; - case AFRC_FORMAT_MOD_CU_SIZE_24: - return 24; - case AFRC_FORMAT_MOD_CU_SIZE_32: - return 32; - default: - unreachable("invalid coding unit size flag in modifier"); - }; -} - -static unsigned -panfrost_afrc_buffer_alignment_from_modifier(uint64_t modifier) -{ - switch (modifier & AFRC_FORMAT_MOD_CU_SIZE_MASK) { - case AFRC_FORMAT_MOD_CU_SIZE_16: - return 1024; - case AFRC_FORMAT_MOD_CU_SIZE_24: - return 512; - case AFRC_FORMAT_MOD_CU_SIZE_32: - return 2048; - default: - unreachable("invalid coding unit size flag in modifier"); - }; -} - -/* - * Determine the number of bytes between rows of paging tiles in an AFRC image - */ -uint32_t -pan_afrc_row_stride(enum pipe_format format, uint64_t modifier, uint32_t width) -{ - struct pan_block_size tile_size = panfrost_afrc_tile_size(format, modifier); - unsigned block_size = panfrost_afrc_block_size_from_modifier(modifier); - - return (width / tile_size.width) * block_size * AFRC_CLUMPS_PER_TILE; -} - /* * Given a format, determine the tile size used for u-interleaving. For formats * that are already block compressed, this is 4x4. For all other formats, this @@ -149,7 +58,7 @@ panfrost_block_size(uint64_t modifier, enum pipe_format format) else if (drm_is_afbc(modifier)) return pan_afbc_superblock_size(modifier); else if (drm_is_afrc(modifier)) - return panfrost_afrc_tile_size(format, modifier); + return pan_afrc_tile_size(format, modifier); else return (struct pan_block_size){1, 1}; } @@ -183,7 +92,7 @@ format_minimum_alignment(unsigned arch, enum pipe_format format, uint64_t mod) return 16; if (drm_is_afrc(mod)) - return panfrost_afrc_buffer_alignment_from_modifier(mod); + return pan_afrc_buffer_alignment_from_modifier(mod); if (arch < 7) return 64; @@ -267,7 +176,7 @@ panfrost_get_legacy_stride(const struct pan_image_layout *layout, return width * util_format_get_blocksize(layout->format); } else if (drm_is_afrc(layout->modifier)) { struct pan_block_size tile_size = - panfrost_afrc_tile_size(layout->format, layout->modifier); + pan_afrc_tile_size(layout->format, layout->modifier); return row_stride / tile_size.height; } else { @@ -288,7 +197,7 @@ panfrost_from_legacy_stride(unsigned legacy_stride, enum pipe_format format, return pan_afbc_row_stride(modifier, width); } else if (drm_is_afrc(modifier)) { struct pan_block_size tile_size = - panfrost_afrc_tile_size(format, modifier); + pan_afrc_tile_size(format, modifier); return legacy_stride * tile_size.height; } else { diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index cecb0777419..30ee0106a73 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -27,6 +27,7 @@ */ #include "pan_afbc.h" +#include "pan_afrc.h" #include "pan_texture.h" #include "util/macros.h" #include "util/u_math.h" @@ -526,13 +527,13 @@ panfrost_emit_plane(const struct pan_image_view *iview, } else if (afrc) { #if PAN_ARCH >= 10 struct pan_afrc_format_info finfo = - panfrost_afrc_get_format_info(iview->format); + pan_afrc_get_format_info(iview->format); cfg.plane_type = MALI_PLANE_TYPE_AFRC; cfg.afrc.block_size = - GENX(pan_afrc_block_size)(layout->modifier, plane_index); + pan_afrc_block_size(layout->modifier, plane_index); cfg.afrc.format = - GENX(pan_afrc_format)(finfo, layout->modifier, plane_index); + pan_afrc_format(finfo, layout->modifier, plane_index); #endif } else { cfg.plane_type = @@ -906,96 +907,3 @@ GENX(panfrost_new_storage_texture)(const struct pan_image_view *iview, } } #endif - -#if PAN_ARCH >= 10 -enum mali_afrc_format -GENX(pan_afrc_format)(struct pan_afrc_format_info info, uint64_t modifier, - unsigned plane) -{ - bool scan = panfrost_afrc_is_scan(modifier); - - assert(info.bpc == 8 || info.bpc == 10); - assert(info.num_comps > 0 && info.num_comps <= 4); - - switch (info.ichange_fmt) { - case PAN_AFRC_ICHANGE_FORMAT_RAW: - assert(plane == 0); - - if (info.bpc == 8) - return (scan ? MALI_AFRC_FORMAT_R8_SCAN : MALI_AFRC_FORMAT_R8_ROT) + - (info.num_comps - 1); - - assert(info.num_comps == 4); - return (scan ? MALI_AFRC_FORMAT_R10G10B10A10_SCAN - : MALI_AFRC_FORMAT_R10G10B10A10_ROT); - - case PAN_AFRC_ICHANGE_FORMAT_YUV444: - if (info.bpc == 8) { - if (plane == 0 || info.num_planes == 3) - return (scan ? MALI_AFRC_FORMAT_R8_444_SCAN - : MALI_AFRC_FORMAT_R8_444_ROT); - - return (scan ? MALI_AFRC_FORMAT_R8G8_444_SCAN - : MALI_AFRC_FORMAT_R8G8_444_ROT); - } - - assert(info.num_planes == 3); - return (scan ? MALI_AFRC_FORMAT_R10_444_SCAN - : MALI_AFRC_FORMAT_R10_444_ROT); - - case PAN_AFRC_ICHANGE_FORMAT_YUV422: - if (info.bpc == 8) { - if (plane == 0 || info.num_planes == 3) - return (scan ? MALI_AFRC_FORMAT_R8_422_SCAN - : MALI_AFRC_FORMAT_R8_422_ROT); - - return (scan ? MALI_AFRC_FORMAT_R8G8_422_SCAN - : MALI_AFRC_FORMAT_R8G8_422_ROT); - } - - if (plane == 0 || info.num_planes == 3) - return (scan ? MALI_AFRC_FORMAT_R10_422_SCAN - : MALI_AFRC_FORMAT_R10_422_ROT); - - return (scan ? MALI_AFRC_FORMAT_R10G10_422_SCAN - : MALI_AFRC_FORMAT_R10G10_422_ROT); - - case PAN_AFRC_ICHANGE_FORMAT_YUV420: - if (info.bpc == 8) { - if (plane == 0 || info.num_planes == 3) - return (scan ? MALI_AFRC_FORMAT_R8_420_SCAN - : MALI_AFRC_FORMAT_R8_420_ROT); - - return (scan ? MALI_AFRC_FORMAT_R8G8_420_SCAN - : MALI_AFRC_FORMAT_R8G8_420_ROT); - } - - if (plane == 0 || info.num_planes == 3) - return (scan ? MALI_AFRC_FORMAT_R10_420_SCAN - : MALI_AFRC_FORMAT_R10_420_ROT); - - return (scan ? MALI_AFRC_FORMAT_R10G10_420_SCAN - : MALI_AFRC_FORMAT_R10G10_420_ROT); - - default: - return MALI_AFRC_FORMAT_INVALID; - } -} - -enum mali_afrc_block_size -GENX(pan_afrc_block_size)(uint64_t modifier, unsigned index) -{ - /* Clump size flag for planes 1 and 2 is shifted by 4 bits */ - unsigned shift = index == 0 ? 0 : 4; - uint64_t flag = (modifier >> shift) & AFRC_FORMAT_MOD_CU_SIZE_MASK; - - /* clang-format off */ - switch (flag) { - case AFRC_FORMAT_MOD_CU_SIZE_16: return MALI_AFRC_BLOCK_SIZE_16; - case AFRC_FORMAT_MOD_CU_SIZE_24: return MALI_AFRC_BLOCK_SIZE_24; - case AFRC_FORMAT_MOD_CU_SIZE_32: return MALI_AFRC_BLOCK_SIZE_32; - default: unreachable("invalid code unit size"); - } - /* clang-format on */ -} -#endif diff --git a/src/panfrost/lib/pan_texture.h b/src/panfrost/lib/pan_texture.h index b7d3cb3aaf2..3911619f552 100644 --- a/src/panfrost/lib/pan_texture.h +++ b/src/panfrost/lib/pan_texture.h @@ -267,67 +267,6 @@ struct pan_block_size { uint32_t pan_slice_align(uint64_t modifier); -/* AFRC */ - -#define AFRC_CLUMPS_PER_TILE 64 - -enum pan_afrc_rate { - PAN_AFRC_RATE_NONE, - PAN_AFRC_RATE_1BPC, - PAN_AFRC_RATE_2BPC, - PAN_AFRC_RATE_3BPC, - PAN_AFRC_RATE_4BPC, - PAN_AFRC_RATE_5BPC, - PAN_AFRC_RATE_6BPC, - PAN_AFRC_RATE_7BPC, - PAN_AFRC_RATE_8BPC, - PAN_AFRC_RATE_9BPC, - PAN_AFRC_RATE_10BPC, - PAN_AFRC_RATE_11BPC, - PAN_AFRC_RATE_12BPC, - PAN_AFRC_RATE_DEFAULT = 0xF -}; - -enum pan_afrc_interchange_format { - PAN_AFRC_ICHANGE_FORMAT_RAW, - PAN_AFRC_ICHANGE_FORMAT_YUV444, - PAN_AFRC_ICHANGE_FORMAT_YUV422, - PAN_AFRC_ICHANGE_FORMAT_YUV420, -}; - -struct pan_afrc_format_info { - unsigned bpc : 4; - unsigned num_comps : 3; - unsigned ichange_fmt : 2; - unsigned num_planes : 2; -}; - -struct pan_afrc_format_info -panfrost_afrc_get_format_info(enum pipe_format format); - -bool panfrost_format_supports_afrc(enum pipe_format format); - -bool panfrost_afrc_is_scan(uint64_t modifier); - -struct pan_block_size panfrost_afrc_clump_size(enum pipe_format format, - bool scan); - -struct pan_block_size panfrost_afrc_tile_size(enum pipe_format format, - uint64_t modifier); - -unsigned panfrost_afrc_block_size_from_modifier(uint64_t modifier); - -unsigned pan_afrc_row_stride(enum pipe_format format, uint64_t modifier, - uint32_t width); - -unsigned panfrost_afrc_query_rates(enum pipe_format format, unsigned max, - uint32_t *rates); - -unsigned panfrost_afrc_get_modifiers(enum pipe_format format, uint32_t rate, - unsigned max, uint64_t *modifiers); - -uint32_t panfrost_afrc_get_rate(enum pipe_format format, uint64_t modifier); - struct pan_block_size panfrost_block_size(uint64_t modifier, enum pipe_format format); @@ -394,14 +333,6 @@ void pan_iview_get_surface(const struct pan_image_view *iview, unsigned level, unsigned layer, unsigned sample, struct pan_surface *surf); -#if PAN_ARCH >= 10 -enum mali_afrc_format -GENX(pan_afrc_format)(struct pan_afrc_format_info info, uint64_t modifier, - unsigned plane); -enum mali_afrc_block_size GENX(pan_afrc_block_size)(uint64_t modifier, - unsigned index); -#endif - #ifdef __cplusplus } /* extern C */ #endif