From 7756aae815a26c533948081c2c319c20bcf5962c Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 24 May 2013 16:17:26 -0400 Subject: [PATCH] draw: implement support for multiple viewports MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: José Fonseca Reviewed-by: Brian Paul Reviewed-by: Roland Scheidegger --- .../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 48f234931cd..09e1fd71334 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 b555c65e858..4250f10d13a 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); } @@ -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. diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c index fa0981ee10e..67e5117c587 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 46d2d614f06..2b0856924d9 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 8da0c41390f..b01e51994cb 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 1b2d55fac55..e5f192b7576 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 f734311e73c..5d2993eaa17 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 afec3760e77..95f678ab2cd 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 d8f030f61eb..0387eafbbce 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]; -- 2.30.2