draw: implement support for multiple viewports

This adds support for multiple viewports to the draw module.
Multiple viewports depend on the presence of geometry shaders
which can write the viewport index.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: José Fonseca<jfonseca@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
Zack Rusin 2013-05-24 16:17:26 -04:00
parent eaabb4ead0
commit 7756aae815
9 changed files with 105 additions and 33 deletions

View File

@ -31,8 +31,6 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
struct draw_vertex_info *info )
{
struct vertex_header *out = info->verts;
const float *scale = pvs->draw->viewport.scale;
const float *trans = pvs->draw->viewport.translate;
/* const */ float (*plane)[4] = pvs->draw->plane;
const unsigned pos = draw_current_shader_position_output(pvs->draw);
const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
@ -44,6 +42,9 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
unsigned j;
unsigned i;
bool have_cd = false;
unsigned viewport_index_output =
draw_current_shader_viewport_index_output(pvs->draw);
cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
@ -52,7 +53,12 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
int viewport_index =
draw_current_shader_uses_viewport_index(pvs->draw) ?
*((unsigned*)out->data[viewport_index_output]): 0;
unsigned mask = 0x0;
const float *scale = pvs->draw->viewports[viewport_index].scale;
const float *trans = pvs->draw->viewports[viewport_index].translate;
initialize_vertex_header(out);

View File

@ -318,17 +318,24 @@ void draw_set_viewport_states( struct draw_context *draw,
{
const struct pipe_viewport_state *viewport = vps;
draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
draw->viewport = *viewport; /* struct copy */
draw->identity_viewport = (viewport->scale[0] == 1.0f &&
viewport->scale[1] == 1.0f &&
viewport->scale[2] == 1.0f &&
viewport->scale[3] == 1.0f &&
viewport->translate[0] == 0.0f &&
viewport->translate[1] == 0.0f &&
viewport->translate[2] == 0.0f &&
viewport->translate[3] == 0.0f);
draw_vs_set_viewport( draw, viewport );
if (start_slot > PIPE_MAX_VIEWPORTS)
return;
if ((start_slot + num_viewports) > PIPE_MAX_VIEWPORTS)
num_viewports = PIPE_MAX_VIEWPORTS - start_slot;
memcpy(draw->viewports + start_slot, vps,
sizeof(struct pipe_viewport_state) * num_viewports);
draw->identity_viewport = (num_viewports == 1) &&
(viewport->scale[0] == 1.0f &&
viewport->scale[1] == 1.0f &&
viewport->scale[2] == 1.0f &&
viewport->scale[3] == 1.0f &&
viewport->translate[0] == 0.0f &&
viewport->translate[1] == 0.0f &&
viewport->translate[2] == 0.0f &&
viewport->translate[3] == 0.0f);
}
@ -693,6 +700,31 @@ draw_current_shader_position_output(const struct draw_context *draw)
}
/**
* Return the index of the shader output which will contain the
* viewport index.
*/
uint
draw_current_shader_viewport_index_output(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->viewport_index_output;
return 0;
}
/**
* Returns true if there's a geometry shader bound and the geometry
* shader writes out a viewport index.
*/
boolean
draw_current_shader_uses_viewport_index(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->info.writes_viewport_index;
return FALSE;
}
/**
* Return the index of the shader output which will contain the
* vertex position.

View File

@ -335,8 +335,13 @@ llvm_fetch_gs_outputs(struct draw_geometry_shader *shader,
int i;
for (i = 0; i < total_verts; ++i) {
struct vertex_header *vh = (struct vertex_header *)(output_ptr + shader->vertex_size * i);
debug_printf("%d) [%f, %f, %f, %f]\n", i,
vh->data[0][0], vh->data[0][1], vh->data[0][2], vh->data[0][3]);
debug_printf("%d) Vertex:\n", i);
for (j = 0; j < shader->info.num_outputs; ++j) {
unsigned *udata = (unsigned*)vh->data[j];
debug_printf(" %d) [%f, %f, %f, %f] [%d, %d, %d, %d]\n", j,
vh->data[j][0], vh->data[j][1], vh->data[j][2], vh->data[j][3],
udata[0], udata[1], udata[2], udata[3]);
}
}
}
@ -784,6 +789,8 @@ draw_create_geometry_shader(struct draw_context *draw,
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
gs->info.output_semantic_index[i] == 0)
gs->position_output = i;
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)
gs->viewport_index_output = i;
}
gs->machine = draw->gs.tgsi.machine;

View File

@ -66,6 +66,7 @@ struct draw_geometry_shader {
struct tgsi_shader_info info;
unsigned position_output;
unsigned viewport_index_output;
unsigned max_output_vertices;
unsigned primitive_boundary;

View File

@ -127,6 +127,8 @@ static void interp( const struct clip_stage *clip,
const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
unsigned j;
float t_nopersp;
unsigned viewport_index_output =
draw_current_shader_viewport_index_output(clip->stage.draw);
/* Vertex header.
*/
@ -145,9 +147,14 @@ static void interp( const struct clip_stage *clip,
* new window coordinates:
*/
{
int viewport_index =
draw_current_shader_uses_viewport_index(clip->stage.draw) ?
*((unsigned*)in->data[viewport_index_output]) : 0;
const float *pos = dst->pre_clip_pos;
const float *scale = clip->stage.draw->viewport.scale;
const float *trans = clip->stage.draw->viewport.translate;
const float *scale =
clip->stage.draw->viewports[viewport_index].scale;
const float *trans =
clip->stage.draw->viewports[viewport_index].translate;
const float oow = 1.0f / pos[3];
dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0];

View File

@ -241,7 +241,7 @@ struct draw_context
/** Rasterizer CSOs without culling/stipple/etc */
void *rasterizer_no_cull[2][2];
struct pipe_viewport_state viewport;
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
boolean identity_viewport;
/** Vertex shader state */
@ -372,9 +372,6 @@ void draw_new_instance(struct draw_context *draw);
boolean draw_vs_init( struct draw_context *draw );
void draw_vs_destroy( struct draw_context *draw );
void draw_vs_set_viewport( struct draw_context *,
const struct pipe_viewport_state * );
/*******************************************************************************
* Geometry shading code:
@ -389,11 +386,14 @@ void draw_gs_destroy( struct draw_context *draw );
*/
uint draw_current_shader_outputs(const struct draw_context *draw);
uint draw_current_shader_position_output(const struct draw_context *draw);
uint draw_current_shader_viewport_index_output(const struct draw_context *draw);
uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index);
int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index);
void draw_remove_extra_vertex_attribs(struct draw_context *draw);
boolean draw_current_shader_uses_viewport_index(
const struct draw_context *draw);
/*******************************************************************************

View File

@ -277,8 +277,8 @@ llvm_middle_end_bind_parameters(struct draw_pt_middle_end *middle)
fpme->llvm->gs_jit_context.planes =
(float (*)[DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
fpme->llvm->jit_context.viewport = (float *) draw->viewport.scale;
fpme->llvm->gs_jit_context.viewport = (float *) draw->viewport.scale;
fpme->llvm->jit_context.viewport = (float *) draw->viewports[0].scale;
fpme->llvm->gs_jit_context.viewport = (float *) draw->viewports[0].scale;
}

View File

@ -49,13 +49,6 @@
DEBUG_GET_ONCE_BOOL_OPTION(gallium_dump_vs, "GALLIUM_DUMP_VS", FALSE)
void draw_vs_set_viewport( struct draw_context *draw,
const struct pipe_viewport_state *viewport )
{
}
struct draw_vertex_shader *
draw_create_vertex_shader(struct draw_context *draw,
const struct pipe_shader_state *shader)

View File

@ -78,6 +78,26 @@ static void vsvg_set_buffer( struct draw_vs_variant *variant,
max_index );
}
static const struct pipe_viewport_state *
find_viewport(struct draw_context *draw,
char *buffer,
unsigned vertex_idx,
unsigned stride)
{
int viewport_index_output =
draw_current_shader_viewport_index_output(draw);
char *ptr = buffer + vertex_idx * stride;
unsigned *data = (unsigned *)ptr;
int viewport_index =
draw_current_shader_uses_viewport_index(draw) ?
data[viewport_index_output * 4] : 0;
debug_assert(viewport_index < PIPE_MAX_VIEWPORTS);
viewport_index = MIN2(viewport_index, PIPE_MAX_VIEWPORTS - 1);
return &draw->viewports[viewport_index];
}
/* Mainly for debug at this stage:
*/
@ -86,14 +106,17 @@ static void do_rhw_viewport( struct draw_vs_variant_generic *vsvg,
void *output_buffer )
{
char *ptr = (char *)output_buffer;
const float *scale = vsvg->base.vs->draw->viewport.scale;
const float *trans = vsvg->base.vs->draw->viewport.translate;
unsigned stride = vsvg->temp_vertex_stride;
unsigned j;
ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
for (j = 0; j < count; j++, ptr += stride) {
const struct pipe_viewport_state *viewport =
find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
j, stride);
const float *scale = viewport->scale;
const float *trans = viewport->translate;
float *data = (float *)ptr;
float w = 1.0f / data[3];
@ -109,14 +132,17 @@ static void do_viewport( struct draw_vs_variant_generic *vsvg,
void *output_buffer )
{
char *ptr = (char *)output_buffer;
const float *scale = vsvg->base.vs->draw->viewport.scale;
const float *trans = vsvg->base.vs->draw->viewport.translate;
unsigned stride = vsvg->temp_vertex_stride;
unsigned j;
ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
for (j = 0; j < count; j++, ptr += stride) {
const struct pipe_viewport_state *viewport =
find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
j, stride);
const float *scale = viewport->scale;
const float *trans = viewport->translate;
float *data = (float *)ptr;
data[0] = data[0] * scale[0] + trans[0];