draw/llvmpipe: allow independent so attachments to the vs

When geometry shaders are present, one needs to be able to create
an empty geometry shader with stream output that needs to be
resolved later and attached to the currently bound vertex shader.
Lets add support for it to llvmpipe and draw. draw allows attaching
independent stream output info to any vertex shader and llvmpipe
resolves at draw time which vertex shader the given empty geometry
shader should be linked to.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: José Fonseca <jfonseca@vmware.com>
This commit is contained in:
Zack Rusin
2013-03-30 06:21:41 -07:00
parent 246e68735f
commit 302df7cc85
6 changed files with 42 additions and 22 deletions

View File

@@ -734,15 +734,6 @@ draw_set_mapped_so_targets(struct draw_context *draw,
draw->so.num_targets = num_targets;
}
void
draw_set_so_state(struct draw_context *draw,
struct pipe_stream_output_info *state)
{
memcpy(&draw->so.state,
state,
sizeof(struct pipe_stream_output_info));
}
void
draw_set_sampler_views(struct draw_context *draw,
unsigned shader_stage,

View File

@@ -171,6 +171,9 @@ void draw_bind_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs);
void draw_delete_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs);
void draw_vs_attach_so(struct draw_vertex_shader *dvs,
const struct pipe_stream_output_info *info);
void draw_vs_reset_so(struct draw_vertex_shader *dvs);
/*
@@ -226,10 +229,6 @@ draw_set_mapped_so_targets(struct draw_context *draw,
int num_targets,
struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS]);
void
draw_set_so_state(struct draw_context *draw,
struct pipe_stream_output_info *state);
/***********************************************************************
* draw_pt.c

View File

@@ -279,7 +279,6 @@ struct draw_context
/** Stream output (vertex feedback) state */
struct {
struct pipe_stream_output_info state;
struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS];
uint num_targets;
} so;

View File

@@ -245,3 +245,16 @@ draw_vs_get_emit( struct draw_context *draw,
return draw->vs.emit;
}
void
draw_vs_attach_so(struct draw_vertex_shader *dvs,
const struct pipe_stream_output_info *info)
{
dvs->state.stream_output = *info;
}
void
draw_vs_reset_so(struct draw_vertex_shader *dvs)
{
memset(&dvs->state.stream_output, 0, sizeof(dvs->state.stream_output));
}

View File

@@ -101,6 +101,13 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
llvmpipe_prepare_geometry_sampling(lp,
lp->num_sampler_views[PIPE_SHADER_GEOMETRY],
lp->sampler_views[PIPE_SHADER_GEOMETRY]);
if (lp->gs && !lp->gs->shader.tokens) {
/* we have an empty geometry shader with stream output, so
attach the stream output info to the current vertex shader */
if (lp->vs) {
draw_vs_attach_so(lp->vs->draw_data, &lp->gs->shader.stream_output);
}
}
/* draw! */
draw_vbo(draw, info);
@@ -116,6 +123,14 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
}
draw_set_mapped_so_targets(draw, 0, NULL);
if (lp->gs && !lp->gs->shader.tokens) {
/* we have attached stream output to the vs for rendering,
now lets reset it */
if (lp->vs) {
draw_vs_reset_so(lp->vs->draw_data);
}
}
llvmpipe_cleanup_vertex_sampling(lp);
llvmpipe_cleanup_geometry_sampling(lp);

View File

@@ -53,15 +53,18 @@ llvmpipe_create_gs_state(struct pipe_context *pipe,
if (0)
tgsi_dump(templ->tokens, 0);
/* copy shader tokens, the ones passed in will go away.
*/
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
/* copy stream output info */
state->shader = *templ;
if (templ->tokens) {
/* copy shader tokens, the ones passed in will go away. */
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
state->draw_data = draw_create_geometry_shader(llvmpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
state->draw_data = draw_create_geometry_shader(llvmpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
}
return state;