aboutsummaryrefslogtreecommitdiffstats
path: root/src/freedreno/fdl
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno/fdl')
-rw-r--r--src/freedreno/fdl/fd5_layout.c60
-rw-r--r--src/freedreno/fdl/fd6_layout.c39
-rw-r--r--src/freedreno/fdl/fd_layout_test.c8
-rw-r--r--src/freedreno/fdl/fd_layout_test.h15
-rw-r--r--src/freedreno/fdl/freedreno_layout.c4
-rw-r--r--src/freedreno/fdl/freedreno_layout.h55
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);