Browse Source

draw/gs: Abstract the portions of GS that are tgsi specific

To be able to add llvm paths later on we need to have some common
interface for them.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: José Fonseca <jfonseca@vmware.com>
tags/mesa-9.2-rc1
Zack Rusin 12 years ago
parent
commit
014c4d1cd7
2 changed files with 156 additions and 128 deletions
  1. 142
    128
      src/gallium/auxiliary/draw/draw_gs.c
  2. 14
    0
      src/gallium/auxiliary/draw/draw_gs.h

+ 142
- 128
src/gallium/auxiliary/draw/draw_gs.c View File

@@ -42,112 +42,6 @@
/* fixme: move it from here */
#define MAX_PRIMITIVES 64

boolean
draw_gs_init( struct draw_context *draw )
{
draw->gs.tgsi.machine = tgsi_exec_machine_create();
if (!draw->gs.tgsi.machine)
return FALSE;

draw->gs.tgsi.machine->Primitives = align_malloc(
MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector), 16);
if (!draw->gs.tgsi.machine->Primitives)
return FALSE;
memset(draw->gs.tgsi.machine->Primitives, 0,
MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector));

return TRUE;
}

void draw_gs_destroy( struct draw_context *draw )
{
if (!draw->gs.tgsi.machine)
return;

align_free(draw->gs.tgsi.machine->Primitives);

tgsi_exec_machine_destroy(draw->gs.tgsi.machine);
}

struct draw_geometry_shader *
draw_create_geometry_shader(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct draw_geometry_shader *gs;
unsigned i;

gs = CALLOC_STRUCT(draw_geometry_shader);

if (!gs)
return NULL;

gs->draw = draw;
gs->state = *state;
gs->state.tokens = tgsi_dup_tokens(state->tokens);
if (!gs->state.tokens) {
FREE(gs);
return NULL;
}

tgsi_scan_shader(state->tokens, &gs->info);

/* setup the defaults */
gs->input_primitive = PIPE_PRIM_TRIANGLES;
gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP;
gs->max_output_vertices = 32;

for (i = 0; i < gs->info.num_properties; ++i) {
if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_INPUT_PRIM)
gs->input_primitive = gs->info.properties[i].data[0];
else if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_OUTPUT_PRIM)
gs->output_primitive = gs->info.properties[i].data[0];
else if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES)
gs->max_output_vertices = gs->info.properties[i].data[0];
}

gs->machine = draw->gs.tgsi.machine;

if (gs)
{
uint i;
for (i = 0; i < gs->info.num_outputs; i++) {
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
gs->info.output_semantic_index[i] == 0)
gs->position_output = i;
}
}

return gs;
}

void draw_bind_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dgs)
{
draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);

if (dgs) {
draw->gs.geometry_shader = dgs;
draw->gs.num_gs_outputs = dgs->info.num_outputs;
draw->gs.position_output = dgs->position_output;
draw_geometry_shader_prepare(dgs, draw);
}
else {
draw->gs.geometry_shader = NULL;
draw->gs.num_gs_outputs = 0;
}
}

void draw_delete_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dgs)
{
FREE(dgs->primitive_lengths);
FREE((void*) dgs->state.tokens);
FREE(dgs);
}

static INLINE int
draw_gs_get_input_index(int semantic, int index,
const struct tgsi_shader_info *input_info)
@@ -165,10 +59,10 @@ draw_gs_get_input_index(int semantic, int index,
}

