diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 078bd7ecd01..96383eb0117 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -3618,10 +3618,11 @@ panfrost_afbc_size(struct panfrost_batch *batch, struct panfrost_resource *src, .src = src->plane.base + slice->offset_B, .layout = layout->ptr.gpu + offset, }; - unsigned stride_sb = pan_afbc_stride_blocks(src->image.props.modifier, + unsigned stride_sb = pan_afbc_stride_blocks(src->image.props.format, + src->image.props.modifier, slice->afbc.header.row_stride_B); unsigned nr_sblocks = - stride_sb * pan_afbc_height_blocks( + stride_sb * pan_afbc_height_blocks(src->image.props.format, src->image.props.modifier, u_minify(src->image.props.extent_px.height, level)); @@ -3642,12 +3643,12 @@ panfrost_afbc_pack(struct panfrost_batch *batch, struct panfrost_resource *src, struct panfrost_device *dev = pan_device(src->base.screen); struct pan_image_slice_layout *src_slice = &src->plane.layout.slices[level]; - unsigned src_stride_sb = pan_afbc_stride_blocks( + unsigned src_stride_sb = pan_afbc_stride_blocks(src->image.props.format, src->image.props.modifier, src_slice->afbc.header.row_stride_B); - unsigned dst_stride_sb = pan_afbc_stride_blocks( + unsigned dst_stride_sb = pan_afbc_stride_blocks(src->image.props.format, src->image.props.modifier, dst_slice->afbc.header.row_stride_B); unsigned nr_sblocks = - src_stride_sb * pan_afbc_height_blocks( + src_stride_sb * pan_afbc_height_blocks(src->image.props.format, src->image.props.modifier, u_minify(src->image.props.extent_px.height, level)); struct panfrost_afbc_pack_info consts = { diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index dca5513baa5..2270fbb1fe5 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -2013,6 +2013,7 @@ pan_resource_afbcp_get_payload_sizes(struct panfrost_context *ctx, struct panfrost_screen *screen = pan_screen(ctx->base.screen); struct panfrost_device *dev = pan_device(ctx->base.screen); + enum pipe_format format = prsrc->base.format; uint64_t modifier = prsrc->modifier; unsigned last_level = prsrc->base.last_level; unsigned layout_size = 0; @@ -2022,9 +2023,9 @@ pan_resource_afbcp_get_payload_sizes(struct panfrost_context *ctx, &prsrc->plane.layout.slices[level]; unsigned nr_blocks = pan_afbc_stride_blocks( - modifier, slice->afbc.header.row_stride_B) * + format, modifier, slice->afbc.header.row_stride_B) * pan_afbc_height_blocks( - modifier, u_minify(prsrc->image.props.extent_px.height, level)); + format, modifier, u_minify(prsrc->image.props.extent_px.height, level)); prsrc->afbcp->layout_offsets[level] = layout_size; layout_size += nr_blocks * sizeof(struct pan_afbc_payload_extent); } @@ -2111,6 +2112,7 @@ pan_resource_afbcp_get_payload_offsets(struct panfrost_context *ctx, struct panfrost_device *dev = pan_device(ctx->base.screen); uint64_t modifier = prsrc->modifier; + enum pipe_format format = prsrc->base.format; unsigned last_level = prsrc->base.last_level; unsigned total_size = 0; @@ -2121,9 +2123,9 @@ pan_resource_afbcp_get_payload_offsets(struct panfrost_context *ctx, &prsrc->afbcp->plane.layout.slices[level]; unsigned nr_blocks_total = pan_afbc_stride_blocks( - modifier, src_slice->afbc.header.row_stride_B) * + format, modifier, src_slice->afbc.header.row_stride_B) * pan_afbc_height_blocks( - modifier, u_minify(prsrc->image.props.extent_px.height, level)); + format, modifier, u_minify(prsrc->image.props.extent_px.height, level)); uint32_t body_offset_B = pan_afbc_body_offset( dev->arch, modifier, src_slice->afbc.header.surface_size_B); struct pan_afbc_payload_extent *layout = diff --git a/src/panfrost/lib/pan_afbc.h b/src/panfrost/lib/pan_afbc.h index 5e87f35e70d..0e6a920d4f9 100644 --- a/src/panfrost/lib/pan_afbc.h +++ b/src/panfrost/lib/pan_afbc.h @@ -387,12 +387,16 @@ pan_afbc_body_offset(unsigned arch, uint64_t modifier, uint32_t header_size) /* * Determine the tile size used by AFBC. This tiles superblocks themselves. - * Current GPUs support either 8x8 tiling or no tiling (1x1) + * Current GPUs support either 8x8 tiling or no tiling (1x1) for most + * formats; but note that formats with more than 32bpp use 4x4 tiling */ static inline unsigned -pan_afbc_tile_size(uint64_t modifier) +pan_afbc_tile_size(enum pipe_format format, uint64_t modifier) { - return (modifier & AFBC_FORMAT_MOD_TILED) ? 8 : 1; + if ( !(modifier & AFBC_FORMAT_MOD_TILED) ) { + return 1; + } + return util_format_get_blocksizebits(format) <= 32 ? 8 : 4; } /* @@ -403,11 +407,11 @@ pan_afbc_tile_size(uint64_t modifier) * header blocks are in a tile together. */ static inline uint32_t -pan_afbc_row_stride(uint64_t modifier, uint32_t width) +pan_afbc_row_stride(enum pipe_format format, uint64_t modifier, uint32_t width) { unsigned block_width = pan_afbc_superblock_width(modifier); - return (width / block_width) * pan_afbc_tile_size(modifier) * + return (width / block_width) * pan_afbc_tile_size(format, modifier) * AFBC_HEADER_BYTES_PER_TILE; } @@ -418,21 +422,21 @@ pan_afbc_row_stride(uint64_t modifier, uint32_t width) * 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) +pan_afbc_stride_blocks(enum pipe_format format, uint64_t modifier, uint32_t row_stride_bytes) { return row_stride_bytes / - (AFBC_HEADER_BYTES_PER_TILE * pan_afbc_tile_size(modifier)); + (AFBC_HEADER_BYTES_PER_TILE * pan_afbc_tile_size(format, modifier)); } /* Returns a height in superblocks taking into account the tile alignment * requirement coming from the modifier. */ static inline uint32_t -pan_afbc_height_blocks(uint64_t modifier, uint32_t height_px) +pan_afbc_height_blocks(enum pipe_format format, uint64_t modifier, uint32_t height_px) { return ALIGN_POT( DIV_ROUND_UP(height_px, pan_afbc_superblock_height(modifier)), - pan_afbc_tile_size(modifier)); + pan_afbc_tile_size(format, modifier)); } static inline enum pipe_format diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index 074850f3372..e3d3915f111 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -371,7 +371,8 @@ GENX(pan_emit_afbc_zs_attachment)(const struct pan_fb_info *fb, #if PAN_ARCH >= 6 cfg.header_row_stride = - pan_afbc_stride_blocks(pref.image->props.modifier, hdr_row_stride); + pan_afbc_stride_blocks(pref.image->props.format, + pref.image->props.modifier, hdr_row_stride); #else cfg.body_size = 0x1000; cfg.chunk_size = 9; @@ -727,7 +728,8 @@ GENX(pan_emit_afbc_color_attachment)(const struct pan_fb_info *fb, #if PAN_ARCH >= 6 cfg.row_stride = - pan_afbc_stride_blocks(image->props.modifier, hdr_row_stride); + pan_afbc_stride_blocks(image->props.format, + image->props.modifier, hdr_row_stride); #else const struct pan_image_plane *plane = image->planes[pref.plane_idx]; const struct pan_image_slice_layout *slayout = diff --git a/src/panfrost/lib/pan_mod.c b/src/panfrost/lib/pan_mod.c index 845c8b8320c..2d61de70732 100644 --- a/src/panfrost/lib/pan_mod.c +++ b/src/panfrost/lib/pan_mod.c @@ -45,7 +45,8 @@ pan_mod_afbc_get_wsi_row_pitch(const struct pan_image *image, tile_extent_el.width * tile_extent_el.height * pan_format_get_plane_blocksize(props->format, plane_idx); const unsigned tile_row_payload_size_B = - pan_afbc_stride_blocks(props->modifier, header_row_stride_B) * + pan_afbc_stride_blocks(props->format, + props->modifier, header_row_stride_B) * tile_payload_size_B; return tile_row_payload_size_B / pan_afbc_superblock_height(props->modifier); @@ -95,10 +96,10 @@ pan_mod_afbc_init_slice_layout( if (props->modifier & AFBC_FORMAT_MOD_TILED) { align_px.width = ALIGN_POT(align_px.width, afbc_tile_extent_px.width * - pan_afbc_tile_size(props->modifier)); + pan_afbc_tile_size(props->format, props->modifier)); align_px.height = ALIGN_POT(align_px.height, afbc_tile_extent_px.height * - pan_afbc_tile_size(props->modifier)); + pan_afbc_tile_size(props->format, props->modifier)); } struct pan_image_extent aligned_extent_px = { @@ -134,7 +135,7 @@ pan_mod_afbc_init_slice_layout( } slayout->afbc.header.row_stride_B = - pan_afbc_row_stride(props->modifier, width_from_wsi_row_stride); + pan_afbc_row_stride(props->format, props->modifier, width_from_wsi_row_stride); if (slayout->afbc.header.row_stride_B & row_align_mask) { mesa_loge("WSI pitch not properly aligned"); return false; @@ -150,7 +151,7 @@ pan_mod_afbc_init_slice_layout( * the resource width to get the size. */ if (!layout_constraints->strict) { slayout->afbc.header.row_stride_B = ALIGN_POT( - pan_afbc_row_stride(props->modifier, aligned_extent_px.width), + pan_afbc_row_stride(props->format, props->modifier, aligned_extent_px.width), row_align_mask + 1); } } else { @@ -158,12 +159,13 @@ pan_mod_afbc_init_slice_layout( ALIGN_POT(layout_constraints ? layout_constraints->offset_B : 0, offset_align_mask + 1); slayout->afbc.header.row_stride_B = ALIGN_POT( - pan_afbc_row_stride(props->modifier, aligned_extent_px.width), + pan_afbc_row_stride(props->format, props->modifier, aligned_extent_px.width), row_align_mask + 1); } - const unsigned row_stride_sb = pan_afbc_stride_blocks( - props->modifier, slayout->afbc.header.row_stride_B); + const unsigned row_stride_sb = pan_afbc_stride_blocks(props->format, + props->modifier, + slayout->afbc.header.row_stride_B); const unsigned surface_stride_sb = row_stride_sb * (aligned_extent_px.height / afbc_tile_extent_px.height); diff --git a/src/panfrost/lib/tests/test-layout.cpp b/src/panfrost/lib/tests/test-layout.cpp index 08cc95ce605..09666fc69ec 100644 --- a/src/panfrost/lib/tests/test-layout.cpp +++ b/src/panfrost/lib/tests/test-layout.cpp @@ -173,10 +173,10 @@ TEST(BlockSize, AFBCSuperblock64x4) * stride calculations. */ static uint32_t -pan_afbc_line_stride(uint64_t modifier, uint32_t width) +pan_afbc_line_stride(enum pipe_format format, uint64_t modifier, uint32_t width) { - return pan_afbc_stride_blocks(modifier, - pan_afbc_row_stride(modifier, width)); + return pan_afbc_stride_blocks(format, modifier, + pan_afbc_row_stride(format, modifier, width)); } /* Which form of the stride we specify is hardware specific (row stride for @@ -196,17 +196,17 @@ TEST(AFBCStride, Linear) for (unsigned m = 0; m < ARRAY_SIZE(modifiers); ++m) { uint64_t modifier = modifiers[m]; - + enum pipe_format format = PIPE_FORMAT_R8G8B8A8_UNORM; uint32_t sw = pan_afbc_superblock_width(modifier); uint32_t cases[] = {1, 4, 17, 39}; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { uint32_t width = sw * cases[i]; - EXPECT_EQ(pan_afbc_row_stride(modifier, width), + EXPECT_EQ(pan_afbc_row_stride(format, modifier, width), 16 * DIV_ROUND_UP(width, sw)); - EXPECT_EQ(pan_afbc_line_stride(modifier, width), + EXPECT_EQ(pan_afbc_line_stride(format, modifier, width), DIV_ROUND_UP(width, sw)); } } @@ -225,17 +225,17 @@ TEST(AFBCStride, Tiled) for (unsigned m = 0; m < ARRAY_SIZE(modifiers); ++m) { uint64_t modifier = modifiers[m]; - + enum pipe_format format = PIPE_FORMAT_R8_UNORM; uint32_t sw = pan_afbc_superblock_width(modifier); uint32_t cases[] = {1, 4, 17, 39}; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { uint32_t width = sw * 8 * cases[i]; - EXPECT_EQ(pan_afbc_row_stride(modifier, width), + EXPECT_EQ(pan_afbc_row_stride(format, modifier, width), 16 * DIV_ROUND_UP(width, (sw * 8)) * 8 * 8); - EXPECT_EQ(pan_afbc_line_stride(modifier, width), + EXPECT_EQ(pan_afbc_line_stride(format, modifier, width), DIV_ROUND_UP(width, sw * 8) * 8); } }