diff options
author | Jonathan Marek <[email protected]> | 2020-07-07 18:27:32 -0400 |
---|---|---|
committer | Marge Bot <[email protected]> | 2020-07-08 20:46:08 +0000 |
commit | 979e7e3680792dc23d434295edd10b161af8aee3 (patch) | |
tree | 3a04deaed74d2a95215e05c8c8ccb00884e05f1b /src/freedreno/fdl | |
parent | 4b290b759a8c85c7d493f1ddd7d38b322bbe1276 (diff) |
freedreno/layout: layout simplifications and pitch from level 0 pitch
This updates a3xx/a4xx/a5xx to fix the fetchsize to "PITCHALIGN" (called
"MINLINEOFFSET" by the a3xx docs), and some simplifications to make things
more like a6xx. Also similar simplifications for a2xx layout code.
The pitch can always be determined using a simple calculation from the base
level pitch, so don't pre-calculate a pitch for each mipmap level.
Signed-off-by: Jonathan Marek <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5796>
Diffstat (limited to 'src/freedreno/fdl')
-rw-r--r-- | src/freedreno/fdl/fd5_layout.c | 60 | ||||
-rw-r--r-- | src/freedreno/fdl/fd6_layout.c | 39 | ||||
-rw-r--r-- | src/freedreno/fdl/fd_layout_test.c | 8 | ||||
-rw-r--r-- | src/freedreno/fdl/fd_layout_test.h | 15 | ||||
-rw-r--r-- | src/freedreno/fdl/freedreno_layout.c | 4 | ||||
-rw-r--r-- | src/freedreno/fdl/freedreno_layout.h | 55 |
6 files changed, 99 insertions, 82 deletions
diff --git a/src/freedreno/fdl/fd5_layout.c b/src/freedreno/fdl/fd5_layout.c index da74b18fe59..159773fff61 100644 --- a/src/freedreno/fdl/fd5_layout.c +++ b/src/freedreno/fdl/fd5_layout.c @@ -29,29 +29,12 @@ #include "freedreno_layout.h" -/* indexed by cpp: */ -static const struct { - unsigned pitchalign; - unsigned heightalign; -} tile_alignment[] = { - [1] = { 128, 32 }, - [2] = { 128, 16 }, - [3] = { 128, 16 }, - [4] = { 64, 16 }, - [8] = { 64, 16 }, - [12] = { 64, 16 }, - [16] = { 64, 16 }, -}; - void fdl5_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) { - const struct util_format_description *format_desc = - util_format_description(format); - assert(nr_samples > 0); layout->width0 = width0; layout->height0 = height0; @@ -65,30 +48,27 @@ fdl5_layout(struct fdl_layout *layout, layout->nr_samples = nr_samples; layout->layer_first = !is_3d; - uint32_t pitchalign; - uint32_t heightalign; - uint32_t width = width0; - uint32_t height = height0; - uint32_t depth = depth0; + uint32_t heightalign = layout->cpp == 1 ? 32 : 16; /* in layer_first layout, the level (slice) contains just one * layer (since in fact the layer contains the slices) */ uint32_t layers_in_level = layout->layer_first ? 1 : array_size; - heightalign = tile_alignment[layout->cpp].heightalign; + /* use 128 pixel alignment for cpp=1 and cpp=2 */ + if (layout->cpp < 4 && layout->tile_mode) + fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 7); + else + fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 6); 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); - uint32_t aligned_height = height; - uint32_t blocks; + uint32_t pitch = fdl_pitch(layout, level); + uint32_t nblocksy = util_format_get_nblocksy(format, u_minify(height0, level)); if (tile_mode) { - pitchalign = tile_alignment[layout->cpp].pitchalign; - aligned_height = align(aligned_height, heightalign); + nblocksy = align(nblocksy, heightalign); } else { - pitchalign = 64; - /* The blits used for mem<->gmem work at a granularity of * 32x32, which can cause faults due to over-fetch on the * last level. The simple solution is to over-allocate a @@ -97,20 +77,10 @@ fdl5_layout(struct fdl_layout *layout, * may not be: */ if (level == mip_levels - 1) - aligned_height = align(aligned_height, 32); + nblocksy = align(nblocksy, 32); } - unsigned pitch_pixels; - if (format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC) - pitch_pixels = - util_align_npot(width, pitchalign * util_format_get_blockwidth(format)); - else - pitch_pixels = align(width, pitchalign); - slice->offset = layout->size; - blocks = util_format_get_nblocks(format, pitch_pixels, aligned_height); - slice->pitch = util_format_get_nblocksx(format, pitch_pixels) * - layout->cpp; const int alignment = is_3d ? 4096 : 1; @@ -123,17 +93,13 @@ fdl5_layout(struct fdl_layout *layout, if (is_3d && ( level == 1 || (level > 1 && layout->slices[level - 1].size0 > 0xf000))) - slice->size0 = align(blocks * layout->cpp, alignment); + slice->size0 = align(nblocksy * pitch, alignment); else if (level == 0 || layout->layer_first || alignment == 1) - slice->size0 = align(blocks * layout->cpp, alignment); + slice->size0 = align(nblocksy * pitch, alignment); else slice->size0 = layout->slices[level - 1].size0; - layout->size += slice->size0 * depth * layers_in_level; - - width = u_minify(width, 1); - height = u_minify(height, 1); - depth = u_minify(depth, 1); + layout->size += slice->size0 * u_minify(depth0, level) * layers_in_level; } } diff --git a/src/freedreno/fdl/fd6_layout.c b/src/freedreno/fdl/fd6_layout.c index 47a6c852da7..096af1672a2 100644 --- a/src/freedreno/fdl/fd6_layout.c +++ b/src/freedreno/fdl/fd6_layout.c @@ -29,10 +29,6 @@ #include "freedreno_layout.h" -#define RGB_TILE_WIDTH_ALIGNMENT 64 -#define RGB_TILE_HEIGHT_ALIGNMENT 16 -#define UBWC_PLANE_SIZE_ALIGNMENT 4096 - static bool is_r8g8(struct fdl_layout *layout) { @@ -103,10 +99,9 @@ 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, - struct fdl_slice *plane_layout) + struct fdl_explicit_layout *explicit_layout) { - uint32_t offset, pitch0; - uint32_t pitchalign, heightalign; + uint32_t offset = 0, heightalign; uint32_t ubwc_blockwidth, ubwc_blockheight; assert(nr_samples > 0); @@ -152,24 +147,20 @@ fdl6_layout(struct fdl_layout *layout, /* when possible, use a bit more alignment than necessary * presumably this is better for performance? */ - if (!plane_layout) + if (!explicit_layout) layout->pitchalign = fdl_cpp_shift(layout); /* not used, avoid "may be used uninitialized" warning */ heightalign = 1; } - pitchalign = 64 << layout->pitchalign; + fdl_set_pitchalign(layout, layout->pitchalign + 6); - if (plane_layout) { - offset = plane_layout->offset; - pitch0 = plane_layout->pitch; - if (align(pitch0, pitchalign) != pitch0) + if (explicit_layout) { + offset = explicit_layout->offset; + layout->pitch0 = explicit_layout->pitch; + if (align(layout->pitch0, 1 << layout->pitchalign) != layout->pitch0) return false; - } else { - uint32_t nblocksx = util_format_get_nblocksx(format, width0); - offset = 0; - pitch0 = util_align_npot(nblocksx * layout->cpp, pitchalign); } uint32_t ubwc_width0 = width0; @@ -185,8 +176,8 @@ fdl6_layout(struct fdl_layout *layout, ubwc_height0 = util_next_power_of_two(height0); ubwc_tile_height_alignment = 64; } - ubwc_width0 = align(DIV_ROUND_UP(ubwc_width0, ubwc_blockwidth), - RGB_TILE_WIDTH_ALIGNMENT); + layout->ubwc_width0 = align(DIV_ROUND_UP(ubwc_width0, ubwc_blockwidth), + RGB_TILE_WIDTH_ALIGNMENT); ubwc_height0 = align(DIV_ROUND_UP(ubwc_height0, ubwc_blockheight), ubwc_tile_height_alignment); @@ -195,6 +186,7 @@ fdl6_layout(struct fdl_layout *layout, struct fdl_slice *slice = &layout->slices[level]; struct fdl_slice *ubwc_slice = &layout->ubwc_slices[level]; uint32_t tile_mode = fdl_tile_mode(layout, level); + uint32_t pitch = fdl_pitch(layout, level); uint32_t height; /* tiled levels of 3D textures are rounded up to PoT dimensions: */ @@ -219,7 +211,6 @@ fdl6_layout(struct fdl_layout *layout, height = align(nblocksy, 4); slice->offset = offset + layout->size; - slice->pitch = align(u_minify(pitch0, level), pitchalign); /* 1d array and 2d array textures must all have the same layer size * for each miplevel on a6xx. 3d textures can have different layer @@ -229,12 +220,12 @@ fdl6_layout(struct fdl_layout *layout, */ if (is_3d) { if (level < 1 || layout->slices[level - 1].size0 > 0xf000) { - slice->size0 = align(nblocksy * slice->pitch, 4096); + slice->size0 = align(nblocksy * pitch, 4096); } else { slice->size0 = layout->slices[level - 1].size0; } } else { - slice->size0 = nblocksy * slice->pitch; + slice->size0 = nblocksy * pitch; } layout->size += slice->size0 * depth * layers_in_level; @@ -243,13 +234,11 @@ fdl6_layout(struct fdl_layout *layout, /* with UBWC every level is aligned to 4K */ layout->size = align(layout->size, 4096); - uint32_t meta_pitch = align(u_minify(ubwc_width0, level), - RGB_TILE_WIDTH_ALIGNMENT); + uint32_t meta_pitch = fdl_ubwc_pitch(layout, level); uint32_t meta_height = align(u_minify(ubwc_height0, level), ubwc_tile_height_alignment); ubwc_slice->size0 = align(meta_pitch * meta_height, UBWC_PLANE_SIZE_ALIGNMENT); - ubwc_slice->pitch = meta_pitch; ubwc_slice->offset = offset + layout->ubwc_layer_size; layout->ubwc_layer_size += ubwc_slice->size0; } diff --git a/src/freedreno/fdl/fd_layout_test.c b/src/freedreno/fdl/fd_layout_test.c index 99d17e52cc6..08e8c1b2509 100644 --- a/src/freedreno/fdl/fd_layout_test.c +++ b/src/freedreno/fdl/fd_layout_test.c @@ -89,12 +89,12 @@ bool fdl_test_layout(const struct testcase *testcase, int gpu_id) testcase->layout.slices[l].offset); ok = false; } - if (layout.slices[l].pitch != testcase->layout.slices[l].pitch) { + if (fdl_pitch(&layout, l) != testcase->layout.slices[l].pitch) { fprintf(stderr, "%s %dx%dx%d@%dx lvl%d: pitch %d != %d\n", util_format_short_name(testcase->format), layout.width0, layout.height0, layout.depth0, layout.nr_samples, l, - layout.slices[l].pitch, + fdl_pitch(&layout, l), testcase->layout.slices[l].pitch); ok = false; } @@ -108,12 +108,12 @@ bool fdl_test_layout(const struct testcase *testcase, int gpu_id) testcase->layout.ubwc_slices[l].offset); ok = false; } - if (layout.ubwc_slices[l].pitch != testcase->layout.ubwc_slices[l].pitch) { + if (fdl_ubwc_pitch(&layout, l) != testcase->layout.ubwc_slices[l].pitch) { fprintf(stderr, "%s %dx%dx%d@%dx lvl%d: UBWC pitch %d != %d\n", util_format_short_name(testcase->format), layout.width0, layout.height0, layout.depth0, layout.nr_samples, l, - layout.ubwc_slices[l].pitch, + fdl_ubwc_pitch(&layout, l), testcase->layout.ubwc_slices[l].pitch); ok = false; } diff --git a/src/freedreno/fdl/fd_layout_test.h b/src/freedreno/fdl/fd_layout_test.h index 0be7a4030a4..edf56cec511 100644 --- a/src/freedreno/fdl/fd_layout_test.h +++ b/src/freedreno/fdl/fd_layout_test.h @@ -28,7 +28,20 @@ struct testcase { bool is_3d; /* Partially filled layout of input parameters and expected results. */ - struct fdl_layout layout; + struct { + uint32_t tile_mode : 2; + bool ubwc : 1; + uint32_t width0, height0, depth0; + uint32_t nr_samples; + struct { + uint32_t offset; + uint32_t pitch; + } slices[FDL_MAX_MIP_LEVELS]; + struct { + uint32_t offset; + uint32_t pitch; + } ubwc_slices[FDL_MAX_MIP_LEVELS]; + } layout; }; bool fdl_test_layout(const struct testcase *testcase, int gpu_id); diff --git a/src/freedreno/fdl/freedreno_layout.c b/src/freedreno/fdl/freedreno_layout.c index 226382f271a..c6dc5ecf769 100644 --- a/src/freedreno/fdl/freedreno_layout.c +++ b/src/freedreno/fdl/freedreno_layout.c @@ -56,9 +56,9 @@ fdl_dump_layout(struct fdl_layout *layout) u_minify(layout->depth0, level), layout->cpp, layout->nr_samples, level, - slice->pitch, + fdl_pitch(layout, level), slice->size0, ubwc_slice->size0, - slice->size0 / slice->pitch, + slice->size0 / fdl_pitch(layout, level), slice->offset, ubwc_slice->offset, layout->layer_size, layout->ubwc_layer_size, fdl_tile_mode(layout, level)); diff --git a/src/freedreno/fdl/freedreno_layout.h b/src/freedreno/fdl/freedreno_layout.h index 3b2cb67c493..bae4be585b0 100644 --- a/src/freedreno/fdl/freedreno_layout.h +++ b/src/freedreno/fdl/freedreno_layout.h @@ -79,10 +79,15 @@ struct fdl_slice { uint32_t offset; /* offset of first layer in slice */ - uint32_t pitch; /* pitch in bytes between rows. */ uint32_t size0; /* size of first layer in slice */ }; +/* parameters for explicit (imported) layout */ +struct fdl_explicit_layout { + uint32_t offset; + uint32_t pitch; +}; + /** * Encapsulates the layout of a resource, including position of given 2d * surface (layer, level) within. Or rather all the information needed @@ -91,6 +96,8 @@ struct fdl_slice { struct fdl_layout { struct fdl_slice slices[FDL_MAX_MIP_LEVELS]; struct fdl_slice ubwc_slices[FDL_MAX_MIP_LEVELS]; + uint32_t pitch0; + uint32_t ubwc_width0; uint32_t layer_size; uint32_t ubwc_layer_size; /* in bytes */ bool ubwc : 1; @@ -121,7 +128,7 @@ struct fdl_layout { uint32_t size; /* Size of the whole image, in bytes. */ uint32_t base_align; /* Alignment of the base address, in bytes. */ - uint8_t pitchalign; /* log2(pitchalign / 64) */ + uint8_t pitchalign; /* log2(pitchalign) */ }; static inline uint32_t @@ -132,6 +139,24 @@ fdl_cpp_shift(const struct fdl_layout *layout) } static inline uint32_t +fdl_pitch(const struct fdl_layout *layout, unsigned level) +{ + return align(u_minify(layout->pitch0, level), 1 << layout->pitchalign); +} + +#define RGB_TILE_WIDTH_ALIGNMENT 64 +#define RGB_TILE_HEIGHT_ALIGNMENT 16 +#define UBWC_PLANE_SIZE_ALIGNMENT 4096 + +static inline uint32_t +fdl_ubwc_pitch(const struct fdl_layout *layout, unsigned level) +{ + if (!layout->ubwc) + return 0; + return align(u_minify(layout->ubwc_width0, level), RGB_TILE_WIDTH_ALIGNMENT); +} + +static inline uint32_t fdl_layer_stride(const struct fdl_layout *layout, unsigned level) { if (layout->layer_first) @@ -140,6 +165,22 @@ fdl_layer_stride(const struct fdl_layout *layout, unsigned level) return layout->slices[level].size0; } +/* a2xx is special and needs PoT alignment for mipmaps: */ +static inline uint32_t +fdl2_pitch(const struct fdl_layout *layout, unsigned level) +{ + uint32_t pitch = fdl_pitch(layout, level); + if (level) + pitch = util_next_power_of_two(pitch); + return pitch; +} + +static inline uint32_t +fdl2_pitch_pixels(const struct fdl_layout *layout, unsigned level) +{ + return fdl2_pitch(layout, level) >> fdl_cpp_shift(layout); +} + static inline uint32_t fdl_surface_offset(const struct fdl_layout *layout, unsigned level, unsigned layer) { @@ -196,7 +237,15 @@ 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, - struct fdl_slice *plane_layout); + struct fdl_explicit_layout *plane_layout); + +static inline void +fdl_set_pitchalign(struct fdl_layout *layout, unsigned pitchalign) +{ + uint32_t nblocksx = util_format_get_nblocksx(layout->format, layout->width0); + layout->pitchalign = pitchalign; + layout->pitch0 = align(nblocksx * layout->cpp, 1 << pitchalign); +} void fdl_dump_layout(struct fdl_layout *layout); |