diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 084d961f751..6949c3fa320 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -762,7 +762,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen, if (dev->ro && (template->bind & PIPE_BIND_SCANOUT)) { struct winsys_handle handle; struct pan_block_size blocksize = - panfrost_block_size(modifier, template->format); + panfrost_renderblock_size(modifier, template->format); /* Block-based texture formats are only used for texture * compression (not framebuffer compression!), which doesn't diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index fd7c3bb5eca..8f9649ef9b3 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -82,11 +82,24 @@ mali_sampling_mode(const struct pan_image_view *view) return MALI_MSAA_SINGLE; } +static bool +renderblock_fits_in_single_pass(const struct pan_image_view *view, + unsigned tile_size) +{ + uint64_t mod = view->planes[0]->layout.modifier; + + if (!drm_is_afbc(mod)) + return tile_size >= 16 * 16; + + struct pan_block_size renderblk_sz = panfrost_afbc_renderblock_size(mod); + return tile_size >= renderblk_sz.width * renderblk_sz.height; +} + int GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size) { - /* Disable CRC when the tile size is not 16x16. In the hardware, CRC - * tiles are the same size as the tiles of the framebuffer. However, + /* Disable CRC when the tile size is smaller than 16x16. In the hardware, + * CRC tiles are the same size as the tiles of the framebuffer. However, * our code only handles 16x16 tiles. Therefore under the current * implementation, we must disable CRC when 16x16 tiles are not used. * @@ -112,6 +125,9 @@ GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size) !pan_image_view_has_crc(fb->rts[i].view)) continue; + if (!renderblock_fits_in_single_pass(fb->rts[i].view, tile_size)) + continue; + bool valid = *(fb->rts[i].crc_valid); bool full = !fb->extent.minx && !fb->extent.miny && fb->extent.maxx == (fb->width - 1) && @@ -692,13 +708,13 @@ pan_force_clean_write_rt(const struct pan_image_view *rt, unsigned tile_size) if (!drm_is_afbc(image->layout.modifier)) return false; - unsigned superblock = panfrost_afbc_superblock_width(image->layout.modifier); + struct pan_block_size renderblk_sz = + panfrost_afbc_renderblock_size(image->layout.modifier); - assert(superblock >= 16); + assert(renderblk_sz.width >= 16 && renderblk_sz.height >= 16); assert(tile_size <= panfrost_max_effective_tile_size(PAN_ARCH)); - /* Tile size and superblock differ unless they are both 16x16 */ - return !(superblock == 16 && tile_size == 16 * 16); + return tile_size != renderblk_sz.width * renderblk_sz.height; } static bool diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index 5e6ce6e4b6e..d9da8474d4f 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -94,6 +94,26 @@ panfrost_afbc_superblock_size(uint64_t modifier) 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. */ @@ -258,6 +278,19 @@ panfrost_block_size(uint64_t modifier, enum pipe_format format) return (struct pan_block_size){1, 1}; } +/* For non-AFBC and non-wide AFBC, the render block size matches + * the block size, but for wide AFBC, the GPU wants the block height + * to be 16 pixels high. + */ +struct pan_block_size +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) @@ -392,7 +425,7 @@ panfrost_get_legacy_stride(const struct pan_image_layout *layout, { unsigned row_stride = layout->slices[level].row_stride; struct pan_block_size block_size = - panfrost_block_size(layout->modifier, layout->format); + panfrost_renderblock_size(layout->modifier, layout->format); if (drm_is_afbc(layout->modifier)) { unsigned width = u_minify(layout->width, level); @@ -415,7 +448,8 @@ unsigned panfrost_from_legacy_stride(unsigned legacy_stride, enum pipe_format format, uint64_t modifier) { - struct pan_block_size block_size = panfrost_block_size(modifier, format); + struct pan_block_size block_size = + panfrost_renderblock_size(modifier, format); if (drm_is_afbc(modifier)) { unsigned width = legacy_stride / util_format_get_blocksize(format); @@ -492,6 +526,8 @@ pan_image_layout_init(unsigned arch, struct pan_image_layout *layout, bool is_3d = layout->dim == MALI_TEXTURE_DIMENSION_3D; uint64_t offset = explicit_layout ? explicit_layout->offset : 0; + struct pan_block_size renderblk_size = + panfrost_renderblock_size(layout->modifier, layout->format); struct pan_block_size block_size = panfrost_block_size(layout->modifier, layout->format); @@ -499,8 +535,8 @@ pan_image_layout_init(unsigned arch, struct pan_image_layout *layout, unsigned height = layout->height; unsigned depth = layout->depth; - unsigned align_w = block_size.width; - unsigned align_h = block_size.height; + unsigned align_w = renderblk_size.width; + unsigned align_h = renderblk_size.height; /* For tiled AFBC, align to tiles of superblocks (this can be large) */ if (afbc) { @@ -560,7 +596,7 @@ pan_image_layout_init(unsigned arch, struct pan_image_layout *layout, slice->afbc.nr_blocks = slice->afbc.stride * (effective_height / block_size.height); slice->afbc.header_size = - ALIGN_POT(slice->row_stride * (effective_height / align_h), + ALIGN_POT(slice->afbc.nr_blocks * AFBC_HEADER_BYTES_PER_TILE, pan_afbc_body_align(arch, layout->modifier)); if (explicit_layout && diff --git a/src/panfrost/lib/pan_texture.h b/src/panfrost/lib/pan_texture.h index 3945d4f4f00..f2297d00605 100644 --- a/src/panfrost/lib/pan_texture.h +++ b/src/panfrost/lib/pan_texture.h @@ -271,6 +271,8 @@ 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); @@ -347,6 +349,9 @@ 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); +struct pan_block_size panfrost_renderblock_size(uint64_t modifier, + enum pipe_format format); + #ifdef PAN_ARCH unsigned GENX(panfrost_estimate_texture_payload_size)( const struct pan_image_view *iview);