/*#define DEBUG_OUTPUTS 1*/
static INLINE void
draw_geometry_fetch_outputs(struct draw_geometry_shader *shader,
unsigned num_primitives,
float (**p_output)[4])
static void
tgsi_fetch_gs_outputs(struct draw_geometry_shader *shader,
unsigned num_primitives,
float (**p_output)[4])
{
struct tgsi_exec_machine *machine = shader->machine;
unsigned prim_idx, j, slot;
@@ -212,7 +106,7 @@ draw_geometry_fetch_outputs(struct draw_geometry_shader *shader,
}

/*#define DEBUG_INPUTS 1*/
static void draw_fetch_gs_input(struct draw_geometry_shader *shader,
static void tgsi_fetch_gs_input(struct draw_geometry_shader *shader,
unsigned *indices,
unsigned num_vertices,
unsigned prim_idx)
@@ -275,14 +169,20 @@ static void draw_fetch_gs_input(struct draw_geometry_shader *shader,
}
}

static void gs_flush(struct draw_geometry_shader *shader,
unsigned input_primitives)
static void tgsi_gs_prepare(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS])
{
unsigned out_prim_count;
struct tgsi_exec_machine *machine = shader->machine;

debug_assert(input_primitives > 0 &&
input_primitives < 4);
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
constants, constants_size);
}

static unsigned tgsi_gs_run(struct draw_geometry_shader *shader,
unsigned input_primitives)
{
struct tgsi_exec_machine *machine = shader->machine;

tgsi_set_exec_mask(machine,
1,
@@ -293,16 +193,26 @@ static void gs_flush(struct draw_geometry_shader *shader,
/* run interpreter */
tgsi_exec_machine_run(machine);

out_prim_count =
return
machine->Temps[TGSI_EXEC_TEMP_PRIMITIVE_I].xyzw[TGSI_EXEC_TEMP_PRIMITIVE_C].u[0];
}

static void gs_flush(struct draw_geometry_shader *shader,
unsigned input_primitives)
{
unsigned out_prim_count;

debug_assert(input_primitives > 0 &&
input_primitives < 4);

out_prim_count = shader->run(shader, input_primitives);
#if 0
debug_printf("PRIM emitted prims = %d (verts=%d), cur prim count = %d\n",
shader->emitted_primitives, shader->emitted_vertices,
out_prim_count);
#endif
draw_geometry_fetch_outputs(shader, out_prim_count,
&shader->tmp_output);
shader->fetch_outputs(shader, out_prim_count,
&shader->tmp_output);
}

static void gs_point(struct draw_geometry_shader *shader,
@@ -312,7 +222,7 @@ static void gs_point(struct draw_geometry_shader *shader,

indices[0] = idx;

draw_fetch_gs_input(shader, indices, 1, 0);
shader->fetch_inputs(shader, indices, 1, 0);
++shader->in_prim_idx;

gs_flush(shader, 1);
@@ -326,7 +236,7 @@ static void gs_line(struct draw_geometry_shader *shader,
indices[0] = i0;
indices[1] = i1;

draw_fetch_gs_input(shader, indices, 2, 0);
shader->fetch_inputs(shader, indices, 2, 0);
++shader->in_prim_idx;

gs_flush(shader, 1);
@@ -342,7 +252,7 @@ static void gs_line_adj(struct draw_geometry_shader *shader,
indices[2] = i2;
indices[3] = i3;

draw_fetch_gs_input(shader, indices, 4, 0);
shader->fetch_inputs(shader, indices, 4, 0);
++shader->in_prim_idx;

gs_flush(shader, 1);
@@ -357,7 +267,7 @@ static void gs_tri(struct draw_geometry_shader *shader,
indices[1] = i1;
indices[2] = i2;

draw_fetch_gs_input(shader, indices, 3, 0);
shader->fetch_inputs(shader, indices, 3, 0);
++shader->in_prim_idx;

gs_flush(shader, 1);
@@ -376,7 +286,7 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
indices[4] = i4;
indices[5] = i5;

draw_fetch_gs_input(shader, indices, 6, 0);
shader->fetch_inputs(shader, indices, 6, 0);
++shader->in_prim_idx;

gs_flush(shader, 1);
@@ -394,7 +304,7 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,


/**
* Execute geometry shader using TGSI interpreter.
* Execute geometry shader.
*/
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
@@ -409,7 +319,6 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
unsigned input_stride = input_verts->vertex_size;
unsigned num_outputs = shader->info.num_outputs;
unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
struct tgsi_exec_machine *machine = shader->machine;
unsigned num_input_verts = input_prim->linear ?
input_verts->count :
input_prim->count;
@@ -451,8 +360,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
FREE(shader->primitive_lengths);
shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));

tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
constants, constants_size);
shader->prepare(shader, constants, constants_size);

if (input_prim->linear)
gs_run(shader, input_prim, input_verts,
@@ -491,3 +399,109 @@ void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
draw->gs.tgsi.sampler);
}
}


boolean
draw_gs_init( struct draw_context *draw )
{
draw->gs.tgsi.machine = tgsi_exec_machine_create();
if (!draw->gs.tgsi.machine)
return FALSE;

draw->gs.tgsi.machine->Primitives = align_malloc(
MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector), 16);
if (!draw->gs.tgsi.machine->Primitives)
return FALSE;
memset(draw->gs.tgsi.machine->Primitives, 0,
MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector));

return TRUE;
}

