From 5486c9d526f393eff4b189e0e0a44eafeedf4407 Mon Sep 17 00:00:00 2001 From: "Kristian H. Kristensen" Date: Fri, 21 Dec 2018 09:14:28 -0800 Subject: [PATCH] freedreno/a6xx: Turn on texture tiling by default The color swap isn't available for tiled formats and it's not needed either. We pick one channel order and use for all non-linear formats. Signed-off-by: Kristian H. Kristensen Reviewed-by: Rob Clark --- .../drivers/freedreno/a6xx/fd6_blitter.c | 28 +++----------- .../drivers/freedreno/a6xx/fd6_format.c | 37 ++++++++++++++----- .../drivers/freedreno/a6xx/fd6_format.h | 3 +- src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 25 +++++++++---- .../drivers/freedreno/a6xx/fd6_image.c | 4 +- .../drivers/freedreno/a6xx/fd6_screen.c | 2 + .../drivers/freedreno/a6xx/fd6_texture.c | 8 +++- 7 files changed, 64 insertions(+), 43 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c index 546661b06bf..3e14e71933d 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c @@ -102,15 +102,6 @@ can_do_blit(const struct pipe_blit_info *info) fail_if(util_format_is_compressed(info->src.format) && info->src.format != info->dst.format); - /* hw ignores {SRC,DST}_INFO.COLOR_SWAP if {SRC,DST}_INFO.TILE_MODE - * is set (not linear). We can kind of get around that when tiling/ - * untiling by setting both src and dst COLOR_SWAP=WZYX, but that - * means the formats must match: - */ - fail_if((fd_resource(info->dst.resource)->tile_mode || - fd_resource(info->src.resource)->tile_mode) && - info->dst.format != info->src.format); - /* src box can be inverted, which we don't support.. dst box cannot: */ fail_if((info->src.box.width < 0) || (info->src.box.height < 0)); @@ -358,8 +349,8 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) dtile = fd_resource_level_linear(info->dst.resource, info->dst.level) ? TILE6_LINEAR : dst->tile_mode; - sswap = fd6_pipe2swap(info->src.format); - dswap = fd6_pipe2swap(info->dst.format); + sswap = stile ? WZYX : fd6_pipe2swap(info->src.format); + dswap = dtile ? WZYX : fd6_pipe2swap(info->dst.format); if (util_format_is_compressed(info->src.format)) { debug_assert(info->src.format == info->dst.format); @@ -386,16 +377,6 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) uint32_t width = DIV_ROUND_UP(u_minify(src->base.width0, info->src.level), blockwidth) * nelements; uint32_t height = DIV_ROUND_UP(u_minify(src->base.height0, info->src.level), blockheight); - /* if dtile, then dswap ignored by hw, and likewise if stile then sswap - * ignored by hw.. but in this case we have already rejected the blit - * if src and dst formats differ, so juse use WZYX for both src and - * dst swap mode (so we don't change component order) - */ - if (stile || dtile) { - debug_assert(info->src.format == info->dst.format); - sswap = dswap = WZYX; - } - OUT_PKT7(ring, CP_SET_MARKER, 1); OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE)); @@ -582,5 +563,8 @@ fd6_tile_mode(const struct pipe_resource *tmpl) /* basically just has to be a format we can blit, so uploads/downloads * via linear staging buffer works: */ - return TILE6_3; + if (ok_format(tmpl->format)) + return TILE6_3; + + return TILE6_LINEAR; } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_format.c b/src/gallium/drivers/freedreno/a6xx/fd6_format.c index 6a55d4e6388..dc1a54243a3 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_format.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_format.c @@ -29,6 +29,7 @@ #include "util/u_format.h" #include "fd6_format.h" +#include "freedreno_resource.h" /* Specifies the table of all the formats and their features. Also supplies @@ -419,8 +420,8 @@ fd6_pipe2depth(enum pipe_format format) } } -static inline enum a6xx_tex_swiz -tex_swiz(unsigned swiz) +enum a6xx_tex_swiz +fd6_pipe2swiz(unsigned swiz) { switch (swiz) { default: @@ -434,19 +435,37 @@ tex_swiz(unsigned swiz) } uint32_t -fd6_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g, +fd6_tex_swiz(struct pipe_resource *prsc, unsigned swizzle_r, unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a) { const struct util_format_description *desc = - util_format_description(format); + util_format_description(prsc->format); unsigned char swiz[4] = { swizzle_r, swizzle_g, swizzle_b, swizzle_a, - }, rswiz[4]; + }, rswiz[4], *swizp; util_format_compose_swizzles(desc->swizzle, swiz, rswiz); - return A6XX_TEX_CONST_0_SWIZ_X(tex_swiz(rswiz[0])) | - A6XX_TEX_CONST_0_SWIZ_Y(tex_swiz(rswiz[1])) | - A6XX_TEX_CONST_0_SWIZ_Z(tex_swiz(rswiz[2])) | - A6XX_TEX_CONST_0_SWIZ_W(tex_swiz(rswiz[3])); + if (fd_resource(prsc)->tile_mode) { + /* for tiled modes, we don't get SWAP, so manually apply that + * extra step of swizzle: + */ + enum a3xx_color_swap swap = fd6_pipe2swap(prsc->format); + unsigned char swapswiz[][4] = { + [WZYX] = { 0, 1, 2, 3 }, + [WXYZ] = { 2, 1, 0, 3 }, + [ZYXW] = { 3, 0, 1, 2 }, + [XYZW] = { 3, 2, 1, 0 }, + }; + + util_format_compose_swizzles(swapswiz[swap], rswiz, swiz); + swizp = swiz; + } else { + swizp = rswiz; + } + + return A6XX_TEX_CONST_0_SWIZ_X(fd6_pipe2swiz(swizp[0])) | + A6XX_TEX_CONST_0_SWIZ_Y(fd6_pipe2swiz(swizp[1])) | + A6XX_TEX_CONST_0_SWIZ_Z(fd6_pipe2swiz(swizp[2])) | + A6XX_TEX_CONST_0_SWIZ_W(fd6_pipe2swiz(swizp[3])); } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_format.h b/src/gallium/drivers/freedreno/a6xx/fd6_format.h index 56166dc4505..bc188ca17a8 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_format.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_format.h @@ -38,8 +38,9 @@ enum a6xx_color_fmt fd6_pipe2color(enum pipe_format format); enum a3xx_color_swap fd6_pipe2swap(enum pipe_format format); enum a6xx_tex_fetchsize fd6_pipe2fetchsize(enum pipe_format format); enum a6xx_depth_format fd6_pipe2depth(enum pipe_format format); +enum a6xx_tex_swiz fd6_pipe2swiz(unsigned swiz); -uint32_t fd6_tex_swiz(enum pipe_format format, unsigned swizzle_r, +uint32_t fd6_tex_swiz(struct pipe_resource *prsc, unsigned swizzle_r, unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a); static inline enum a6xx_2d_ifmt diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c index 75d8025e2a6..cb5c582476f 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -64,6 +64,7 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb, struct fd_resource_slice *slice = NULL; uint32_t stride = 0; uint32_t offset = 0; + uint32_t tile_mode; if (!pfb->cbufs[i]) continue; @@ -79,7 +80,6 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb, uint32_t base = gmem ? gmem->cbuf_base[i] : 0; slice = fd_resource_slice(rsc, psurf->u.tex.level); format = fd6_pipe2color(pformat); - swap = fd6_pipe2swap(pformat); sint = util_format_is_pure_sint(pformat); uint = util_format_is_pure_uint(pformat); @@ -90,13 +90,20 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb, psurf->u.tex.first_layer); stride = slice->pitch * rsc->cpp * pfb->samples; + swap = rsc->tile_mode ? WZYX : fd6_pipe2swap(pformat); + + if (rsc->tile_mode && + fd_resource_level_linear(psurf->texture, psurf->u.tex.level)) + tile_mode = TILE6_LINEAR; + else + tile_mode = rsc->tile_mode; debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer); debug_assert((offset + slice->size0) <= fd_bo_size(rsc->bo)); OUT_PKT4(ring, REG_A6XX_RB_MRT_BUF_INFO(i), 6); OUT_RING(ring, A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) | - A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(rsc->tile_mode) | + A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) | A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap)); OUT_RING(ring, A6XX_RB_MRT_PITCH(stride)); OUT_RING(ring, A6XX_RB_MRT_ARRAY_PITCH(slice->size0)); @@ -617,18 +624,20 @@ emit_blit(struct fd_batch *batch, enum a6xx_color_fmt format = fd6_pipe2color(pfmt); uint32_t stride = slice->pitch * rsc->cpp; uint32_t size = slice->size0; - enum a3xx_color_swap swap = fd6_pipe2swap(pfmt); + enum a3xx_color_swap swap = rsc->tile_mode ? WZYX : fd6_pipe2swap(pfmt); enum a3xx_msaa_samples samples = fd_msaa_samples(rsc->base.nr_samples); + uint32_t tile_mode; - // TODO: tile mode - // bool tiled; - // tiled = rsc->tile_mode && - // !fd_resource_level_linear(&rsc->base, psurf->u.tex.level); + if (rsc->tile_mode && + fd_resource_level_linear(&rsc->base, psurf->u.tex.level)) + tile_mode = TILE6_LINEAR; + else + tile_mode = rsc->tile_mode; OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 5); OUT_RING(ring, - A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) | + A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) | A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) | A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) | A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap)); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_image.c b/src/gallium/drivers/freedreno/a6xx/fd6_image.c index e79ee2f90ad..f7419d8d9ac 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_image.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_image.c @@ -43,6 +43,7 @@ static enum a6xx_state_block imgsb[] = { }; struct fd6_image { + struct pipe_resource *prsc; enum pipe_format pfmt; enum a6xx_tex_fmt fmt; enum a6xx_tex_fetchsize fetchsize; @@ -70,6 +71,7 @@ static void translate_image(struct fd6_image *img, struct pipe_image_view *pimg) return; } + img->prsc = prsc; img->pfmt = format; img->fmt = fd6_pipe2tex(format); img->fetchsize = fd6_pipe2fetchsize(format); @@ -112,7 +114,7 @@ static void emit_image_tex(struct fd_ringbuffer *ring, unsigned slot, OUT_RING(ring, CP_LOAD_STATE6_2_EXT_SRC_ADDR_HI(0)); OUT_RING(ring, A6XX_TEX_CONST_0_FMT(img->fmt) | - fd6_tex_swiz(img->pfmt, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, + fd6_tex_swiz(img->prsc, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W) | COND(img->srgb, A6XX_TEX_CONST_0_SRGB)); OUT_RING(ring, A6XX_TEX_CONST_1_WIDTH(img->width) | diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_screen.c b/src/gallium/drivers/freedreno/a6xx/fd6_screen.c index 910a71ccc96..be92d4a877b 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_screen.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_screen.c @@ -29,6 +29,7 @@ #include "util/u_format.h" #include "fd6_screen.h" +#include "fd6_blitter.h" #include "fd6_context.h" #include "fd6_format.h" #include "fd6_resource.h" @@ -134,4 +135,5 @@ fd6_screen_init(struct pipe_screen *pscreen) pscreen->is_format_supported = fd6_screen_is_format_supported; screen->setup_slices = fd6_setup_slices; + screen->tile_mode = fd6_tile_mode; } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c index e516e94b0d9..af5f49fd3f2 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c @@ -246,7 +246,7 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, so->texconst0 = A6XX_TEX_CONST_0_FMT(fd6_pipe2tex(format)) | A6XX_TEX_CONST_0_SAMPLES(fd_msaa_samples(prsc->nr_samples)) | - fd6_tex_swiz(format, cso->swizzle_r, cso->swizzle_g, + fd6_tex_swiz(prsc, cso->swizzle_r, cso->swizzle_g, cso->swizzle_b, cso->swizzle_a); /* NOTE: since we sample z24s8 using 8888_UINT format, the swizzle @@ -257,8 +257,12 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, * Note that gallium expects stencil sampler to return (s,s,s,s) * which isn't quite true. To make that happen we'd have to massage * the swizzle. But in practice only the .x component is used. + * + * Skip this in the tile case because tiled formats are not swapped + * and we have already applied the inverse swap in fd6_tex_swiz() + * to componsate for that. */ - if (format == PIPE_FORMAT_X24S8_UINT) { + if ((format == PIPE_FORMAT_X24S8_UINT) && !rsc->tile_mode) { so->texconst0 |= A6XX_TEX_CONST_0_SWAP(XYZW); } -- 2.30.2