[Mesa-dev] [PATCH 2/4] draw: implement support for multiple viewports
Zack Rusin
zackr at vmware.com
Fri May 24 13:56:04 PDT 2013
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 at vmware.com>
---
src/gallium/auxiliary/draw/draw_cliptest_tmp.h | 10 +++-
src/gallium/auxiliary/draw/draw_context.c | 52 ++++++++++++++++----
src/gallium/auxiliary/draw/draw_gs.c | 11 ++++-
src/gallium/auxiliary/draw/draw_gs.h | 1 +
src/gallium/auxiliary/draw/draw_pipe_clip.c | 11 ++++-
src/gallium/auxiliary/draw/draw_private.h | 8 +--
.../draw/draw_pt_fetch_shade_pipeline_llvm.c | 4 +-
src/gallium/auxiliary/draw/draw_vs.c | 7 ---
src/gallium/auxiliary/draw/draw_vs_variant.c | 34 +++++++++++--
9 files changed, 105 insertions(+), 33 deletions(-)
diff --git a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
index 48f2349..09e1fd7 100644
--- a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
@@ -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);
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index b555c65..4250f10 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -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);
}
@@ -695,6 +702,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.
*/
uint
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index fa0981e..67e5117 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
index 46d2d61..2b08569 100644
--- a/src/gallium/auxiliary/draw/draw_gs.h
+++ b/src/gallium/auxiliary/draw/draw_gs.h
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index 8da0c41..b01e519 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -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];
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 1b2d55f..e5f192b 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -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);
/*******************************************************************************
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 f734311..5d2993e 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
@@ -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;
}
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index afec376..95f678a 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -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)
diff --git a/src/gallium/auxiliary/draw/draw_vs_variant.c b/src/gallium/auxiliary/draw/draw_vs_variant.c
index d8f030f..0387eaf 100644
--- a/src/gallium/auxiliary/draw/draw_vs_variant.c
+++ b/src/gallium/auxiliary/draw/draw_vs_variant.c
@@ -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];
--
1.7.10.4
More information about the mesa-dev
mailing list