From fa3baeab76dadeb61b7edfc849b6c5d379cc358a Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Fri, 6 Sep 2019 12:59:15 -0400 Subject: [PATCH] freedreno/a2xx: add missing vertex formats (SSCALE/USCALE/FIXED) Mostly for vertex formats, but they are supported as texture formats too (untested however). Signed-off-by: Jonathan Marek Reviewed-by: Rob Clark --- src/freedreno/registers/a2xx.xml | 2 +- src/gallium/drivers/freedreno/a2xx/fd2_gmem.c | 3 +- .../drivers/freedreno/a2xx/fd2_program.c | 31 ++++--------- .../drivers/freedreno/a2xx/fd2_screen.c | 14 +++--- .../drivers/freedreno/a2xx/fd2_texture.c | 23 +++++----- src/gallium/drivers/freedreno/a2xx/fd2_util.c | 45 +++++++++++++++++-- src/gallium/drivers/freedreno/a2xx/fd2_util.h | 11 ++++- .../drivers/freedreno/a2xx/instr-a2xx.h | 4 +- 8 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/freedreno/registers/a2xx.xml b/src/freedreno/registers/a2xx.xml index 4817ab31bb3..e486f804bc7 100644 --- a/src/freedreno/registers/a2xx.xml +++ b/src/freedreno/registers/a2xx.xml @@ -1620,7 +1620,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - + diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c b/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c index 6a78db5377e..bf112149b03 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c @@ -52,6 +52,7 @@ static uint32_t fmt2swap(enum pipe_format format) case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B4G4R4A4_UNORM: case PIPE_FORMAT_B4G4R4X4_UNORM: + case PIPE_FORMAT_B2G3R3_UNORM: return 1; default: return 0; @@ -248,7 +249,7 @@ emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base, A2XX_SQ_TEX_0_CLAMP_Z(SQ_TEX_WRAP) | A2XX_SQ_TEX_0_PITCH(slice->pitch)); OUT_RELOC(ring, rsc->bo, offset, - fd2_pipe2surface(format) | + A2XX_SQ_TEX_1_FORMAT(fd2_pipe2surface(format).format) | A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL), 0); OUT_RING(ring, A2XX_SQ_TEX_2_WIDTH(psurf->width - 1) | A2XX_SQ_TEX_2_HEIGHT(psurf->height - 1)); diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_program.c b/src/gallium/drivers/freedreno/a2xx/fd2_program.c index c4c23ff0d5b..9efc473b4a7 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_program.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_program.c @@ -166,30 +166,15 @@ static void patch_vtx_fetch(struct fd_context *ctx, struct pipe_vertex_element *elem, instr_fetch_vtx_t *instr, uint16_t dst_swiz) { - struct pipe_vertex_buffer *vb = - &ctx->vtx.vertexbuf.vb[elem->vertex_buffer_index]; - enum pipe_format format = elem->src_format; - const struct util_format_description *desc = - util_format_description(format); - unsigned j; - - /* Find the first non-VOID channel. */ - for (j = 0; j < 4; j++) - if (desc->channel[j].type != UTIL_FORMAT_TYPE_VOID) - break; - - instr->format = fd2_pipe2surface(format); - instr->num_format_all = !desc->channel[j].normalized; - instr->format_comp_all = desc->channel[j].type == UTIL_FORMAT_TYPE_SIGNED; - instr->stride = vb->stride; + struct surface_format fmt = fd2_pipe2surface(elem->src_format); + + instr->dst_swiz = fd2_vtx_swiz(elem->src_format, dst_swiz); + instr->format_comp_all = fmt.sign == SQ_TEX_SIGN_SIGNED; + instr->num_format_all = fmt.num_format; + instr->format = fmt.format; + instr->exp_adjust_all = fmt.exp_adjust; + instr->stride = ctx->vtx.vertexbuf.vb[elem->vertex_buffer_index].stride; instr->offset = elem->src_offset; - - unsigned swiz = 0; - for (int i = 0; i < 4; i++) { - unsigned s = dst_swiz >> i*3 & 7; - swiz |= (s >= 4 ? s : desc->swizzle[s]) << i*3; - } - instr->dst_swiz = swiz; } static void diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_screen.c b/src/gallium/drivers/freedreno/a2xx/fd2_screen.c index 42c0c024e61..361660857ee 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_screen.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_screen.c @@ -59,13 +59,13 @@ fd2_screen_is_format_supported(struct pipe_screen *pscreen, } if ((usage & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_VERTEX_BUFFER)) && - !util_format_is_srgb(format)) { - enum a2xx_sq_surfaceformat fmt = fd2_pipe2surface(format); - unsigned block_size = util_format_get_blocksize(format); - if (fmt != ~0) - retval |= usage & PIPE_BIND_VERTEX_BUFFER; - if (fmt != ~0 && block_size != 3 && block_size != 6 && - (block_size != 12 || format == PIPE_FORMAT_R32G32B32_FLOAT)) + !util_format_is_srgb(format) && + !util_format_is_pure_integer(format) && + fd2_pipe2surface(format).format != FMT_INVALID) { + retval |= usage & PIPE_BIND_VERTEX_BUFFER; + /* the only npot blocksize supported texture format is R32G32B32_FLOAT */ + if (util_is_power_of_two_or_zero(util_format_get_blocksize(format)) || + format == PIPE_FORMAT_R32G32B32_FLOAT) retval |= usage & PIPE_BIND_SAMPLER_VIEW; } diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_texture.c b/src/gallium/drivers/freedreno/a2xx/fd2_texture.c index 7aa26ca5673..b6ceb323f0b 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_texture.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_texture.c @@ -170,6 +170,7 @@ fd2_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, { struct fd2_pipe_sampler_view *so = CALLOC_STRUCT(fd2_pipe_sampler_view); struct fd_resource *rsc = fd_resource(prsc); + struct surface_format fmt = fd2_pipe2surface(cso->format); if (!so) return NULL; @@ -180,26 +181,24 @@ fd2_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, so->base.reference.count = 1; so->base.context = pctx; - enum sq_tex_sign sign = SQ_TEX_SIGN_UNSIGNED; - if (util_format_is_snorm(cso->format)) - sign = SQ_TEX_SIGN_SIGNED; - /* note: SQ_TEX_SIGN_GAMMA same as SQ_TEX_SIGN_UNSIGNED (a200) */ - so->tex0 = - A2XX_SQ_TEX_0_SIGN_X(sign) | - A2XX_SQ_TEX_0_SIGN_Y(sign) | - A2XX_SQ_TEX_0_SIGN_Z(sign) | - A2XX_SQ_TEX_0_SIGN_W(sign) | + A2XX_SQ_TEX_0_SIGN_X(fmt.sign) | + A2XX_SQ_TEX_0_SIGN_Y(fmt.sign) | + A2XX_SQ_TEX_0_SIGN_Z(fmt.sign) | + A2XX_SQ_TEX_0_SIGN_W(fmt.sign) | A2XX_SQ_TEX_0_PITCH(rsc->slices[0].pitch) | COND(rsc->tile_mode, A2XX_SQ_TEX_0_TILED); so->tex1 = - A2XX_SQ_TEX_1_FORMAT(fd2_pipe2surface(cso->format)) | + A2XX_SQ_TEX_1_FORMAT(fmt.format) | A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL); so->tex2 = A2XX_SQ_TEX_2_HEIGHT(prsc->height0 - 1) | A2XX_SQ_TEX_2_WIDTH(prsc->width0 - 1); - so->tex3 = fd2_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g, - cso->swizzle_b, cso->swizzle_a); + so->tex3 = + A2XX_SQ_TEX_3_NUM_FORMAT(fmt.num_format) | + fd2_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g, + cso->swizzle_b, cso->swizzle_a) | + A2XX_SQ_TEX_3_EXP_ADJUST(fmt.exp_adjust); so->tex4 = A2XX_SQ_TEX_4_MIP_MIN_LEVEL(fd_sampler_first_level(cso)) | diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_util.c b/src/gallium/drivers/freedreno/a2xx/fd2_util.c index af570701e54..ed1bbb1368d 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_util.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_util.c @@ -29,8 +29,8 @@ #include "fd2_util.h" -enum a2xx_sq_surfaceformat -fd2_pipe2surface(enum pipe_format format) +static enum a2xx_sq_surfaceformat +pipe2surface(enum pipe_format format, struct surface_format *fmt) { const struct util_format_description *desc = util_format_description(format); @@ -66,6 +66,15 @@ fd2_pipe2surface(enum pipe_format format) for (unsigned i = 0; i < 4; i++) channel_size |= desc->channel[i].size << i*8; + unsigned i = util_format_get_first_non_void_channel(format); + if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED || + desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED) + fmt->sign = SQ_TEX_SIGN_SIGNED; + if (!desc->channel[i].normalized) + fmt->num_format = SQ_TEX_NUM_FORMAT_INT; + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED) + fmt->exp_adjust = -16; + /* Note: the 3 channel 24bpp/48bpp/96bpp formats are only for vertex fetch * we can use the 4 channel format and ignore the 4th component just isn't used * XXX: is it possible for the extra loaded component to cause a MMU fault? @@ -83,7 +92,7 @@ fd2_pipe2surface(enum pipe_format format) CASE(32, 32, 32, 0): return FMT_32_32_32_FLOAT; CASE(32, 32, 32, 32): return FMT_32_32_32_32_FLOAT; } - } else if (desc->is_unorm || desc->is_snorm) { + } else { switch (channel_size) { CASE( 8, 0, 0, 0): return FMT_8; CASE( 8, 8, 0, 0): return FMT_8_8; @@ -102,6 +111,7 @@ fd2_pipe2surface(enum pipe_format format) CASE( 5, 6, 5, 0): return FMT_5_6_5; CASE(10, 10, 10, 2): return FMT_2_10_10_10; CASE( 8, 24, 0, 0): return FMT_24_8; + CASE( 2, 3, 3, 0): return FMT_2_3_3; /* Note: R/B swapped */ } } #undef CASE @@ -109,6 +119,18 @@ fd2_pipe2surface(enum pipe_format format) return ~0; } +struct surface_format +fd2_pipe2surface(enum pipe_format format) +{ + struct surface_format fmt = { + .sign = SQ_TEX_SIGN_UNSIGNED, + .num_format = SQ_TEX_NUM_FORMAT_FRAC, + .exp_adjust = 0, + }; + fmt.format = pipe2surface(format, &fmt); + return fmt; +} + enum a2xx_colorformatx fd2_pipe2color(enum pipe_format format) { @@ -116,6 +138,8 @@ fd2_pipe2color(enum pipe_format format) /* 8-bit buffers. */ case PIPE_FORMAT_R8_UNORM: return COLORX_8; + case PIPE_FORMAT_B2G3R3_UNORM: + return COLORX_2_3_3; /* note: untested */ /* 16-bit buffers. */ case PIPE_FORMAT_B5G6R5_UNORM: @@ -190,3 +214,18 @@ fd2_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g, A2XX_SQ_TEX_3_SWIZ_Z(tex_swiz(rswiz[2])) | A2XX_SQ_TEX_3_SWIZ_W(tex_swiz(rswiz[3])); } + +uint32_t +fd2_vtx_swiz(enum pipe_format format, unsigned swizzle) +{ + const struct util_format_description *desc = + util_format_description(format); + unsigned char swiz[4], rswiz[4]; + + for (unsigned i = 0; i < 4; i++) + swiz[i] = (swizzle >> i * 3) & 7; + + util_format_compose_swizzles(desc->swizzle, swiz, rswiz); + + return rswiz[0] | rswiz[1] << 3 | rswiz[2] << 6 | rswiz[3] << 9; +} diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_util.h b/src/gallium/drivers/freedreno/a2xx/fd2_util.h index d2758f3f0b2..cf945b14475 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_util.h +++ b/src/gallium/drivers/freedreno/a2xx/fd2_util.h @@ -31,10 +31,19 @@ #include "a2xx.xml.h" -enum a2xx_sq_surfaceformat fd2_pipe2surface(enum pipe_format format); +struct surface_format { +#define FMT_INVALID 0x7f + enum a2xx_sq_surfaceformat format : 7; + enum sq_tex_sign sign : 2; + enum sq_tex_num_format num_format : 1; + int exp_adjust : 6; +}; + +struct surface_format fd2_pipe2surface(enum pipe_format format); enum a2xx_colorformatx fd2_pipe2color(enum pipe_format format); uint32_t fd2_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a); +uint32_t fd2_vtx_swiz(enum pipe_format format, unsigned swizzle); /* convert x,y to dword */ static inline uint32_t xy2d(uint16_t x, uint16_t y) diff --git a/src/gallium/drivers/freedreno/a2xx/instr-a2xx.h b/src/gallium/drivers/freedreno/a2xx/instr-a2xx.h index 2591062ee3c..0078b24b509 100644 --- a/src/gallium/drivers/freedreno/a2xx/instr-a2xx.h +++ b/src/gallium/drivers/freedreno/a2xx/instr-a2xx.h @@ -372,8 +372,8 @@ typedef struct PACKED { uint8_t signed_rf_mode_all : 1; uint8_t reserved1 : 1; instr_surf_fmt_t format : 6; - uint8_t reserved2 : 1; - uint8_t exp_adjust_all : 7; + uint8_t reserved2 : 2; + uint8_t exp_adjust_all : 6; uint8_t reserved3 : 1; uint8_t pred_select : 1; /* dword2: */ -- 2.30.2