From 490a7b1c73babd528b6d883471a8636157c5853a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 1 Feb 2008 17:12:20 -0800 Subject: [PATCH] Vectorize vertex puller --- src/mesa/pipe/cell/spu/spu_vertex_fetch.c | 186 +++++++-------------- src/mesa/pipe/cell/spu/spu_vertex_shader.h | 4 +- 2 files changed, 61 insertions(+), 129 deletions(-) diff --git a/src/mesa/pipe/cell/spu/spu_vertex_fetch.c b/src/mesa/pipe/cell/spu/spu_vertex_fetch.c index 5b0f2a6470c..4133fbba179 100644 --- a/src/mesa/pipe/cell/spu/spu_vertex_fetch.c +++ b/src/mesa/pipe/cell/spu/spu_vertex_fetch.c @@ -42,6 +42,8 @@ #define DRAW_DBG 0 +static const vec_float4 defaults = { 0.0, 0.0, 0.0, 1.0 }; + /** * Fetch a float[4] vertex attribute from memory, doing format/type * conversion as needed. @@ -50,19 +52,16 @@ * conversion, texture sampling etc. */ #define FETCH_ATTRIB( NAME, SZ, CVT ) \ -static void \ -fetch_##NAME(const void *ptr, float *attrib) \ +static qword \ +fetch_##NAME(const void *ptr) \ { \ - static const float defaults[4] = { 0,0,0,1 }; \ + vec_float4 attrib = defaults; \ int i; \ \ for (i = 0; i < SZ; i++) { \ - attrib[i] = CVT; \ - } \ - \ - for (; i < 4; i++) { \ - attrib[i] = defaults[i]; \ + attrib = spu_insert(CVT, attrib, i); \ } \ + return (qword) attrib; \ } #define CVT_64_FLOAT (float) ((double *) ptr)[i] @@ -309,106 +308,59 @@ static spu_fetch_func get_fetch_func( enum pipe_format format ) } -static void -transpose_4x4( float *out, const float *in ) -{ - /* This can be achieved in 12 sse instructions, plus the final - * stores I guess. This is probably a bit more than that - maybe - * 32 or so? - */ - out[0] = in[0]; out[1] = in[4]; out[2] = in[8]; out[3] = in[12]; - out[4] = in[1]; out[5] = in[5]; out[6] = in[9]; out[7] = in[13]; - out[8] = in[2]; out[9] = in[6]; out[10] = in[10]; out[11] = in[14]; - out[12] = in[3]; out[13] = in[7]; out[14] = in[11]; out[15] = in[15]; -} - - - -static void fetch_xyz_rgb( struct spu_vs_context *draw, - struct spu_exec_machine *machine, - const unsigned *elts, - unsigned count ) +void +spu_transpose_4x4(qword *out, const qword *in) { - assert(count <= 4); - -// _mesa_printf("%s\n", __FUNCTION__); - - /* loop over vertex attributes (vertex shader inputs) - */ - - const unsigned *pitch = draw->vertex_fetch.pitch; - const ubyte **src = draw->vertex_fetch.src_ptr; - int i; - - for (i = 0; i < 4; i++) { + static const qword masks[8] = { { - const float *in = (const float *)(src[0] + elts[i] * pitch[0]); - float *out = &machine->Inputs[0].xyzw[0].f[i]; - out[0] = in[0]; - out[4] = in[1]; - out[8] = in[2]; - out[12] = 1.0f; - } - + 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + }, { - const float *in = (const float *)(src[1] + elts[i] * pitch[1]); - float *out = &machine->Inputs[1].xyzw[0].f[i]; - out[0] = in[0]; - out[4] = in[1]; - out[8] = in[2]; - out[12] = 1.0f; - } - } -} - - - - -static void fetch_xyz_rgb_st( struct spu_vs_context *draw, - struct spu_exec_machine *machine, - const unsigned *elts, - unsigned count ) -{ - assert(count <= 4); - - /* loop over vertex attributes (vertex shader inputs) - */ - - const unsigned *pitch = draw->vertex_fetch.pitch; - const ubyte **src = draw->vertex_fetch.src_ptr; - int i; - - for (i = 0; i < 4; i++) { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, + }, + + { + 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + }, + { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, + }, + + { + 0x08, 0x09, 0x0a, 0x0b, 0x18, 0x19, 0x1a, 0x1b, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + }, + { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x08, 0x09, 0x0a, 0x0b, 0x18, 0x19, 0x1a, 0x1b, + }, + + { + 0x0c, 0x0d, 0x0e, 0x0f, 0x1c, 0x1d, 0x1e, 0x1f, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + }, { - const float *in = (const float *)(src[0] + elts[i] * pitch[0]); - float *out = &machine->Inputs[0].xyzw[0].f[i]; - out[0] = in[0]; - out[4] = in[1]; - out[8] = in[2]; - out[12] = 1.0f; - } + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x0c, 0x0d, 0x0e, 0x0f, 0x1c, 0x1d, 0x1e, 0x1f, + }, + }; - { - const float *in = (const float *)(src[1] + elts[i] * pitch[1]); - float *out = &machine->Inputs[1].xyzw[0].f[i]; - out[0] = in[0]; - out[4] = in[1]; - out[8] = in[2]; - out[12] = 1.0f; - } + out[0] = si_shufb(in[0], in[1], masks[0]); + out[0] = si_or(out[0], si_shufb(in[2], in[3], masks[1])); - { - const float *in = (const float *)(src[2] + elts[i] * pitch[2]); - float *out = &machine->Inputs[1].xyzw[0].f[i]; - out[0] = in[0]; - out[4] = in[1]; - out[8] = 0.0f; - out[12] = 1.0f; - } - } -} + out[1] = si_shufb(in[0], in[1], masks[2]); + out[1] = si_or(out[1], si_shufb(in[2], in[3], masks[3])); + out[2] = si_shufb(in[0], in[1], masks[4]); + out[2] = si_or(out[2], si_shufb(in[2], in[3], masks[5])); + out[3] = si_shufb(in[0], in[1], masks[6]); + out[3] = si_or(out[3], si_shufb(in[2], in[3], masks[7])); +} /** @@ -435,7 +387,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw, const uint64_t src = draw->vertex_fetch.src_ptr[attr]; const spu_fetch_func fetch = draw->vertex_fetch.fetch[attr]; unsigned i; - float p[4][4]; + qword p[4]; /* Fetch four attributes for four vertices. @@ -452,17 +404,15 @@ static void generic_vertex_fetch(struct spu_vs_context *draw, mfc_get(buffer, addr & ~0x0f, size, TAG_VERTEX_BUFFER, 0, 0); wait_on_mask(1 << TAG_VERTEX_BUFFER); - memmove(& buffer, buffer + (addr & 0x0f), 16); - - fetch(buffer, p[i]); + p[i] = (*fetch)(buffer + (addr & 0x0f)); } /* Be nice and zero out any missing vertices: */ for (/* empty */; i < 4; i++) - p[i][0] = p[i][1] = p[i][2] = p[i][3] = 0; - - /* Transpose/swizzle into sse-friendly format. Currently + p[i] = si_xor(p[i], p[i]); + + /* Transpose/swizzle into vector-friendly format. Currently * assuming that all vertex shader inputs are float[4], but this * isn't true -- if the vertex shader only wants tex0.xy, we * could optimize for that. @@ -471,7 +421,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw, * excessive number of fetch functions, but we could at least * minimize the transpose step: */ - transpose_4x4( (float *)&machine->Inputs[attr].xyzw[0].f[0], (float *)p ); + spu_transpose_4x4(&machine->Inputs[attr].xyzw[0].q, p); } } @@ -487,24 +437,4 @@ void spu_update_vertex_fetch( struct spu_vs_context *draw ) } draw->vertex_fetch.fetch_func = generic_vertex_fetch; - - /* Disable the fast path because they don't use mfc_get yet. - */ -#if 0 - switch (draw->vertex_fetch.nr_attrs) { - case 2: - if (draw->vertex_fetch.format[0] == PIPE_FORMAT_R32G32B32_FLOAT && - draw->vertex_fetch.format[1] == PIPE_FORMAT_R32G32B32_FLOAT) - draw->vertex_fetch.fetch_func = fetch_xyz_rgb; - break; - case 3: - if (draw->vertex_fetch.format[0] == PIPE_FORMAT_R32G32B32_FLOAT && - draw->vertex_fetch.format[1] == PIPE_FORMAT_R32G32B32_FLOAT && - draw->vertex_fetch.format[2] == PIPE_FORMAT_R32G32_FLOAT) - draw->vertex_fetch.fetch_func = fetch_xyz_rgb_st; - break; - default: - break; - } -#endif } diff --git a/src/mesa/pipe/cell/spu/spu_vertex_shader.h b/src/mesa/pipe/cell/spu/spu_vertex_shader.h index b261ab44a21..2435b7ddae0 100644 --- a/src/mesa/pipe/cell/spu/spu_vertex_shader.h +++ b/src/mesa/pipe/cell/spu/spu_vertex_shader.h @@ -6,7 +6,7 @@ struct spu_vs_context; -typedef void (*spu_fetch_func)(const void *ptr, float *attrib); +typedef qword (*spu_fetch_func)(const void *ptr); typedef void (*spu_full_fetch_func)( struct spu_vs_context *draw, struct spu_exec_machine *machine, const unsigned *elts, @@ -39,6 +39,8 @@ struct spu_vs_context { extern void spu_update_vertex_fetch(struct spu_vs_context *draw); +extern void spu_transpose_4x4(qword *out, const qword *in); + static INLINE void spu_vertex_fetch(struct spu_vs_context *draw, struct spu_exec_machine *machine, const unsigned *elts, -- 2.30.2