mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-29 08:30:42 +02:00
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:
parent
5bae5871f0
commit
d088d640fc
4 changed files with 147 additions and 8 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue