gallium: plug in vertex passthrough code

Based on a patch from Zack.
Basically, implement a new draw_arrays function that copies the incoming
user-vertices to the hardware vertex buffer, doing format/type conversion
as needed.
The vertex fetch/store code is totally temporary for now.
This commit is contained in:
Brian 2008-03-13 17:10:28 -06:00
parent 5bae5871f0
commit d088d640fc
4 changed files with 147 additions and 8 deletions

View file

@ -15,6 +15,7 @@ C_SOURCES = \
draw_debug.c \
draw_flatshade.c \
draw_offset.c \
draw_passthrough.c \
draw_prim.c \
draw_pstipple.c \
draw_stipple.c \

View file

@ -15,6 +15,7 @@ draw = env.ConvenienceLibrary(
'draw_flatshade.c',
'draw_offset.c',
'draw_prim.c',
'draw_passthrough.c',
'draw_pstipple.c',
'draw_passthrough.c',
'draw_stipple.c',

View file

@ -66,6 +66,95 @@
#include "draw/draw_vertex.h"
/**
* General-purpose fetch from user's vertex arrays, emit to driver's
* vertex buffer.
*
* XXX this is totally temporary.
*/
static void
fetch_store_general( struct draw_context *draw,
float *out,
unsigned start,
unsigned count )
{
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
const unsigned nr_attrs = vinfo->num_attribs;
uint i, j;
const unsigned *pitch = draw->vertex_fetch.pitch;
const ubyte **src = draw->vertex_fetch.src_ptr;
for (i = start; i < count; i++) {
for (j = 0; j < nr_attrs; j++) {
const uint jj = vinfo->src_index[j];
const enum pipe_format srcFormat = draw->vertex_element[jj].src_format;
const ubyte *from = src[jj] + i * pitch[jj];
float attrib[4];
switch (srcFormat) {
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = f[1];
attrib[2] = f[2];
attrib[3] = f[3];
}
break;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = f[1];
attrib[2] = f[2];
attrib[3] = 1.0;
}
break;
case PIPE_FORMAT_R32G32_FLOAT:
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = f[1];
attrib[2] = 0.0;
attrib[3] = 1.0;
}
break;
case PIPE_FORMAT_R32_FLOAT:
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = 0.0;
attrib[2] = 0.0;
attrib[3] = 1.0;
}
break;
default:
abort();
}
/* XXX this will probably only work for softpipe */
switch (vinfo->emit[j]) {
case EMIT_HEADER:
memset(out, 0, sizeof(struct vertex_header));
out += sizeof(struct vertex_header) / 4;
break;
case EMIT_4F:
out[0] = attrib[0];
out[1] = attrib[1];
out[2] = attrib[2];
out[3] = attrib[3];
out += 4;
break;
default:
abort();
}
}
}
}
/* Example of a fetch/emit passthrough shader which could be
* generated when bypass_clipping is enabled on a passthrough vertex
@ -116,7 +205,6 @@ static void fetch_xyz_rgb_st( struct draw_context *draw,
}
}
static boolean update_shader( struct draw_context *draw )
{
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
@ -143,11 +231,15 @@ static boolean update_shader( struct draw_context *draw )
/* Just trying to figure out how this would work:
*/
if (nr_attrs == 3 &&
0 /* some other tests */)
if (draw->rasterizer->bypass_vs ||
(nr_attrs == 3 && 0 /* some other tests */))
{
#if 0
draw->vertex_fetch.pt_fetch = fetch_xyz_rgb_st;
assert(vinfo->size == 10);
#else
draw->vertex_fetch.pt_fetch = fetch_store_general;
#endif
/*assert(vinfo->size == 10);*/
return TRUE;
}
@ -175,7 +267,6 @@ static boolean set_prim( struct draw_context *draw,
}
boolean
draw_passthrough_arrays(struct draw_context *draw,
unsigned prim,
@ -184,10 +275,13 @@ draw_passthrough_arrays(struct draw_context *draw,
{
float *hw_verts;
if (draw_need_pipeline(draw))
return FALSE;
if (!set_prim(draw, prim))
return FALSE;
if (!update_shader( draw ))
if (!update_shader(draw))
return FALSE;
hw_verts = draw->render->allocate_vertices( draw->render,

View file

@ -31,6 +31,7 @@
*/
#include "pipe/p_debug.h"
#include "pipe/p_util.h"
#include "draw_private.h"
#include "draw_context.h"
@ -118,7 +119,42 @@ static void draw_prim_queue_flush( struct draw_context *draw )
draw_vertex_cache_unreference( draw );
}
static INLINE void fetch_and_store(struct draw_context *draw)
{
unsigned i;
/* run vertex shader on vertex cache entries, four per invokation */
#if 0
{
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
memcpy(draw->vs.queue[0].vertex, draw->vs.queue[i + j].elt,
count * vinfo->size);
}
#elif 0
draw_update_vertex_fetch(draw);
for (i = 0; i < draw->vs.queue_nr; i += 4) {
struct vertex_header *dests[4];
unsigned elts[4];
struct tgsi_exec_machine *machine = &draw->machine;
int j, n = MIN2(4, draw->vs.queue_nr - i);
for (j = 0; j < n; j++) {
elts[j] = draw->vs.queue[i + j].elt;
dests[j] = draw->vs.queue[i + j].vertex;
}
for ( ; j < 4; j++) {
elts[j] = elts[0];
dests[j] = draw->vs.queue[i + j].vertex;
}
//fetch directly into dests
draw->vertex_fetch.fetch_func(draw, machine, dests, count);
}
#endif
draw->vs.post_nr = draw->vs.queue_nr;
draw->vs.queue_nr = 0;
}
void draw_do_flush( struct draw_context *draw, unsigned flags )
{
@ -134,7 +170,10 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
if (draw->vs.queue_nr)
(*draw->shader_queue_flush)(draw);
if (draw->rasterizer->bypass_vs)
fetch_and_store(draw);
else
(*draw->shader_queue_flush)(draw);
if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
if (draw->pq.queue_nr)
@ -485,7 +524,11 @@ draw_arrays(struct draw_context *draw, unsigned prim,
}
/* drawing done here: */
draw_prim(draw, prim, start, count);
if (!draw->rasterizer->bypass_vs ||
!draw_passthrough_arrays(draw, prim, start, count)) {
/* we have to run the whole pipeline */
draw_prim(draw, prim, start, count);
}
}