summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/a6xx
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2019-01-03 10:10:28 -0500
committerRob Clark <[email protected]>2019-01-10 14:21:39 -0500
commit031e94dc72bda818e440bb66a8caf52e3d669748 (patch)
tree241ef862783c50fda091917cf67e96af9db47533 /src/gallium/drivers/freedreno/a6xx
parentc92c18c70caf22eb9d733d8037da736ee78d5cf6 (diff)
freedreno/a6xx: fix 3d+tiled layout
The last round of fixing 3d layer+level layout skipped the tiled case, since tiled texture support was not in place yet. This finishes the job. Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/a6xx')
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_resource.c86
1 files changed, 52 insertions, 34 deletions
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c
index fb24d230c44..ff869d7d87b 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c
@@ -27,18 +27,26 @@
#include "fd6_resource.h"
-/* indexed by cpp: */
+/* indexed by cpp, including msaa 2x and 4x: */
static const struct {
unsigned pitchalign;
unsigned heightalign;
} tile_alignment[] = {
[1] = { 128, 32 },
- [2] = { 128, 16 },
- [3] = { 128, 16 },
+ [2] = { 64, 32 },
+ [3] = { 64, 32 },
[4] = { 64, 16 },
+ [6] = { 64, 16 },
[8] = { 64, 16 },
[12] = { 64, 16 },
[16] = { 64, 16 },
+ [24] = { 64, 16 },
+ [32] = { 64, 16 },
+ [48] = { 64, 16 },
+ [64] = { 64, 16 },
+
+ /* special cases for r16: */
+ [0] = { 128, 16 },
};
/* NOTE: good way to test this is: (for example)
@@ -51,53 +59,61 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format forma
struct fd_screen *screen = fd_screen(prsc->screen);
enum util_format_layout layout = util_format_description(format)->layout;
uint32_t pitchalign = screen->gmem_alignw;
- uint32_t heightalign;
uint32_t level, size = 0;
- uint32_t width = prsc->width0;
- uint32_t height = prsc->height0;
uint32_t depth = prsc->depth0;
+ /* linear dimensions: */
+ uint32_t lwidth = prsc->width0;
+ uint32_t lheight = prsc->height0;
+ /* tile_mode dimensions: */
+ uint32_t twidth = util_next_power_of_two(lwidth);
+ uint32_t theight = util_next_power_of_two(lheight);
/* in layer_first layout, the level (slice) contains just one
* layer (since in fact the layer contains the slices)
*/
uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size;
+ int ta = rsc->cpp;
+
+ /* The z16/r16 formats seem to not play by the normal tiling rules: */
+ if ((rsc->cpp == 2) && (util_format_get_nr_components(format) == 1))
+ ta = 0;
- heightalign = tile_alignment[rsc->cpp].heightalign;
+ debug_assert(ta < ARRAY_SIZE(tile_alignment));
+ debug_assert(tile_alignment[ta].pitchalign);
for (level = 0; level <= prsc->last_level; level++) {
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
bool linear_level = fd_resource_level_linear(prsc, level);
+ uint32_t width, height;
+
+ /* tiled levels of 3D textures are rounded up to PoT dimensions: */
+ if ((prsc->target == PIPE_TEXTURE_3D) && rsc->tile_mode && !linear_level) {
+ width = twidth;
+ height = theight;
+ } else {
+ width = lwidth;
+ height = lheight;
+ }
uint32_t aligned_height = height;
uint32_t blocks;
if (rsc->tile_mode && !linear_level) {
- pitchalign = tile_alignment[rsc->cpp].pitchalign;
- aligned_height = align(aligned_height, heightalign);
+ pitchalign = tile_alignment[ta].pitchalign;
+ aligned_height = align(aligned_height,
+ tile_alignment[ta].heightalign);
} else {
- if (prsc->target == PIPE_TEXTURE_3D) {
- unsigned a;
- if (width >= 64) {
- a = util_next_power_of_two(MAX2(width, height));
- } else {
- a = 16;
- }
-
- pitchalign = align(a, 64);
- aligned_height = align(aligned_height, a);
- } 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
- * bit the last level to ensure any over-fetch is harmless.
- * The pitch is already sufficiently aligned, but height
- * may not be:
- */
- if ((level == prsc->last_level) && (prsc->target != PIPE_BUFFER))
- aligned_height = align(aligned_height, 32);
+ 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
+ * bit the last level to ensure any over-fetch is harmless.
+ * The pitch is already sufficiently aligned, but height
+ * may not be:
+ */
+ if ((level == prsc->last_level) && (prsc->target != PIPE_BUFFER))
+ aligned_height = align(aligned_height, 32);
+
if (layout == UTIL_FORMAT_LAYOUT_ASTC)
slice->pitch =
util_align_npot(width, pitchalign * util_format_get_blockwidth(format));
@@ -133,9 +149,11 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format forma
slice->size0, size, aligned_height, blocks);
#endif
- width = u_minify(width, 1);
- height = u_minify(height, 1);
depth = u_minify(depth, 1);
+ lwidth = u_minify(lwidth, 1);
+ lheight = u_minify(lheight, 1);
+ twidth = u_minify(twidth, 1);
+ theight = u_minify(theight, 1);
}
return size;