summaryrefslogtreecommitdiffstats
path: root/src/freedreno/fdl/fd6_layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno/fdl/fd6_layout.c')
-rw-r--r--src/freedreno/fdl/fd6_layout.c108
1 files changed, 89 insertions, 19 deletions
diff --git a/src/freedreno/fdl/fd6_layout.c b/src/freedreno/fdl/fd6_layout.c
index 82b3a3e715c..966a3e4bbc4 100644
--- a/src/freedreno/fdl/fd6_layout.c
+++ b/src/freedreno/fdl/fd6_layout.c
@@ -29,28 +29,39 @@
#include "freedreno_layout.h"
-/* indexed by cpp, including msaa 2x and 4x: */
+/* indexed by cpp, including msaa 2x and 4x:
+ * TODO:
+ * cpp=1 UBWC needs testing at larger texture sizes
+ * missing UBWC blockwidth/blockheight for npot+64 cpp
+ * missing 96/128 CPP for 8x MSAA with 32_32_32/32_32_32_32
+ */
static const struct {
unsigned pitchalign;
unsigned heightalign;
+ uint8_t ubwc_blockwidth;
+ uint8_t ubwc_blockheight;
} tile_alignment[] = {
- [1] = { 128, 32 },
- [2] = { 128, 16 },
+ [1] = { 128, 32, 16, 4 },
+ [2] = { 128, 16, 16, 4 },
[3] = { 64, 32 },
- [4] = { 64, 16 },
+ [4] = { 64, 16, 16, 4 },
[6] = { 64, 16 },
- [8] = { 64, 16 },
+ [8] = { 64, 16, 8, 4, },
[12] = { 64, 16 },
- [16] = { 64, 16 },
+ [16] = { 64, 16, 4, 4, },
[24] = { 64, 16 },
- [32] = { 64, 16 },
+ [32] = { 64, 16, 4, 2 },
[48] = { 64, 16 },
[64] = { 64, 16 },
/* special cases for r8g8: */
- [0] = { 64, 32 },
+ [0] = { 64, 32, 16, 4 },
};
+#define RGB_TILE_WIDTH_ALIGNMENT 64
+#define RGB_TILE_HEIGHT_ALIGNMENT 16
+#define UBWC_PLANE_SIZE_ALIGNMENT 4096
+
/* NOTE: good way to test this is: (for example)
* piglit/bin/texelFetch fs sampler3D 100x100x8
*/
@@ -58,7 +69,7 @@ void
fdl6_layout(struct fdl_layout *layout,
enum pipe_format format, uint32_t nr_samples,
uint32_t width0, uint32_t height0, uint32_t depth0,
- uint32_t mip_levels, uint32_t array_size, bool is_3d)
+ uint32_t mip_levels, uint32_t array_size, bool is_3d, bool ubwc)
{
assert(nr_samples > 0);
layout->width0 = width0;
@@ -70,7 +81,6 @@ fdl6_layout(struct fdl_layout *layout,
const struct util_format_description *format_desc =
util_format_description(format);
- uint32_t level;
uint32_t depth = depth0;
/* linear dimensions: */
uint32_t lwidth = width0;
@@ -100,9 +110,11 @@ fdl6_layout(struct fdl_layout *layout,
debug_assert(ta < ARRAY_SIZE(tile_alignment));
debug_assert(tile_alignment[ta].pitchalign);
- for (level = 0; level < mip_levels; level++) {
+ for (uint32_t level = 0; level < mip_levels; level++) {
struct fdl_slice *slice = &layout->slices[level];
- uint32_t tile_mode = fdl_tile_mode(layout, level);
+ struct fdl_slice *ubwc_slice = &layout->ubwc_slices[level];
+ uint32_t tile_mode = (ubwc ?
+ layout->tile_mode : fdl_tile_mode(layout, level));
uint32_t width, height;
/* tiled levels of 3D textures are rounded up to PoT dimensions: */
@@ -162,13 +174,30 @@ fdl6_layout(struct fdl_layout *layout,
layout->size += slice->size0 * depth * layers_in_level;
- if (false) {
- fprintf(stderr, "%s: %ux%ux%u@%u:\t%2u: stride=%4u, size=%6u,%7u, aligned_height=%3u, blocks=%u, offset=0x%x tiling=%d\n",
- util_format_name(format),
- width, height, depth, layout->cpp,
- level, slice->pitch * layout->cpp,
- slice->size0, layout->size, aligned_height, blocks,
- slice->offset, tile_mode);
+ if (ubwc) {
+ /* with UBWC every level is aligned to 4K */
+ layout->size = align(layout->size, 4096);
+
+ uint32_t block_width = tile_alignment[ta].ubwc_blockwidth;
+ uint32_t block_height = tile_alignment[ta].ubwc_blockheight;
+ uint32_t meta_pitch = align(DIV_ROUND_UP(width, block_width),
+ RGB_TILE_WIDTH_ALIGNMENT);
+ uint32_t meta_height = align(DIV_ROUND_UP(height, block_height),
+ RGB_TILE_HEIGHT_ALIGNMENT);
+
+ /* it looks like mipmaps need alignment to power of two
+ * TODO: needs testing with large npot textures
+ * (needed for the first level?)
+ */
+ if (mip_levels > 1) {
+ meta_pitch = util_next_power_of_two(meta_pitch);
+ meta_height = util_next_power_of_two(meta_height);
+ }
+
+ ubwc_slice->size0 = align(meta_pitch * meta_height, UBWC_PLANE_SIZE_ALIGNMENT);
+ ubwc_slice->pitch = meta_pitch;
+ ubwc_slice->offset = layout->ubwc_size;
+ layout->ubwc_size += ubwc_slice->size0;
}
depth = u_minify(depth, 1);
@@ -182,4 +211,45 @@ fdl6_layout(struct fdl_layout *layout,
layout->layer_size = align(layout->size, 4096);
layout->size = layout->layer_size * array_size;
}
+
+ /* Place the UBWC slices before the uncompressed slices, because the
+ * kernel expects UBWC to be at the start of the buffer. In the HW, we
+ * get to program the UBWC and non-UBWC offset/strides
+ * independently.
+ */
+ if (ubwc) {
+ for (uint32_t level = 0; level < mip_levels; level++)
+ layout->slices[level].offset += layout->ubwc_size * array_size;
+ layout->size += layout->ubwc_size * array_size;
+ }
+
+ if (false) {
+ for (uint32_t level = 0; level < mip_levels; level++) {
+ struct fdl_slice *slice = &layout->slices[level];
+ struct fdl_slice *ubwc_slice = &layout->ubwc_slices[level];
+ uint32_t tile_mode = (ubwc ?
+ layout->tile_mode : fdl_tile_mode(layout, level));
+
+ fprintf(stderr, "%s: %ux%ux%u@%ux%u:\t%2u: stride=%4u, size=%6u,%6u, aligned_height=%3u, offset=0x%x,0x%x tiling=%d\n",
+ util_format_name(format),
+ u_minify(layout->width0, level),
+ u_minify(layout->height0, level),
+ u_minify(layout->depth0, level),
+ layout->cpp, nr_samples,
+ level,
+ slice->pitch * layout->cpp,
+ slice->size0, ubwc_slice->size0,
+ slice->size0 / (slice->pitch * layout->cpp),
+ slice->offset, ubwc_slice->offset,
+ tile_mode);
+ }
+ }
+}
+
+void
+fdl6_get_ubwc_blockwidth(struct fdl_layout *layout,
+ uint32_t *blockwidth, uint32_t *blockheight)
+{
+ *blockwidth = tile_alignment[layout->cpp].ubwc_blockwidth;
+ *blockheight = tile_alignment[layout->cpp].ubwc_blockheight;
}