From 207fb558e458106241740fe77adba27af8300983 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 30 Dec 2018 19:17:10 -0500 Subject: [PATCH] nv30: fix some s3tc layout issues s3tc layouts are a bit finicky - they're packed, but not swizzled. Adjust logic to allow for that case: - Don't set a uniform pitch for POT-sized compressed textures - Adjust define_rect API to be less confused about block sizes - Only mark a texture as linear if it has a uniform pitch set This has been tested to fix xonotic (as well as the s3tc-* piglits) on nv3x and keeps it working on nv4x. Signed-off-by: Ilia Mirkin --- .../drivers/nouveau/nv30/nv30_miptree.c | 31 +++++++++++++++---- .../drivers/nouveau/nv30/nv30_texture.c | 2 +- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c index d103ec133b5..4c8558bdf55 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c @@ -116,8 +116,22 @@ define_rect(struct pipe_resource *pt, unsigned level, unsigned z, rect->x0 = util_format_get_nblocksx(pt->format, x) << mt->ms_x; rect->y0 = util_format_get_nblocksy(pt->format, y) << mt->ms_y; - rect->x1 = rect->x0 + (w << mt->ms_x); - rect->y1 = rect->y0 + (h << mt->ms_y); + rect->x1 = rect->x0 + (util_format_get_nblocksx(pt->format, w) << mt->ms_x); + rect->y1 = rect->y0 + (util_format_get_nblocksy(pt->format, h) << mt->ms_y); + + /* XXX There's some indication that swizzled formats > 4 bytes are treated + * differently. However that only applies to RGBA16_FLOAT, RGBA32_FLOAT, + * and the DXT* formats. The former aren't properly supported yet, and the + * latter avoid swizzled layouts. + + if (mt->swizzled && rect->cpp > 4) { + unsigned scale = rect->cpp / 4; + rect->w *= scale; + rect->x0 *= scale; + rect->x1 *= scale; + rect->cpp = 4; + } + */ } void @@ -286,7 +300,7 @@ nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, tx->nblocksy = util_format_get_nblocksy(pt->format, box->height); define_rect(pt, level, box->z, box->x, box->y, - tx->nblocksx, tx->nblocksy, &tx->img); + box->width, box->height, &tx->img); ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, tx->base.layer_stride * tx->base.box.depth, NULL, @@ -435,8 +449,7 @@ nv30_miptree_create(struct pipe_screen *pscreen, !util_is_power_of_two_or_zero(pt->width0) || !util_is_power_of_two_or_zero(pt->height0) || !util_is_power_of_two_or_zero(pt->depth0) || - util_format_is_compressed(pt->format) || - util_format_is_float(pt->format) || mt->ms_mode) { + mt->ms_mode) { mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz; mt->uniform_pitch = align(mt->uniform_pitch, 64); if (pt->bind & PIPE_BIND_SCANOUT) { @@ -449,8 +462,14 @@ nv30_miptree_create(struct pipe_screen *pscreen, } } - if (!mt->uniform_pitch) + if (util_format_is_compressed(pt->format)) { + // Compressed (DXT) formats are packed tightly. We don't mark them as + // swizzled, since their layout is largely linear. However we do end up + // omitting the LINEAR flag when texturing them, as the levels are not + // uniformly sized (for POT sizes). + } else if (!mt->uniform_pitch) { mt->swizzled = true; + } size = 0; for (l = 0; l <= pt->last_level; l++) { diff --git a/src/gallium/drivers/nouveau/nv30/nv30_texture.c b/src/gallium/drivers/nouveau/nv30/nv30_texture.c index e5d3db39f17..358b3bbc32c 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_texture.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_texture.c @@ -287,7 +287,7 @@ nv30_sampler_view_create(struct pipe_context *pipe, struct pipe_resource *pt, so->npot_size0 = (pt->width0 << 16) | pt->height0; if (eng3d->oclass >= NV40_3D_CLASS) { so->npot_size1 = (pt->depth0 << 20) | mt->uniform_pitch; - if (!mt->swizzled) + if (mt->uniform_pitch) so->fmt |= NV40_3D_TEX_FORMAT_LINEAR; so->fmt |= 0x00008000; so->fmt |= (pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT; -- 2.30.2