draw/llvmpipe: fix transform feedback position + enable other extensions

This builds on the previous draw/softpipe patch.

So llvmpipe does streamout calls after clip/viewport stages,
but we have the pre-clip position stored for later use, so
when we are doing transform feedback, and its the position vertex
grab the vertex from the stored pre clip position.

The perfect fix is too probably add a codegen transform feedback
stage in between shader and clip stages, but this is good enough
for now.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2012-12-13 20:17:58 +10:00
parent 55d37eb40e
commit 9e41b0badb
6 changed files with 27 additions and 8 deletions

View file

@ -185,7 +185,7 @@ struct pt_emit *draw_pt_emit_create( struct draw_context *draw );
*/
struct pt_so_emit;
void draw_pt_so_emit_prepare( struct pt_so_emit *emit );
void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos);
void draw_pt_so_emit( struct pt_so_emit *emit,
const struct draw_vertex_info *vert_info,

View file

@ -117,7 +117,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->rasterizer->gl_rasterization_rules,
(draw->vs.edgeflag_output ? TRUE : FALSE) );
draw_pt_so_emit_prepare( fpme->so_emit );
draw_pt_so_emit_prepare( fpme->so_emit, FALSE );
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,

View file

@ -102,7 +102,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->rasterizer->gl_rasterization_rules,
(draw->vs.edgeflag_output ? TRUE : FALSE) );
draw_pt_so_emit_prepare( fpme->so_emit );
draw_pt_so_emit_prepare( fpme->so_emit, TRUE );
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,

View file

@ -42,20 +42,24 @@ struct pt_so_emit {
unsigned input_vertex_stride;
const float (*inputs)[4];
const float (*pre_clip_pos)[4];
boolean has_so;
boolean use_pre_clip_pos;
int pos_idx;
unsigned emitted_primitives;
unsigned emitted_vertices;
unsigned generated_primitives;
};
void draw_pt_so_emit_prepare(struct pt_so_emit *emit)
void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos)
{
struct draw_context *draw = emit->draw;
emit->use_pre_clip_pos = use_pre_clip_pos;
emit->has_so = (draw->vs.vertex_shader->state.stream_output.num_outputs > 0);
if (use_pre_clip_pos)
emit->pos_idx = draw_current_shader_position_output(draw);
/* if we have a state with outputs make sure we have
* buffers to output to */
@ -87,12 +91,15 @@ static void so_emit_prim(struct pt_so_emit *so,
unsigned input_vertex_stride = so->input_vertex_stride;
struct draw_context *draw = so->draw;
const float (*input_ptr)[4];
const float (*pcp_ptr)[4] = NULL;
const struct pipe_stream_output_info *state =
&draw->vs.vertex_shader->state.stream_output;
float *buffer;
int buffer_total_bytes[PIPE_MAX_SO_BUFFERS];
input_ptr = so->inputs;
if (so->use_pre_clip_pos)
pcp_ptr = so->pre_clip_pos;
++so->generated_primitives;
@ -117,12 +124,17 @@ static void so_emit_prim(struct pt_so_emit *so,
for (i = 0; i < num_vertices; ++i) {
const float (*input)[4];
const float (*pre_clip_pos)[4];
unsigned total_written_compos = 0;
int ob;
/*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));
if (pcp_ptr)
pre_clip_pos = (const float (*)[4])(
(const char *)pcp_ptr + (indices[i] * input_vertex_stride));
for (slot = 0; slot < state->num_outputs; ++slot) {
unsigned idx = state->output[slot].register_index;
unsigned start_comp = state->output[slot].start_component;
@ -133,7 +145,10 @@ static void so_emit_prim(struct pt_so_emit *so,
buffer = (float *)((char *)draw->so.targets[ob]->mapping +
draw->so.targets[ob]->target.buffer_offset +
draw->so.targets[ob]->internal_offset) + state->output[slot].dst_offset;
memcpy(buffer, &input[idx][start_comp], num_comps * sizeof(float));
if (idx == so->pos_idx && pcp_ptr)
memcpy(buffer, &pre_clip_pos[start_comp], num_comps * sizeof(float));
else
memcpy(buffer, &input[idx][start_comp], num_comps * sizeof(float));
total_written_compos += num_comps;
}
for (ob = 0; ob < draw->so.num_targets; ++ob)
@ -203,6 +218,9 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
emit->emitted_primitives = 0;
emit->generated_primitives = 0;
emit->input_vertex_stride = input_verts->stride;
if (emit->use_pre_clip_pos)
emit->pre_clip_pos = (const float (*)[4])input_verts->verts->pre_clip_pos;
emit->inputs = (const float (*)[4])input_verts->verts->data;
/* XXX: need to flush to get prim_vbuf.c to release its allocation??*/

View file

@ -80,6 +80,7 @@ draw_create_vertex_shader(struct draw_context *draw,
{
uint i;
bool found_clipvertex = FALSE;
vs->position_output = -1;
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
vs->info.output_semantic_index[i] == 0)

View file

@ -188,7 +188,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
return 16*4;
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
return 0;
return 1;
case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
return 0;