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>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user