From: Zack Rusin Date: Fri, 24 May 2013 20:17:26 +0000 (-0400) Subject: draw: implement support for multiple viewports X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7756aae815a26c533948081c2c319c20bcf5962c;p=mesa.git 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 Reviewed-by: José Fonseca Reviewed-by: Brian Paul Reviewed-by: Roland Scheidegger --- 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];