mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 02:28:10 +02:00
panfrost: Improve AFBC header block accesses
Add an AFBC header block structure pan_afbc_headerblock to improve readability when accessing header blocks. get_superblock_size(), which will be used for AFBC packing in the next commits, has been moved to pan_afbc.h and renamed to pan_afbc_payload_size() so that it can be tested. Other utility functions pan_afbc_header_subblock_size() and pan_afbc_header_subblock_uncompressed_size() hasve been added to help retrieve the compressed or uncompressed size of a subblock from a header. This commit also fixes a few issues like arch handling. Signed-off-by: Loïc Molinari <loic.molinari@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com> Acked-by: Eric R. Smith <eric.smith@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35001>
This commit is contained in:
parent
a0bdbcbae6
commit
f750620982
2 changed files with 117 additions and 41 deletions
|
|
@ -1392,62 +1392,31 @@ panfrost_load_tiled_images(struct panfrost_transfer *transfer,
|
|||
|
||||
#if MESA_DEBUG
|
||||
|
||||
static unsigned
|
||||
get_superblock_size(uint32_t *hdr, unsigned uncompressed_size)
|
||||
{
|
||||
/* AFBC superblock layout 0 */
|
||||
unsigned body_base_ptr_len = 32;
|
||||
unsigned nr_subblocks = 16;
|
||||
unsigned sz_len = 6; /* bits */
|
||||
unsigned mask = (1 << sz_len) - 1;
|
||||
unsigned size = 0;
|
||||
|
||||
/* Sum up all of the subblock sizes */
|
||||
for (int i = 0; i < nr_subblocks; i++) {
|
||||
unsigned bitoffset = body_base_ptr_len + (i * sz_len);
|
||||
unsigned start = bitoffset / 32;
|
||||
unsigned end = (bitoffset + (sz_len - 1)) / 32;
|
||||
unsigned offset = bitoffset % 32;
|
||||
unsigned subblock_size;
|
||||
|
||||
if (start != end)
|
||||
subblock_size = (hdr[start] >> offset) | (hdr[end] << (32 - offset));
|
||||
else
|
||||
subblock_size = hdr[start] >> offset;
|
||||
subblock_size = (subblock_size == 1) ? uncompressed_size : subblock_size;
|
||||
size += subblock_size & mask;
|
||||
|
||||
if (i == 0 && size == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_block(struct panfrost_resource *rsrc, uint32_t idx)
|
||||
dump_headerblock(struct panfrost_resource *rsrc, uint32_t idx)
|
||||
{
|
||||
panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
|
||||
|
||||
uint8_t *ptr = rsrc->bo->ptr.cpu;
|
||||
uint32_t *header = (uint32_t *)(ptr + (idx * AFBC_HEADER_BYTES_PER_TILE));
|
||||
uint32_t body_base_ptr = header[0];
|
||||
uint32_t *body = (uint32_t *)(ptr + body_base_ptr);
|
||||
struct pan_afbc_headerblock *header = (struct pan_afbc_headerblock *)
|
||||
(ptr + (idx * AFBC_HEADER_BYTES_PER_TILE));
|
||||
uint32_t *header_u32 = (uint32_t *)header;
|
||||
uint32_t *body = (uint32_t *)(ptr + header->payload.offset);
|
||||
struct pan_image_block_size block_sz =
|
||||
pan_afbc_subblock_size(rsrc->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);
|
||||
uint32_t size = pan_afbc_payload_size(7, *header, uncompressed_size);
|
||||
|
||||
fprintf(stderr, " Header: %08x %08x %08x %08x (size: %u bytes)\n",
|
||||
header[0], header[1], header[2], header[3], size);
|
||||
header_u32[0], header_u32[1], header_u32[2], header_u32[3], size);
|
||||
if (size > 0) {
|
||||
fprintf(stderr, " Body: %08x %08x %08x %08x\n", body[0], body[1],
|
||||
body[2], body[3]);
|
||||
} else {
|
||||
uint8_t *comp = (uint8_t *)(header + 2);
|
||||
fprintf(stderr, " Color: 0x%02x%02x%02x%02x\n", comp[0], comp[1],
|
||||
comp[2], comp[3]);
|
||||
fprintf(stderr, " Color: 0x%02x%02x%02x%02x\n",
|
||||
header->color.rgba8888.r, header->color.rgba8888.g,
|
||||
header->color.rgba8888.b, header->color.rgba8888.a);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,42 @@ enum pan_afbc_mode {
|
|||
PAN_AFBC_MODE_INVALID
|
||||
};
|
||||
|
||||
/*
|
||||
* An AFBC header block provides access to an associated superblock payload of
|
||||
* 4x4 subblocks or to an embedded solid color.
|
||||
*/
|
||||
struct pan_afbc_headerblock {
|
||||
union {
|
||||
/* Superblock payload. */
|
||||
struct {
|
||||
/* Offset in bytes from the start of the AFBC buffer (1st header
|
||||
* block) to the start of the superblock payload data. */
|
||||
uint32_t offset;
|
||||
|
||||
/* Sizes in bytes of the 4x4 6-bit subblocks. */
|
||||
uint8_t subblock_sizes[12];
|
||||
} payload;
|
||||
|
||||
/* Solid color. */
|
||||
struct {
|
||||
uint64_t reserved;
|
||||
|
||||
/* RGBA 8-8-8-8 color format. */
|
||||
/* XXX: Add other formats. */
|
||||
struct {
|
||||
uint8_t r, g, b, a;
|
||||
uint32_t reserved;
|
||||
} rgba8888;
|
||||
} color;
|
||||
|
||||
/* Random access. */
|
||||
uint8_t u8[16];
|
||||
uint16_t u16[8];
|
||||
uint32_t u32[4];
|
||||
uint64_t u64[2];
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Given an AFBC modifier, return the superblock size.
|
||||
*
|
||||
|
|
@ -215,6 +251,77 @@ pan_afbc_subblock_size(uint64_t modifier)
|
|||
return (struct pan_image_block_size){4, 4};
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an AFBC header block, return the size of the subblock at the given
|
||||
* index in the range [0, 15].
|
||||
*/
|
||||
static inline unsigned
|
||||
pan_afbc_header_subblock_size(struct pan_afbc_headerblock header,
|
||||
uint32_t index)
|
||||
{
|
||||
uint64_t mask = BITFIELD_MASK(6);
|
||||
|
||||
switch (index) {
|
||||
case 0: return (header.u64[0] >> 32) & mask; break;
|
||||
case 1: return (header.u64[0] >> 38) & mask; break;
|
||||
case 2: return (header.u64[0] >> 44) & mask; break;
|
||||
case 3: return (header.u64[0] >> 50) & mask; break;
|
||||
case 4: return (header.u64[0] >> 56) & mask; break;
|
||||
case 5: return ((header.u64[0] >> 62) |
|
||||
(header.u64[1] << 2)) & mask; break;
|
||||
case 6: return (header.u64[1] >> 4) & mask; break;
|
||||
case 7: return (header.u64[1] >> 10) & mask; break;
|
||||
case 8: return (header.u64[1] >> 16) & mask; break;
|
||||
case 9: return (header.u64[1] >> 22) & mask; break;
|
||||
case 10: return (header.u64[1] >> 28) & mask; break;
|
||||
case 11: return (header.u64[1] >> 34) & mask; break;
|
||||
case 12: return (header.u64[1] >> 40) & mask; break;
|
||||
case 13: return (header.u64[1] >> 46) & mask; break;
|
||||
case 14: return (header.u64[1] >> 52) & mask; break;
|
||||
case 15: return (header.u64[1] >> 58) & mask; break;
|
||||
default: unreachable("invalid index"); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an AFBC header block, return the size in bytes of the associated
|
||||
* superblock payload data (for the superblock layouts 0, 3, 4 and 7).
|
||||
*/
|
||||
static inline uint32_t
|
||||
pan_afbc_payload_size(unsigned arch,
|
||||
struct pan_afbc_headerblock header,
|
||||
uint32_t uncompressed_size)
|
||||
{
|
||||
/* Skip sum if the 1st subblock is 0 (solid color encoding). */
|
||||
if (arch >= 7 && pan_afbc_header_subblock_size(header, 0) == 0)
|
||||
return 0;
|
||||
|
||||
uint64_t size = 0;
|
||||
|
||||
for (unsigned i = 0; i < 16; i++) {
|
||||
unsigned sub_size = pan_afbc_header_subblock_size(header, i);
|
||||
size += sub_size != 1 ? sub_size : uncompressed_size;
|
||||
}
|
||||
|
||||
return ALIGN_POT(size, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a format and a modifier, return the size in bytes of an uncompressed
|
||||
* superblock payload.
|
||||
*/
|
||||
static inline uint32_t
|
||||
pan_afbc_payload_uncompressed_size(enum pipe_format format, uint64_t modifier)
|
||||
{
|
||||
struct pan_image_block_size size_px = pan_afbc_subblock_size(modifier);
|
||||
uint32_t size_B = util_format_get_blocksizebits(format) / 8;
|
||||
size_B *= size_px.width * size_px.height;
|
||||
|
||||
assert(size_B == ALIGN_POT(size_B, 16));
|
||||
|
||||
return size_B;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
pan_afbc_header_row_stride_align(unsigned arch, enum pipe_format format,
|
||||
uint64_t modifier)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue