summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/draw
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/draw')
-rw-r--r--src/gallium/auxiliary/draw/Makefile1
-rw-r--r--src/gallium/auxiliary/draw/SConscript1
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h29
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c65
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c12
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c243
-rw-r--r--src/gallium/auxiliary/draw/draw_vbuf.c20
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.c5
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex_cache.c37
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex_shader.c22
-rw-r--r--src/gallium/auxiliary/draw/draw_vf.c56
-rw-r--r--src/gallium/auxiliary/draw/draw_vf.h4
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h33
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_exec.c181
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c48
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_sse.c193
20 files changed, 570 insertions, 403 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index 28262a92c6..5ab3cfe5ce 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -19,6 +19,7 @@ C_SOURCES = \
draw_pt_vcache.c \
draw_pt_fetch_emit.c \
draw_pt_fetch_pipeline.c \
+ draw_pt_fetch_shade_pipeline.c \
draw_pt_pipeline.c \
draw_pt_elts.c \
draw_prim.c \
diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript
index 52107912f5..a7fb5dbd61 100644
--- a/src/gallium/auxiliary/draw/SConscript
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -18,6 +18,7 @@ draw = env.ConvenienceLibrary(
'draw_pt_vcache.c',
'draw_pt_fetch_emit.c',
'draw_pt_fetch_pipeline.c',
+ 'draw_pt_fetch_shade_pipeline.c',
'draw_pt_pipeline.c',
'draw_pt_elts.c',
'draw_prim.c',
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index b3c65c90d6..0c314f6e1d 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -49,6 +49,8 @@ struct draw_context *draw_create( void )
draw->use_sse = FALSE;
#endif
+ draw->use_pt_shaders = GETENV( "GALLIUM_PT_SHADERS" ) != NULL;
+
/* create pipeline stages */
draw->pipeline.wide_line = draw_wide_line_stage( draw );
draw->pipeline.wide_point = draw_wide_point_stage( draw );
@@ -86,14 +88,11 @@ struct draw_context *draw_create( void )
/* Statically allocate maximum sized vertices for the cache - could be cleverer...
*/
{
- uint i;
- const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
- char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16);
+ char *tmp = align_malloc(VS_QUEUE_LENGTH * MAX_VERTEX_ALLOCATION, 16);
if (!tmp)
goto fail;
- for (i = 0; i < Elements(draw->vs.queue); i++)
- draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);
+ draw->vs.vertex_cache = tmp;
}
draw->shader_queue_flush = draw_vertex_shader_queue_flush;
@@ -156,8 +155,8 @@ void draw_destroy( struct draw_context *draw )
tgsi_exec_machine_free_data(&draw->machine);
- if (draw->vs.queue[0].vertex)
- align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
+ if (draw->vs.vertex_cache)
+ align_free( draw->vs.vertex_cache ); /* Frees all the vertices. */
/* Not so fast -- we're just borrowing this at the moment.
*
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 4d056f6dba..c8cb96c8ba 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -56,6 +56,8 @@ struct gallivm_cpu_engine;
struct draw_pt_middle_end;
struct draw_pt_front_end;
+#define MAX_SHADER_VERTICES 128
+
/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
@@ -76,6 +78,7 @@ struct vertex_header {
/* XXX This is too large */
#define MAX_VERTEX_SIZE ((2 + PIPE_MAX_SHADER_OUTPUTS) * 4 * sizeof(float))
+#define MAX_VERTEX_ALLOCATION ((MAX_VERTEX_SIZE + 0x0f) & ~0x0f)
@@ -146,12 +149,13 @@ struct draw_vertex_shader {
/* Run the shader - this interface will get cleaned up in the
* future:
*/
- void (*run)( struct draw_vertex_shader *shader,
- struct draw_context *draw,
- const unsigned *elts,
- unsigned count,
- struct vertex_header *vOut[] );
-
+ boolean (*run)( struct draw_vertex_shader *shader,
+ struct draw_context *draw,
+ const unsigned *elts,
+ unsigned count,
+ void *out,
+ unsigned vertex_size);
+
void (*delete)( struct draw_vertex_shader * );
};
@@ -274,6 +278,7 @@ struct draw_context
boolean line_stipple; /**< do line stipple? */
boolean point_sprite; /**< convert points to quads for sprites? */
boolean use_sse;
+ boolean use_pt_shaders; /* temporary flag to switch on pt shader paths */
/* If a prim stage introduces new vertex attributes, they'll be stored here
*/
@@ -319,10 +324,8 @@ struct draw_context
/* Vertex shader queue:
*/
struct {
- struct {
- unsigned elt; /**< index into the user's vertex arrays */
- struct vertex_header *vertex;
- } queue[VS_QUEUE_LENGTH];
+ unsigned elts[VS_QUEUE_LENGTH]; /**< index into the user's vertex arrays */
+ char *vertex_cache;
unsigned queue_nr;
unsigned post_nr;
} vs;
@@ -448,4 +451,10 @@ dot4(const float *a, const float *b)
return result;
}
+static INLINE struct vertex_header *
+draw_header_from_block(char *block, int size, int num)
+{
+ return (struct vertex_header*)(block + num * size);
+}
+
#endif /* DRAW_PRIVATE_H */
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index f59fb86f78..3d2e7bf7b8 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -36,21 +36,25 @@
#include "draw/draw_pt.h"
-/* XXX: Shouldn't those two functions below use the '>' operator???
- */
-
-static boolean too_many_verts( struct draw_context *draw,
- unsigned verts )
+#if 0
+static boolean too_many_elts( struct draw_context *draw,
+ unsigned elts )
{
- return verts < 1024;
+ return elts > (8 * 1024);
}
+#endif
-static boolean too_many_elts( struct draw_context *draw,
- unsigned elts )
+static INLINE unsigned reduced_prim(unsigned prim)
{
- return elts < (16 * 1024);
+ /*FIXME*/
+ return prim;
}
+static INLINE boolean good_prim(unsigned prim)
+{
+ /*FIXME*/
+ return FALSE;
+}
boolean
draw_pt_arrays(struct draw_context *draw,
@@ -64,6 +68,9 @@ draw_pt_arrays(struct draw_context *draw,
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
+ if (!draw->render)
+ return FALSE;
+ /*debug_printf("XXXXXXXXXX needs_pipeline = %d\n", pipeline);*/
/* Overall we do:
* - frontend -- prepare fetch_elts, draw_elts - eg vcache
@@ -72,6 +79,9 @@ draw_pt_arrays(struct draw_context *draw,
* - backend -- the vbuf_render provided by the driver.
*/
+ if (shading && !draw->use_pt_shaders)
+ return FALSE;
+
if (!cliptest && !pipeline && !shading) {
/* This is the 'passthrough' path:
@@ -87,7 +97,6 @@ draw_pt_arrays(struct draw_context *draw,
*/
middle = draw->pt.middle.fetch_pipeline;
}
-#if 0
else if (!cliptest && !pipeline) {
/* Fetch user verts, run vertex shader, emit hw verts:
*/
@@ -111,23 +120,15 @@ draw_pt_arrays(struct draw_context *draw,
*/
middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
}
- else if (!cliptest) {
- /* Fetch user verts, run vertex shader, run pipeline:
- */
- middle = draw->pt.middle.fetch_shade_pipeline;
- }
else {
/* This is what we're currently always doing:
*/
- /* Fetch user verts, run vertex shader, cliptest, run pipeline:
+ /* Fetch user verts, run vertex shader, cliptest, run pipeline
+ * or
+ * Fetch user verts, run vertex shader, run pipeline
*/
- middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
- }
-#else
- else {
- return FALSE;
+ middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
}
-#endif
/* If !pipeline, need to make sure we respect the driver's limited
@@ -143,7 +144,7 @@ draw_pt_arrays(struct draw_context *draw,
frontend = draw->pt.front.vcache;
hw_prim = reduced_prim(prim);
}
-
+#if 0
if (too_many_verts(nr_verts)) {
/* if (is_verts(draw) && can_split(prim)) {
draw = draw_arrays_split;
@@ -153,6 +154,7 @@ draw_pt_arrays(struct draw_context *draw,
hw_prim = reduced_prim(prim);
}
}
+#endif
if (too_many_elts(count)) {
@@ -166,17 +168,13 @@ draw_pt_arrays(struct draw_context *draw,
}
if (!good_prim(hw_prim)) {
- draw = draw->pt.front.vcache;
+ frontend = draw->pt.front.vcache;
}
}
#else
frontend = draw->pt.front.vcache;
#endif
- /* XXX: need to flush to get prim_vbuf.c to release its allocation??
- */
- draw_do_flush( draw, DRAW_FLUSH_BACKEND );
-
frontend->prepare( frontend, prim, middle );
frontend->run( frontend,
@@ -200,6 +198,11 @@ boolean draw_pt_init( struct draw_context *draw )
if (!draw->pt.middle.fetch_pipeline)
return FALSE;
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit =
+ draw_pt_fetch_pipeline_or_emit( draw );
+ if (!draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit)
+ return FALSE;
+
draw->pt.front.vcache = draw_pt_vcache( draw );
if (!draw->pt.front.vcache)
return FALSE;
@@ -220,6 +223,12 @@ void draw_pt_destroy( struct draw_context *draw )
draw->pt.middle.fetch_pipeline = NULL;
}
+ if (draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit) {
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit->destroy(
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit );
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit = NULL;
+ }
+
if (draw->pt.front.vcache) {
draw->pt.front.vcache->destroy( draw->pt.front.vcache );
draw->pt.front.vcache = NULL;
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 590823fd33..48413b648a 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -123,7 +123,7 @@ const void *draw_pt_elt_ptr( struct draw_context *draw,
struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw );
struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
struct draw_pt_middle_end *draw_pt_fetch_pipeline( struct draw_context *draw );
-
+struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
#endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index 0806076956..3a26a5d712 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -145,7 +145,6 @@ fetch_store_general( struct fetch_emit_middle_end *feme,
unsigned count )
{
float *out = (float *)out_ptr;
- struct vbuf_render *render = feme->draw->render;
uint i, j;
for (i = 0; i < count; i++) {
@@ -167,7 +166,6 @@ fetch_store_general( struct fetch_emit_middle_end *feme,
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
unsigned prim )
{
- static const float zero = 0;
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
const struct vertex_info *vinfo;
@@ -212,12 +210,6 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
case EMIT_1F:
feme->fetch[i].emit = emit_R32_FLOAT;
break;
- case EMIT_HEADER:
- feme->fetch[i].ptr = (const ubyte *)&zero;
- feme->fetch[i].pitch = 0;
- feme->fetch[i].fetch = fetch_R32_FLOAT;
- feme->fetch[i].emit = emit_R32_FLOAT;
- break;
case EMIT_1F_PSIZE:
feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
feme->fetch[i].pitch = 0;
@@ -249,6 +241,10 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
struct draw_context *draw = feme->draw;
void *hw_verts;
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)feme->hw_vertex_size,
(ushort)fetch_count );
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
index 4c2a281b29..a70d129c93 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
@@ -87,7 +87,7 @@ struct fetch_pipeline_middle_end {
};
-
+#if 0
static void emit_R32_FLOAT( const float *attrib,
float **out )
{
@@ -111,7 +111,7 @@ static void emit_R32G32B32_FLOAT( const float *attrib,
(*out)[2] = attrib[2];
(*out) += 3;
}
-
+#endif
static void emit_R32G32B32A32_FLOAT( const float *attrib,
float **out )
{
@@ -211,7 +211,6 @@ fetch_store_general( struct fetch_pipeline_middle_end *fpme,
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned prim )
{
- static const float zero = 0;
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
unsigned i, nr = 0;
@@ -264,7 +263,6 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
unsigned draw_count )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
- struct draw_context *draw = fpme->draw;
char *pipeline_verts;
pipeline_verts = MALLOC( fpme->pipeline_vertex_size *
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
new file mode 100644
index 0000000000..04b3d2c4cf
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -0,0 +1,243 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+
+struct fetch_pipeline_middle_end {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct {
+ const ubyte *ptr;
+ unsigned pitch;
+ void (*fetch)( const void *from, float *attrib);
+ void (*emit)( const float *attrib, float **out );
+ } fetch[PIPE_MAX_ATTRIBS];
+
+ unsigned nr_fetch;
+ unsigned pipeline_vertex_size;
+ unsigned hw_vertex_size;
+ unsigned prim;
+};
+
+#if 0
+static void emit_R32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out) += 1;
+}
+
+static void emit_R32G32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out) += 2;
+}
+
+static void emit_R32G32B32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out)[2] = attrib[2];
+ (*out) += 3;
+}
+#endif
+static void emit_R32G32B32A32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out)[2] = attrib[2];
+ (*out)[3] = attrib[3];
+ (*out) += 4;
+}
+
+static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ unsigned i, nr = 0;
+ boolean ok;
+ const struct vertex_info *vinfo;
+
+ fpme->prim = prim;
+
+ ok = draw->render->set_primitive(draw->render, prim);
+ if (!ok) {
+ assert(0);
+ return;
+ }
+ /* Must do this after set_primitive() above:
+ */
+ vinfo = draw->render->get_vertex_info(draw->render);
+
+ /* Need to look at vertex shader inputs (we know it is a
+ * passthrough shader, so these define the outputs too). If we
+ * were running a shader, we'd still be looking at the inputs at
+ * this point.
+ */
+ for (i = 0; i < draw->vertex_shader->info.num_inputs; i++) {
+ unsigned buf = draw->vertex_element[i].vertex_buffer_index;
+ enum pipe_format format = draw->vertex_element[i].src_format;
+
+ fpme->fetch[nr].ptr = ((const ubyte *) draw->user.vbuffer[buf] +
+ draw->vertex_buffer[buf].buffer_offset +
+ draw->vertex_element[i].src_offset);
+
+ fpme->fetch[nr].pitch = draw->vertex_buffer[buf].pitch;
+ fpme->fetch[nr].fetch = draw_get_fetch_func( format );
+
+ /* Always do this -- somewhat redundant...
+ */
+ fpme->fetch[nr].emit = emit_R32G32B32A32_FLOAT;
+ nr++;
+ }
+
+ fpme->nr_fetch = nr;
+ //fpme->pipeline_vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
+ fpme->pipeline_vertex_size = MAX_VERTEX_ALLOCATION;
+ fpme->hw_vertex_size = vinfo->size * 4;
+}
+
+
+
+
+static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ struct draw_vertex_shader *shader = draw->vertex_shader;
+ char *pipeline_verts;
+
+ pipeline_verts = MALLOC(fpme->pipeline_vertex_size *
+ fetch_count);
+
+ if (!pipeline_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Shade
+ */
+ shader->prepare(shader, draw);
+ if (shader->run(shader, draw, fetch_elts, fetch_count, pipeline_verts,
+ fpme->pipeline_vertex_size)) {
+ /* Run the pipeline */
+ draw_pt_run_pipeline( fpme->draw,
+ fpme->prim,
+ pipeline_verts,
+ fpme->pipeline_vertex_size,
+ fetch_count,
+ draw_elts,
+ draw_count );
+ } else {
+ unsigned i, j;
+ void *hw_verts;
+ float *out;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ hw_verts = draw->render->allocate_vertices(draw->render,
+ (ushort)fpme->hw_vertex_size,
+ (ushort)fetch_count);
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+ out = (float *)hw_verts;
+ for (i = 0; i < fetch_count; i++) {
+ struct vertex_header *header =
+ (struct vertex_header*)(pipeline_verts + (fpme->pipeline_vertex_size * i));
+
+ for (j = 0; j < fpme->nr_fetch; j++) {
+ float *attrib = header->data[j];
+ /*debug_printf("emiting [%f, %f, %f, %f]\n",
+ attrib[0], attrib[1],
+ attrib[2], attrib[3]);*/
+ fpme->fetch[j].emit(attrib, &out);
+ }
+ }
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw(draw->render,
+ draw_elts,
+ draw_count);
+
+ draw->render->release_vertices(draw->render,
+ hw_verts,
+ fpme->hw_vertex_size,
+ fetch_count);
+ }
+
+
+ FREE(pipeline_verts);
+}
+
+
+
+static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
+{
+ /* nothing to do */
+}
+
+static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
+{
+ FREE(middle);
+}
+
+
+struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
+{
+ struct fetch_pipeline_middle_end *fetch_pipeline = CALLOC_STRUCT( fetch_pipeline_middle_end );
+
+ fetch_pipeline->base.prepare = fetch_pipeline_prepare;
+ fetch_pipeline->base.run = fetch_pipeline_run;
+ fetch_pipeline->base.finish = fetch_pipeline_finish;
+ fetch_pipeline->base.destroy = fetch_pipeline_destroy;
+
+ fetch_pipeline->draw = draw;
+
+ return &fetch_pipeline->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_vbuf.c b/src/gallium/auxiliary/draw/draw_vbuf.c
index f83b441e93..e3216ff711 100644
--- a/src/gallium/auxiliary/draw/draw_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_vbuf.c
@@ -126,13 +126,6 @@ dump_emitted_vertex(const struct vertex_info *vinfo, const uint8_t *data)
case EMIT_OMIT:
debug_printf("EMIT_OMIT:");
break;
- case EMIT_ALL:
- assert(i == 0);
- assert(j == 0);
- debug_printf("EMIT_ALL:\t");
- for(k = 0; k < vinfo->size*4; ++k)
- debug_printf("%02x ", *data++);
- break;
case EMIT_1F:
debug_printf("EMIT_1F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
@@ -217,19 +210,6 @@ emit_vertex( struct vbuf_stage *vbuf,
case EMIT_OMIT:
/* no-op */
break;
- case EMIT_ALL:
- /* just copy the whole vertex as-is to the vbuf */
- assert(i == 0);
- assert(j == 0);
- memcpy(vbuf->vertex_ptr, vertex, vinfo->size * 4);
- vbuf->vertex_ptr += vinfo->size;
- count += vinfo->size;
- break;
- case EMIT_HEADER:
- memcpy(vbuf->vertex_ptr, vertex, sizeof(*vertex));
- *vbuf->vertex_ptr += sizeof(*vertex) / 4;
- count += sizeof(*vertex) / 4;
- break;
case EMIT_1F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
count++;
diff --git a/src/gallium/auxiliary/draw/draw_vertex.c b/src/gallium/auxiliary/draw/draw_vertex.c
index 970adc95e7..168036eee8 100644
--- a/src/gallium/auxiliary/draw/draw_vertex.c
+++ b/src/gallium/auxiliary/draw/draw_vertex.c
@@ -52,9 +52,6 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
switch (vinfo->emit[i]) {
case EMIT_OMIT:
break;
- case EMIT_HEADER:
- vinfo->size += sizeof(struct vertex_header) / 4;
- break;
case EMIT_4UB:
/* fall-through */
case EMIT_1F_PSIZE:
@@ -71,8 +68,6 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
case EMIT_4F:
vinfo->size += 4;
break;
- case EMIT_ALL:
- /* fall-through */
default:
assert(0);
}
diff --git a/src/gallium/auxiliary/draw/draw_vertex.h b/src/gallium/auxiliary/draw/draw_vertex.h
index abd2017ed3..65818463ca 100644
--- a/src/gallium/auxiliary/draw/draw_vertex.h
+++ b/src/gallium/auxiliary/draw/draw_vertex.h
@@ -47,8 +47,6 @@
*/
enum attrib_emit {
EMIT_OMIT, /**< don't emit the attribute */
- EMIT_ALL, /**< emit whole post-xform vertex, w/ header */
- EMIT_HEADER, /**< emit vertex_header struct (XXX temp?) */
EMIT_1F,
EMIT_1F_PSIZE, /**< insert constant point size */
EMIT_2F,
diff --git a/src/gallium/auxiliary/draw/draw_vertex_cache.c b/src/gallium/auxiliary/draw/draw_vertex_cache.c
index c0248979e2..730c18bcb3 100644
--- a/src/gallium/auxiliary/draw/draw_vertex_cache.c
+++ b/src/gallium/auxiliary/draw/draw_vertex_cache.c
@@ -71,25 +71,28 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
/* Cache hit?
*/
if (draw->vcache.idx[slot].in == i) {
-// _mesa_printf("HIT %d %d\n", slot, i);
+ /*debug_printf("HIT %d %d\n", slot, i);*/
assert(draw->vcache.idx[slot].out < draw->vs.queue_nr);
- return draw->vs.queue[draw->vcache.idx[slot].out].vertex;
+ return draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION,
+ draw->vcache.idx[slot].out);
}
/* Otherwise a collision
*/
slot = VCACHE_SIZE + draw->vcache.overflow++;
-// _mesa_printf("XXX %d --> %d\n", i, slot);
+ /*debug_printf("XXX %d --> %d\n", i, slot);*/
}
/* Deal with the cache miss:
*/
{
unsigned out;
-
+ struct vertex_header *header;
+
assert(slot < Elements(draw->vcache.idx));
-// _mesa_printf("NEW %d %d\n", slot, i);
+ /*debug_printf("NEW %d %d\n", slot, i);*/
draw->vcache.idx[slot].in = i;
draw->vcache.idx[slot].out = out = draw->vs.queue_nr++;
draw->vcache.referenced |= (1 << slot);
@@ -99,17 +102,21 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
*/
assert(draw->vs.queue_nr < VS_QUEUE_LENGTH);
- draw->vs.queue[out].elt = i;
- draw->vs.queue[out].vertex->clipmask = 0;
- draw->vs.queue[out].vertex->edgeflag = draw_get_edgeflag(draw, i);
- draw->vs.queue[out].vertex->pad = 0;
- draw->vs.queue[out].vertex->vertex_id = UNDEFINED_VERTEX_ID;
+ header = draw_header_from_block(draw->vs.vertex_cache, MAX_VERTEX_ALLOCATION,
+ out);
+ draw->vs.elts[out] = i;
+ header->clipmask = 0;
+ header->edgeflag = draw_get_edgeflag(draw, i);
+ header->pad = 0;
+ header->vertex_id = UNDEFINED_VERTEX_ID;
/* Need to set the vertex's edge flag here. If we're being called
* by do_ef_triangle(), that function needs edge flag info!
*/
- return draw->vs.queue[draw->vcache.idx[slot].out].vertex;
+ return draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION,
+ draw->vcache.idx[slot].out);
}
}
@@ -142,8 +149,12 @@ void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw )
{
unsigned i;
- for (i = 0; i < draw->vs.post_nr; i++)
- draw->vs.queue[i].vertex->vertex_id = UNDEFINED_VERTEX_ID;
+ for (i = 0; i < draw->vs.post_nr; i++) {
+ struct vertex_header * header =
+ draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION, i);
+ header->vertex_id = UNDEFINED_VERTEX_ID;
+ }
}
diff --git a/src/gallium/auxiliary/draw/draw_vertex_shader.c b/src/gallium/auxiliary/draw/draw_vertex_shader.c
index 133418baca..8572a6d40c 100644
--- a/src/gallium/auxiliary/draw/draw_vertex_shader.c
+++ b/src/gallium/auxiliary/draw/draw_vertex_shader.c
@@ -37,8 +37,6 @@
#include "draw_context.h"
#include "draw_vs.h"
-
-
/**
* Run the vertex shader on all vertices in the vertex queue.
* Called by the draw module when the vertx cache needs to be flushed.
@@ -58,25 +56,25 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)
// fprintf(stderr, "%s %d\n", __FUNCTION__, draw->vs.queue_nr );
/* run vertex shader on vertex cache entries, four per invokation */
- for (i = 0; i < draw->vs.queue_nr; i += 4) {
- struct vertex_header *dests[4];
- unsigned elts[4];
- int j, n = MIN2(4, draw->vs.queue_nr - i);
+ for (i = 0; i < draw->vs.queue_nr; i += MAX_SHADER_VERTICES) {
+ unsigned elts[MAX_SHADER_VERTICES];
+ int j, n = MIN2(MAX_SHADER_VERTICES, draw->vs.queue_nr - i);
+ struct vertex_header *dests =
+ draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION, i);
for (j = 0; j < n; j++) {
- elts[j] = draw->vs.queue[i + j].elt;
- dests[j] = draw->vs.queue[i + j].vertex;
+ elts[j] = draw->vs.elts[i + j];
}
- for ( ; j < 4; j++) {
+ for ( ; j < MAX_SHADER_VERTICES; j++) {
elts[j] = elts[0];
- dests[j] = draw->vs.queue[i + j].vertex;
}
assert(n > 0);
- assert(n <= 4);
+ assert(n <= MAX_SHADER_VERTICES);
- shader->run(shader, draw, elts, n, dests);
+ shader->run(shader, draw, elts, n, dests, MAX_VERTEX_ALLOCATION);
}
draw->vs.post_nr = draw->vs.queue_nr;
diff --git a/src/gallium/auxiliary/draw/draw_vf.c b/src/gallium/auxiliary/draw/draw_vf.c
index 7bb34ace7a..9d0154c50d 100644
--- a/src/gallium/auxiliary/draw/draw_vf.c
+++ b/src/gallium/auxiliary/draw/draw_vf.c
@@ -205,7 +205,7 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf,
const struct vertex_info *vinfo,
float point_size )
{
- unsigned i, j, k;
+ unsigned i, j;
struct draw_vf_attr *a = vf->attr;
struct draw_vf_attr_map attrs[PIPE_MAX_SHADER_INPUTS];
unsigned count = 0; /* for debug/sanity */
@@ -217,60 +217,6 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf,
case EMIT_OMIT:
/* no-op */
break;
- case EMIT_ALL: {
- /* just copy the whole vertex as-is to the vbuf */
- unsigned s = vinfo->size;
- assert(i == 0);
- assert(j == 0);
- /* copy the vertex header */
- /* XXX: we actually don't copy the header, just pad it */
- attrs[nr_attrs].attrib = 0;
- attrs[nr_attrs].format = DRAW_EMIT_PAD;
- attrs[nr_attrs].offset = offsetof(struct vertex_header, data);
- s -= offsetof(struct vertex_header, data)/4;
- count += offsetof(struct vertex_header, data)/4;
- nr_attrs++;
- /* copy the vertex data */
- for(k = 0; k < (s & ~0x3); k += 4) {
- attrs[nr_attrs].attrib = k/4;
- attrs[nr_attrs].format = DRAW_EMIT_4F;
- attrs[nr_attrs].offset = 0;
- nr_attrs++;
- count += 4;
- }
- /* tail */
- /* XXX: actually, this shouldn't be needed */
- attrs[nr_attrs].attrib = k/4;
- attrs[nr_attrs].offset = 0;
- switch(s & 0x3) {
- case 0:
- break;
- case 1:
- attrs[nr_attrs].format = DRAW_EMIT_1F;
- nr_attrs++;
- count += 1;
- break;
- case 2:
- attrs[nr_attrs].format = DRAW_EMIT_2F;
- nr_attrs++;
- count += 2;
- break;
- case 3:
- attrs[nr_attrs].format = DRAW_EMIT_3F;
- nr_attrs++;
- count += 3;
- break;
- }
- break;
- }
- case EMIT_HEADER:
- /* XXX emit new DRAW_EMIT_HEADER attribute??? */
- attrs[nr_attrs].attrib = 0;
- attrs[nr_attrs].format = DRAW_EMIT_PAD;
- attrs[nr_attrs].offset = offsetof(struct vertex_header, data);
- count += offsetof(struct vertex_header, data)/4;
- nr_attrs++;
- break;
case EMIT_1F:
attrs[nr_attrs].attrib = j;
attrs[nr_attrs].format = DRAW_EMIT_1F;
diff --git a/src/gallium/auxiliary/draw/draw_vf.h b/src/gallium/auxiliary/draw/draw_vf.h
index 7555d1bd58..0ef98d6257 100644
--- a/src/gallium/auxiliary/draw/draw_vf.h
+++ b/src/gallium/auxiliary/draw/draw_vf.h
@@ -128,9 +128,6 @@ draw_vf_destroy( struct draw_vertex_fetch *vf );
struct draw_vf_attr;
-typedef void (*draw_vf_extract_func)( const struct draw_vf_attr *a,
- float *out,
- const uint8_t *v );
typedef void (*draw_vf_insert_func)( const struct draw_vf_attr *a,
uint8_t *v,
@@ -164,7 +161,6 @@ struct draw_vf_attr
uint8_t *inputptr;
const draw_vf_insert_func *insert;
draw_vf_insert_func do_insert;
- draw_vf_extract_func extract;
};
struct draw_vertex_fetch
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index 4ee7e705e9..33ce1e335e 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -31,6 +31,10 @@
#ifndef DRAW_VS_H
#define DRAW_VS_H
+#include "draw_context.h"
+#include "draw_private.h"
+
+
struct draw_vertex_shader;
struct draw_context;
struct pipe_shader_state;
@@ -47,4 +51,33 @@ struct draw_vertex_shader *
draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *templ);
+
+/* Should be part of the generated shader:
+ */
+static INLINE unsigned
+compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
+{
+ unsigned mask = 0x0;
+ unsigned i;
+
+ /* Do the hardwired planes first:
+ */
+ if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
+ if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
+ if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
+ if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
+ if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
+ if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
+
+ /* Followed by any remaining ones:
+ */
+ for (i = 6; i < nr; i++) {
+ if (dot4(clip, plane[i]) < 0)
+ mask |= (1<<i);
+ }
+
+ return mask;
+}
+
+
#endif
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
index c6e503686a..5c88c2e24e 100644
--- a/src/gallium/auxiliary/draw/draw_vs_exec.c
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -40,32 +40,7 @@
#include "tgsi/util/tgsi_parse.h"
-
-static INLINE unsigned
-compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
-{
- unsigned mask = 0;
- unsigned i;
-
- /* Do the hardwired planes first:
- */
- if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
- if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
- if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
- if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
- if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
- if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
-
- /* Followed by any remaining ones:
- */
- for (i = 6; i < nr; i++) {
- if (dot4(clip, plane[i]) < 0)
- mask |= (1<<i);
- }
-
- return mask;
-}
-
+#define MAX_TGSI_VERTICES 4
static void
vs_exec_prepare( struct draw_vertex_shader *shader,
@@ -89,22 +64,23 @@ vs_exec_prepare( struct draw_vertex_shader *shader,
* \param count number of vertices to shade [1..4]
* \param vOut array of pointers to four output vertices
*/
-static void
+static boolean
vs_exec_run( struct draw_vertex_shader *shader,
struct draw_context *draw,
const unsigned *elts,
unsigned count,
- struct vertex_header *vOut[] )
+ void *vOut,
+ unsigned vertex_size)
{
struct tgsi_exec_machine *machine = &draw->machine;
- unsigned int j;
+ unsigned int i, j;
+ unsigned int clipped = 0;
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_MAX_ATTRIBS);
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_MAX_ATTRIBS);
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
- assert(count <= 4);
assert(draw->vertex_shader->info.output_semantic_name[0]
== TGSI_SEMANTIC_POSITION);
@@ -118,80 +94,87 @@ vs_exec_run( struct draw_vertex_shader *shader,
machine->Outputs = ALIGN16_ASSIGN(outputs);
}
- draw->vertex_fetch.fetch_func( draw, machine, elts, count );
-
- if (!draw->rasterizer->bypass_vs) {
- /* run interpreter */
- tgsi_exec_machine_run( machine );
- }
+ for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
+ unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
+ draw->vertex_fetch.fetch_func( draw, machine, &elts[i], max_vertices );
- /* store machine results */
- for (j = 0; j < count; j++) {
- unsigned slot;
- float x, y, z, w;
-
- /* Handle attr[0] (position) specially:
- *
- * XXX: Computing the clipmask should be done in the vertex
- * program as a set of DP4 instructions appended to the
- * user-provided code.
- */
- x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
- y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
- z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
- w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
-
- if (!draw->rasterizer->bypass_clipping) {
- vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
-
- /* divide by w */
- w = 1.0f / w;
- x *= w;
- y *= w;
- z *= w;
- }
- else {
- vOut[j]->clipmask = 0;
- }
- vOut[j]->edgeflag = 1;
-
- if (!draw->identity_viewport) {
- /* Viewport mapping */
- vOut[j]->data[0][0] = x * scale[0] + trans[0];
- vOut[j]->data[0][1] = y * scale[1] + trans[1];
- vOut[j]->data[0][2] = z * scale[2] + trans[2];
- vOut[j]->data[0][3] = w;
- }
- else {
- vOut[j]->data[0][0] = x;
- vOut[j]->data[0][1] = y;
- vOut[j]->data[0][2] = z;
- vOut[j]->data[0][3] = w;
+ if (!draw->rasterizer->bypass_vs) {
+ /* run interpreter */
+ tgsi_exec_machine_run( machine );
}
- /* Remaining attributes are packed into sequential post-transform
- * vertex attrib slots.
- */
- for (slot = 1; slot < draw->num_vs_outputs; slot++) {
- vOut[j]->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
- vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
- vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
- vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
- }
+ /* store machine results */
+ for (j = 0; j < max_vertices; j++) {
+ unsigned slot;
+ float x, y, z, w;
+ struct vertex_header *out =
+ draw_header_from_block(vOut, vertex_size, i + j);
+
+ /* Handle attr[0] (position) specially:
+ *
+ * XXX: Computing the clipmask should be done in the vertex
+ * program as a set of DP4 instructions appended to the
+ * user-provided code.
+ */
+ x = out->clip[0] = machine->Outputs[0].xyzw[0].f[j];
+ y = out->clip[1] = machine->Outputs[0].xyzw[1].f[j];
+ z = out->clip[2] = machine->Outputs[0].xyzw[2].f[j];
+ w = out->clip[3] = machine->Outputs[0].xyzw[3].f[j];
+
+ if (!draw->rasterizer->bypass_clipping) {
+ out->clipmask = compute_clipmask(out->clip, draw->plane,
+ draw->nr_planes);
+ clipped += out->clipmask;
+
+ /* divide by w */
+ w = 1.0f / w;
+ x *= w;
+ y *= w;
+ z *= w;
+ }
+ else {
+ out->clipmask = 0;
+ }
+ out->edgeflag = 1;
+ out->vertex_id = UNDEFINED_VERTEX_ID;
+
+ if (!draw->identity_viewport) {
+ /* Viewport mapping */
+ out->data[0][0] = x * scale[0] + trans[0];
+ out->data[0][1] = y * scale[1] + trans[1];
+ out->data[0][2] = z * scale[2] + trans[2];
+ out->data[0][3] = w;
+ }
+ else {
+ out->data[0][0] = x;
+ out->data[0][1] = y;
+ out->data[0][2] = z;
+ out->data[0][3] = w;
+ }
+
+ /* Remaining attributes are packed into sequential post-transform
+ * vertex attrib slots.
+ */
+ for (slot = 1; slot < draw->num_vs_outputs; slot++) {
+ out->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ out->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ out->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ out->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ }
#if 0 /*DEBUG*/
- printf("Post xform vert:\n");
- for (slot = 0; slot < draw->num_vs_outputs; slot++) {
- printf("%d: %f %f %f %f\n", slot,
- vOut[j]->data[slot][0],
- vOut[j]->data[slot][1],
- vOut[j]->data[slot][2],
- vOut[j]->data[slot][3]);
- }
-#endif
-
-
- } /* loop over vertices */
+ printf("%d) Post xform vert:\n", i + j);
+ for (slot = 0; slot < draw->num_vs_outputs; slot++) {
+ printf("\t%d: %f %f %f %f\n", slot,
+ out->data[slot][0],
+ out->data[slot][1],
+ out->data[slot][2],
+ out->data[slot][3]);
+ }
+#endif
+ } /* loop over vertices */
+ }
+ return clipped != 0;
}
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
index c8268317ef..73076d2467 100644
--- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -50,33 +50,6 @@ struct draw_llvm_vertex_shader {
};
-static INLINE unsigned
-compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
-{
- unsigned mask = 0;
- unsigned i;
-
- /* Do the hardwired planes first:
- */
- if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
- if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
- if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
- if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
- if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
- if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
-
- /* Followed by any remaining ones:
- */
- for (i = 6; i < nr; i++) {
- if (dot4(clip, plane[i]) < 0)
- mask |= (1<<i);
- }
-
- return mask;
-}
-
-
-
static void
vs_llvm_prepare( struct draw_vertex_shader *base,
struct draw_context *draw )
@@ -94,18 +67,19 @@ vs_llvm_prepare( struct draw_vertex_shader *base,
* \param count number of vertices to shade [1..4]
* \param vOut array of pointers to four output vertices
*/
-static void
+static boolean
vs_llvm_run( struct draw_vertex_shader *base,
- struct draw_context *draw,
- const unsigned *elts,
+ struct draw_context *draw,
+ const unsigned *elts,
unsigned count,
- struct vertex_header *vOut[] )
+ void *vOut )
{
- struct draw_llvm_vertex_shader *shader =
+ struct draw_llvm_vertex_shader *shader =
(struct draw_llvm_vertex_shader *)base;
struct tgsi_exec_machine *machine = &draw->machine;
unsigned int j;
+ unsigned int clipped = 0;
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_MAX_ATTRIBS);
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_MAX_ATTRIBS);
@@ -152,19 +126,22 @@ vs_llvm_run( struct draw_vertex_shader *base,
w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
if (!draw->rasterizer->bypass_clipping) {
- vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
+ vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane,
+ draw->nr_planes);
+ clipped += vOut[j]->clipmask;
/* divide by w */
w = 1.0f / w;
x *= w;
y *= w;
- z *= w;
+ z *= w;
}
else {
vOut[j]->clipmask = 0;
}
vOut[j]->edgeflag = 1;
-
+ vOut[j]->vertex_id = UNDEFINED_VERTEX_ID;
+
if (!draw->identity_viewport) {
/* Viewport mapping */
vOut[j]->data[0][0] = x * scale[0] + trans[0];
@@ -189,6 +166,7 @@ vs_llvm_run( struct draw_vertex_shader *base,
vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
}
} /* loop over vertices */
+ return clipped != 0;
}
static void
diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c
index f40d65df08..ee0a3105b9 100644
--- a/src/gallium/auxiliary/draw/draw_vs_sse.c
+++ b/src/gallium/auxiliary/draw/draw_vs_sse.c
@@ -45,49 +45,24 @@
#include "tgsi/exec/tgsi_sse2.h"
#include "tgsi/util/tgsi_parse.h"
+#define SSE_MAX_VERTICES 4
typedef void (XSTDCALL *codegen_function) (
const struct tgsi_exec_vector *input,
struct tgsi_exec_vector *output,
float (*constant)[4],
- struct tgsi_exec_vector *temporary );
+ struct tgsi_exec_vector *temporary,
+ float (*immediates)[4] );
struct draw_sse_vertex_shader {
struct draw_vertex_shader base;
struct x86_function sse2_program;
codegen_function func;
+ float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
};
-/* Should be part of the generated shader:
- */
-static INLINE unsigned
-compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
-{
- unsigned mask = 0;
- unsigned i;
-
- /* Do the hardwired planes first:
- */
- if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
- if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
- if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
- if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
- if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
- if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
-
- /* Followed by any remaining ones:
- */
- for (i = 6; i < nr; i++) {
- if (dot4(clip, plane[i]) < 0)
- mask |= (1<<i);
- }
-
- return mask;
-}
-
-
static void
vs_sse_prepare( struct draw_vertex_shader *base,
struct draw_context *draw )
@@ -103,23 +78,24 @@ vs_sse_prepare( struct draw_vertex_shader *base,
* \param count number of vertices to shade [1..4]
* \param vOut array of pointers to four output vertices
*/
-static void
+static boolean
vs_sse_run( struct draw_vertex_shader *base,
struct draw_context *draw,
const unsigned *elts,
unsigned count,
- struct vertex_header *vOut[] )
+ void *vOut,
+ unsigned vertex_size )
{
struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
struct tgsi_exec_machine *machine = &draw->machine;
- unsigned int j;
+ unsigned int i, j;
+ unsigned int clipped = 0;
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_MAX_ATTRIBS);
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_MAX_ATTRIBS);
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
- assert(count <= 4);
assert(draw->vertex_shader->info.output_semantic_name[0]
== TGSI_SEMANTIC_POSITION);
@@ -134,76 +110,93 @@ vs_sse_run( struct draw_vertex_shader *base,
machine->Outputs = ALIGN16_ASSIGN(outputs);
}
-
- /* Fetch vertices. This may at some point be integrated into the
- * compiled shader -- that would require a reorganization where
- * multiple versions of the compiled shader might exist,
- * specialized for each fetch state.
- */
- draw->vertex_fetch.fetch_func( draw, machine, elts, count );
-
-
- if (!draw->rasterizer->bypass_vs) {
- /* run compiled shader
- */
- shader->func(machine->Inputs,
- machine->Outputs,
- machine->Consts,
- machine->Temps );
- }
-
-
- /* XXX: Computing the clipmask and emitting results should be done
- * in the vertex program as a set of instructions appended to
- * the user-provided code.
- */
- for (j = 0; j < count; j++) {
- unsigned slot;
- float x, y, z, w;
-
- x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
- y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
- z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
- w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
-
- if (!draw->rasterizer->bypass_clipping) {
- vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
-
- /* divide by w */
- w = 1.0f / w;
- x *= w;
- y *= w;
- z *= w;
- }
- else {
- vOut[j]->clipmask = 0;
- }
- vOut[j]->edgeflag = 1;
-
- if (!draw->identity_viewport) {
- /* Viewport mapping */
- vOut[j]->data[0][0] = x * scale[0] + trans[0];
- vOut[j]->data[0][1] = y * scale[1] + trans[1];
- vOut[j]->data[0][2] = z * scale[2] + trans[2];
- vOut[j]->data[0][3] = w;
- }
- else {
- vOut[j]->data[0][0] = x;
- vOut[j]->data[0][1] = y;
- vOut[j]->data[0][2] = z;
- vOut[j]->data[0][3] = w;
+ for (i = 0; i < count; i += SSE_MAX_VERTICES) {
+ unsigned int max_vertices = MIN2(SSE_MAX_VERTICES, count - i);
+ /* Fetch vertices. This may at some point be integrated into the
+ * compiled shader -- that would require a reorganization where
+ * multiple versions of the compiled shader might exist,
+ * specialized for each fetch state.
+ */
+ draw->vertex_fetch.fetch_func(draw, machine, &elts[i], max_vertices);
+
+ if (!draw->rasterizer->bypass_vs) {
+ /* run compiled shader
+ */
+ shader->func(machine->Inputs,
+ machine->Outputs,
+ machine->Consts,
+ machine->Temps,
+ shader->immediates);
}
- /* Remaining attributes are packed into sequential post-transform
- * vertex attrib slots.
+ /* XXX: Computing the clipmask and emitting results should be done
+ * in the vertex program as a set of instructions appended to
+ * the user-provided code.
*/
- for (slot = 1; slot < draw->num_vs_outputs; slot++) {
- vOut[j]->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
- vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
- vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
- vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ for (j = 0; j < max_vertices; j++) {
+ unsigned slot;
+ float x, y, z, w;
+ struct vertex_header *out =
+ draw_header_from_block(vOut, vertex_size, i + j);
+
+ x = out->clip[0] = machine->Outputs[0].xyzw[0].f[j];
+ y = out->clip[1] = machine->Outputs[0].xyzw[1].f[j];
+ z = out->clip[2] = machine->Outputs[0].xyzw[2].f[j];
+ w = out->clip[3] = machine->Outputs[0].xyzw[3].f[j];
+
+ if (!draw->rasterizer->bypass_clipping) {
+ out->clipmask = compute_clipmask(out->clip, draw->plane,
+ draw->nr_planes);
+ clipped += out->clipmask;
+
+ /* divide by w */
+ w = 1.0f / w;
+ x *= w;
+ y *= w;
+ z *= w;
+ }
+ else {
+ out->clipmask = 0;
+ }
+ out->edgeflag = 1;
+ out->vertex_id = UNDEFINED_VERTEX_ID;
+
+ if (!draw->identity_viewport) {
+ /* Viewport mapping */
+ out->data[0][0] = x * scale[0] + trans[0];
+ out->data[0][1] = y * scale[1] + trans[1];
+ out->data[0][2] = z * scale[2] + trans[2];
+ out->data[0][3] = w;
+ }
+ else {
+ out->data[0][0] = x;
+ out->data[0][1] = y;
+ out->data[0][2] = z;
+ out->data[0][3] = w;
+ }
+
+ /* Remaining attributes are packed into sequential post-transform
+ * vertex attrib slots.
+ */
+ for (slot = 1; slot < draw->num_vs_outputs; slot++) {
+ out->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ out->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ out->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ out->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ }
+#if 0 /*DEBUG*/
+ printf("%d) Post xform vert:\n", i + j);
+ for (slot = 0; slot < draw->num_vs_outputs; slot++) {
+ printf("\t%d: %f %f %f %f\n", slot,
+ out->data[slot][0],
+ out->data[slot][1],
+ out->data[slot][2],
+ out->data[slot][3]);
+ }
+#endif
}
- }
+ }
+ return clipped != 0;
}
@@ -243,7 +236,7 @@ draw_create_vs_sse(struct draw_context *draw,
x86_init_func( &vs->sse2_program );
if (!tgsi_emit_sse2( (struct tgsi_token *) vs->base.state.tokens,
- &vs->sse2_program ))
+ &vs->sse2_program, vs->immediates ))
goto fail;
vs->func = (codegen_function) x86_get_func( &vs->sse2_program );