Mostly for vertex formats, but they are supported as texture formats too (untested however). Signed-off-by: Jonathan Marek <jonathan@marek.ca> Reviewed-by: Rob Clark <robdclark@gmail.com>tags/19.3-branchpoint
@@ -1620,7 +1620,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> | |||
<bitfield name="SWIZ_Y" low="4" high="6" type="sq_tex_swiz"/> | |||
<bitfield name="SWIZ_Z" low="7" high="9" type="sq_tex_swiz"/> | |||
<bitfield name="SWIZ_W" low="10" high="12" type="sq_tex_swiz"/> | |||
<bitfield name="EXP_ADJUST" low="13" high="18" type="uint"/> | |||
<bitfield name="EXP_ADJUST" low="13" high="18" type="int"/> | |||
<bitfield name="XY_MAG_FILTER" low="19" high="20" type="sq_tex_filter"/> | |||
<bitfield name="XY_MIN_FILTER" low="21" high="22" type="sq_tex_filter"/> | |||
<bitfield name="MIP_FILTER" low="23" high="24" type="sq_tex_filter"/> |
@@ -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)); |
@@ -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 |
@@ -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; | |||
} | |||
@@ -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)) | |
@@ -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; | |||
} |
@@ -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) |
@@ -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: */ |