ail: Introduce support for compression
The main buffer is twiddled as before, but there's now also an auxiliary compression buffer that we need to reserve space for. With compression, the main buffer is aligned less. The macOS logic seems to be to align to the page size only if the texture is both 3D and mipmapped, *and* the layer stride is greater than the page size. That's gated on compression being enabled. Page alignment seems to be needed for uncompressed twiddled cube maps. Signed-off-by: Asahi Lina <lina@asahilina.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19999>
This commit is contained in:
@@ -163,11 +163,52 @@ ail_initialize_twiddled(struct ail_layout *layout)
|
||||
poth_el = u_minify(poth_el, 1);
|
||||
}
|
||||
|
||||
/* Arrays and cubemaps have the entire miptree duplicated and page aligned */
|
||||
layout->layer_stride_B = ALIGN_POT(offset_B, AIL_PAGESIZE);
|
||||
/* Arrays and cubemaps have the entire miptree duplicated and page aligned,
|
||||
* but only when mipmaps are enabled and the layer is larger than one page.
|
||||
*/
|
||||
if ((layout->levels != 1 && layout->depth_px != 1 && offset_B > AIL_PAGESIZE)
|
||||
|| layout->tiling != AIL_TILING_TWIDDLED_COMPRESSED)
|
||||
layout->layer_stride_B = ALIGN_POT(offset_B, AIL_PAGESIZE);
|
||||
else
|
||||
layout->layer_stride_B = offset_B;
|
||||
|
||||
layout->size_B = layout->layer_stride_B * layout->depth_px;
|
||||
}
|
||||
|
||||
static void
|
||||
ail_initialize_compression(struct ail_layout *layout)
|
||||
{
|
||||
assert(!util_format_is_compressed(layout->format) && "Compressed pixel formats not supported");
|
||||
assert(util_format_get_blockwidth(layout->format) == 1);
|
||||
assert(util_format_get_blockheight(layout->format) == 1);
|
||||
assert(layout->width_px >= 16 && "Small textures are never compressed");
|
||||
assert(layout->height_px >= 16 && "Small textures are never compressed");
|
||||
|
||||
layout->metadata_offset_B = layout->size_B;
|
||||
|
||||
unsigned width_px = layout->width_px;
|
||||
unsigned height_px = layout->height_px;
|
||||
|
||||
unsigned compbuf_B = 0;
|
||||
|
||||
for (unsigned l = 0; l < layout->levels; ++l) {
|
||||
if (width_px < 16 && height_px < 16)
|
||||
break;
|
||||
|
||||
/* The compression buffer seems to have one byte per 8 x 4
|
||||
* pixel block.
|
||||
*/
|
||||
unsigned cmpw_el = DIV_ROUND_UP(util_next_power_of_two(width_px), 8);
|
||||
unsigned cmph_el = DIV_ROUND_UP(util_next_power_of_two(height_px), 4);
|
||||
compbuf_B += ALIGN_POT(cmpw_el * cmph_el, AIL_CACHELINE);
|
||||
|
||||
width_px = u_minify(width_px, 1);
|
||||
height_px = u_minify(height_px, 1);
|
||||
}
|
||||
|
||||
layout->size_B += compbuf_B * layout->depth_px;
|
||||
}
|
||||
|
||||
void
|
||||
ail_make_miptree(struct ail_layout *layout)
|
||||
{
|
||||
@@ -193,13 +234,21 @@ ail_make_miptree(struct ail_layout *layout)
|
||||
assert(util_format_get_blockdepth(layout->format) == 1 &&
|
||||
"Deep formats unsupported");
|
||||
|
||||
if (layout->tiling == AIL_TILING_LINEAR)
|
||||
switch (layout->tiling) {
|
||||
case AIL_TILING_LINEAR:
|
||||
ail_initialize_linear(layout);
|
||||
else if (layout->tiling == AIL_TILING_TWIDDLED)
|
||||
break;
|
||||
case AIL_TILING_TWIDDLED:
|
||||
ail_initialize_twiddled(layout);
|
||||
else
|
||||
break;
|
||||
case AIL_TILING_TWIDDLED_COMPRESSED:
|
||||
ail_initialize_twiddled(layout);
|
||||
ail_initialize_compression(layout);
|
||||
break;
|
||||
default:
|
||||
unreachable("Unsupported tiling");
|
||||
}
|
||||
|
||||
layout->size_B = ALIGN_POT(layout->size_B, AIL_PAGESIZE);
|
||||
layout->size_B = ALIGN_POT(layout->size_B, AIL_CACHELINE);
|
||||
assert(layout->size_B > 0 && "Invalid dimensions");
|
||||
}
|
||||
|
||||
@@ -48,6 +48,11 @@ enum ail_tiling {
|
||||
* Twiddled (Morton order). Always allowed.
|
||||
*/
|
||||
AIL_TILING_TWIDDLED,
|
||||
|
||||
/**
|
||||
* Twiddled (Morton order) with compression.
|
||||
*/
|
||||
AIL_TILING_TWIDDLED_COMPRESSED,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -106,6 +111,9 @@ struct ail_layout {
|
||||
*/
|
||||
struct ail_tile tilesize_el[AIL_MAX_MIP_LEVELS];
|
||||
|
||||
/* Offset of the start of the compression metadata buffer */
|
||||
uint32_t metadata_offset_B;
|
||||
|
||||
/* Size of entire texture */
|
||||
uint32_t size_B;
|
||||
};
|
||||
@@ -174,6 +182,12 @@ ail_get_linear_pixel_B(struct ail_layout *layout, ASSERTED unsigned level,
|
||||
(x_px * util_format_get_blocksize(layout->format));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ail_is_compressed(struct ail_layout *layout)
|
||||
{
|
||||
return layout->tiling == AIL_TILING_TWIDDLED_COMPRESSED;
|
||||
}
|
||||
|
||||
void ail_make_miptree(struct ail_layout *layout);
|
||||
|
||||
void
|
||||
|
||||
@@ -56,7 +56,7 @@ TEST(Miptree, SmokeTestBuffer)
|
||||
|
||||
ail_make_miptree(&layout);
|
||||
|
||||
EXPECT_EQ(layout.size_B, ALIGN_POT(81946, 0x4000));
|
||||
EXPECT_EQ(layout.size_B, ALIGN_POT(81946, AIL_CACHELINE));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user