aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/a2xx
diff options
context:
space:
mode:
authorJonathan Marek <[email protected]>2019-09-06 12:59:15 -0400
committerJonathan Marek <[email protected]>2019-10-30 18:04:17 +0000
commitfa3baeab76dadeb61b7edfc849b6c5d379cc358a (patch)
treef241eeb852c3055984da1250c01ea1625dfe6293 /src/gallium/drivers/freedreno/a2xx
parent03a132912f6343bda834973e40eb35df33f75d8e (diff)
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 <[email protected]> Reviewed-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/a2xx')
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_gmem.c3
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_program.c31
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_screen.c14
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_texture.c23
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_util.c45
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_util.h11
-rw-r--r--src/gallium/drivers/freedreno/a2xx/instr-a2xx.h4
7 files changed, 82 insertions, 49 deletions
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: */