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 <hoegsberg@chromium.org> Reviewed-by: Rob Clark <robdclark@gmail.com>tags/19.0-branchpoint
@@ -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; | |||
} |
@@ -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])); | |||
} |
@@ -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 |
@@ -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)); |
@@ -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) | |
@@ -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; | |||
} |
@@ -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); | |||
} | |||