summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorIlia Mirkin <[email protected]>2015-03-15 16:38:42 -0400
committerIlia Mirkin <[email protected]>2015-03-28 14:54:41 -0400
commit738c8319ac85b175994b35d1fdc4860e18184b93 (patch)
treefa4e619e073edd5ee486a7fde3f2c0cd5ace8f45 /src/gallium
parent3735643df3fc29d7ce84b2156c53f23a3092765c (diff)
freedreno/a3xx: fix 3d texture layout
The SZ2 field contains the layer size of a lower miplevel. It only contains 4 bits, which limits the maximum layer size it can describe. In situations where the next miplevel would be too big, the hardware appears to keep minifying the size until it hits one of that size. Unfortunately the hardware's ideas about sizes can differ from freedreno's which can still lead to issues. Minimize those by stopping to minify as soon as possible. Signed-off-by: Ilia Mirkin <[email protected]> Cc: "10.4 10.5" <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_texture.c7
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c16
2 files changed, 16 insertions, 7 deletions
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
index 05d826e40ec..69e2d587c93 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
@@ -212,6 +212,7 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
struct fd_resource *rsc = fd_resource(prsc);
unsigned lvl = cso->u.tex.first_level;
unsigned miplevels = cso->u.tex.last_level - lvl;
+ uint32_t sz2 = 0;
if (!so)
return NULL;
@@ -251,8 +252,10 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
case PIPE_TEXTURE_3D:
so->texconst3 =
A3XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) |
- A3XX_TEX_CONST_3_LAYERSZ1(rsc->slices[0].size0) |
- A3XX_TEX_CONST_3_LAYERSZ2(rsc->slices[0].size0);
+ A3XX_TEX_CONST_3_LAYERSZ1(rsc->slices[lvl].size0);
+ while (lvl < cso->u.tex.last_level && sz2 != rsc->slices[lvl+1].size0)
+ sz2 = rsc->slices[++lvl].size0;
+ so->texconst3 |= A3XX_TEX_CONST_3_LAYERSZ2(sz2);
break;
default:
so->texconst3 = 0x00000000;
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c
index 69e54526848..efafb8988b4 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -215,14 +215,20 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
slice->pitch = width = align(width, 32);
slice->offset = size;
- /* 1d array, 2d array, 3d textures (but not cube!) must all have the
- * same layer size for each miplevel on a3xx. These are also the
- * targets that have non-1 alignment.
+ /* 1d array and 2d array textures must all have the same layer size
+ * for each miplevel on a3xx. 3d textures can have different layer
+ * sizes for high levels, but the hw auto-sizer is buggy (or at least
+ * different than what this code does), so as soon as the layer size
+ * range gets into range, we stop reducing it.
*/
- if (level == 0 || layers_in_level == 1 || alignment == 1)
+ if (prsc->target == PIPE_TEXTURE_3D && (
+ level == 1 ||
+ (level > 1 && rsc->slices[level - 1].size0 > 0xf000)))
+ slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
+ else if (level == 0 || rsc->layer_first || alignment == 1)
slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
else
- slice->size0 = rsc->slices[0].size0;
+ slice->size0 = rsc->slices[level - 1].size0;
size += slice->size0 * depth * layers_in_level;