diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 80f92e74813..edd9b6aabd5 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -42,6 +42,7 @@ #include "genxml/gen_macros.h" +#include "pan_afbc.h" #include "pan_mod_conv_cso.h" #include "pan_blend.h" #include "pan_bo.h" @@ -177,7 +178,7 @@ static void pan_afbc_reswizzle_border_color(const struct pipe_sampler_state *cso, struct panfrost_sampler_state *so) { - if (!panfrost_format_supports_afbc(PAN_ARCH, cso->border_color_format)) + if (!pan_format_supports_afbc(PAN_ARCH, cso->border_color_format)) return; /* On v7, pan_texture.c composes the API swizzle with a bijective @@ -1771,7 +1772,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so, /* v7 requires AFBC reswizzle */ if (!util_format_is_depth_or_stencil(format) && !panfrost_format_is_yuv(format) && - panfrost_format_supports_afbc(PAN_ARCH, format)) + pan_format_supports_afbc(PAN_ARCH, format)) GENX(panfrost_texture_afbc_reswizzle)(&iview); #endif diff --git a/src/gallium/drivers/panfrost/pan_fb_preload.c b/src/gallium/drivers/panfrost/pan_fb_preload.c index 418b4a6178f..f98e2b55f4f 100644 --- a/src/gallium/drivers/panfrost/pan_fb_preload.c +++ b/src/gallium/drivers/panfrost/pan_fb_preload.c @@ -29,6 +29,7 @@ #include #include "compiler/nir/nir_builder.h" #include "util/u_math.h" +#include "pan_afbc.h" #include "pan_blend_cso.h" #include "pan_desc.h" #include "pan_encoder.h" @@ -920,7 +921,7 @@ pan_preload_emit_textures(struct pan_pool *pool, const struct pan_fb_info *fb, #if PAN_ARCH == 7 /* v7 requires AFBC reswizzle. */ if (!panfrost_format_is_yuv(view->format) && - panfrost_format_supports_afbc(PAN_ARCH, view->format)) { + pan_format_supports_afbc(PAN_ARCH, view->format)) { struct pan_image_view *pview = &patched_views[patched_count++]; *pview = *view; GENX(panfrost_texture_afbc_reswizzle)(pview); diff --git a/src/gallium/drivers/panfrost/pan_mod_conv_cso.c b/src/gallium/drivers/panfrost/pan_mod_conv_cso.c index b48ce9edfc1..3fa3bc913d7 100644 --- a/src/gallium/drivers/panfrost/pan_mod_conv_cso.c +++ b/src/gallium/drivers/panfrost/pan_mod_conv_cso.c @@ -24,6 +24,7 @@ #include "pan_mod_conv_cso.h" #include "nir/pipe_nir.h" #include "nir_builder.h" +#include "pan_afbc.h" #include "pan_context.h" #include "pan_resource.h" #include "pan_screen.h" diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 943341901ca..b9be8407bf6 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -49,6 +49,7 @@ #include "util/streaming-load-memcpy.h" #include "decode.h" +#include "pan_afbc.h" #include "pan_bo.h" #include "pan_context.h" #include "pan_resource.h" @@ -324,7 +325,7 @@ panfrost_should_afbc(struct panfrost_device *dev, return false; /* Only a small selection of formats are AFBC'able */ - if (!panfrost_format_supports_afbc(dev->arch, fmt)) + if (!pan_format_supports_afbc(dev->arch, fmt)) return false; /* AFBC does not support layered (GLES3 style) multisampling. Use @@ -370,7 +371,7 @@ static bool panfrost_should_tile_afbc(const struct panfrost_device *dev, const struct panfrost_resource *pres) { - return panfrost_afbc_can_tile(dev->arch) && pres->base.width0 >= 128 && + return pan_afbc_can_tile(dev->arch) && pres->base.width0 >= 128 && pres->base.height0 >= 128 && !(dev->debug & PAN_DBG_FORCE_PACK); } @@ -382,7 +383,7 @@ panfrost_should_pack_afbc(struct panfrost_device *dev, PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - return panfrost_afbc_can_pack(prsrc->base.format) && panfrost_is_2d(prsrc) && + return pan_afbc_can_pack(prsrc->base.format) && panfrost_is_2d(prsrc) && drm_is_afbc(prsrc->image.layout.modifier) && (prsrc->image.layout.modifier & AFBC_FORMAT_MOD_SPARSE) && !(prsrc->image.layout.modifier & AFBC_FORMAT_MOD_SPLIT) && @@ -503,7 +504,7 @@ panfrost_best_modifier(struct pipe_screen *pscreen, if (panfrost_should_afbc(dev, pres, fmt)) { uint64_t afbc = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE; - if (panfrost_afbc_can_ytr(pres->base.format)) + if (pan_afbc_can_ytr(pres->base.format)) afbc |= AFBC_FORMAT_MOD_YTR; if (panfrost_should_tile_afbc(dev, pres)) @@ -1083,7 +1084,7 @@ dump_block(struct panfrost_resource *rsrc, uint32_t idx) uint32_t body_base_ptr = header[0]; uint32_t *body = (uint32_t *)(ptr + body_base_ptr); struct pan_block_size block_sz = - panfrost_afbc_subblock_size(rsrc->image.layout.modifier); + pan_afbc_subblock_size(rsrc->image.layout.modifier); unsigned pixel_sz = util_format_get_blocksize(rsrc->base.format); unsigned uncompressed_size = pixel_sz * block_sz.width * block_sz.height; unsigned size = get_superblock_size(header, uncompressed_size); @@ -1587,8 +1588,8 @@ pan_legalize_format(struct panfrost_context *ctx, return; if (drm_is_afbc(rsrc->image.layout.modifier)) { - compatible = (panfrost_afbc_format(dev->arch, old_format) == - panfrost_afbc_format(dev->arch, new_format)); + compatible = (pan_afbc_format(dev->arch, old_format) == + 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); @@ -1734,6 +1735,7 @@ panfrost_pack_afbc(struct panfrost_context *ctx, struct pan_image_slice_layout *dst_slice = &slice_infos[level]; unsigned src_stride = pan_afbc_stride_blocks(src_modifier, src_slice->row_stride); + uint32_t offset = 0; struct pan_afbc_block_info *meta = metadata_bo->ptr.cpu + metadata_offsets[level]; @@ -1772,9 +1774,9 @@ panfrost_pack_afbc(struct panfrost_context *ctx, unsigned width = u_minify(prsrc->base.width0, level); unsigned height = u_minify(prsrc->base.height0, level); unsigned dst_stride = - DIV_ROUND_UP(width, panfrost_afbc_superblock_width(dst_modifier)); + DIV_ROUND_UP(width, pan_afbc_superblock_width(dst_modifier)); unsigned dst_height = - DIV_ROUND_UP(height, panfrost_afbc_superblock_height(dst_modifier)); + DIV_ROUND_UP(height, pan_afbc_superblock_height(dst_modifier)); dst_slice->afbc.stride = dst_stride; dst_slice->afbc.nr_blocks = dst_stride * dst_height; diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index 173a36f5d07..b60711bda98 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -46,6 +46,7 @@ #include "drm-uapi/panfrost_drm.h" #include "decode.h" +#include "pan_afbc.h" #include "pan_bo.h" #include "pan_fence.h" #include "pan_public.h" @@ -248,9 +249,9 @@ panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen, /* Query AFBC status */ struct panfrost_device *dev = pan_device(screen); bool afbc = - dev->has_afbc && panfrost_format_supports_afbc(dev->arch, format); - bool ytr = panfrost_afbc_can_ytr(format); - bool tiled_afbc = panfrost_afbc_can_tile(dev->arch); + 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); PAN_SUPPORTED_MODIFIERS(supported_mods); @@ -262,7 +263,7 @@ panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen, continue; if ((supported_mods[i] & AFBC_FORMAT_MOD_SPLIT) && - !panfrost_afbc_can_split(dev->arch, format, supported_mods[i])) + !pan_afbc_can_split(dev->arch, format, supported_mods[i])) continue; if ((supported_mods[i] & AFBC_FORMAT_MOD_YTR) && !ytr) diff --git a/src/panfrost/lib/meson.build b/src/panfrost/lib/meson.build index 5bbd42e8002..a817d8de630 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_afbc.c', 'pan_afrc.c', 'pan_attributes.c', 'pan_blend.c', diff --git a/src/panfrost/lib/pan_afbc.c b/src/panfrost/lib/pan_afbc.c deleted file mode 100644 index d9c3b69c6c2..00000000000 --- a/src/panfrost/lib/pan_afbc.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2019 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: - * Alyssa Rosenzweig - */ - -#include "pan_texture.h" - -/* Arm FrameBuffer Compression (AFBC) is a lossless compression scheme natively - * implemented in Mali GPUs (as well as many display controllers paired with - * Mali GPUs, etc). Where possible, Panfrost prefers to use AFBC for both - * rendering and texturing. In most cases, this is a performance-win due to a - * dramatic reduction in memory bandwidth and cache locality compared to a - * linear resources. - * - * AFBC divides the framebuffer into 16x16 tiles (other sizes possible, TODO: - * do we need to support this?). So, the width and height each must be aligned - * up to 16 pixels. This is inherently good for performance; note that for a 4 - * byte-per-pixel format like RGBA8888, that means that rows are 16*4=64 byte - * aligned, which is the cache-line size. - * - * For each AFBC-compressed resource, there is a single contiguous - * (CPU/GPU-shared) buffer. This buffer itself is divided into two parts: - * header and body, placed immediately after each other. - * - * The AFBC header contains 16 bytes of metadata per tile. - * - * The AFBC body is the same size as the original linear resource (padded to - * the nearest tile). Although the body comes immediately after the header, it - * must also be cache-line aligned, so there can sometimes be a bit of padding - * between the header and body. - * - * As an example, a 64x64 RGBA framebuffer contains 64/16 = 4 tiles horizontally - * and 4 tiles vertically. There are 4*4=16 tiles in total, each containing 16 - * bytes of metadata, so there is a 16*16=256 byte header. 64x64 is already - * tile aligned, so the body is 64*64 * 4 bytes per pixel = 16384 bytes of - * body. - * - * From userspace, Panfrost needs to be able to calculate these sizes. It - * explicitly does not and can not know the format of the data contained within - * this header and body. The GPU has native support for AFBC encode/decode. For - * an internal FBO or a framebuffer used for scanout with an AFBC-compatible - * winsys/display-controller, the buffer is maintained AFBC throughout flight, - * and the driver never needs to know the internal data. For edge cases where - * the driver really does need to read/write from the AFBC resource, we - * generate a linear staging buffer and use the GPU to blit AFBC<--->linear. - */ - -static enum pipe_format -unswizzled_format(unsigned arch, enum pipe_format format) -{ - switch (format) { - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - return PIPE_FORMAT_R8_UNORM; - - case PIPE_FORMAT_L8A8_UNORM: - return PIPE_FORMAT_R8G8_UNORM; - - case PIPE_FORMAT_B8G8R8_UNORM: - return PIPE_FORMAT_R8G8B8_UNORM; - - case PIPE_FORMAT_R8G8B8X8_UNORM: - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - return PIPE_FORMAT_R8G8B8A8_UNORM; - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_X8B8G8R8_UNORM: - case PIPE_FORMAT_A8B8G8R8_UNORM: - /* v7 can only support AFBC for RGB and BGR */ - return arch == 7 ? format : PIPE_FORMAT_R8G8B8A8_UNORM; - - case PIPE_FORMAT_B5G6R5_UNORM: - return PIPE_FORMAT_R5G6B5_UNORM; - - case PIPE_FORMAT_B5G5R5A1_UNORM: - return PIPE_FORMAT_R5G5B5A1_UNORM; - - case PIPE_FORMAT_R10G10B10X2_UNORM: - case PIPE_FORMAT_B10G10R10A2_UNORM: - case PIPE_FORMAT_B10G10R10X2_UNORM: - return PIPE_FORMAT_R10G10B10A2_UNORM; - - case PIPE_FORMAT_B4G4R4A4_UNORM: - return PIPE_FORMAT_R4G4B4A4_UNORM; - case PIPE_FORMAT_A4B4G4R4_UNORM: - /* v7 can only support AFBC for RGB and BGR */ - return arch == 7 ? format : PIPE_FORMAT_R4G4B4A4_UNORM; - - default: - return format; - } -} - -/* AFBC supports compressing a few canonical formats. Additional formats are - * available by using a canonical internal format. Given a PIPE format, find - * the canonical AFBC internal format if it exists, or NONE if the format - * cannot be compressed. */ - -enum pan_afbc_mode -panfrost_afbc_format(unsigned arch, enum pipe_format format) -{ - /* sRGB does not change the pixel format itself, only the - * interpretation. The interpretation is handled by conversion hardware - * independent to the compression hardware, so we can compress sRGB - * formats by using the corresponding linear format. - */ - format = util_format_linear(format); - - /* Luminance-alpha not supported for AFBC on v7+ */ - switch (format) { - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - if (arch >= 7) - return PAN_AFBC_MODE_INVALID; - else - break; - default: - break; - } - - /* We handle swizzling orthogonally to AFBC */ - format = unswizzled_format(arch, format); - - /* clang-format off */ - switch (format) { - case PIPE_FORMAT_R8_UNORM: return PAN_AFBC_MODE_R8; - case PIPE_FORMAT_R8G8_UNORM: return PAN_AFBC_MODE_R8G8; - case PIPE_FORMAT_R8G8B8_UNORM: return PAN_AFBC_MODE_R8G8B8; - case PIPE_FORMAT_R8G8B8A8_UNORM: return PAN_AFBC_MODE_R8G8B8A8; - case PIPE_FORMAT_R5G6B5_UNORM: return PAN_AFBC_MODE_R5G6B5; - case PIPE_FORMAT_R5G5B5A1_UNORM: return PAN_AFBC_MODE_R5G5B5A1; - case PIPE_FORMAT_R10G10B10A2_UNORM: return PAN_AFBC_MODE_R10G10B10A2; - case PIPE_FORMAT_R4G4B4A4_UNORM: return PAN_AFBC_MODE_R4G4B4A4; - case PIPE_FORMAT_Z16_UNORM: return PAN_AFBC_MODE_R8G8; - - case PIPE_FORMAT_Z24_UNORM_S8_UINT: return PAN_AFBC_MODE_R8G8B8A8; - case PIPE_FORMAT_Z24X8_UNORM: return PAN_AFBC_MODE_R8G8B8A8; - case PIPE_FORMAT_X24S8_UINT: return PAN_AFBC_MODE_R8G8B8A8; - - default: return PAN_AFBC_MODE_INVALID; - } - /* clang-format on */ -} - -/* The lossless colour transform (AFBC_FORMAT_MOD_YTR) requires RGB. */ - -bool -panfrost_afbc_can_ytr(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - - /* YTR is only defined for RGB(A) */ - if (desc->nr_channels != 3 && desc->nr_channels != 4) - return false; - - /* The fourth channel if it exists doesn't matter */ - return desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB; -} - -bool -panfrost_afbc_can_split(unsigned arch, enum pipe_format format, - uint64_t modifier) -{ - unsigned block_width = panfrost_afbc_superblock_width(modifier); - - if (arch < 6) - return false; - - if (block_width == 16) { - return true; - } else if (block_width == 32) { - enum pan_afbc_mode mode = panfrost_afbc_format(arch, format); - return (mode == PAN_AFBC_MODE_R8G8B8A8 || - mode == PAN_AFBC_MODE_R10G10B10A2); - } - - return false; -} - -/* Only support packing for RGB formats for now. */ - -bool -panfrost_afbc_can_pack(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - - return desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB; -} diff --git a/src/panfrost/lib/pan_afbc.h b/src/panfrost/lib/pan_afbc.h new file mode 100644 index 00000000000..c4763b044a8 --- /dev/null +++ b/src/panfrost/lib/pan_afbc.h @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2008 VMware, Inc. + * Copyright (C) 2014 Broadcom + * Copyright (C) 2018-2019 Alyssa Rosenzweig + * Copyright (C) 2019-2020 Collabora, Ltd. + * + * SPDX-License-Identifier: MIT + * + * Authors: + * Alyssa Rosenzweig + */ + +#ifndef __PAN_AFBC_H +#define __PAN_AFBC_H + +#include "pan_format.h" +#include "pan_texture.h" + +#include "drm-uapi/drm_fourcc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Arm FrameBuffer Compression (AFBC) is a lossless compression scheme natively + * implemented in Mali GPUs (as well as many display controllers paired with + * Mali GPUs, etc). Where possible, Panfrost prefers to use AFBC for both + * rendering and texturing. In most cases, this is a performance-win due to a + * dramatic reduction in memory bandwidth and cache locality compared to a + * linear resources. + * + * AFBC divides the framebuffer into 16x16 tiles (other sizes possible, TODO: + * do we need to support this?). So, the width and height each must be aligned + * up to 16 pixels. This is inherently good for performance; note that for a 4 + * byte-per-pixel format like RGBA8888, that means that rows are 16*4=64 byte + * aligned, which is the cache-line size. + * + * For each AFBC-compressed resource, there is a single contiguous + * (CPU/GPU-shared) buffer. This buffer itself is divided into two parts: + * header and body, placed immediately after each other. + * + * The AFBC header contains 16 bytes of metadata per tile. + * + * The AFBC body is the same size as the original linear resource (padded to + * the nearest tile). Although the body comes immediately after the header, it + * must also be cache-line aligned, so there can sometimes be a bit of padding + * between the header and body. + * + * As an example, a 64x64 RGBA framebuffer contains 64/16 = 4 tiles horizontally + * and 4 tiles vertically. There are 4*4=16 tiles in total, each containing 16 + * bytes of metadata, so there is a 16*16=256 byte header. 64x64 is already + * tile aligned, so the body is 64*64 * 4 bytes per pixel = 16384 bytes of + * body. + * + * From userspace, Panfrost needs to be able to calculate these sizes. It + * explicitly does not and can not know the format of the data contained within + * this header and body. The GPU has native support for AFBC encode/decode. For + * an internal FBO or a framebuffer used for scanout with an AFBC-compatible + * winsys/display-controller, the buffer is maintained AFBC throughout flight, + * and the driver never needs to know the internal data. For edge cases where + * the driver really does need to read/write from the AFBC resource, we + * generate a linear staging buffer and use the GPU to blit AFBC<--->linear. + */ + +#define AFBC_HEADER_BYTES_PER_TILE 16 + +/* AFBC format mode. The ordering is intended to match the Valhall hardware enum + * ("AFBC Compression Mode"), but this enum is required in software on older + * hardware for correct handling of texture views. Defining the enum lets us + * unify these code paths. + */ +enum pan_afbc_mode { + PAN_AFBC_MODE_R8, + PAN_AFBC_MODE_R8G8, + PAN_AFBC_MODE_R5G6B5, + PAN_AFBC_MODE_R4G4B4A4, + PAN_AFBC_MODE_R5G5B5A1, + PAN_AFBC_MODE_R8G8B8, + PAN_AFBC_MODE_R8G8B8A8, + PAN_AFBC_MODE_R10G10B10A2, + PAN_AFBC_MODE_R11G11B10, + PAN_AFBC_MODE_S8, + + /* Sentintel signalling a format that cannot be compressed */ + PAN_AFBC_MODE_INVALID +}; + +/* + * Given an AFBC modifier, return the superblock size. + * + * We do not yet have any use cases for multiplanar YCBCr formats with different + * superblock sizes on the luma and chroma planes. These formats are unsupported + * for now. + */ +static inline struct pan_block_size +pan_afbc_superblock_size(uint64_t modifier) +{ + unsigned index = (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK); + + assert(drm_is_afbc(modifier)); + + switch (index) { + case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: + return (struct pan_block_size){16, 16}; + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: + return (struct pan_block_size){32, 8}; + case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4: + return (struct pan_block_size){64, 4}; + default: + assert(!"Unsupported AFBC block size"); + return (struct pan_block_size){0, 0}; + } +} + +/* + * Given an AFBC modifier, return the render size. + */ +static inline struct pan_block_size +pan_afbc_renderblock_size(uint64_t modifier) +{ + struct pan_block_size blk_size = pan_afbc_superblock_size(modifier); + + /* The GPU needs to render 16x16 tiles. For wide tiles, that means we + * have to extend the render region to have a height of 16 pixels. + */ + blk_size.height = ALIGN_POT(blk_size.height, 16); + return blk_size; +} + +/* + * Given an AFBC modifier, return the width of the superblock. + */ +static inline unsigned +pan_afbc_superblock_width(uint64_t modifier) +{ + return pan_afbc_superblock_size(modifier).width; +} + +/* + * Given an AFBC modifier, return the height of the superblock. + */ +static inline unsigned +pan_afbc_superblock_height(uint64_t modifier) +{ + return pan_afbc_superblock_size(modifier).height; +} + +/* + * Given an AFBC modifier, return if "wide blocks" are used. Wide blocks are + * defined as superblocks wider than 16 pixels, the minimum (and default) super + * block width. + */ +static inline bool +pan_afbc_is_wide(uint64_t modifier) +{ + return pan_afbc_superblock_width(modifier) > 16; +} + +/* + * Given an AFBC modifier, return the subblock size (subdivision of a + * superblock). This is always 4x4 for now as we only support one AFBC + * superblock layout. + */ +static inline struct pan_block_size +pan_afbc_subblock_size(uint64_t modifier) +{ + return (struct pan_block_size){4, 4}; +} + +/* + * Determine the required alignment for the body offset of an AFBC image. For + * now, this depends only on whether tiling is in use. These minimum alignments + * are required on all current GPUs. + */ +static inline uint32_t +pan_afbc_body_align(unsigned arch, uint64_t modifier) +{ + if (modifier & AFBC_FORMAT_MOD_TILED) + return 4096; + + if (arch >= 6) + return 128; + + return 64; +} + +/* + * Determine the tile size used by AFBC. This tiles superblocks themselves. + * Current GPUs support either 8x8 tiling or no tiling (1x1) + */ +static inline unsigned +pan_afbc_tile_size(uint64_t modifier) +{ + return (modifier & AFBC_FORMAT_MOD_TILED) ? 8 : 1; +} + +/* + * Determine the number of bytes between header rows for an AFBC image. For an + * image with linear headers, this is simply the number of header blocks + * (=superblocks) per row times the numbers of bytes per header block. For an + * image with tiled headers, this is multipled by the number of rows of + * header blocks are in a tile together. + */ +static inline uint32_t +pan_afbc_row_stride(uint64_t modifier, uint32_t width) +{ + unsigned block_width = pan_afbc_superblock_width(modifier); + + return (width / block_width) * pan_afbc_tile_size(modifier) * + AFBC_HEADER_BYTES_PER_TILE; +} + +/* + * Determine the number of header blocks between header rows. This is equal to + * the number of bytes between header rows divided by the bytes per blocks of a + * header tile. This is also divided by the tile size to give a "line stride" in + * blocks, rather than a real row stride. This is required by Bifrost. + */ +static inline uint32_t +pan_afbc_stride_blocks(uint64_t modifier, uint32_t row_stride_bytes) +{ + return row_stride_bytes / + (AFBC_HEADER_BYTES_PER_TILE * pan_afbc_tile_size(modifier)); +} + +static inline enum pipe_format +pan_afbc_unswizzled_format(unsigned arch, enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + return PIPE_FORMAT_R8_UNORM; + + case PIPE_FORMAT_L8A8_UNORM: + return PIPE_FORMAT_R8G8_UNORM; + + case PIPE_FORMAT_B8G8R8_UNORM: + return PIPE_FORMAT_R8G8B8_UNORM; + + case PIPE_FORMAT_R8G8B8X8_UNORM: + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_X8B8G8R8_UNORM: + case PIPE_FORMAT_A8B8G8R8_UNORM: + /* v7 can only support AFBC for RGB and BGR */ + return arch == 7 ? format : PIPE_FORMAT_R8G8B8A8_UNORM; + + case PIPE_FORMAT_B5G6R5_UNORM: + return PIPE_FORMAT_R5G6B5_UNORM; + + case PIPE_FORMAT_B5G5R5A1_UNORM: + return PIPE_FORMAT_R5G5B5A1_UNORM; + + case PIPE_FORMAT_R10G10B10X2_UNORM: + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_B10G10R10X2_UNORM: + return PIPE_FORMAT_R10G10B10A2_UNORM; + + case PIPE_FORMAT_B4G4R4A4_UNORM: + return PIPE_FORMAT_R4G4B4A4_UNORM; + case PIPE_FORMAT_A4B4G4R4_UNORM: + /* v7 can only support AFBC for RGB and BGR */ + return arch == 7 ? format : PIPE_FORMAT_R4G4B4A4_UNORM; + + default: + return format; + } +} + +/* AFBC supports compressing a few canonical formats. Additional formats are + * available by using a canonical internal format. Given a PIPE format, find + * the canonical AFBC internal format if it exists, or NONE if the format + * cannot be compressed. */ + +static inline enum pan_afbc_mode +pan_afbc_format(unsigned arch, enum pipe_format format) +{ + /* sRGB does not change the pixel format itself, only the + * interpretation. The interpretation is handled by conversion hardware + * independent to the compression hardware, so we can compress sRGB + * formats by using the corresponding linear format. + */ + format = util_format_linear(format); + + /* Luminance-alpha not supported for AFBC on v7+ */ + switch (format) { + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8A8_UNORM: + if (arch >= 7) + return PAN_AFBC_MODE_INVALID; + else + break; + default: + break; + } + + /* We handle swizzling orthogonally to AFBC */ + format = pan_afbc_unswizzled_format(arch, format); + + /* clang-format off */ + switch (format) { + case PIPE_FORMAT_R8_UNORM: return PAN_AFBC_MODE_R8; + case PIPE_FORMAT_R8G8_UNORM: return PAN_AFBC_MODE_R8G8; + case PIPE_FORMAT_R8G8B8_UNORM: return PAN_AFBC_MODE_R8G8B8; + case PIPE_FORMAT_R8G8B8A8_UNORM: return PAN_AFBC_MODE_R8G8B8A8; + case PIPE_FORMAT_R5G6B5_UNORM: return PAN_AFBC_MODE_R5G6B5; + case PIPE_FORMAT_R5G5B5A1_UNORM: return PAN_AFBC_MODE_R5G5B5A1; + case PIPE_FORMAT_R10G10B10A2_UNORM: return PAN_AFBC_MODE_R10G10B10A2; + case PIPE_FORMAT_R4G4B4A4_UNORM: return PAN_AFBC_MODE_R4G4B4A4; + case PIPE_FORMAT_Z16_UNORM: return PAN_AFBC_MODE_R8G8; + + case PIPE_FORMAT_Z24_UNORM_S8_UINT: return PAN_AFBC_MODE_R8G8B8A8; + case PIPE_FORMAT_Z24X8_UNORM: return PAN_AFBC_MODE_R8G8B8A8; + case PIPE_FORMAT_X24S8_UINT: return PAN_AFBC_MODE_R8G8B8A8; + + default: return PAN_AFBC_MODE_INVALID; + } + /* clang-format on */ +} + +/* A format may be compressed as AFBC if it has an AFBC internal format */ + +static inline bool +pan_format_supports_afbc(unsigned arch, enum pipe_format format) +{ + return pan_afbc_format(arch, format) != PAN_AFBC_MODE_INVALID; +} + +/* The lossless colour transform (AFBC_FORMAT_MOD_YTR) requires RGB. */ + +static inline bool +pan_afbc_can_ytr(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + /* YTR is only defined for RGB(A) */ + if (desc->nr_channels != 3 && desc->nr_channels != 4) + return false; + + /* The fourth channel if it exists doesn't matter */ + return desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB; +} + +static inline bool +pan_afbc_can_split(unsigned arch, enum pipe_format format, uint64_t modifier) +{ + unsigned block_width = pan_afbc_superblock_width(modifier); + + if (arch < 6) + return false; + + if (block_width == 16) { + return true; + } else if (block_width == 32) { + enum pan_afbc_mode mode = pan_afbc_format(arch, format); + return (mode == PAN_AFBC_MODE_R8G8B8A8 || + mode == PAN_AFBC_MODE_R10G10B10A2); + } + + return false; +} + +/* Only support packing for RGB formats for now. */ + +static inline bool +pan_afbc_can_pack(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + return desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB; +} + +/* + * Check if a gen supports AFBC with tiled headers (and hence also solid + * colour blocks). + */ +static inline bool +pan_afbc_can_tile(unsigned arch) +{ + return arch >= 7; +} + +#if PAN_ARCH >= 9 +static inline enum mali_afbc_compression_mode +pan_afbc_compression_mode(enum pipe_format format) +{ + /* There's a special case for texturing the stencil part from a combined + * depth/stencil texture, handle it separately. + */ + if (format == PIPE_FORMAT_X24S8_UINT) + return MALI_AFBC_COMPRESSION_MODE_X24S8; + + /* Otherwise, map canonical formats to the hardware enum. This only + * needs to handle the subset of formats returned by + * pan_afbc_format. + */ + switch (pan_afbc_format(PAN_ARCH, format)) { + case PAN_AFBC_MODE_R8: + return MALI_AFBC_COMPRESSION_MODE_R8; + case PAN_AFBC_MODE_R8G8: + return MALI_AFBC_COMPRESSION_MODE_R8G8; + case PAN_AFBC_MODE_R5G6B5: + return MALI_AFBC_COMPRESSION_MODE_R5G6B5; + case PAN_AFBC_MODE_R4G4B4A4: + return MALI_AFBC_COMPRESSION_MODE_R4G4B4A4; + case PAN_AFBC_MODE_R5G5B5A1: + return MALI_AFBC_COMPRESSION_MODE_R5G5B5A1; + case PAN_AFBC_MODE_R8G8B8: + return MALI_AFBC_COMPRESSION_MODE_R8G8B8; + case PAN_AFBC_MODE_R8G8B8A8: + return MALI_AFBC_COMPRESSION_MODE_R8G8B8A8; + case PAN_AFBC_MODE_R10G10B10A2: + return MALI_AFBC_COMPRESSION_MODE_R10G10B10A2; + case PAN_AFBC_MODE_R11G11B10: + return MALI_AFBC_COMPRESSION_MODE_R11G11B10; + case PAN_AFBC_MODE_S8: + return MALI_AFBC_COMPRESSION_MODE_S8; + case PAN_AFBC_MODE_INVALID: + unreachable("Invalid AFBC format"); + } + + unreachable("all AFBC formats handled"); +} +#endif + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index 79b05e99852..c205f47aee5 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -29,6 +29,7 @@ #include "genxml/gen_macros.h" +#include "pan_afbc.h" #include "pan_desc.h" #include "pan_encoder.h" #include "pan_props.h" @@ -97,7 +98,7 @@ renderblock_fits_in_single_pass(const struct pan_image_view *view, if (!drm_is_afbc(mod)) return tile_size >= 16 * 16; - struct pan_block_size renderblk_sz = panfrost_afbc_renderblock_size(mod); + struct pan_block_size renderblk_sz = pan_afbc_renderblock_size(mod); return tile_size >= renderblk_sz.width * renderblk_sz.height; } @@ -615,14 +616,14 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx, if (image->layout.modifier & AFBC_FORMAT_MOD_YTR) cfg->afbc.yuv_transform = true; - cfg->afbc.wide_block = panfrost_afbc_is_wide(image->layout.modifier); + cfg->afbc.wide_block = pan_afbc_is_wide(image->layout.modifier); cfg->afbc.split_block = (image->layout.modifier & AFBC_FORMAT_MOD_SPLIT); cfg->afbc.header = surf.afbc.header; cfg->afbc.body_offset = surf.afbc.body - surf.afbc.header; assert(surf.afbc.body >= surf.afbc.header); - cfg->afbc.compression_mode = GENX(pan_afbc_compression_mode)(rt->format); + cfg->afbc.compression_mode = pan_afbc_compression_mode(rt->format); cfg->afbc.row_stride = row_stride; #else const struct pan_image_slice_layout *slice = &image->layout.slices[level]; @@ -631,7 +632,7 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx, cfg->afbc.row_stride = pan_afbc_stride_blocks(image->layout.modifier, slice->row_stride); cfg->afbc.afbc_wide_block_enable = - panfrost_afbc_is_wide(image->layout.modifier); + pan_afbc_is_wide(image->layout.modifier); cfg->afbc.afbc_split_block_enable = (image->layout.modifier & AFBC_FORMAT_MOD_SPLIT); #else @@ -790,7 +791,7 @@ pan_force_clean_write_on(const struct pan_image *image, unsigned tile_size) return false; struct pan_block_size renderblk_sz = - panfrost_afbc_renderblock_size(image->layout.modifier); + pan_afbc_renderblock_size(image->layout.modifier); assert(renderblk_sz.width >= 16 && renderblk_sz.height >= 16); assert(tile_size <= panfrost_max_effective_tile_size(PAN_ARCH)); diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index b94dd2ab524..b399ea9baa1 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -26,94 +26,10 @@ #include "util/log.h" #include "util/macros.h" #include "util/u_math.h" +#include "pan_afbc.h" #include "pan_props.h" #include "pan_texture.h" -/* Table of AFBC superblock sizes */ -static const struct pan_block_size afbc_superblock_sizes[] = { - [AFBC_FORMAT_MOD_BLOCK_SIZE_16x16] = {16, 16}, - [AFBC_FORMAT_MOD_BLOCK_SIZE_32x8] = {32, 8}, - [AFBC_FORMAT_MOD_BLOCK_SIZE_64x4] = {64, 4}, -}; - -/* - * Given an AFBC modifier, return the superblock size. - * - * We do not yet have any use cases for multiplanar YCBCr formats with different - * superblock sizes on the luma and chroma planes. These formats are unsupported - * for now. - */ -struct pan_block_size -panfrost_afbc_superblock_size(uint64_t modifier) -{ - unsigned index = (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK); - - assert(drm_is_afbc(modifier)); - assert(index < ARRAY_SIZE(afbc_superblock_sizes)); - - return afbc_superblock_sizes[index]; -} - -/* - * Given an AFBC modifier, return the render size. - */ -struct pan_block_size -panfrost_afbc_renderblock_size(uint64_t modifier) -{ - unsigned index = (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK); - - assert(drm_is_afbc(modifier)); - assert(index < ARRAY_SIZE(afbc_superblock_sizes)); - - struct pan_block_size blk_size = afbc_superblock_sizes[index]; - - /* The GPU needs to render 16x16 tiles. For wide tiles, that means we - * have to extend the render region to have a height of 16 pixels. - */ - blk_size.height = ALIGN_POT(blk_size.height, 16); - return blk_size; -} - -/* - * Given an AFBC modifier, return the width of the superblock. - */ -unsigned -panfrost_afbc_superblock_width(uint64_t modifier) -{ - return panfrost_afbc_superblock_size(modifier).width; -} - -/* - * Given an AFBC modifier, return the height of the superblock. - */ -unsigned -panfrost_afbc_superblock_height(uint64_t modifier) -{ - return panfrost_afbc_superblock_size(modifier).height; -} - -/* - * Given an AFBC modifier, return if "wide blocks" are used. Wide blocks are - * defined as superblocks wider than 16 pixels, the minimum (and default) super - * block width. - */ -bool -panfrost_afbc_is_wide(uint64_t modifier) -{ - return panfrost_afbc_superblock_width(modifier) > 16; -} - -/* - * Given an AFBC modifier, return the subblock size (subdivision of a - * superblock). This is always 4x4 for now as we only support one AFBC - * superblock layout. - */ -struct pan_block_size -panfrost_afbc_subblock_size(uint64_t modifier) -{ - return (struct pan_block_size){4, 4}; -} - /* * Given an AFRC modifier, return whether the layout is optimized for scan * order (vs rotation order). @@ -231,7 +147,7 @@ panfrost_block_size(uint64_t modifier, enum pipe_format format) if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) return panfrost_u_interleaved_tile_size(format); else if (drm_is_afbc(modifier)) - return panfrost_afbc_superblock_size(modifier); + return pan_afbc_superblock_size(modifier); else if (drm_is_afrc(modifier)) return panfrost_afrc_tile_size(format, modifier); else @@ -248,46 +164,7 @@ panfrost_renderblock_size(uint64_t modifier, enum pipe_format format) if (!drm_is_afbc(modifier)) return panfrost_block_size(modifier, format); - return panfrost_afbc_renderblock_size(modifier); -} - -/* - * Determine the tile size used by AFBC. This tiles superblocks themselves. - * Current GPUs support either 8x8 tiling or no tiling (1x1) - */ -static inline unsigned -pan_afbc_tile_size(uint64_t modifier) -{ - return (modifier & AFBC_FORMAT_MOD_TILED) ? 8 : 1; -} - -/* - * Determine the number of bytes between header rows for an AFBC image. For an - * image with linear headers, this is simply the number of header blocks - * (=superblocks) per row times the numbers of bytes per header block. For an - * image with tiled headers, this is multipled by the number of rows of - * header blocks are in a tile together. - */ -uint32_t -pan_afbc_row_stride(uint64_t modifier, uint32_t width) -{ - unsigned block_width = panfrost_afbc_superblock_width(modifier); - - return (width / block_width) * pan_afbc_tile_size(modifier) * - AFBC_HEADER_BYTES_PER_TILE; -} - -/* - * Determine the number of header blocks between header rows. This is equal to - * the number of bytes between header rows divided by the bytes per blocks of a - * header tile. This is also divided by the tile size to give a "line stride" in - * blocks, rather than a real row stride. This is required by Bifrost. - */ -uint32_t -pan_afbc_stride_blocks(uint64_t modifier, uint32_t row_stride_bytes) -{ - return row_stride_bytes / - (AFBC_HEADER_BYTES_PER_TILE * pan_afbc_tile_size(modifier)); + return pan_afbc_renderblock_size(modifier); } /* @@ -299,23 +176,6 @@ pan_slice_align(uint64_t modifier) return 64; } -/* - * Determine the required alignment for the body offset of an AFBC image. For - * now, this depends only on whether tiling is in use. These minimum alignments - * are required on all current GPUs. - */ -uint32_t -pan_afbc_body_align(unsigned arch, uint64_t modifier) -{ - if (modifier & AFBC_FORMAT_MOD_TILED) - return 4096; - - if (arch >= 6) - return 128; - - return 64; -} - static inline unsigned format_minimum_alignment(unsigned arch, enum pipe_format format, uint64_t mod) { diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index b80c11bcab3..cecb0777419 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -26,6 +26,7 @@ * */ +#include "pan_afbc.h" #include "pan_texture.h" #include "util/macros.h" #include "util/u_math.h" @@ -93,7 +94,7 @@ panfrost_compression_tag(const struct util_format_description *desc, /* Prefetch enable */ flags |= MALI_AFBC_SURFACE_FLAG_PREFETCH; - if (panfrost_afbc_is_wide(modifier)) + if (pan_afbc_is_wide(modifier)) flags |= MALI_AFBC_SURFACE_FLAG_WIDE_BLOCK; if (modifier & AFBC_FORMAT_MOD_SPLIT) @@ -520,8 +521,7 @@ panfrost_emit_plane(const struct pan_image_view *iview, cfg.afbc.split_block = (layout->modifier & AFBC_FORMAT_MOD_SPLIT); cfg.afbc.tiled_header = (layout->modifier & AFBC_FORMAT_MOD_TILED); cfg.afbc.prefetch = true; - cfg.afbc.compression_mode = - GENX(pan_afbc_compression_mode)(iview->format); + cfg.afbc.compression_mode = pan_afbc_compression_mode(iview->format); cfg.afbc.header_stride = layout->slices[level].afbc.header_size; } else if (afrc) { #if PAN_ARCH >= 10 @@ -710,7 +710,7 @@ GENX(panfrost_texture_afbc_reswizzle)(struct pan_image_view *iview) */ assert(!util_format_is_depth_or_stencil(iview->format)); assert(!panfrost_format_is_yuv(iview->format)); - assert(panfrost_format_supports_afbc(PAN_ARCH, iview->format)); + assert(pan_format_supports_afbc(PAN_ARCH, iview->format)); uint32_t mali_format = GENX(panfrost_format_from_pipe_format)(iview->format)->hw; @@ -907,40 +907,6 @@ GENX(panfrost_new_storage_texture)(const struct pan_image_view *iview, } #endif -#if PAN_ARCH >= 9 -enum mali_afbc_compression_mode -GENX(pan_afbc_compression_mode)(enum pipe_format format) -{ - /* There's a special case for texturing the stencil part from a combined - * depth/stencil texture, handle it separately. - */ - if (format == PIPE_FORMAT_X24S8_UINT) - return MALI_AFBC_COMPRESSION_MODE_X24S8; - - /* Otherwise, map canonical formats to the hardware enum. This only - * needs to handle the subset of formats returned by - * panfrost_afbc_format. - */ - /* clang-format off */ - switch (panfrost_afbc_format(PAN_ARCH, format)) { - case PAN_AFBC_MODE_R8: return MALI_AFBC_COMPRESSION_MODE_R8; - case PAN_AFBC_MODE_R8G8: return MALI_AFBC_COMPRESSION_MODE_R8G8; - case PAN_AFBC_MODE_R5G6B5: return MALI_AFBC_COMPRESSION_MODE_R5G6B5; - case PAN_AFBC_MODE_R4G4B4A4: return MALI_AFBC_COMPRESSION_MODE_R4G4B4A4; - case PAN_AFBC_MODE_R5G5B5A1: return MALI_AFBC_COMPRESSION_MODE_R5G5B5A1; - case PAN_AFBC_MODE_R8G8B8: return MALI_AFBC_COMPRESSION_MODE_R8G8B8; - case PAN_AFBC_MODE_R8G8B8A8: return MALI_AFBC_COMPRESSION_MODE_R8G8B8A8; - case PAN_AFBC_MODE_R10G10B10A2: return MALI_AFBC_COMPRESSION_MODE_R10G10B10A2; - case PAN_AFBC_MODE_R11G11B10: return MALI_AFBC_COMPRESSION_MODE_R11G11B10; - case PAN_AFBC_MODE_S8: return MALI_AFBC_COMPRESSION_MODE_S8; - case PAN_AFBC_MODE_INVALID: unreachable("Invalid AFBC format"); - } - /* clang-format on */ - - unreachable("all AFBC formats handled"); -} -#endif - #if PAN_ARCH >= 10 enum mali_afrc_format GENX(pan_afrc_format)(struct pan_afrc_format_info info, uint64_t modifier, diff --git a/src/panfrost/lib/pan_texture.h b/src/panfrost/lib/pan_texture.h index 334f29f4b8f..b7d3cb3aaf2 100644 --- a/src/panfrost/lib/pan_texture.h +++ b/src/panfrost/lib/pan_texture.h @@ -253,55 +253,6 @@ unsigned panfrost_compute_checksum_size(unsigned arch, struct pan_image_slice_layout *slice, unsigned width, unsigned height); -/* AFBC format mode. The ordering is intended to match the Valhall hardware enum - * ("AFBC Compression Mode"), but this enum is required in software on older - * hardware for correct handling of texture views. Defining the enum lets us - * unify these code paths. - */ -enum pan_afbc_mode { - PAN_AFBC_MODE_R8, - PAN_AFBC_MODE_R8G8, - PAN_AFBC_MODE_R5G6B5, - PAN_AFBC_MODE_R4G4B4A4, - PAN_AFBC_MODE_R5G5B5A1, - PAN_AFBC_MODE_R8G8B8, - PAN_AFBC_MODE_R8G8B8A8, - PAN_AFBC_MODE_R10G10B10A2, - PAN_AFBC_MODE_R11G11B10, - PAN_AFBC_MODE_S8, - - /* Sentintel signalling a format that cannot be compressed */ - PAN_AFBC_MODE_INVALID -}; - -enum pan_afbc_mode panfrost_afbc_format(unsigned arch, enum pipe_format format); - -/* A format may be compressed as AFBC if it has an AFBC internal format */ - -static inline bool -panfrost_format_supports_afbc(unsigned arch, enum pipe_format format) -{ - return panfrost_afbc_format(arch, format) != PAN_AFBC_MODE_INVALID; -} - -#define AFBC_HEADER_BYTES_PER_TILE 16 - -bool panfrost_afbc_can_ytr(enum pipe_format format); - -bool panfrost_afbc_can_split(unsigned arch, enum pipe_format format, - uint64_t modifier); - -bool panfrost_afbc_can_pack(enum pipe_format format); - -/* - * Check if a gen supports AFBC with tiled headers (and hence also solid - * colour blocks). - */ -static inline bool panfrost_afbc_can_tile(unsigned arch) -{ - return arch >= 7; -} - /* * Represents the block size of a single plane. For AFBC, this represents the * superblock size. For u-interleaving, this represents the tile size. @@ -314,26 +265,8 @@ struct pan_block_size { unsigned height; }; -struct pan_block_size panfrost_afbc_superblock_size(uint64_t modifier); - -unsigned panfrost_afbc_superblock_width(uint64_t modifier); - -unsigned panfrost_afbc_superblock_height(uint64_t modifier); - -struct pan_block_size panfrost_afbc_renderblock_size(uint64_t modifier); - -bool panfrost_afbc_is_wide(uint64_t modifier); - -struct pan_block_size panfrost_afbc_subblock_size(uint64_t modifier); - -uint32_t pan_afbc_row_stride(uint64_t modifier, uint32_t width); - -uint32_t pan_afbc_stride_blocks(uint64_t modifier, uint32_t row_stride_bytes); - uint32_t pan_slice_align(uint64_t modifier); -uint32_t pan_afbc_body_align(unsigned arch, uint64_t modifier); - /* AFRC */ #define AFRC_CLUMPS_PER_TILE 64 @@ -461,11 +394,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 >= 9 -enum mali_afbc_compression_mode -GENX(pan_afbc_compression_mode)(enum pipe_format format); -#endif - #if PAN_ARCH >= 10 enum mali_afrc_format GENX(pan_afrc_format)(struct pan_afrc_format_info info, uint64_t modifier, diff --git a/src/panfrost/lib/tests/test-layout.cpp b/src/panfrost/lib/tests/test-layout.cpp index db25d43afd8..12c6f7072a6 100644 --- a/src/panfrost/lib/tests/test-layout.cpp +++ b/src/panfrost/lib/tests/test-layout.cpp @@ -21,6 +21,7 @@ * SOFTWARE. */ +#include "pan_afbc.h" #include "pan_texture.h" #include @@ -111,13 +112,13 @@ TEST(BlockSize, AFBCSuperblock16x16) DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR); - EXPECT_EQ(panfrost_afbc_superblock_size(modifier).width, 16); - EXPECT_EQ(panfrost_afbc_superblock_width(modifier), 16); + EXPECT_EQ(pan_afbc_superblock_size(modifier).width, 16); + EXPECT_EQ(pan_afbc_superblock_width(modifier), 16); - EXPECT_EQ(panfrost_afbc_superblock_size(modifier).height, 16); - EXPECT_EQ(panfrost_afbc_superblock_height(modifier), 16); + EXPECT_EQ(pan_afbc_superblock_size(modifier).height, 16); + EXPECT_EQ(pan_afbc_superblock_height(modifier), 16); - EXPECT_FALSE(panfrost_afbc_is_wide(modifier)); + EXPECT_FALSE(pan_afbc_is_wide(modifier)); } TEST(BlockSize, AFBCSuperblock32x8) @@ -125,13 +126,13 @@ TEST(BlockSize, AFBCSuperblock32x8) uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | AFBC_FORMAT_MOD_SPARSE); - EXPECT_EQ(panfrost_afbc_superblock_size(modifier).width, 32); - EXPECT_EQ(panfrost_afbc_superblock_width(modifier), 32); + EXPECT_EQ(pan_afbc_superblock_size(modifier).width, 32); + EXPECT_EQ(pan_afbc_superblock_width(modifier), 32); - EXPECT_EQ(panfrost_afbc_superblock_size(modifier).height, 8); - EXPECT_EQ(panfrost_afbc_superblock_height(modifier), 8); + EXPECT_EQ(pan_afbc_superblock_size(modifier).height, 8); + EXPECT_EQ(pan_afbc_superblock_height(modifier), 8); - EXPECT_TRUE(panfrost_afbc_is_wide(modifier)); + EXPECT_TRUE(pan_afbc_is_wide(modifier)); } TEST(BlockSize, AFBCSuperblock64x4) @@ -139,13 +140,13 @@ TEST(BlockSize, AFBCSuperblock64x4) uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 | AFBC_FORMAT_MOD_SPARSE); - EXPECT_EQ(panfrost_afbc_superblock_size(modifier).width, 64); - EXPECT_EQ(panfrost_afbc_superblock_width(modifier), 64); + EXPECT_EQ(pan_afbc_superblock_size(modifier).width, 64); + EXPECT_EQ(pan_afbc_superblock_width(modifier), 64); - EXPECT_EQ(panfrost_afbc_superblock_size(modifier).height, 4); - EXPECT_EQ(panfrost_afbc_superblock_height(modifier), 4); + EXPECT_EQ(pan_afbc_superblock_size(modifier).height, 4); + EXPECT_EQ(pan_afbc_superblock_height(modifier), 4); - EXPECT_TRUE(panfrost_afbc_is_wide(modifier)); + EXPECT_TRUE(pan_afbc_is_wide(modifier)); } /* Calculate Bifrost line stride, since we have reference formulas for Bifrost @@ -176,7 +177,7 @@ TEST(AFBCStride, Linear) for (unsigned m = 0; m < ARRAY_SIZE(modifiers); ++m) { uint64_t modifier = modifiers[m]; - uint32_t sw = panfrost_afbc_superblock_width(modifier); + uint32_t sw = pan_afbc_superblock_width(modifier); uint32_t cases[] = {1, 4, 17, 39}; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { @@ -205,7 +206,7 @@ TEST(AFBCStride, Tiled) for (unsigned m = 0; m < ARRAY_SIZE(modifiers); ++m) { uint64_t modifier = modifiers[m]; - uint32_t sw = panfrost_afbc_superblock_width(modifier); + uint32_t sw = pan_afbc_superblock_width(modifier); uint32_t cases[] = {1, 4, 17, 39}; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { diff --git a/src/panfrost/vulkan/panvk_image.c b/src/panfrost/vulkan/panvk_image.c index db9a28d6c4f..8a4079408cf 100644 --- a/src/panfrost/vulkan/panvk_image.c +++ b/src/panfrost/vulkan/panvk_image.c @@ -26,6 +26,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include "pan_afbc.h" #include "pan_props.h" #include "panvk_device.h" @@ -80,7 +81,7 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod) VK_IMAGE_USAGE_STORAGE_BIT) || image->vk.samples > 1 || !panfrost_query_afbc(&phys_dev->kmod.props) || - !panfrost_format_supports_afbc(arch, pfmt) || + !pan_format_supports_afbc(arch, pfmt) || image->vk.tiling == VK_IMAGE_TILING_LINEAR || image->vk.image_type == VK_IMAGE_TYPE_1D || (image->vk.image_type == VK_IMAGE_TYPE_3D && arch < 7) || diff --git a/src/panfrost/vulkan/panvk_vX_buffer_view.c b/src/panfrost/vulkan/panvk_vX_buffer_view.c index 3dccc2f6f6b..a9dbfe18588 100644 --- a/src/panfrost/vulkan/panvk_vX_buffer_view.c +++ b/src/panfrost/vulkan/panvk_vX_buffer_view.c @@ -17,6 +17,8 @@ #include "panvk_entrypoints.h" #include "panvk_priv_bo.h" +#include "pan_afbc.h" + #include "vk_format.h" #include "vk_log.h" @@ -94,7 +96,7 @@ panvk_per_arch(CreateBufferView)(VkDevice _device, /* v7 requires AFBC reswizzle. */ if (!util_format_is_depth_or_stencil(pfmt) && !panfrost_format_is_yuv(pfmt) && - panfrost_format_supports_afbc(PAN_ARCH, pfmt)) + pan_format_supports_afbc(PAN_ARCH, pfmt)) GENX(panfrost_texture_afbc_reswizzle)(&pview); #endif diff --git a/src/panfrost/vulkan/panvk_vX_image_view.c b/src/panfrost/vulkan/panvk_vX_image_view.c index 177b3f95cbf..7c343bd59d2 100644 --- a/src/panfrost/vulkan/panvk_vX_image_view.c +++ b/src/panfrost/vulkan/panvk_vX_image_view.c @@ -18,6 +18,8 @@ #include "panvk_image_view.h" #include "panvk_priv_bo.h" +#include "pan_afbc.h" + #include "genxml/gen_macros.h" static enum mali_texture_dimension @@ -103,7 +105,7 @@ prepare_tex_descs(struct panvk_image_view *view) #if PAN_ARCH == 7 /* v7 requires AFBC reswizzle. */ else if (!panfrost_format_is_yuv(view->pview.format) && - panfrost_format_supports_afbc(PAN_ARCH, view->pview.format)) + pan_format_supports_afbc(PAN_ARCH, view->pview.format)) GENX(panfrost_texture_afbc_reswizzle)(&pview); #endif diff --git a/src/panfrost/vulkan/panvk_vX_sampler.c b/src/panfrost/vulkan/panvk_vX_sampler.c index 87e49332af4..5cd0623cfad 100644 --- a/src/panfrost/vulkan/panvk_vX_sampler.c +++ b/src/panfrost/vulkan/panvk_vX_sampler.c @@ -9,6 +9,7 @@ #include "panvk_entrypoints.h" #include "panvk_sampler.h" +#include "pan_afbc.h" #include "pan_encoder.h" #include "pan_format.h" @@ -83,7 +84,7 @@ panvk_afbc_reswizzle_border_color(VkClearColorValue *border_color, VkFormat fmt) enum pipe_format pfmt = vk_format_to_pipe_format(fmt); if (panfrost_format_is_yuv(pfmt) || util_format_is_depth_or_stencil(pfmt) || - !panfrost_format_supports_afbc(PAN_ARCH, pfmt)) + !pan_format_supports_afbc(PAN_ARCH, pfmt)) return; const struct util_format_description *fdesc = util_format_description(pfmt);