void draw_gs_destroy( struct draw_context *draw )
{
if (draw->gs.tgsi.machine) {
align_free(draw->gs.tgsi.machine->Primitives);
tgsi_exec_machine_destroy(draw->gs.tgsi.machine);
}
}

struct draw_geometry_shader *
draw_create_geometry_shader(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct draw_geometry_shader *gs;
unsigned i;

gs = CALLOC_STRUCT(draw_geometry_shader);

if (!gs)
return NULL;

gs->draw = draw;
gs->state = *state;
gs->state.tokens = tgsi_dup_tokens(state->tokens);
if (!gs->state.tokens) {
FREE(gs);
return NULL;
}

tgsi_scan_shader(state->tokens, &gs->info);

/* setup the defaults */
gs->input_primitive = PIPE_PRIM_TRIANGLES;
gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP;
gs->max_output_vertices = 32;

for (i = 0; i < gs->info.num_properties; ++i) {
if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_INPUT_PRIM)
gs->input_primitive = gs->info.properties[i].data[0];
else if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_OUTPUT_PRIM)
gs->output_primitive = gs->info.properties[i].data[0];
else if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES)
gs->max_output_vertices = gs->info.properties[i].data[0];
}

for (i = 0; i < gs->info.num_outputs; i++) {
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
gs->info.output_semantic_index[i] == 0)
gs->position_output = i;
}

gs->machine = draw->gs.tgsi.machine;

gs->fetch_outputs = tgsi_fetch_gs_outputs;
gs->fetch_inputs = tgsi_fetch_gs_input;
gs->prepare = tgsi_gs_prepare;
gs->run = tgsi_gs_run;

return gs;
}

void draw_bind_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dgs)
{
draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);

if (dgs) {
draw->gs.geometry_shader = dgs;
draw->gs.num_gs_outputs = dgs->info.num_outputs;
draw->gs.position_output = dgs->position_output;
draw_geometry_shader_prepare(dgs, draw);
}
else {
draw->gs.geometry_shader = NULL;
draw->gs.num_gs_outputs = 0;
}
}

void draw_delete_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dgs)
{
FREE(dgs->primitive_lengths);
FREE((void*) dgs->state.tokens);
FREE(dgs);
}

+ 14
- 0
src/gallium/auxiliary/draw/draw_gs.h View File

@@ -65,6 +65,20 @@ struct draw_geometry_shader {
unsigned input_vertex_stride;
const float (*input)[4];
const struct tgsi_shader_info *input_info;

void (*fetch_inputs)(struct draw_geometry_shader *shader,
unsigned *indices,
unsigned num_vertices,
unsigned prim_idx);
void (*fetch_outputs)(struct draw_geometry_shader *shader,
unsigned num_primitives,
float (**p_output)[4]);

void (*prepare)(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS]);
unsigned (*run)(struct draw_geometry_shader *shader,
unsigned input_primitives);
};

/*

Loading…
Cancel
Save