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/draw_context.c35
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h9
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c423
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.h33
-rw-r--r--src/gallium/auxiliary/draw/draw_gs_tmp.h152
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c71
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h97
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c117
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_aaline.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_aapoint.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_cull.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_flatshade.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_offset.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_pstipple.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_stipple.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_twoside.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_unfilled.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_wide_line.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_wide_point.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h52
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c19
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h32
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c41
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c45
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c403
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c391
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_post_vs.c77
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_so_emit.c303
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray.c10
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c40
-rw-r--r--src/gallium/auxiliary/draw/draw_so_emit_tmp.h123
-rw-r--r--src/gallium/auxiliary/draw/draw_vbuf.h8
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c5
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c120
38 files changed, 1956 insertions, 779 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 61980c3e4f..dab95e5051 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -435,13 +435,18 @@ draw_num_shader_outputs(const struct draw_context *draw)
*/
void
draw_texture_samplers(struct draw_context *draw,
+ uint shader,
uint num_samplers,
struct tgsi_sampler **samplers)
{
- draw->vs.num_samplers = num_samplers;
- draw->vs.samplers = samplers;
- draw->gs.num_samplers = num_samplers;
- draw->gs.samplers = samplers;
+ if (shader == PIPE_SHADER_VERTEX) {
+ draw->vs.num_samplers = num_samplers;
+ draw->vs.samplers = samplers;
+ } else {
+ debug_assert(shader == PIPE_SHADER_GEOMETRY);
+ draw->gs.num_samplers = num_samplers;
+ draw->gs.samplers = samplers;
+ }
}
@@ -574,3 +579,25 @@ draw_get_rasterizer_no_cull( struct draw_context *draw,
}
return draw->rasterizer_no_cull[scissor][flatshade];
}
+
+void
+draw_set_mapped_so_buffers(struct draw_context *draw,
+ void *buffers[PIPE_MAX_SO_BUFFERS],
+ unsigned num_buffers)
+{
+ int i;
+
+ for (i = 0; i < num_buffers; ++i) {
+ draw->so.buffers[i] = buffers[i];
+ }
+ draw->so.num_buffers = num_buffers;
+}
+
+void
+draw_set_so_state(struct draw_context *draw,
+ struct pipe_stream_output_state *state)
+{
+ memcpy(&draw->so.state,
+ state,
+ sizeof(struct pipe_stream_output_state));
+}
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index b905c2f2da..c0122f2aca 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -97,6 +97,7 @@ draw_num_shader_outputs(const struct draw_context *draw);
void
draw_texture_samplers(struct draw_context *draw,
+ uint shader_type,
uint num_samplers,
struct tgsi_sampler **samplers);
@@ -162,6 +163,14 @@ draw_set_mapped_constant_buffer(struct draw_context *draw,
const void *buffer,
unsigned size);
+void
+draw_set_mapped_so_buffers(struct draw_context *draw,
+ void *buffers[PIPE_MAX_SO_BUFFERS],
+ unsigned num_buffers);
+void
+draw_set_so_state(struct draw_context *draw,
+ struct pipe_stream_output_state *state);
+
/***********************************************************************
* draw_prim.c
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 131deed43e..79a57a67f3 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -37,8 +37,8 @@
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_prim.h"
-#define MAX_PRIM_VERTICES 6
/* fixme: move it from here */
#define MAX_PRIMITIVES 64
@@ -75,6 +75,7 @@ draw_gs_set_constants(struct draw_context *draw,
const void *constants,
unsigned size)
{
+ /* noop */
}
@@ -90,6 +91,7 @@ draw_create_geometry_shader(struct draw_context *draw,
if (!gs)
return NULL;
+ gs->draw = draw;
gs->state = *state;
gs->state.tokens = tgsi_dup_tokens(state->tokens);
if (!gs->state.tokens) {
@@ -112,7 +114,7 @@ draw_create_geometry_shader(struct draw_context *draw,
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_VERTICES)
+ TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES)
gs->max_output_vertices = gs->info.properties[i].data[0];
}
@@ -154,128 +156,37 @@ void draw_delete_geometry_shader(struct draw_context *draw,
FREE(dgs);
}
-static INLINE int num_vertices_for_prim(int prim)
-{
- switch(prim) {
- case PIPE_PRIM_POINTS:
- return 1;
- case PIPE_PRIM_LINES:
- return 2;
- case PIPE_PRIM_LINE_LOOP:
- return 2;
- case PIPE_PRIM_LINE_STRIP:
- return 2;
- case PIPE_PRIM_TRIANGLES:
- return 3;
- case PIPE_PRIM_TRIANGLE_STRIP:
- return 3;
- case PIPE_PRIM_TRIANGLE_FAN:
- return 3;
- case PIPE_PRIM_LINES_ADJACENCY:
- case PIPE_PRIM_LINE_STRIP_ADJACENCY:
- return 4;
- case PIPE_PRIM_TRIANGLES_ADJACENCY:
- case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
- return 6;
- default:
- assert(!"Bad geometry shader input");
- return 0;
- }
-}
-
-static void draw_fetch_geometry_input(struct draw_geometry_shader *shader,
- int start_primitive,
- int num_primitives,
- const float (*input_ptr)[4],
- unsigned input_vertex_stride,
- unsigned inputs_from_vs)
-{
- struct tgsi_exec_machine *machine = shader->machine;
- unsigned slot, vs_slot, k, j;
- unsigned num_vertices = num_vertices_for_prim(shader->input_primitive);
- int idx = 0;
-
- for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; slot++) {
- /*debug_printf("Slot = %d (semantic = %d)\n", slot,
- shader->info.input_semantic_name[slot]);*/
- if (shader->info.input_semantic_name[slot] ==
- TGSI_SEMANTIC_PRIMID) {
- for (j = 0; j < num_primitives; ++j) {
- machine->Inputs[idx].xyzw[0].f[j] = (float)start_primitive + j;
- machine->Inputs[idx].xyzw[1].f[j] = (float)start_primitive + j;
- machine->Inputs[idx].xyzw[2].f[j] = (float)start_primitive + j;
- machine->Inputs[idx].xyzw[3].f[j] = (float)start_primitive + j;
- }
- ++idx;
- } else {
- for (j = 0; j < num_primitives; ++j) {
- int vidx = idx;
- const float (*prim_ptr)[4];
- /*debug_printf(" %d) Prim (num_verts = %d)\n", start_primitive + j,
- num_vertices);*/
- prim_ptr = (const float (*)[4])(
- (const char *)input_ptr +
- (j * num_vertices * input_vertex_stride));
-
- for (k = 0; k < num_vertices; ++k, ++vidx) {
- const float (*input)[4];
- input = (const float (*)[4])(
- (const char *)prim_ptr + (k * input_vertex_stride));
- vidx = k * TGSI_EXEC_MAX_INPUT_ATTRIBS + slot;
- /*debug_printf("\t%d)(%d) Input vert:\n", vidx, k);*/
-#if 1
- assert(!util_is_inf_or_nan(input[vs_slot][0]));
- assert(!util_is_inf_or_nan(input[vs_slot][1]));
- assert(!util_is_inf_or_nan(input[vs_slot][2]));
- assert(!util_is_inf_or_nan(input[vs_slot][3]));
-#endif
- machine->Inputs[vidx].xyzw[0].f[j] = input[vs_slot][0];
- machine->Inputs[vidx].xyzw[1].f[j] = input[vs_slot][1];
- machine->Inputs[vidx].xyzw[2].f[j] = input[vs_slot][2];
- machine->Inputs[vidx].xyzw[3].f[j] = input[vs_slot][3];
-#if 0
- debug_printf("\t\t%d %f %f %f %f\n", slot,
- machine->Inputs[vidx].xyzw[0].f[j],
- machine->Inputs[vidx].xyzw[1].f[j],
- machine->Inputs[vidx].xyzw[2].f[j],
- machine->Inputs[vidx].xyzw[3].f[j]);
-#endif
- }
- }
- ++vs_slot;
- idx += num_vertices;
- }
- }
-}
-
+/*#define DEBUG_OUTPUTS 1*/
static INLINE void
draw_geometry_fetch_outputs(struct draw_geometry_shader *shader,
int num_primitives,
- float (*output)[4],
- unsigned vertex_size)
+ float (**p_output)[4])
{
struct tgsi_exec_machine *machine = shader->machine;
unsigned prim_idx, j, slot;
+ float (*output)[4];
+
+ output = *p_output;
/* Unswizzle all output results.
*/
- /* FIXME: handle all the primitives produced by the gs, not just
- * the first one
- unsigned prim_count =
- mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0];*/
+
for (prim_idx = 0; prim_idx < num_primitives; ++prim_idx) {
- unsigned num_verts_per_prim = machine->Primitives[0];
+ unsigned num_verts_per_prim = machine->Primitives[prim_idx];
+ shader->primitive_lengths[prim_idx + shader->emitted_primitives] =
+ machine->Primitives[prim_idx];
+ shader->emitted_vertices += num_verts_per_prim;
for (j = 0; j < num_verts_per_prim; j++) {
int idx = (prim_idx * num_verts_per_prim + j) *
shader->info.num_outputs;
#ifdef DEBUG_OUTPUTS
- debug_printf("%d) Output vert:\n", idx);
+ debug_printf("%d) Output vert:\n", idx / shader->info.num_outputs);
#endif
for (slot = 0; slot < shader->info.num_outputs; slot++) {
- output[slot][0] = machine->Outputs[idx + slot].xyzw[0].f[prim_idx];
- output[slot][1] = machine->Outputs[idx + slot].xyzw[1].f[prim_idx];
- output[slot][2] = machine->Outputs[idx + slot].xyzw[2].f[prim_idx];
- output[slot][3] = machine->Outputs[idx + slot].xyzw[3].f[prim_idx];
+ output[slot][0] = machine->Outputs[idx + slot].xyzw[0].f[0];
+ output[slot][1] = machine->Outputs[idx + slot].xyzw[1].f[0];
+ output[slot][2] = machine->Outputs[idx + slot].xyzw[2].f[0];
+ output[slot][3] = machine->Outputs[idx + slot].xyzw[3].f[0];
#ifdef DEBUG_OUTPUTS
debug_printf("\t%d: %f %f %f %f\n", slot,
output[slot][0],
@@ -285,52 +196,286 @@ draw_geometry_fetch_outputs(struct draw_geometry_shader *shader,
#endif
debug_assert(!util_is_inf_or_nan(output[slot][0]));
}
- output = (float (*)[4])((char *)output + vertex_size);
+ output = (float (*)[4])((char *)output + shader->vertex_size);
}
}
+ *p_output = output;
+ shader->emitted_primitives += num_primitives;
}
-void draw_geometry_shader_run(struct draw_geometry_shader *shader,
- const float (*input)[4],
- float (*output)[4],
- const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
- unsigned count,
- unsigned input_stride,
- unsigned vertex_size)
+/*#define DEBUG_INPUTS 1*/
+static void draw_fetch_gs_input(struct draw_geometry_shader *shader,
+ unsigned *indices,
+ unsigned num_vertices,
+ unsigned prim_idx)
{
struct tgsi_exec_machine *machine = shader->machine;
- unsigned int i;
- unsigned num_vertices = num_vertices_for_prim(shader->input_primitive);
- unsigned num_primitives = count/num_vertices;
- unsigned inputs_from_vs = 0;
+ unsigned slot, vs_slot, i;
+ unsigned input_vertex_stride = shader->input_vertex_stride;
+ const float (*input_ptr)[4];
- for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
- machine->Consts[i] = constants[i];
- }
+ input_ptr = shader->input;
- for (i = 0; i < shader->info.num_inputs; ++i) {
- if (shader->info.input_semantic_name[i] != TGSI_SEMANTIC_PRIMID)
- ++inputs_from_vs;
+ for (i = 0; i < num_vertices; ++i) {
+ const float (*input)[4];
+#if DEBUG_INPUTS
+ debug_printf("%d) vertex index = %d (prim idx = %d)\n",
+ i, indices[i], prim_idx);
+#endif
+ input = (const float (*)[4])(
+ (const char *)input_ptr + (indices[i] * input_vertex_stride));
+ for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {
+ unsigned idx = i * TGSI_EXEC_MAX_INPUT_ATTRIBS + slot;
+ if (shader->info.input_semantic_name[slot] == TGSI_SEMANTIC_PRIMID) {
+ machine->Inputs[idx].xyzw[0].f[prim_idx] =
+ (float)shader->in_prim_idx;
+ machine->Inputs[idx].xyzw[1].f[prim_idx] =
+ (float)shader->in_prim_idx;
+ machine->Inputs[idx].xyzw[2].f[prim_idx] =
+ (float)shader->in_prim_idx;
+ machine->Inputs[idx].xyzw[3].f[prim_idx] =
+ (float)shader->in_prim_idx;
+ } else {
+#if DEBUG_INPUTS
+ debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
+ slot, vs_slot, idx);
+#endif
+#if 1
+ assert(!util_is_inf_or_nan(input[vs_slot][0]));
+ assert(!util_is_inf_or_nan(input[vs_slot][1]));
+ assert(!util_is_inf_or_nan(input[vs_slot][2]));
+ assert(!util_is_inf_or_nan(input[vs_slot][3]));
+#endif
+ machine->Inputs[idx].xyzw[0].f[prim_idx] = input[vs_slot][0];
+ machine->Inputs[idx].xyzw[1].f[prim_idx] = input[vs_slot][1];
+ machine->Inputs[idx].xyzw[2].f[prim_idx] = input[vs_slot][2];
+ machine->Inputs[idx].xyzw[3].f[prim_idx] = input[vs_slot][3];
+#if DEBUG_INPUTS
+ debug_printf("\t\t%f %f %f %f\n",
+ machine->Inputs[idx].xyzw[0].f[prim_idx],
+ machine->Inputs[idx].xyzw[1].f[prim_idx],
+ machine->Inputs[idx].xyzw[2].f[prim_idx],
+ machine->Inputs[idx].xyzw[3].f[prim_idx]);
+#endif
+ ++vs_slot;
+ }
+ }
}
+}
+
+static void gs_flush(struct draw_geometry_shader *shader,
+ unsigned input_primitives)
+{
+ unsigned out_prim_count;
+ struct tgsi_exec_machine *machine = shader->machine;
+
+ debug_assert(input_primitives > 0 &&
+ input_primitives < 4);
+
+ tgsi_set_exec_mask(machine,
+ 1,
+ input_primitives > 1,
+ input_primitives > 2,
+ input_primitives > 3);
+
+ /* run interpreter */
+ tgsi_exec_machine_run(machine);
+
+ out_prim_count =
+ machine->Temps[TGSI_EXEC_TEMP_PRIMITIVE_I].xyzw[TGSI_EXEC_TEMP_PRIMITIVE_C].u[0];
+
+#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);
+}
+
+static void gs_point(struct draw_geometry_shader *shader,
+ int idx)
+{
+ unsigned indices[1];
- for (i = 0; i < num_primitives; ++i) {
- unsigned int max_primitives = 1;
+ indices[0] = idx;
- draw_fetch_geometry_input(shader, i, max_primitives, input,
- input_stride, inputs_from_vs);
+ draw_fetch_gs_input(shader, indices, 1, 0);
+ ++shader->in_prim_idx;
- tgsi_set_exec_mask(machine,
- 1,
- max_primitives > 1,
- max_primitives > 2,
- max_primitives > 3);
+ gs_flush(shader, 1);
+}
+
+static void gs_line(struct draw_geometry_shader *shader,
+ int i0, int i1)
+{
+ unsigned indices[2];
+
+ indices[0] = i0;
+ indices[1] = i1;
+
+ draw_fetch_gs_input(shader, indices, 2, 0);
+ ++shader->in_prim_idx;
+
+ gs_flush(shader, 1);
+}
+
+static void gs_line_adj(struct draw_geometry_shader *shader,
+ int i0, int i1, int i2, int i3)
+{
+ unsigned indices[4];
+
+ indices[0] = i0;
+ indices[1] = i1;
+ indices[2] = i2;
+ indices[3] = i3;
+
+ draw_fetch_gs_input(shader, indices, 4, 0);
+ ++shader->in_prim_idx;
+
+ gs_flush(shader, 1);
+}
+
+static void gs_tri(struct draw_geometry_shader *shader,
+ int i0, int i1, int i2)
+{
+ unsigned indices[3];
+
+ indices[0] = i0;
+ indices[1] = i1;
+ indices[2] = i2;
+
+ draw_fetch_gs_input(shader, indices, 3, 0);
+ ++shader->in_prim_idx;
+
+ gs_flush(shader, 1);
+}
+
+static void gs_tri_adj(struct draw_geometry_shader *shader,
+ int i0, int i1, int i2,
+ int i3, int i4, int i5)
+{
+ unsigned indices[6];
+
+ indices[0] = i0;
+ indices[1] = i1;
+ indices[2] = i2;
+ indices[3] = i3;
+ indices[4] = i4;
+ indices[5] = i5;
- /* run interpreter */
- tgsi_exec_machine_run(machine);
+ draw_fetch_gs_input(shader, indices, 6, 0);
+ ++shader->in_prim_idx;
- draw_geometry_fetch_outputs(shader, max_primitives,
- output, vertex_size);
+ gs_flush(shader, 1);
+}
+
+#define TRIANGLE(gs,i0,i1,i2) gs_tri(gs,i0,i1,i2)
+#define TRI_ADJ(gs,i0,i1,i2,i3,i4,i5) gs_tri_adj(gs,i0,i1,i2,i3,i4,i5)
+#define LINE(gs,i0,i1) gs_line(gs,i0,i1)
+#define LINE_ADJ(gs,i0,i1,i2,i3) gs_line_adj(gs,i0,i1,i2,i3)
+#define POINT(gs,i0) gs_point(gs,i0)
+#define FUNC gs_run
+#define LOCAL_VARS
+#include "draw_gs_tmp.h"
+
+
+#define TRIANGLE(gs,i0,i1,i2) gs_tri(gs,elts[i0],elts[i1],elts[i2])
+#define TRI_ADJ(gs,i0,i1,i2,i3,i4,i5) \
+ gs_tri_adj(gs,elts[i0],elts[i1],elts[i2],elts[i3], \
+ elts[i4],elts[i5])
+#define LINE(gs,i0,i1) gs_line(gs,elts[i0],elts[i1])
+#define LINE_ADJ(gs,i0,i1,i2,i3) gs_line_adj(gs,elts[i0], \
+ elts[i1], \
+ elts[i2],elts[i3])
+#define POINT(gs,i0) gs_point(gs,elts[i0])
+#define FUNC gs_run_elts
+#define LOCAL_VARS \
+ const ushort *elts = input_prims->elts;
+#include "draw_gs_tmp.h"
+
+int draw_geometry_shader_run(struct draw_geometry_shader *shader,
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const struct draw_vertex_info *input_verts,
+ const struct draw_prim_info *input_prim,
+ struct draw_vertex_info *output_verts,
+ struct draw_prim_info *output_prims )
+{
+ const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
+ unsigned input_stride = input_verts->vertex_size;
+ unsigned vertex_size = input_verts->vertex_size;
+ struct tgsi_exec_machine *machine = shader->machine;
+ unsigned int i;
+ unsigned num_input_verts = input_prim->linear ?
+ input_verts->count :
+ input_prim->count;
+ unsigned num_in_primitives =
+ MAX2(u_gs_prims_for_vertices(input_prim->prim, num_input_verts),
+ u_gs_prims_for_vertices(shader->input_primitive, num_input_verts));
+ unsigned max_out_prims = u_gs_prims_for_vertices(shader->output_primitive,
+ shader->max_output_vertices)
+ * num_in_primitives;
+
+ output_verts->vertex_size = input_verts->vertex_size;
+ output_verts->stride = input_verts->vertex_size;
+ output_verts->verts =
+ (struct vertex_header *)MALLOC(input_verts->vertex_size *
+ num_in_primitives *
+ shader->max_output_vertices);
+
+
+#if 0
+ debug_printf("%s count = %d (in prims # = %d)\n",
+ __FUNCTION__, num_input_verts, num_in_primitives);
+ debug_printf("\tlinear = %d, prim_info->count = %d\n",
+ input_prim->linear, input_prim->count);
+ debug_printf("\tprimt pipe = %d, shader in = %d, shader out = %d, max out = %d\n",
+ input_prim->prim, shader->input_primitive,
+ shader->output_primitive,
+ shader->max_output_vertices);
+#endif
+
+ shader->emitted_vertices = 0;
+ shader->emitted_primitives = 0;
+ shader->vertex_size = vertex_size;
+ shader->tmp_output = (float (*)[4])output_verts->verts->data;
+ shader->in_prim_idx = 0;
+ shader->input_vertex_stride = input_stride;
+ shader->input = input;
+ if (shader->primitive_lengths) {
+ FREE(shader->primitive_lengths);
}
+ shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));
+
+ for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
+ machine->Consts[i] = constants[i];
+ }
+
+ if (input_prim->linear)
+ gs_run(shader, input_prim, input_verts,
+ output_prims, output_verts);
+ else
+ gs_run_elts(shader, input_prim, input_verts,
+ output_prims, output_verts);
+
+ /* Update prim_info:
+ */
+ output_prims->linear = TRUE;
+ output_prims->elts = NULL;
+ output_prims->start = 0;
+ output_prims->count = shader->emitted_vertices;
+ output_prims->prim = shader->output_primitive;
+ output_prims->primitive_lengths = shader->primitive_lengths;
+ output_prims->primitive_count = shader->emitted_primitives;
+ output_verts->count = shader->emitted_vertices;
+
+#if 0
+ debug_printf("GS finished, prims = %d, verts = %d\n",
+ output_prims->primitive_count,
+ output_verts->count);
+#endif
+
+ return shader->emitted_vertices;
}
void draw_geometry_shader_delete(struct draw_geometry_shader *shader)
diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
index d8eb210343..2cb634818c 100644
--- a/src/gallium/auxiliary/draw/draw_gs.h
+++ b/src/gallium/auxiliary/draw/draw_gs.h
@@ -54,23 +54,36 @@ struct draw_geometry_shader {
unsigned input_primitive;
unsigned output_primitive;
- /* Extracted from shader:
- */
- const float (*immediates)[4];
+ unsigned *primitive_lengths;
+ unsigned emitted_vertices;
+ unsigned emitted_primitives;
+
+ float (*tmp_output)[4];
+ unsigned vertex_size;
+
+ unsigned in_prim_idx;
+ unsigned input_vertex_stride;
+ const float (*input)[4];
};
-void draw_geometry_shader_run(struct draw_geometry_shader *shader,
- const float (*input)[4],
- float (*output)[4],
- const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
- unsigned count,
- unsigned input_stride,
- unsigned output_stride);
+/*
+ * Returns the number of vertices emitted.
+ * The vertex shader can emit any number of vertices as long as it's
+ * smaller than the GS_MAX_OUTPUT_VERTICES shader property.
+ */
+int draw_geometry_shader_run(struct draw_geometry_shader *shader,
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const struct draw_vertex_info *input_verts,
+ const struct draw_prim_info *input_prim,
+ struct draw_vertex_info *output_verts,
+ struct draw_prim_info *output_prims );
void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
struct draw_context *draw);
void draw_geometry_shader_delete(struct draw_geometry_shader *shader);
+int draw_gs_max_output_vertices(struct draw_geometry_shader *shader,
+ unsigned pipe_prim);
#endif
diff --git a/src/gallium/auxiliary/draw/draw_gs_tmp.h b/src/gallium/auxiliary/draw/draw_gs_tmp.h
new file mode 100644
index 0000000000..7a8683cf7c
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_gs_tmp.h
@@ -0,0 +1,152 @@
+
+static void FUNC( struct draw_geometry_shader *shader,
+ const struct draw_prim_info *input_prims,
+ const struct draw_vertex_info *input_verts,
+ struct draw_prim_info *output_prims,
+ struct draw_vertex_info *output_verts)
+{
+ struct draw_context *draw = shader->draw;
+
+ boolean flatfirst = (draw->rasterizer->flatshade &&
+ draw->rasterizer->flatshade_first);
+ unsigned i, j;
+ unsigned count = input_prims->count;
+ LOCAL_VARS
+
+ if (0) debug_printf("%s %d\n", __FUNCTION__, count);
+
+ debug_assert(input_prims->primitive_count == 1);
+
+ switch (input_prims->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i++) {
+ POINT( shader, i + 0 );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ LINE( shader , i + 0 , i + 1 );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+
+ for (i = 1; i < count; i++) {
+ LINE( shader, i - 1, i );
+ }
+
+ LINE( shader, i - 1, 0 );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < count; i++) {
+ LINE( shader, i - 1, i );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ TRIANGLE( shader, i + 0, i + 1, i + 2 );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( shader,
+ i + 0,
+ i + 1 + (i&1),
+ i + 2 - (i&1) );
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( shader,
+ i + 0 + (i&1),
+ i + 1 - (i&1),
+ i + 2 );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( shader,
+ i + 1,
+ i + 2,
+ 0 );
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( shader,
+ 0,
+ i + 1,
+ i + 2 );
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ {
+ for (i = 0; i+2 < count; i++) {
+
+ if (flatfirst) {
+ TRIANGLE( shader, 0, i + 1, i + 2 );
+ }
+ else {
+ TRIANGLE( shader, i + 1, i + 2, 0 );
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_LINES_ADJACENCY:
+ for (i = 0; i+3 < count; i += 4) {
+ LINE_ADJ( shader , i + 0 , i + 1, i + 2, i + 3 );
+ }
+ break;
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ for (i = 1; i + 2 < count; i++) {
+ LINE_ADJ( shader, i - 1, i, i + 1, i + 2 );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ for (i = 0; i+5 < count; i += 5) {
+ TRI_ADJ( shader, i + 0, i + 1, i + 2,
+ i + 3, i + 4, i + 5);
+ }
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ for (i = 0, j = 0; i+5 < count; i += 2, ++j) {
+ TRI_ADJ( shader,
+ i + 0,
+ i + 1 + 2*(j&1),
+ i + 2 + 2*(j&1),
+ i + 3 - 2*(j&1),
+ i + 4 - 2*(j&1),
+ i + 5);
+ }
+ break;
+
+ default:
+ debug_assert(!"Unsupported primitive in geometry shader");
+ break;
+ }
+}
+
+
+#undef TRIANGLE
+#undef TRI_ADJ
+#undef POINT
+#undef LINE
+#undef LINE_ADJ
+#undef FUNC
+#undef LOCAL_VARS
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index bd5d8853cf..f521669fcd 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -1,3 +1,30 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * 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 VMWARE 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 "draw_llvm.h"
#include "draw_context.h"
@@ -173,6 +200,8 @@ draw_llvm_create(struct draw_context *draw)
#endif
llvm = CALLOC_STRUCT( draw_llvm );
+ if (!llvm)
+ return NULL;
llvm->draw = draw;
llvm->engine = draw->engine;
@@ -217,6 +246,9 @@ draw_llvm_create(struct draw_context *draw)
LLVMDumpModule(llvm->module);
}
+ llvm->nr_variants = 0;
+ make_empty_list(&llvm->vs_variants_list);
+
return llvm;
}
@@ -229,9 +261,13 @@ draw_llvm_destroy(struct draw_llvm *llvm)
}
struct draw_llvm_variant *
-draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs)
+draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs)
{
struct draw_llvm_variant *variant = MALLOC(sizeof(struct draw_llvm_variant));
+ struct llvm_vertex_shader *shader =
+ llvm_vertex_shader(llvm->draw->vs.vertex_shader);
+
+ variant->llvm = llvm;
draw_llvm_make_variant_key(llvm, &variant->key);
@@ -240,6 +276,12 @@ draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs)
draw_llvm_generate(llvm, variant);
draw_llvm_generate_elts(llvm, variant);
+ variant->shader = shader;
+ variant->list_item_global.base = variant;
+ variant->list_item_local.base = variant;
+ /*variant->no = */shader->variants_created++;
+ variant->list_item_global.base = variant;
+
return variant;
}
@@ -895,3 +937,30 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm,
&llvm->draw->vs.vertex_shader->state,
sizeof(struct pipe_shader_state));
}
+
+void
+draw_llvm_destroy_variant(struct draw_llvm_variant *variant)
+{
+ struct draw_llvm *llvm = variant->llvm;
+ struct draw_context *draw = llvm->draw;
+
+ if (variant->function_elts) {
+ if (variant->function_elts)
+ LLVMFreeMachineCodeForFunction(draw->engine,
+ variant->function_elts);
+ LLVMDeleteFunction(variant->function_elts);
+ }
+
+ if (variant->function) {
+ if (variant->function)
+ LLVMFreeMachineCodeForFunction(draw->engine,
+ variant->function);
+ LLVMDeleteFunction(variant->function);
+ }
+
+ remove_from_list(&variant->list_item_local);
+ variant->shader->variants_cached--;
+ remove_from_list(&variant->list_item_global);
+ llvm->nr_variants--;
+ FREE(variant);
+}
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index 58fee7f9d6..c98d7fb393 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -1,15 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * 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 VMWARE 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.
+ *
+ **************************************************************************/
+
#ifndef HAVE_LLVM_H
#define HAVE_LLVM_H
#include "draw/draw_private.h"
+#include "draw/draw_vs.h"
+
#include "pipe/p_context.h"
+#include "util/u_simple_list.h"
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/Target.h>
#include <llvm-c/ExecutionEngine.h>
+struct draw_llvm;
+struct llvm_vertex_shader;
+
struct draw_jit_texture
{
uint32_t width;
@@ -104,11 +137,50 @@ typedef void
unsigned stride,
struct pipe_vertex_buffer *vertex_buffers);
+struct draw_llvm_variant_key
+{
+ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+ unsigned nr_vertex_elements;
+ struct pipe_shader_state vs;
+};
+
+struct draw_llvm_variant_list_item
+{
+ struct draw_llvm_variant *base;
+ struct draw_llvm_variant_list_item *next, *prev;
+};
+
+struct draw_llvm_variant
+{
+ struct draw_llvm_variant_key key;
+ LLVMValueRef function;
+ LLVMValueRef function_elts;
+ draw_jit_vert_func jit_func;
+ draw_jit_vert_func_elts jit_func_elts;
+
+ struct llvm_vertex_shader *shader;
+
+ struct draw_llvm *llvm;
+ struct draw_llvm_variant_list_item list_item_global;
+ struct draw_llvm_variant_list_item list_item_local;
+};
+
+struct llvm_vertex_shader {
+ struct draw_vertex_shader base;
+
+ struct draw_llvm_variant_list_item variants;
+ unsigned variants_created;
+ unsigned variants_cached;
+};
+
struct draw_llvm {
struct draw_context *draw;
struct draw_jit_context jit_context;
+ struct draw_llvm_variant_list_item vs_variants_list;
+ int nr_variants;
+
LLVMModuleRef module;
LLVMExecutionEngineRef engine;
LLVMModuleProviderRef provider;
@@ -121,23 +193,12 @@ struct draw_llvm {
LLVMTypeRef vb_ptr_type;
};
-struct draw_llvm_variant_key
+static struct llvm_vertex_shader *
+llvm_vertex_shader(struct draw_vertex_shader *vs)
{
- struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
- unsigned nr_vertex_elements;
- struct pipe_shader_state vs;
-};
+ return (struct llvm_vertex_shader *)vs;
+}
-struct draw_llvm_variant
-{
- struct draw_llvm_variant_key key;
- LLVMValueRef function;
- LLVMValueRef function_elts;
- draw_jit_vert_func jit_func;
- draw_jit_vert_func_elts jit_func_elts;
-
- struct draw_llvm_variant *next;
-};
struct draw_llvm *
draw_llvm_create(struct draw_context *draw);
@@ -146,7 +207,10 @@ void
draw_llvm_destroy(struct draw_llvm *llvm);
struct draw_llvm_variant *
-draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs);
+draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs);
+
+void
+draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
void
draw_llvm_make_variant_key(struct draw_llvm *llvm,
@@ -156,4 +220,5 @@ LLVMValueRef
draw_llvm_translate_from(LLVMBuilderRef builder,
LLVMValueRef vbuffer,
enum pipe_format from_format);
+
#endif
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 7ea04e3819..8cd75ecf9a 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -177,15 +177,15 @@ static void do_triangle( struct draw_context *draw,
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * elts[i0], \
- verts + stride * elts[i1], \
- verts + stride * elts[i2]); \
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_1 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * elts[i0], \
- verts + stride * elts[i2], \
- verts + stride * elts[i3])
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
/* emit last quad vertex as last vertex in triangles */
#define QUAD_LAST_PV(i0,i1,i2,i3) \
@@ -193,15 +193,15 @@ static void do_triangle( struct draw_context *draw,
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * elts[i0], \
- verts + stride * elts[i1], \
- verts + stride * elts[i3]); \
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * elts[i1], \
- verts + stride * elts[i2], \
- verts + stride * elts[i3])
+ verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, \
@@ -218,7 +218,7 @@ static void do_triangle( struct draw_context *draw,
#define POINT(i0) \
do_point( draw, \
- verts + stride * elts[i0] )
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK) )
#define FUNC pipe_run
#define ARGS \
@@ -256,27 +256,34 @@ static void do_triangle( struct draw_context *draw,
* draw_vbuf.c code uses when it has to perform a flush.
*/
void draw_pipeline_run( struct draw_context *draw,
- unsigned prim,
- struct vertex_header *vertices,
- unsigned vertex_count,
- unsigned stride,
- const ushort *elts,
- unsigned count )
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
{
- char *verts = (char *)vertices;
+ unsigned i, start;
+
+ draw->pipeline.verts = (char *)vert_info->verts;
+ draw->pipeline.vertex_stride = vert_info->stride;
+ draw->pipeline.vertex_count = vert_info->count;
+
+ for (start = i = 0;
+ i < prim_info->primitive_count;
+ start += prim_info->primitive_lengths[i], i++)
+ {
+ unsigned count = prim_info->primitive_lengths[i];
+
+ pipe_run(draw,
+ prim_info->prim,
+ vert_info->verts,
+ vert_info->stride,
+ prim_info->elts + start,
+ count);
+ }
- draw->pipeline.verts = verts;
- draw->pipeline.vertex_stride = stride;
- draw->pipeline.vertex_count = vertex_count;
-
- pipe_run(draw, prim, vertices, stride, elts, count);
-
draw->pipeline.verts = NULL;
draw->pipeline.vertex_count = 0;
}
-
/*
* Set up macros for draw_pt_decompose.h template code.
* This code is for non-indexed (aka linear) rendering (no elts).
@@ -289,14 +296,14 @@ void draw_pipeline_run( struct draw_context *draw,
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1), \
- verts + stride * (i2)); \
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_1 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i2), \
- verts + stride * (i3))
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
/* emit last quad vertex as last vertex in triangles */
#define QUAD_LAST_PV(i0,i1,i2,i3) \
@@ -305,31 +312,31 @@ void draw_pipeline_run( struct draw_context *draw,
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1), \
- verts + stride * (i3)); \
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i2), \
- verts + stride * (i3))
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, \
flags, /* flags */ \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1), \
- verts + stride * (i2))
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK))
#define LINE(flags,i0,i1) \
do_line( draw, \
flags, \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (i1))
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK))
#define POINT(i0) \
do_point( draw, \
- verts + stride * i0 )
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK) )
#define FUNC pipe_run_linear
#define ARGS \
@@ -354,17 +361,29 @@ void draw_pipeline_run( struct draw_context *draw,
* For drawing non-indexed primitives.
*/
void draw_pipeline_run_linear( struct draw_context *draw,
- unsigned prim,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride )
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
{
- char *verts = (char *)vertices;
- draw->pipeline.verts = verts;
- draw->pipeline.vertex_stride = stride;
- draw->pipeline.vertex_count = count;
-
- pipe_run_linear(draw, prim, vertices, stride, count);
+ unsigned i, start;
+
+ for (start = i = 0;
+ i < prim_info->primitive_count;
+ start += prim_info->primitive_lengths[i], i++)
+ {
+ unsigned count = prim_info->primitive_lengths[i];
+ char *verts = ((char*)vert_info->verts) +
+ (start * vert_info->stride);
+
+ draw->pipeline.verts = verts;
+ draw->pipeline.vertex_stride = vert_info->stride;
+ draw->pipeline.vertex_count = count;
+
+ pipe_run_linear(draw,
+ prim_info->prim,
+ (struct vertex_header*)verts,
+ vert_info->stride,
+ count);
+ }
draw->pipeline.verts = NULL;
draw->pipeline.vertex_count = 0;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
index 4faf0a779c..debd17fd74 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
@@ -788,9 +788,6 @@ draw_aaline_stage(struct draw_context *draw)
if (aaline == NULL)
return NULL;
- if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
- goto fail;
-
aaline->stage.draw = draw;
aaline->stage.name = "aaline";
aaline->stage.next = NULL;
@@ -801,11 +798,14 @@ draw_aaline_stage(struct draw_context *draw)
aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
aaline->stage.destroy = aaline_destroy;
+ if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
+ goto fail;
+
return aaline;
fail:
if (aaline)
- aaline_destroy(&aaline->stage);
+ aaline->stage.destroy(&aaline->stage);
return NULL;
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c
index bba6f50c02..d406a86ccb 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c
@@ -780,9 +780,6 @@ draw_aapoint_stage(struct draw_context *draw)
if (aapoint == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &aapoint->stage, 4 ))
- goto fail;
-
aapoint->stage.draw = draw;
aapoint->stage.name = "aapoint";
aapoint->stage.next = NULL;
@@ -793,11 +790,14 @@ draw_aapoint_stage(struct draw_context *draw)
aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter;
aapoint->stage.destroy = aapoint_destroy;
+ if (!draw_alloc_temp_verts( &aapoint->stage, 4 ))
+ goto fail;
+
return aapoint;
fail:
if (aapoint)
- aapoint_destroy(&aapoint->stage);
+ aapoint->stage.destroy(&aapoint->stage);
return NULL;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index df8d82e367..122b1c7968 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -522,9 +522,6 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw )
if (clipper == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &clipper->stage, MAX_CLIPPED_VERTICES+1 ))
- goto fail;
-
clipper->stage.draw = draw;
clipper->stage.name = "clipper";
clipper->stage.point = clip_point;
@@ -536,6 +533,9 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw )
clipper->plane = draw->plane;
+ if (!draw_alloc_temp_verts( &clipper->stage, MAX_CLIPPED_VERTICES+1 ))
+ goto fail;
+
return &clipper->stage;
fail:
diff --git a/src/gallium/auxiliary/draw/draw_pipe_cull.c b/src/gallium/auxiliary/draw/draw_pipe_cull.c
index bf84ce30ed..2f4d01d23a 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_cull.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_cull.c
@@ -129,9 +129,6 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw )
if (cull == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &cull->stage, 0 ))
- goto fail;
-
cull->stage.draw = draw;
cull->stage.name = "cull";
cull->stage.next = NULL;
@@ -142,6 +139,9 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw )
cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
cull->stage.destroy = cull_destroy;
+ if (!draw_alloc_temp_verts( &cull->stage, 0 ))
+ goto fail;
+
return &cull->stage;
fail:
diff --git a/src/gallium/auxiliary/draw/draw_pipe_flatshade.c b/src/gallium/auxiliary/draw/draw_pipe_flatshade.c
index 34afb1a0b6..693f2895aa 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_flatshade.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_flatshade.c
@@ -257,9 +257,6 @@ struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
if (flatshade == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
- goto fail;
-
flatshade->stage.draw = draw;
flatshade->stage.name = "flatshade";
flatshade->stage.next = NULL;
@@ -270,6 +267,9 @@ struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
flatshade->stage.destroy = flatshade_destroy;
+ if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
+ goto fail;
+
return &flatshade->stage;
fail:
diff --git a/src/gallium/auxiliary/draw/draw_pipe_offset.c b/src/gallium/auxiliary/draw/draw_pipe_offset.c
index 8e321946ce..8afbbfa156 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_offset.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_offset.c
@@ -161,9 +161,7 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw )
{
struct offset_stage *offset = CALLOC_STRUCT(offset_stage);
if (offset == NULL)
- return NULL;
-
- draw_alloc_temp_verts( &offset->stage, 3 );
+ goto fail;
offset->stage.draw = draw;
offset->stage.name = "offset";
@@ -175,5 +173,14 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw )
offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
offset->stage.destroy = offset_destroy;
+ if (!draw_alloc_temp_verts( &offset->stage, 3 ))
+ goto fail;
+
return &offset->stage;
+
+fail:
+ if (offset)
+ offset->stage.destroy( &offset->stage );
+
+ return NULL;
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
index ef30db094f..fff960c7eb 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
@@ -607,8 +607,8 @@ static struct pstip_stage *
draw_pstip_stage(struct draw_context *draw)
{
struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
-
- draw_alloc_temp_verts( &pstip->stage, 8 );
+ if (pstip == NULL)
+ goto fail;
pstip->stage.draw = draw;
pstip->stage.name = "pstip";
@@ -620,7 +620,16 @@ draw_pstip_stage(struct draw_context *draw)
pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
pstip->stage.destroy = pstip_destroy;
+ if (!draw_alloc_temp_verts( &pstip->stage, 8 ))
+ goto fail;
+
return pstip;
+
+fail:
+ if (pstip)
+ pstip->stage.destroy( &pstip->stage );
+
+ return NULL;
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_stipple.c b/src/gallium/auxiliary/draw/draw_pipe_stipple.c
index 70fbab9ea7..4b3f4e7ae1 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_stipple.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_stipple.c
@@ -235,8 +235,8 @@ stipple_destroy( struct draw_stage *stage )
struct draw_stage *draw_stipple_stage( struct draw_context *draw )
{
struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage);
-
- draw_alloc_temp_verts( &stipple->stage, 2 );
+ if (stipple == NULL)
+ goto fail;
stipple->stage.draw = draw;
stipple->stage.name = "stipple";
@@ -248,5 +248,14 @@ struct draw_stage *draw_stipple_stage( struct draw_context *draw )
stipple->stage.flush = stipple_flush;
stipple->stage.destroy = stipple_destroy;
+ if (!draw_alloc_temp_verts( &stipple->stage, 2 ))
+ goto fail;
+
return &stipple->stage;
+
+fail:
+ if (stipple)
+ stipple->stage.destroy( &stipple->stage );
+
+ return NULL;
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_twoside.c b/src/gallium/auxiliary/draw/draw_pipe_twoside.c
index 808b2fb0b5..9a3f3fee62 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_twoside.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_twoside.c
@@ -177,9 +177,6 @@ struct draw_stage *draw_twoside_stage( struct draw_context *draw )
if (twoside == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &twoside->stage, 3 ))
- goto fail;
-
twoside->stage.draw = draw;
twoside->stage.name = "twoside";
twoside->stage.next = NULL;
@@ -190,6 +187,9 @@ struct draw_stage *draw_twoside_stage( struct draw_context *draw )
twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
twoside->stage.destroy = twoside_destroy;
+ if (!draw_alloc_temp_verts( &twoside->stage, 3 ))
+ goto fail;
+
return &twoside->stage;
fail:
diff --git a/src/gallium/auxiliary/draw/draw_pipe_unfilled.c b/src/gallium/auxiliary/draw/draw_pipe_unfilled.c
index e333d26a93..d87741b91e 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_unfilled.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_unfilled.c
@@ -202,9 +202,6 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
if (unfilled == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))
- goto fail;
-
unfilled->stage.draw = draw;
unfilled->stage.name = "unfilled";
unfilled->stage.next = NULL;
@@ -216,6 +213,9 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
unfilled->stage.destroy = unfilled_destroy;
+ if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))
+ goto fail;
+
return &unfilled->stage;
fail:
diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c
index d7ac95b740..98da9cfb99 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c
@@ -202,8 +202,8 @@ static void wideline_destroy( struct draw_stage *stage )
struct draw_stage *draw_wide_line_stage( struct draw_context *draw )
{
struct wideline_stage *wide = CALLOC_STRUCT(wideline_stage);
-
- draw_alloc_temp_verts( &wide->stage, 4 );
+ if (wide == NULL)
+ goto fail;
wide->stage.draw = draw;
wide->stage.name = "wide-line";
@@ -215,5 +215,14 @@ struct draw_stage *draw_wide_line_stage( struct draw_context *draw )
wide->stage.reset_stipple_counter = wideline_reset_stipple_counter;
wide->stage.destroy = wideline_destroy;
+ if (!draw_alloc_temp_verts( &wide->stage, 4 ))
+ goto fail;
+
return &wide->stage;
+
+fail:
+ if (wide)
+ wide->stage.destroy( &wide->stage );
+
+ return NULL;
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
index a86fe19586..3e6e538995 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
@@ -324,9 +324,6 @@ struct draw_stage *draw_wide_point_stage( struct draw_context *draw )
if (wide == NULL)
goto fail;
- if (!draw_alloc_temp_verts( &wide->stage, 4 ))
- goto fail;
-
wide->stage.draw = draw;
wide->stage.name = "wide-point";
wide->stage.next = NULL;
@@ -337,6 +334,9 @@ struct draw_stage *draw_wide_point_stage( struct draw_context *draw )
wide->stage.reset_stipple_counter = widepoint_reset_stipple_counter;
wide->stage.destroy = widepoint_destroy;
+ if (!draw_alloc_temp_verts( &wide->stage, 4 ))
+ goto fail;
+
return &wide->stage;
fail:
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index a2bfb693c0..54944a7c67 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -81,6 +81,9 @@ struct vertex_header {
#define UNDEFINED_VERTEX_ID 0xffff
+/* maximum number of shader variants we can cache */
+#define DRAW_MAX_SHADER_VARIANTS 1024
+
/**
* Private context for the drawing module.
*/
@@ -235,6 +238,12 @@ struct draw_context
struct tgsi_sampler **samplers;
} gs;
+ struct {
+ struct pipe_stream_output_state state;
+ void *buffers[PIPE_MAX_SO_BUFFERS];
+ uint num_buffers;
+ } so;
+
/* Clip derived state:
*/
float plane[12][4];
@@ -259,6 +268,34 @@ struct draw_context
void *driver_private;
};
+
+struct draw_fetch_info {
+ boolean linear;
+ unsigned start;
+ const unsigned *elts;
+ unsigned count;
+};
+
+struct draw_vertex_info {
+ struct vertex_header *verts;
+ unsigned vertex_size;
+ unsigned stride;
+ unsigned count;
+};
+
+struct draw_prim_info {
+ boolean linear;
+ unsigned start;
+
+ const ushort *elts;
+ unsigned count;
+
+ unsigned prim;
+ unsigned *primitive_lengths;
+ unsigned primitive_count;
+};
+
+
/*******************************************************************************
* Draw common initialization code
*/
@@ -336,18 +373,13 @@ void draw_pipeline_destroy( struct draw_context *draw );
#define DRAW_PIPE_FLAG_MASK (0xf<<12)
void draw_pipeline_run( struct draw_context *draw,
- unsigned prim,
- struct vertex_header *vertices,
- unsigned vertex_count,
- unsigned stride,
- const ushort *elts,
- unsigned count );
+ const struct draw_vertex_info *vert,
+ const struct draw_prim_info *prim);
void draw_pipeline_run_linear( struct draw_context *draw,
- unsigned prim,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride );
+ const struct draw_vertex_info *vert,
+ const struct draw_prim_info *prim);
+
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index b853f3a89f..6234272d6c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -31,6 +31,7 @@
*/
#include "draw/draw_context.h"
+#include "draw/draw_gs.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
#include "tgsi/tgsi_dump.h"
@@ -74,30 +75,34 @@ draw_pt_arrays(struct draw_context *draw,
{
unsigned first, incr;
draw_pt_split_prim(prim, &first, &incr);
- count = trim(count, first, incr);
+ count = trim(count, first, incr);
if (count < first)
return TRUE;
}
if (!draw->force_passthrough) {
+ unsigned gs_out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ prim);
+
if (!draw->render) {
opt |= PT_PIPELINE;
}
-
+
if (draw_need_pipeline(draw,
draw->rasterizer,
- prim)) {
+ gs_out_prim)) {
opt |= PT_PIPELINE;
}
if (!draw->bypass_clipping && !draw->pt.test_fse) {
opt |= PT_CLIPTEST;
}
-
+
opt |= PT_SHADE;
}
-
- if (draw->pt.middle.llvm) {
+
+ if (draw->pt.middle.llvm && !draw->gs.geometry_shader) {
middle = draw->pt.middle.llvm;
} else {
if (opt == 0)
@@ -119,7 +124,7 @@ draw_pt_arrays(struct draw_context *draw,
frontend->prepare( frontend, prim, middle, opt );
- frontend->run(frontend,
+ frontend->run(frontend,
draw_pt_elt_func(draw),
draw_pt_elt_ptr(draw, start),
draw->pt.user.eltBias,
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 3e3ea320cc..44356fba4c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -39,6 +39,8 @@ typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
struct draw_pt_middle_end;
struct draw_context;
+struct draw_prim_info;
+struct draw_vertex_info;
#define PT_SHADE 0x1
@@ -162,21 +164,31 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
unsigned *max_vertices );
void draw_pt_emit( struct pt_emit *emit,
- const float (*vertex_data)[4],
- unsigned vertex_count,
- unsigned stride,
- const ushort *elts,
- unsigned count );
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info);
void draw_pt_emit_linear( struct pt_emit *emit,
- const float (*vertex_data)[4],
- unsigned stride,
- unsigned count );
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info);
void draw_pt_emit_destroy( struct pt_emit *emit );
struct pt_emit *draw_pt_emit_create( struct draw_context *draw );
+/*******************************************************************************
+ * HW stream output emit:
+ */
+struct pt_so_emit;
+
+void draw_pt_so_emit_prepare( struct pt_so_emit *emit );
+
+void draw_pt_so_emit( struct pt_so_emit *emit,
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info );
+
+void draw_pt_so_emit_destroy( struct pt_so_emit *emit );
+
+struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw );
/*******************************************************************************
* API vertex fetch:
@@ -208,9 +220,7 @@ struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw );
struct pt_post_vs;
boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
- struct vertex_header *pipeline_verts,
- unsigned stride,
- unsigned count );
+ struct draw_vertex_info *info );
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
boolean bypass_clipping,
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index f623c0743d..0229bcc7fe 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -127,15 +127,17 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
void draw_pt_emit( struct pt_emit *emit,
- const float (*vertex_data)[4],
- unsigned vertex_count,
- unsigned stride,
- const ushort *elts,
- unsigned count )
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
{
+ const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
+ unsigned vertex_count = vert_info->count;
+ unsigned stride = vert_info->stride;
+ const ushort *elts = prim_info->elts;
struct draw_context *draw = emit->draw;
struct translate *translate = emit->translate;
struct vbuf_render *render = draw->render;
+ unsigned start, i;
void *hw_verts;
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
@@ -190,23 +192,31 @@ void draw_pt_emit( struct pt_emit *emit,
0,
vertex_count - 1 );
- render->draw_elements(render,
- elts,
- count);
+ for (start = i = 0;
+ i < prim_info->primitive_count;
+ start += prim_info->primitive_lengths[i], i++)
+ {
+ render->draw_elements(render,
+ elts + start,
+ prim_info->primitive_lengths[i]);
+ }
render->release_vertices(render);
}
void draw_pt_emit_linear(struct pt_emit *emit,
- const float (*vertex_data)[4],
- unsigned stride,
- unsigned count)
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
{
+ const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
+ unsigned stride = vert_info->stride;
+ unsigned count = vert_info->count;
struct draw_context *draw = emit->draw;
struct translate *translate = emit->translate;
struct vbuf_render *render = draw->render;
void *hw_verts;
+ unsigned start, i;
#if 0
debug_printf("Linear emit\n");
@@ -258,7 +268,14 @@ void draw_pt_emit_linear(struct pt_emit *emit,
render->unmap_vertices( render, 0, count - 1 );
- render->draw_arrays(render, 0, count);
+ for (start = i = 0;
+ i < prim_info->primitive_count;
+ start += prim_info->primitive_lengths[i], i++)
+ {
+ render->draw_arrays(render,
+ start,
+ prim_info->primitive_lengths[i]);
+ }
render->release_vertices(render);
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index a1347221b5..ae12ee24bd 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -29,7 +29,6 @@
#include "util/u_math.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
-#include "draw/draw_vbuf.h"
#include "draw/draw_pt.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
@@ -69,31 +68,12 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
fetch->vertex_size = vertex_size;
- /* Always emit/leave space for a vertex header.
- *
- * It's worth considering whether the vertex headers should contain
- * a pointer to the 'data', rather than having it inline.
- * Something to look at after we've fully switched over to the pt
- * paths.
+ /* Leave the clipmask/edgeflags/pad/vertex_id untouched
*/
- {
- /* Need to set header->vertex_id = 0xffff somehow.
- */
- key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
- key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
- key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
- key.element[nr].input_offset = 0;
- key.element[nr].instance_divisor = 0;
- key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
- key.element[nr].output_offset = dst_offset;
- dst_offset += 1 * sizeof(float);
- nr++;
-
-
- /* Just leave the clip[] array untouched.
- */
- dst_offset += 4 * sizeof(float);
- }
+ dst_offset += 1 * sizeof(float);
+ /* Just leave the clip[] array untouched.
+ */
+ dst_offset += 4 * sizeof(float);
if (instance_id_index != ~0) {
num_extra_inputs++;
@@ -132,26 +112,11 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
key.nr_elements = nr;
key.output_stride = vertex_size;
-
if (!fetch->translate ||
translate_key_compare(&fetch->translate->key, &key) != 0)
{
translate_key_sanitize(&key);
fetch->translate = translate_cache_find(fetch->cache, &key);
-
- {
- static struct vertex_header vh = { 0,
- 1,
- 0,
- UNDEFINED_VERTEX_ID,
- { .0f, .0f, .0f, .0f } };
-
- fetch->translate->set_buffer(fetch->translate,
- draw->pt.nr_vertex_buffers,
- &vh,
- 0,
- ~0);
- }
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index 5158c6341c..5c8af17c8e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -36,6 +36,7 @@
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
+#include "draw/draw_gs.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
@@ -100,9 +101,14 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
boolean ok;
struct translate_key key;
+ unsigned gs_out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ prim);
+
+
ok = draw->render->set_primitive( draw->render,
- prim );
+ gs_out_prim );
if (!ok) {
assert(0);
return;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
index f0fc591bf5..b8270280b6 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -67,9 +67,8 @@ struct fetch_shade_emit {
-
static void fse_prepare( struct draw_pt_middle_end *middle,
- unsigned prim,
+ unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -79,9 +78,12 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
const struct vertex_info *vinfo;
unsigned i;
unsigned nr_vbs = 0;
-
- if (!draw->render->set_primitive( draw->render,
+ /* Can't support geometry shader on this path.
+ */
+ assert(!draw->gs.geometry_shader);
+
+ if (!draw->render->set_primitive( draw->render,
prim )) {
assert(0);
return;
@@ -90,7 +92,6 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
/* Must do this after set_primitive() above:
*/
fse->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
-
fse->key.output_stride = vinfo->size * 4;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index da5106463a..121dfc414a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -27,6 +27,7 @@
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_prim.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
@@ -40,16 +41,16 @@ struct fetch_pipeline_middle_end {
struct draw_context *draw;
struct pt_emit *emit;
+ struct pt_so_emit *so_emit;
struct pt_fetch *fetch;
struct pt_post_vs *post_vs;
unsigned vertex_data_offset;
unsigned vertex_size;
- unsigned prim;
+ unsigned input_prim;
unsigned opt;
};
-
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned prim,
unsigned opt,
@@ -61,6 +62,10 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned instance_id_index = ~0;
+ unsigned gs_out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ prim);
+
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
@@ -76,7 +81,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
}
}
- fpme->prim = prim;
+ fpme->input_prim = prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@@ -98,11 +103,13 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)draw->identity_viewport,
(boolean)draw->rasterizer->gl_rasterization_rules,
- (draw->vs.edgeflag_output ? true : false) );
+ (draw->vs.edgeflag_output ? TRUE : FALSE) );
+
+ draw_pt_so_emit_prepare( fpme->so_emit );
if (!(opt & PT_PIPELINE)) {
- draw_pt_emit_prepare( fpme->emit,
- prim,
+ draw_pt_emit_prepare( fpme->emit,
+ gs_out_prim,
max_vertices );
*max_vertices = MAX2( *max_vertices,
@@ -121,147 +128,146 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
}
-
-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 )
+static void fetch( struct pt_fetch *fetch,
+ const struct draw_fetch_info *fetch_info,
+ char *output)
{
- struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
- struct draw_context *draw = fpme->draw;
- struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
- struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
- unsigned opt = fpme->opt;
- unsigned alloc_count = align( fetch_count, 4 );
-
- struct vertex_header *pipeline_verts =
- (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
-
- if (!pipeline_verts) {
- /* Not much we can do here - just skip the rendering.
- */
- assert(0);
- return;
+ if (fetch_info->linear) {
+ draw_pt_fetch_run_linear( fetch,
+ fetch_info->start,
+ fetch_info->count,
+ output );
}
-
- /* Fetch into our vertex buffer
- */
- draw_pt_fetch_run( fpme->fetch,
- fetch_elts,
- fetch_count,
- (char *)pipeline_verts );
-
- /* Run the shader, note that this overwrites the data[] parts of
- * the pipeline verts.
- */
- if (opt & PT_SHADE)
- {
- vshader->run_linear(vshader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- draw->pt.user.vs_constants,
- fetch_count,
- fpme->vertex_size,
- fpme->vertex_size);
- if (gshader)
- draw_geometry_shader_run(gshader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- draw->pt.user.gs_constants,
- fetch_count,
- fpme->vertex_size,
- fpme->vertex_size);
+ else {
+ draw_pt_fetch_run( fetch,
+ fetch_info->elts,
+ fetch_info->count,
+ output );
}
+}
- if (draw_pt_post_vs_run( fpme->post_vs,
- pipeline_verts,
- fetch_count,
- fpme->vertex_size ))
- {
- opt |= PT_PIPELINE;
- }
- /* Do we need to run the pipeline?
- */
- if (opt & PT_PIPELINE) {
+static void pipeline(struct fetch_pipeline_middle_end *fpme,
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
+{
+ if (prim_info->linear)
+ draw_pipeline_run_linear( fpme->draw,
+ vert_info,
+ prim_info);
+ else
draw_pipeline_run( fpme->draw,
- fpme->prim,
- pipeline_verts,
- fetch_count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
+ vert_info,
+ prim_info );
+}
+
+static void emit(struct pt_emit *emit,
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
+{
+ if (prim_info->linear) {
+ draw_pt_emit_linear(emit, vert_info, prim_info);
}
else {
- draw_pt_emit( fpme->emit,
- (const float (*)[4])pipeline_verts->data,
- fetch_count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
+ draw_pt_emit(emit, vert_info, prim_info);
}
+}
- FREE(pipeline_verts);
+static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const struct draw_vertex_info *input_verts,
+ struct draw_vertex_info *output_verts )
+{
+ output_verts->vertex_size = input_verts->vertex_size;
+ output_verts->stride = input_verts->vertex_size;
+ output_verts->count = input_verts->count;
+ output_verts->verts =
+ (struct vertex_header *)MALLOC(output_verts->vertex_size *
+ align(output_verts->count, 4));
+
+ vshader->run_linear(vshader,
+ (const float (*)[4])input_verts->verts->data,
+ ( float (*)[4])output_verts->verts->data,
+ constants,
+ input_verts->count,
+ input_verts->vertex_size,
+ input_verts->vertex_size);
}
-
-static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
- unsigned start,
- unsigned count)
+static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
+ const struct draw_fetch_info *fetch_info,
+ const struct draw_prim_info *prim_info )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
- struct draw_vertex_shader *shader = draw->vs.vertex_shader;
- struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
+ struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
+ struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
+ struct draw_prim_info gs_prim_info;
+ struct draw_vertex_info fetched_vert_info;
+ struct draw_vertex_info vs_vert_info;
+ struct draw_vertex_info gs_vert_info;
+ struct draw_vertex_info *vert_info;
unsigned opt = fpme->opt;
- unsigned alloc_count = align( count, 4 );
-
- struct vertex_header *pipeline_verts =
- (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
- if (!pipeline_verts) {
- /* Not much we can do here - just skip the rendering.
- */
+ fetched_vert_info.count = fetch_info->count;
+ fetched_vert_info.vertex_size = fpme->vertex_size;
+ fetched_vert_info.stride = fpme->vertex_size;
+ fetched_vert_info.verts =
+ (struct vertex_header *)MALLOC(fpme->vertex_size *
+ align(fetch_info->count, 4));
+ if (!fetched_vert_info.verts) {
assert(0);
return;
}
- /* Fetch into our vertex buffer
+ /* Fetch into our vertex buffer.
*/
- draw_pt_fetch_run_linear( fpme->fetch,
- start,
- count,
- (char *)pipeline_verts );
+ fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
+
+ /* Finished with fetch:
+ */
+ fetch_info = NULL;
+ vert_info = &fetched_vert_info;
/* Run the shader, note that this overwrites the data[] parts of
* the pipeline verts.
*/
- if (opt & PT_SHADE)
- {
- shader->run_linear(shader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- draw->pt.user.vs_constants,
- count,
- fpme->vertex_size,
- fpme->vertex_size);
-
- if (geometry_shader)
- draw_geometry_shader_run(geometry_shader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- draw->pt.user.gs_constants,
- count,
- fpme->vertex_size,
- fpme->vertex_size);
+ if (fpme->opt & PT_SHADE) {
+ draw_vertex_shader_run(vshader,
+ draw->pt.user.vs_constants,
+ vert_info,
+ &vs_vert_info);
+
+ FREE(vert_info->verts);
+ vert_info = &vs_vert_info;
}
+ if ((fpme->opt & PT_SHADE) && gshader) {
+ draw_geometry_shader_run(gshader,
+ draw->pt.user.gs_constants,
+ vert_info,
+ prim_info,
+ &gs_vert_info,
+ &gs_prim_info);
+
+ FREE(vert_info->verts);
+ vert_info = &gs_vert_info;
+ prim_info = &gs_prim_info;
+ }
+
+
+ /* Stream output needs to be done before clipping.
+ *
+ * XXX: Stream output surely needs to respect the prim_info->elt
+ * lists.
+ */
+ draw_pt_so_emit( fpme->so_emit,
+ vert_info,
+ prim_info );
+
if (draw_pt_post_vs_run( fpme->post_vs,
- pipeline_verts,
- count,
- fpme->vertex_size ))
+ vert_info ))
{
opt |= PT_PIPELINE;
}
@@ -269,102 +275,96 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
/* Do we need to run the pipeline?
*/
if (opt & PT_PIPELINE) {
- draw_pipeline_run_linear( fpme->draw,
- fpme->prim,
- pipeline_verts,
- count,
- fpme->vertex_size);
+ pipeline( fpme,
+ vert_info,
+ prim_info );
}
else {
- draw_pt_emit_linear( fpme->emit,
- (const float (*)[4])pipeline_verts->data,
- fpme->vertex_size,
- count );
+ emit( fpme->emit,
+ vert_info,
+ prim_info );
}
-
- FREE(pipeline_verts);
+ FREE(vert_info->verts);
}
+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_fetch_info fetch_info;
+ struct draw_prim_info prim_info;
+
+ fetch_info.linear = FALSE;
+ fetch_info.start = 0;
+ fetch_info.elts = fetch_elts;
+ fetch_info.count = fetch_count;
+
+ prim_info.linear = FALSE;
+ prim_info.start = 0;
+ prim_info.count = draw_count;
+ prim_info.elts = draw_elts;
+ prim_info.prim = fpme->input_prim;
+ prim_info.primitive_count = 1;
+ prim_info.primitive_lengths = &draw_count;
+
+ fetch_pipeline_generic( middle, &fetch_info, &prim_info );
+}
-static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
- unsigned start,
- unsigned count,
- const ushort *draw_elts,
- unsigned draw_count )
+static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned 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->vs.vertex_shader;
- struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
- unsigned opt = fpme->opt;
- unsigned alloc_count = align( count, 4 );
+ struct draw_fetch_info fetch_info;
+ struct draw_prim_info prim_info;
+
+ fetch_info.linear = TRUE;
+ fetch_info.start = start;
+ fetch_info.count = count;
+ fetch_info.elts = NULL;
+
+ prim_info.linear = TRUE;
+ prim_info.start = 0;
+ prim_info.count = count;
+ prim_info.elts = NULL;
+ prim_info.prim = fpme->input_prim;
+ prim_info.primitive_count = 1;
+ prim_info.primitive_lengths = &count;
+
+ fetch_pipeline_generic( middle, &fetch_info, &prim_info );
+}
- struct vertex_header *pipeline_verts =
- (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
- if (!pipeline_verts)
- return FALSE;
- /* Fetch into our vertex buffer
- */
- draw_pt_fetch_run_linear( fpme->fetch,
- start,
- count,
- (char *)pipeline_verts );
+static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_fetch_info fetch_info;
+ struct draw_prim_info prim_info;
- /* Run the shader, note that this overwrites the data[] parts of
- * the pipeline verts.
- */
- if (opt & PT_SHADE)
- {
- shader->run_linear(shader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- draw->pt.user.vs_constants,
- count,
- fpme->vertex_size,
- fpme->vertex_size);
-
- if (geometry_shader)
- draw_geometry_shader_run(geometry_shader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- draw->pt.user.gs_constants,
- count,
- fpme->vertex_size,
- fpme->vertex_size);
- }
+ fetch_info.linear = TRUE;
+ fetch_info.start = start;
+ fetch_info.count = count;
+ fetch_info.elts = NULL;
- if (draw_pt_post_vs_run( fpme->post_vs,
- pipeline_verts,
- count,
- fpme->vertex_size ))
- {
- opt |= PT_PIPELINE;
- }
+ prim_info.linear = FALSE;
+ prim_info.start = 0;
+ prim_info.count = draw_count;
+ prim_info.elts = draw_elts;
+ prim_info.prim = fpme->input_prim;
+ prim_info.primitive_count = 1;
+ prim_info.primitive_lengths = &draw_count;
- /* Do we need to run the pipeline?
- */
- if (opt & PT_PIPELINE) {
- draw_pipeline_run( fpme->draw,
- fpme->prim,
- pipeline_verts,
- count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
- }
- else {
- draw_pt_emit( fpme->emit,
- (const float (*)[4])pipeline_verts->data,
- count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
- }
+ fetch_pipeline_generic( middle, &fetch_info, &prim_info );
- FREE(pipeline_verts);
return TRUE;
}
@@ -385,6 +385,9 @@ static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
if (fpme->emit)
draw_pt_emit_destroy( fpme->emit );
+ if (fpme->so_emit)
+ draw_pt_so_emit_destroy( fpme->so_emit );
+
if (fpme->post_vs)
draw_pt_post_vs_destroy( fpme->post_vs );
@@ -416,7 +419,11 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *
goto fail;
fpme->emit = draw_pt_emit_create( draw );
- if (!fpme->emit)
+ if (!fpme->emit)
+ goto fail;
+
+ fpme->so_emit = draw_pt_so_emit_create( draw );
+ if (!fpme->so_emit)
goto fail;
return &fpme->base;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index d56889b5f6..d33969ac70 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -28,6 +28,7 @@
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
+#include "draw/draw_gs.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
@@ -40,52 +41,58 @@ struct llvm_middle_end {
struct draw_context *draw;
struct pt_emit *emit;
+ struct pt_so_emit *so_emit;
struct pt_fetch *fetch;
struct pt_post_vs *post_vs;
unsigned vertex_data_offset;
unsigned vertex_size;
- unsigned prim;
+ unsigned input_prim;
unsigned opt;
struct draw_llvm *llvm;
- struct draw_llvm_variant *variants;
struct draw_llvm_variant *current_variant;
- int nr_variants;
};
static void
llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
- unsigned prim,
+ unsigned in_prim,
unsigned opt,
unsigned *max_vertices )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
- struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ struct llvm_vertex_shader *shader =
+ llvm_vertex_shader(draw->vs.vertex_shader);
struct draw_llvm_variant_key key;
struct draw_llvm_variant *variant = NULL;
+ struct draw_llvm_variant_list_item *li;
unsigned i;
unsigned instance_id_index = ~0;
+
+ unsigned out_prim = (draw->gs.geometry_shader ?
+ draw->gs.geometry_shader->output_primitive :
+ in_prim);
+
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
- unsigned nr = MAX2( vs->info.num_inputs,
- vs->info.num_outputs + 1 );
+ unsigned nr = MAX2( shader->base.info.num_inputs,
+ shader->base.info.num_outputs + 1 );
/* Scan for instanceID system value.
*/
- for (i = 0; i < vs->info.num_inputs; i++) {
- if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
+ for (i = 0; i < shader->base.info.num_inputs; i++) {
+ if (shader->base.info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
instance_id_index = i;
break;
}
}
- fpme->prim = prim;
+ fpme->input_prim = in_prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@@ -102,11 +109,13 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)(draw->identity_viewport),
(boolean)draw->rasterizer->gl_rasterization_rules,
- (draw->vs.edgeflag_output ? true : false) );
+ (draw->vs.edgeflag_output ? TRUE : FALSE) );
+
+ draw_pt_so_emit_prepare( fpme->so_emit );
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
- prim,
+ out_prim,
max_vertices );
*max_vertices = MAX2( *max_vertices,
@@ -121,20 +130,41 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
draw_llvm_make_variant_key(fpme->llvm, &key);
- variant = fpme->variants;
- while(variant) {
- if(memcmp(&variant->key, &key, sizeof key) == 0)
+ li = first_elem(&shader->variants);
+ while(!at_end(&shader->variants, li)) {
+ if(memcmp(&li->base->key, &key, sizeof key) == 0) {
+ variant = li->base;
break;
+ }
+ li = next_elem(li);
+ }
- variant = variant->next;
+ if (variant) {
+ move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
}
+ else {
+ unsigned i;
+ if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) {
+ /*
+ * XXX: should we flush here ?
+ */
+ for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
+ struct draw_llvm_variant_list_item *item =
+ last_elem(&fpme->llvm->vs_variants_list);
+ draw_llvm_destroy_variant(item->base);
+ }
+ }
+
+ variant = draw_llvm_create_variant(fpme->llvm, nr);
- if (!variant) {
- variant = draw_llvm_prepare(fpme->llvm, nr);
- variant->next = fpme->variants;
- fpme->variants = variant;
- ++fpme->nr_variants;
+ if (variant) {
+ insert_at_head(&shader->variants, &variant->list_item_local);
+ insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
+ fpme->llvm->nr_variants++;
+ shader->variants_cached++;
+ }
}
+
fpme->current_variant = variant;
/*XXX we only support one constant buffer */
@@ -145,66 +175,142 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
}
+static void pipeline(struct llvm_middle_end *llvm,
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
+{
+ if (prim_info->linear)
+ draw_pipeline_run_linear( llvm->draw,
+ vert_info,
+ prim_info);
+ else
+ draw_pipeline_run( llvm->draw,
+ vert_info,
+ prim_info );
+}
-static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
- const unsigned *fetch_elts,
- unsigned fetch_count,
- const ushort *draw_elts,
- unsigned draw_count )
+static void emit(struct pt_emit *emit,
+ const struct draw_vertex_info *vert_info,
+ const struct draw_prim_info *prim_info)
+{
+ if (prim_info->linear) {
+ draw_pt_emit_linear(emit, vert_info, prim_info);
+ }
+ else {
+ draw_pt_emit(emit, vert_info, prim_info);
+ }
+}
+
+static void
+llvm_pipeline_generic( struct draw_pt_middle_end *middle,
+ const struct draw_fetch_info *fetch_info,
+ const struct draw_prim_info *prim_info )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
+ struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
+ struct draw_prim_info gs_prim_info;
+ struct draw_vertex_info llvm_vert_info;
+ struct draw_vertex_info gs_vert_info;
+ struct draw_vertex_info *vert_info;
unsigned opt = fpme->opt;
- unsigned alloc_count = align( fetch_count, 4 );
- struct vertex_header *pipeline_verts =
- (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
-
- if (!pipeline_verts) {
- /* Not much we can do here - just skip the rendering.
- */
+ llvm_vert_info.count = fetch_info->count;
+ llvm_vert_info.vertex_size = fpme->vertex_size;
+ llvm_vert_info.stride = fpme->vertex_size;
+ llvm_vert_info.verts =
+ (struct vertex_header *)MALLOC(fpme->vertex_size *
+ align(fetch_info->count, 4));
+ if (!llvm_vert_info.verts) {
assert(0);
return;
}
- fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
- pipeline_verts,
- (const char **)draw->pt.user.vbuffer,
- fetch_elts,
- fetch_count,
- fpme->vertex_size,
- draw->pt.vertex_buffer );
-
- if (draw_pt_post_vs_run( fpme->post_vs,
- pipeline_verts,
- fetch_count,
- fpme->vertex_size ))
- {
+ if (fetch_info->linear)
+ fpme->current_variant->jit_func( &fpme->llvm->jit_context,
+ llvm_vert_info.verts,
+ (const char **)draw->pt.user.vbuffer,
+ fetch_info->start,
+ fetch_info->count,
+ fpme->vertex_size,
+ draw->pt.vertex_buffer );
+ else
+ fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
+ llvm_vert_info.verts,
+ (const char **)draw->pt.user.vbuffer,
+ fetch_info->elts,
+ fetch_info->count,
+ fpme->vertex_size,
+ draw->pt.vertex_buffer);
+
+ /* Finished with fetch and vs:
+ */
+ fetch_info = NULL;
+ vert_info = &llvm_vert_info;
+
+
+ if ((opt & PT_SHADE) && gshader) {
+ draw_geometry_shader_run(gshader,
+ draw->pt.user.gs_constants,
+ vert_info,
+ prim_info,
+ &gs_vert_info,
+ &gs_prim_info);
+
+ FREE(vert_info->verts);
+ vert_info = &gs_vert_info;
+ prim_info = &gs_prim_info;
+ }
+
+ /* stream output needs to be done before clipping */
+ draw_pt_so_emit( fpme->so_emit,
+ vert_info,
+ prim_info );
+
+ if (draw_pt_post_vs_run( fpme->post_vs, vert_info )) {
opt |= PT_PIPELINE;
}
/* Do we need to run the pipeline?
*/
if (opt & PT_PIPELINE) {
- draw_pipeline_run( fpme->draw,
- fpme->prim,
- pipeline_verts,
- fetch_count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
+ pipeline( fpme,
+ vert_info,
+ prim_info );
}
else {
- draw_pt_emit( fpme->emit,
- (const float (*)[4])pipeline_verts->data,
- fetch_count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
+ emit( fpme->emit,
+ vert_info,
+ prim_info );
}
+ FREE(vert_info->verts);
+}
- FREE(pipeline_verts);
+static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
+ struct draw_fetch_info fetch_info;
+ struct draw_prim_info prim_info;
+
+ fetch_info.linear = FALSE;
+ fetch_info.start = 0;
+ fetch_info.elts = fetch_elts;
+ fetch_info.count = fetch_count;
+
+ prim_info.linear = FALSE;
+ prim_info.start = 0;
+ prim_info.count = draw_count;
+ prim_info.elts = draw_elts;
+ prim_info.prim = fpme->input_prim;
+ prim_info.primitive_count = 1;
+ prim_info.primitive_lengths = &draw_count;
+
+ llvm_pipeline_generic( middle, &fetch_info, &prim_info );
}
@@ -213,57 +319,23 @@ static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
unsigned count)
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
- struct draw_context *draw = fpme->draw;
- unsigned opt = fpme->opt;
- unsigned alloc_count = align( count, 4 );
-
- struct vertex_header *pipeline_verts =
- (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
-
- if (!pipeline_verts) {
- /* Not much we can do here - just skip the rendering.
- */
- assert(0);
- return;
- }
-
-#if 0
- debug_printf("#### Pipeline = %p (data = %p)\n",
- pipeline_verts, pipeline_verts->data);
-#endif
- fpme->current_variant->jit_func( &fpme->llvm->jit_context,
- pipeline_verts,
- (const char **)draw->pt.user.vbuffer,
- start,
- count,
- fpme->vertex_size,
- draw->pt.vertex_buffer );
-
- if (draw_pt_post_vs_run( fpme->post_vs,
- pipeline_verts,
- count,
- fpme->vertex_size ))
- {
- opt |= PT_PIPELINE;
- }
-
- /* Do we need to run the pipeline?
- */
- if (opt & PT_PIPELINE) {
- draw_pipeline_run_linear( fpme->draw,
- fpme->prim,
- pipeline_verts,
- count,
- fpme->vertex_size);
- }
- else {
- draw_pt_emit_linear( fpme->emit,
- (const float (*)[4])pipeline_verts->data,
- fpme->vertex_size,
- count );
- }
-
- FREE(pipeline_verts);
+ struct draw_fetch_info fetch_info;
+ struct draw_prim_info prim_info;
+
+ fetch_info.linear = TRUE;
+ fetch_info.start = start;
+ fetch_info.count = count;
+ fetch_info.elts = NULL;
+
+ prim_info.linear = TRUE;
+ prim_info.start = 0;
+ prim_info.count = count;
+ prim_info.elts = NULL;
+ prim_info.prim = fpme->input_prim;
+ prim_info.primitive_count = 1;
+ prim_info.primitive_lengths = &count;
+
+ llvm_pipeline_generic( middle, &fetch_info, &prim_info );
}
@@ -276,53 +348,24 @@ llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
unsigned draw_count )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
- struct draw_context *draw = fpme->draw;
- unsigned opt = fpme->opt;
- unsigned alloc_count = align( count, 4 );
-
- struct vertex_header *pipeline_verts =
- (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
-
- if (!pipeline_verts)
- return FALSE;
-
- fpme->current_variant->jit_func( &fpme->llvm->jit_context,
- pipeline_verts,
- (const char **)draw->pt.user.vbuffer,
- start,
- count,
- fpme->vertex_size,
- draw->pt.vertex_buffer );
-
- if (draw_pt_post_vs_run( fpme->post_vs,
- pipeline_verts,
- count,
- fpme->vertex_size ))
- {
- opt |= PT_PIPELINE;
- }
+ struct draw_fetch_info fetch_info;
+ struct draw_prim_info prim_info;
- /* Do we need to run the pipeline?
- */
- if (opt & PT_PIPELINE) {
- draw_pipeline_run( fpme->draw,
- fpme->prim,
- pipeline_verts,
- count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
- }
- else {
- draw_pt_emit( fpme->emit,
- (const float (*)[4])pipeline_verts->data,
- count,
- fpme->vertex_size,
- draw_elts,
- draw_count );
- }
+ fetch_info.linear = TRUE;
+ fetch_info.start = start;
+ fetch_info.count = count;
+ fetch_info.elts = NULL;
+
+ prim_info.linear = FALSE;
+ prim_info.start = 0;
+ prim_info.count = draw_count;
+ prim_info.elts = draw_elts;
+ prim_info.prim = fpme->input_prim;
+ prim_info.primitive_count = 1;
+ prim_info.primitive_lengths = &draw_count;
+
+ llvm_pipeline_generic( middle, &fetch_info, &prim_info );
- FREE(pipeline_verts);
return TRUE;
}
@@ -336,37 +379,16 @@ static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
- struct draw_context *draw = fpme->draw;
- struct draw_llvm_variant *variant = NULL;
- variant = fpme->variants;
- while(variant) {
- struct draw_llvm_variant *next = variant->next;
-
- if (variant->function_elts) {
- if (variant->function_elts)
- LLVMFreeMachineCodeForFunction(draw->engine,
- variant->function_elts);
- LLVMDeleteFunction(variant->function_elts);
- }
-
- if (variant->function) {
- if (variant->function)
- LLVMFreeMachineCodeForFunction(draw->engine,
- variant->function);
- LLVMDeleteFunction(variant->function);
- }
-
- FREE(variant);
-
- variant = next;
- }
if (fpme->fetch)
draw_pt_fetch_destroy( fpme->fetch );
if (fpme->emit)
draw_pt_emit_destroy( fpme->emit );
+ if (fpme->so_emit)
+ draw_pt_so_emit_destroy( fpme->so_emit );
+
if (fpme->post_vs)
draw_pt_post_vs_destroy( fpme->post_vs );
@@ -377,7 +399,8 @@ static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
}
-struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_context *draw )
+struct draw_pt_middle_end *
+draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw)
{
struct llvm_middle_end *fpme = 0;
@@ -409,13 +432,15 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_cont
if (!fpme->emit)
goto fail;
+ fpme->so_emit = draw_pt_so_emit_create( draw );
+ if (!fpme->so_emit)
+ goto fail;
+
fpme->llvm = draw_llvm_create(draw);
if (!fpme->llvm)
goto fail;
- fpme->variants = NULL;
fpme->current_variant = NULL;
- fpme->nr_variants = 0;
return &fpme->base;
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
index 5525dfc748..e850cc2edd 100644
--- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -29,19 +29,23 @@
#include "pipe/p_context.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
-#include "draw/draw_vbuf.h"
#include "draw/draw_pt.h"
struct pt_post_vs {
struct draw_context *draw;
boolean (*run)( struct pt_post_vs *pvs,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride );
+ struct draw_vertex_info *info );
};
-
+static INLINE void
+initialize_vertex_header(struct vertex_header *header)
+{
+ header->clipmask = 0;
+ header->edgeflag = 1;
+ header->pad = 0;
+ header->vertex_id = UNDEFINED_VERTEX_ID;
+}
static INLINE float
dot4(const float *a, const float *b)
@@ -52,8 +56,6 @@ dot4(const float *a, const float *b)
a[3]*b[3]);
}
-
-
static INLINE unsigned
compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
{
@@ -92,22 +94,21 @@ compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
* instructions
*/
static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride )
+ struct draw_vertex_info *info )
{
- struct vertex_header *out = vertices;
+ struct vertex_header *out = info->verts;
const float *scale = pvs->draw->viewport.scale;
const float *trans = pvs->draw->viewport.translate;
const unsigned pos = draw_current_shader_position_output(pvs->draw);
unsigned clipped = 0;
unsigned j;
- if (0) debug_printf("%s\n", __FUNCTION__);
+ if (0) debug_printf("%s count, %d\n", __FUNCTION__, info->count);
- for (j = 0; j < count; j++) {
+ for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
+ initialize_vertex_header(out);
#if 0
debug_printf("%d) io = %p, data = %p = [%f, %f, %f, %f]\n",
j, out, position, position[0], position[1], position[2], position[3]);
@@ -143,7 +144,7 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
#endif
}
- out = (struct vertex_header *)( (char *)out + stride );
+ out = (struct vertex_header *)( (char *)out + info->stride );
}
return clipped != 0;
@@ -153,29 +154,27 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
/* As above plus edgeflags
*/
-static boolean
+static boolean
post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride )
+ struct draw_vertex_info *info)
{
unsigned j;
boolean needpipe;
- needpipe = post_vs_cliptest_viewport_gl( pvs, vertices, count, stride);
+ needpipe = post_vs_cliptest_viewport_gl(pvs, info);
/* If present, copy edgeflag VS output into vertex header.
* Otherwise, leave header as is.
*/
if (pvs->draw->vs.edgeflag_output) {
- struct vertex_header *out = vertices;
+ struct vertex_header *out = info->verts;
int ef = pvs->draw->vs.edgeflag_output;
- for (j = 0; j < count; j++) {
+ for (j = 0; j < info->count; j++) {
const float *edgeflag = out->data[ef];
out->edgeflag = !(edgeflag[0] != 1.0f);
needpipe |= !out->edgeflag;
- out = (struct vertex_header *)( (char *)out + stride );
+ out = (struct vertex_header *)( (char *)out + info->stride );
}
}
return needpipe;
@@ -187,29 +186,28 @@ post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
/* If bypass_clipping is set, skip cliptest and rhw divide.
*/
static boolean post_vs_viewport( struct pt_post_vs *pvs,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride )
+ struct draw_vertex_info *info )
{
- struct vertex_header *out = vertices;
+ struct vertex_header *out = info->verts;
const float *scale = pvs->draw->viewport.scale;
const float *trans = pvs->draw->viewport.translate;
const unsigned pos = draw_current_shader_position_output(pvs->draw);
unsigned j;
if (0) debug_printf("%s\n", __FUNCTION__);
- for (j = 0; j < count; j++) {
+ for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
+ initialize_vertex_header(out);
/* Viewport mapping only, no cliptest/rhw divide
*/
position[0] = position[0] * scale[0] + trans[0];
position[1] = position[1] * scale[1] + trans[1];
position[2] = position[2] * scale[2] + trans[2];
- out = (struct vertex_header *)((char *)out + stride);
+ out = (struct vertex_header *)((char *)out + info->stride);
}
-
+
return FALSE;
}
@@ -218,20 +216,25 @@ static boolean post_vs_viewport( struct pt_post_vs *pvs,
* to do.
*/
static boolean post_vs_none( struct pt_post_vs *pvs,
- struct vertex_header *vertices,
- unsigned count,
- unsigned stride )
+ struct draw_vertex_info *info )
{
+ struct vertex_header *out = info->verts;
+ unsigned j;
+
if (0) debug_printf("%s\n", __FUNCTION__);
+ /* just initialize the vertex_id in all headers */
+ for (j = 0; j < info->count; j++) {
+ initialize_vertex_header(out);
+
+ out = (struct vertex_header *)((char *)out + info->stride);
+ }
return FALSE;
}
boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
- struct vertex_header *pipeline_verts,
- unsigned count,
- unsigned stride )
+ struct draw_vertex_info *info )
{
- return pvs->run( pvs, pipeline_verts, count, stride );
+ return pvs->run( pvs, info );
}
@@ -272,7 +275,7 @@ struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw )
return NULL;
pvs->draw = draw;
-
+
return pvs;
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
new file mode 100644
index 0000000000..5d82934889
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
@@ -0,0 +1,303 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * 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 VMWARE 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 "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+struct pt_so_emit {
+ struct draw_context *draw;
+
+ void *buffers[PIPE_MAX_SO_BUFFERS];
+
+ unsigned input_vertex_stride;
+ const float (*inputs)[4];
+
+ boolean has_so;
+
+ boolean single_buffer;
+
+ unsigned emitted_primitives;
+ unsigned emitted_vertices;
+};
+
+
+void draw_pt_so_emit_prepare(struct pt_so_emit *emit)
+{
+ struct draw_context *draw = emit->draw;
+
+ emit->has_so = (draw->so.state.num_outputs > 0);
+
+ /* if we have a state with outputs make sure we have
+ * buffers to output to */
+ if (emit->has_so) {
+ boolean has_valid_buffer = FALSE;
+ unsigned i;
+ for (i = 0; i < draw->so.num_buffers; ++i) {
+ if (draw->so.buffers[i]) {
+ has_valid_buffer = TRUE;
+ break;
+ }
+ }
+ emit->has_so = has_valid_buffer;
+ }
+
+ if (!emit->has_so)
+ return;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+}
+
+static boolean
+is_component_writable(unsigned mask,
+ unsigned compo)
+{
+ switch (mask) {
+ case TGSI_WRITEMASK_NONE:
+ return FALSE;
+ case TGSI_WRITEMASK_X:
+ return compo == 0;
+ case TGSI_WRITEMASK_Y:
+ return compo == 1;
+ case TGSI_WRITEMASK_XY:
+ return compo == 0 || compo == 1;
+ case TGSI_WRITEMASK_Z:
+ return compo == 2;
+ case TGSI_WRITEMASK_XZ:
+ return compo == 0 || compo == 2;
+ case TGSI_WRITEMASK_YZ:
+ return compo == 1 || compo == 2;
+ case TGSI_WRITEMASK_XYZ:
+ return compo == 0 || compo == 1 || compo == 2;
+ case TGSI_WRITEMASK_W:
+ return compo == 3;
+ case TGSI_WRITEMASK_XW:
+ return compo == 0 || compo == 3;
+ case TGSI_WRITEMASK_YW:
+ return compo == 1 || compo == 3;
+ case TGSI_WRITEMASK_XYW:
+ return compo == 0 || compo == 1 || compo == 3;
+ case TGSI_WRITEMASK_ZW:
+ return compo == 2 || compo == 3;
+ case TGSI_WRITEMASK_XZW:
+ return compo == 0 || compo == 1 || compo == 3;
+ case TGSI_WRITEMASK_YZW:
+ return compo == 1 || compo == 2 || compo == 4;
+ case TGSI_WRITEMASK_XYZW:
+ return compo < 4;
+ default:
+ debug_assert(!"Unknown writemask in stream out");
+ return compo < 4;
+ }
+}
+
+static void so_emit_prim(struct pt_so_emit *so,
+ unsigned *indices,
+ unsigned num_vertices)
+{
+ unsigned slot, i;
+ unsigned input_vertex_stride = so->input_vertex_stride;
+ struct draw_context *draw = so->draw;
+ const float (*input_ptr)[4];
+ const struct pipe_stream_output_state *state =
+ &draw->so.state;
+ float **buffer = 0;
+
+ input_ptr = so->inputs;
+
+ for (i = 0; i < num_vertices; ++i) {
+ const float (*input)[4];
+ unsigned total_written_compos = 0;
+ /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
+ input = (const float (*)[4])(
+ (const char *)input_ptr + (indices[i] * input_vertex_stride));
+ for (slot = 0; slot < state->num_outputs; ++slot) {
+ unsigned idx = state->register_index[slot];
+ unsigned writemask = state->register_mask[slot];
+ unsigned written_compos = 0;
+ unsigned compo;
+
+ buffer = (float**)&so->buffers[state->output_buffer[slot]];
+
+ /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
+ slot, vs_slot, idx);*/
+#if 1
+ assert(!util_is_inf_or_nan(input[idx][0]));
+ assert(!util_is_inf_or_nan(input[idx][1]));
+ assert(!util_is_inf_or_nan(input[idx][2]));
+ assert(!util_is_inf_or_nan(input[idx][3]));
+#endif
+ for (compo = 0; compo < 4; ++compo) {
+ if (is_component_writable(writemask, compo)) {
+ float *buf = *buffer;
+ buf[written_compos++] = input[idx][compo];
+ }
+ }
+#if 0
+ debug_printf("\t\t(writemask = %d)%f %f %f %f\n",
+ writemask,
+ input[idx][0],
+ input[idx][1],
+ input[idx][2],
+ input[idx][3]);
+#endif
+ *buffer += written_compos;
+ total_written_compos += written_compos;
+ }
+ if (so->single_buffer) {
+ int stride = (int)state->stride -
+ sizeof(float) * total_written_compos;
+
+ debug_assert(stride >= 0);
+ *buffer = (float*) (((char*)*buffer) + stride);
+ }
+ }
+ so->emitted_vertices += num_vertices;
+ ++so->emitted_primitives;
+}
+
+static void so_point(struct pt_so_emit *so, int idx)
+{
+ unsigned indices[1];
+
+ indices[0] = idx;
+
+ so_emit_prim(so, indices, 1);
+}
+
+static void so_line(struct pt_so_emit *so, int i0, int i1)
+{
+ unsigned indices[2];
+
+ indices[0] = i0;
+ indices[1] = i1;
+
+ so_emit_prim(so, indices, 2);
+}
+
+static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2)
+{
+ unsigned indices[3];
+
+ indices[0] = i0;
+ indices[1] = i1;
+ indices[2] = i2;
+
+ so_emit_prim(so, indices, 3);
+}
+
+
+#define TRIANGLE(gs,i0,i1,i2) so_tri(so,i0,i1,i2)
+#define LINE(gs,i0,i1) so_line(so,i0,i1)
+#define POINT(gs,i0) so_point(so,i0)
+#define FUNC so_run_linear
+#define LOCAL_VARS
+#include "draw_so_emit_tmp.h"
+#undef LOCAL_VARS
+#undef FUNC
+
+
+#define TRIANGLE(gs,i0,i1,i2) so_tri(gs,elts[i0],elts[i1],elts[i2])
+#define LINE(gs,i0,i1) so_line(gs,elts[i0],elts[i1])
+#define POINT(gs,i0) so_point(gs,elts[i0])
+#define FUNC so_run_elts
+#define LOCAL_VARS \
+ const ushort *elts = input_prims->elts;
+#include "draw_so_emit_tmp.h"
+#undef LOCAL_VARS
+#undef FUNC
+
+
+void draw_pt_so_emit( struct pt_so_emit *emit,
+ const struct draw_vertex_info *input_verts,
+ const struct draw_prim_info *input_prims )
+{
+ struct draw_context *draw = emit->draw;
+ struct vbuf_render *render = draw->render;
+ unsigned start, i;
+
+ if (!emit->has_so)
+ return;
+
+ emit->emitted_vertices = 0;
+ emit->emitted_primitives = 0;
+ emit->input_vertex_stride = input_verts->stride;
+ emit->inputs = (const float (*)[4])input_verts->verts->data;
+ for (i = 0; i < draw->so.num_buffers; ++i) {
+ emit->buffers[i] = draw->so.buffers[i];
+ }
+ emit->single_buffer = TRUE;
+ for (i = 0; i < draw->so.state.num_outputs; ++i) {
+ if (draw->so.state.output_buffer[i] != 0)
+ emit->single_buffer = FALSE;
+ }
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ for (start = i = 0; i < input_prims->primitive_count;
+ start += input_prims->primitive_lengths[i], i++)
+ {
+ unsigned count = input_prims->primitive_lengths[i];
+
+ if (input_prims->linear) {
+ so_run_linear(emit, input_prims, input_verts,
+ start, count);
+ } else {
+ so_run_elts(emit, input_prims, input_verts,
+ start, count);
+ }
+ }
+
+ render->set_stream_output_info(render,
+ emit->emitted_primitives,
+ emit->emitted_vertices);
+}
+
+
+struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw )
+{
+ struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit);
+ if (!emit)
+ return NULL;
+
+ emit->draw = draw;
+
+ return emit;
+}
+
+void draw_pt_so_emit_destroy( struct pt_so_emit *emit )
+{
+ FREE(emit);
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c
index d0e16c9bc3..d89d5cd20f 100644
--- a/src/gallium/auxiliary/draw/draw_pt_varray.c
+++ b/src/gallium/auxiliary/draw/draw_pt_varray.c
@@ -136,7 +136,7 @@ static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = {
static void varray_prepare(struct draw_pt_front_end *frontend,
- unsigned prim,
+ unsigned in_prim,
struct draw_pt_middle_end *middle,
unsigned opt)
{
@@ -144,11 +144,13 @@ static void varray_prepare(struct draw_pt_front_end *frontend,
varray->base.run = varray_run;
- varray->input_prim = prim;
- varray->output_prim = decompose_prim[prim];
+ varray->input_prim = in_prim;
+ varray->output_prim = decompose_prim[in_prim];
varray->middle = middle;
- middle->prepare(middle, varray->output_prim, opt, &varray->driver_fetch_max );
+ middle->prepare(middle,
+ varray->output_prim,
+ opt, &varray->driver_fetch_max );
/* check that the max is even */
assert((varray->driver_fetch_max & 1) == 0);
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
index 6a48e61e62..b7e0da7d44 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -54,7 +54,7 @@ struct vcache_frontend {
unsigned draw_count;
unsigned fetch_count;
unsigned fetch_max;
-
+
struct draw_pt_middle_end *middle;
unsigned input_prim;
@@ -64,14 +64,14 @@ struct vcache_frontend {
unsigned opt;
};
-static INLINE void
+static INLINE void
vcache_flush( struct vcache_frontend *vcache )
{
if (vcache->middle_prim != vcache->output_prim) {
vcache->middle_prim = vcache->output_prim;
- vcache->middle->prepare( vcache->middle,
- vcache->middle_prim,
- vcache->opt,
+ vcache->middle->prepare( vcache->middle,
+ vcache->middle_prim,
+ vcache->opt,
&vcache->fetch_max );
}
@@ -356,19 +356,19 @@ vcache_check_run( struct draw_pt_front_end *frontend,
if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count,
vcache->fetch_max,
draw_count);
-
+
if (elt_bias + max_index >= DRAW_PIPE_MAX_VERTICES ||
fetch_count >= UNDEFINED_VERTEX_ID ||
fetch_count > draw_count) {
if (0) debug_printf("fail\n");
goto fail;
}
-
+
if (vcache->middle_prim != vcache->input_prim) {
vcache->middle_prim = vcache->input_prim;
- vcache->middle->prepare( vcache->middle,
- vcache->middle_prim,
- vcache->opt,
+ vcache->middle->prepare( vcache->middle,
+ vcache->middle_prim,
+ vcache->opt,
&vcache->fetch_max );
}
@@ -467,9 +467,9 @@ vcache_check_run( struct draw_pt_front_end *frontend,
-static void
+static void
vcache_prepare( struct draw_pt_front_end *frontend,
- unsigned prim,
+ unsigned in_prim,
struct draw_pt_middle_end *middle,
unsigned opt )
{
@@ -479,13 +479,19 @@ vcache_prepare( struct draw_pt_front_end *frontend,
{
vcache->base.run = vcache_run_extras;
}
- else
+ else
{
vcache->base.run = vcache_check_run;
}
- vcache->input_prim = prim;
- vcache->output_prim = u_reduced_prim(prim);
+ /* VCache will always emit the reduced version of its input
+ * primitive, ie STRIP/FANS become TRIS, etc.
+ *
+ * This is not to be confused with what the GS might be up to,
+ * which is a separate issue.
+ */
+ vcache->input_prim = in_prim;
+ vcache->output_prim = u_reduced_prim(in_prim);
vcache->middle = middle;
vcache->opt = opt;
@@ -494,7 +500,9 @@ vcache_prepare( struct draw_pt_front_end *frontend,
* doing so:
*/
vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim;
- middle->prepare( middle, vcache->middle_prim, opt, &vcache->fetch_max );
+ middle->prepare( middle,
+ vcache->middle_prim,
+ opt, &vcache->fetch_max );
}
diff --git a/src/gallium/auxiliary/draw/draw_so_emit_tmp.h b/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
new file mode 100644
index 0000000000..01212a8e53
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
@@ -0,0 +1,123 @@
+
+static void FUNC( struct pt_so_emit *so,
+ const struct draw_prim_info *input_prims,
+ const struct draw_vertex_info *input_verts,
+ unsigned start,
+ unsigned count)
+{
+ struct draw_context *draw = so->draw;
+
+ boolean flatfirst = (draw->rasterizer->flatshade &&
+ draw->rasterizer->flatshade_first);
+ unsigned i;
+ LOCAL_VARS
+
+ if (0) debug_printf("%s %d\n", __FUNCTION__, count);
+
+ debug_assert(input_prims->primitive_count == 1);
+
+ switch (input_prims->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i++) {
+ POINT( so, start + i + 0 );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ LINE( so , start + i + 0 , start + i + 1 );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+
+ for (i = 1; i < count; i++) {
+ LINE( so, start + i - 1, start + i );
+ }
+
+ LINE( so, start + i - 1, start );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < count; i++) {
+ LINE( so, start + i - 1, start + i );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ TRIANGLE( so, start + i + 0, start + i + 1, start + i + 2 );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( so,
+ start + i + 0,
+ start + i + 1 + (i&1),
+ start + i + 2 - (i&1) );
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( so,
+ start + i + 0 + (i&1),
+ start + i + 1 - (i&1),
+ start + i + 2 );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( so,
+ start + i + 1,
+ start + i + 2,
+ start );
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( so,
+ start,
+ start + i + 1,
+ start + i + 2 );
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ {
+ /* These bitflags look a little odd because we submit the
+ * vertices as (1,2,0) to satisfy flatshade requirements.
+ */
+
+ for (i = 0; i+2 < count; i++) {
+
+ if (flatfirst) {
+ TRIANGLE( so, start + 0, start + i + 1, start + i + 2 );
+ }
+ else {
+ TRIANGLE( so, start + i + 1, start + i + 2, start + 0 );
+ }
+ }
+ }
+ break;
+
+ default:
+ debug_assert(!"Unsupported primitive in stream output");
+ break;
+ }
+}
+
+
+#undef TRIANGLE
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h
index 83ae26a9c2..e32803c072 100644
--- a/src/gallium/auxiliary/draw/draw_vbuf.h
+++ b/src/gallium/auxiliary/draw/draw_vbuf.h
@@ -117,6 +117,14 @@ struct vbuf_render {
void (*release_vertices)( struct vbuf_render * );
void (*destroy)( struct vbuf_render * );
+
+
+ /**
+ * Called after writing data to the stream out buffers
+ */
+ void (*set_stream_output_info)( struct vbuf_render *vbufr,
+ unsigned primitive_count,
+ unsigned vertices_count );
};
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index b9db886a24..57ea63fc06 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -98,6 +98,11 @@ draw_create_vertex_shader(struct draw_context *draw,
vs = draw_create_vs_ppc( draw, shader );
#endif
}
+#if HAVE_LLVM
+ else {
+ vs = draw_create_vs_llvm(draw, shader);
+ }
+#endif
if (!vs) {
vs = draw_create_vs_exec( draw, shader );
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index 6c7e94db43..a731994523 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -165,7 +165,6 @@ draw_create_vs_ppc(struct draw_context *draw,
const struct pipe_shader_state *templ);
-
struct draw_vs_varient_key;
struct draw_vertex_shader;
@@ -173,6 +172,11 @@ struct draw_vs_varient *
draw_vs_create_varient_aos_sse( struct draw_vertex_shader *vs,
const struct draw_vs_varient_key *key );
+#if HAVE_LLVM
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *state);
+#endif
/********************************************************************************
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
new file mode 100644
index 0000000000..6c13df7913
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -0,0 +1,120 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * 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 VMWARE 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 "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+#include "draw_vs.h"
+#include "draw_llvm.h"
+
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+
+static void
+vs_llvm_prepare(struct draw_vertex_shader *shader,
+ struct draw_context *draw)
+{
+ /*struct llvm_vertex_shader *evs = llvm_vertex_shader(shader);*/
+}
+
+static void
+vs_llvm_run_linear( struct draw_vertex_shader *shader,
+ const float (*input)[4],
+ float (*output)[4],
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ /* we should never get here since the entire pipeline is
+ * generated in draw_pt_fetch_shade_pipeline_llvm.c */
+ debug_assert(0);
+}
+
+
+static void
+vs_llvm_delete( struct draw_vertex_shader *dvs )
+{
+ struct llvm_vertex_shader *shader = llvm_vertex_shader(dvs);
+ struct pipe_fence_handle *fence = NULL;
+ struct draw_llvm_variant_list_item *li;
+ struct pipe_context *pipe = dvs->draw->pipe;
+
+ /*
+ * XXX: This might be not neccessary at all.
+ */
+ pipe->flush(pipe, 0, &fence);
+ if (fence) {
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ }
+
+
+ li = first_elem(&shader->variants);
+ while(!at_end(&shader->variants, li)) {
+ struct draw_llvm_variant_list_item *next = next_elem(li);
+ draw_llvm_destroy_variant(li->base);
+ li = next;
+ }
+
+ assert(shader->variants_cached == 0);
+ FREE((void*) dvs->state.tokens);
+ FREE( dvs );
+}
+
+
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *state)
+{
+ struct llvm_vertex_shader *vs = CALLOC_STRUCT( llvm_vertex_shader );
+
+ if (vs == NULL)
+ return NULL;
+
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
+ if (!vs->base.state.tokens) {
+ FREE(vs);
+ return NULL;
+ }
+
+ tgsi_scan_shader(state->tokens, &vs->base.info);
+
+ vs->base.draw = draw;
+ vs->base.prepare = vs_llvm_prepare;
+ vs->base.run_linear = vs_llvm_run_linear;
+ vs->base.delete = vs_llvm_delete;
+ vs->base.create_varient = draw_vs_create_varient_generic;
+
+ make_empty_list(&vs->variants);
+
+ return &vs->base;
+}