From b4c4ee076244d0518af98e0beca1c12942c4bc36 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Tue, 4 Apr 2017 12:47:49 -0600 Subject: [PATCH] svga: disable rasterization if rasterizer_discard is set or FS undefined With this patch, rasterization will be disabled if the rasterizer_discard flag is set or the fragment shader is undefined due to missing position output from the vertex/geometry shader. Tested with piglit test glsl-1.50-geometry-primitive-id-restart. Also tested with full MTT glretrace and piglit. v2: As suggested by Roland, to properly disable rasterization, besides setting FS to NULL, we will also need to disable depth and stencil test. v3: As suggested by Brian, set SVGA_NEW_DEPTH_STENCIL_ALPHA dirty bit in svga_bind_rasterizer_state() if the rasterizer_discard flag is changed. Reviewed-by: Brian Paul --- src/gallium/drivers/svga/svga_context.c | 7 ++ src/gallium/drivers/svga/svga_context.h | 6 ++ src/gallium/drivers/svga/svga_pipe_draw.c | 14 ++- .../drivers/svga/svga_pipe_rasterizer.c | 17 ++- src/gallium/drivers/svga/svga_state_fs.c | 21 ++++ src/gallium/drivers/svga/svga_state_rss.c | 102 ++++++++++++------ 6 files changed, 128 insertions(+), 39 deletions(-) diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index ec86073ccc9..04466fb7dee 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -67,6 +67,11 @@ svga_destroy(struct pipe_context *pipe) } } + /* free depthstencil_disable state */ + if (svga->depthstencil_disable) { + pipe->delete_depth_stencil_alpha_state(pipe, svga->depthstencil_disable); + } + /* free HW constant buffers */ for (shader = 0; shader < ARRAY_SIZE(svga->state.hw_draw.constbuf); shader++) { pipe_resource_reference(&svga->state.hw_draw.constbuf[shader], NULL); @@ -248,6 +253,7 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags) svga->state.hw_draw.num_views = 0; svga->state.hw_draw.num_rendertargets = 0; svga->state.hw_draw.dsv = NULL; + svga->state.hw_draw.rasterizer_discard = FALSE; /* Initialize the shader pointers */ svga->state.hw_draw.vs = NULL; @@ -289,6 +295,7 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags) svga->dirty = ~0; svga->pred.query_id = SVGA3D_INVALID_ID; + svga->disable_rasterizer = FALSE; return &svga->pipe; diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 40966e9b52e..2b95a787870 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -399,6 +399,8 @@ struct svga_hw_draw_state /* used for rebinding */ unsigned default_constbuf_size[PIPE_SHADER_TYPES]; + + boolean rasterizer_discard; /* set if rasterization is disabled */ }; @@ -583,6 +585,9 @@ struct svga_context /** Alternate rasterizer states created for point sprite */ struct svga_rasterizer_state *rasterizer_no_cull[2]; + /** Depth stencil state created to disable depth stencil test */ + struct svga_depth_stencil_state *depthstencil_disable; + /** Current conditional rendering predicate */ struct { SVGA3dQueryId query_id; @@ -590,6 +595,7 @@ struct svga_context } pred; boolean render_condition; + boolean disable_rasterizer; /* Set if to disable rasterization */ }; /* A flag for each state_tracker state object: diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 30524a0e3ec..eaf46811ff7 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -45,6 +45,16 @@ #include "svga_debug.h" #include "svga_resource_buffer.h" +/* Returns TRUE if we are currently using flat shading. + */ +static boolean +is_using_flat_shading(const struct svga_context *svga) +{ + return + svga->state.hw_draw.fs ? svga->state.hw_draw.fs->uses_flat_interp : FALSE; +} + + static enum pipe_error retry_draw_range_elements( struct svga_context *svga, struct pipe_resource *index_buffer, @@ -74,7 +84,7 @@ retry_draw_range_elements( struct svga_context *svga, */ svga_hwtnl_set_flatshade(svga->hwtnl, svga->curr.rast->templ.flatshade || - svga->state.hw_draw.fs->uses_flat_interp, + is_using_flat_shading(svga), svga->curr.rast->templ.flatshade_first); ret = svga_hwtnl_draw_range_elements( svga->hwtnl, @@ -126,7 +136,7 @@ retry_draw_arrays( struct svga_context *svga, */ svga_hwtnl_set_flatshade(svga->hwtnl, svga->curr.rast->templ.flatshade || - svga->state.hw_draw.fs->uses_flat_interp, + is_using_flat_shading(svga), svga->curr.rast->templ.flatshade_first); ret = svga_hwtnl_draw_arrays(svga->hwtnl, prim, start, count, diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index 70d89f5cc63..35351fc6080 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -378,11 +378,18 @@ svga_bind_rasterizer_state(struct pipe_context *pipe, void *state) struct svga_context *svga = svga_context(pipe); struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state; - if (!raster || - !svga->curr.rast || - raster->templ.poly_stipple_enable != - svga->curr.rast->templ.poly_stipple_enable) { - svga->dirty |= SVGA_NEW_STIPPLE; + if (!raster || !svga->curr.rast) { + svga->dirty |= SVGA_NEW_STIPPLE | SVGA_NEW_DEPTH_STENCIL_ALPHA; + } + else { + if (raster->templ.poly_stipple_enable != + svga->curr.rast->templ.poly_stipple_enable) { + svga->dirty |= SVGA_NEW_STIPPLE; + } + if (raster->templ.rasterizer_discard != + svga->curr.rast->templ.rasterizer_discard) { + svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA; + } } svga->curr.rast = raster; diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index 48987445025..07a3614d79d 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -408,6 +408,27 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty) SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITFS); + /* Disable rasterization if rasterizer_discard flag is set or + * vs/gs does not output position. + */ + svga->disable_rasterizer = + svga->curr.rast->templ.rasterizer_discard || + (svga->curr.gs && !svga->curr.gs->base.info.writes_position) || + (!svga->curr.gs && !svga->curr.vs->base.info.writes_position); + + /* Set FS to NULL when rasterization is to be disabled */ + if (svga->disable_rasterizer) { + /* Set FS to NULL if it has not been done */ + if (svga->state.hw_draw.fs) { + ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_PS, NULL); + if (ret != PIPE_OK) + goto done; + } + svga->rebind.flags.fs = FALSE; + svga->state.hw_draw.fs = NULL; + goto done; + } + /* SVGA_NEW_BLEND * SVGA_NEW_TEXTURE_BINDING * SVGA_NEW_RAST diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index e22268d5b8f..d04ef8d6dd9 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -336,6 +336,21 @@ get_no_cull_rasterizer_state(struct svga_context *svga) return svga->rasterizer_no_cull[aa_point]; } + +/** Returns a depth stencil state object with depth and stencil test disabled. + */ +static struct svga_depth_stencil_state * +get_no_depth_stencil_test_state(struct svga_context *svga) +{ + if (!svga->depthstencil_disable) { + struct pipe_depth_stencil_alpha_state ds = {{0}}; + svga->depthstencil_disable = + svga->pipe.create_depth_stencil_alpha_state(&svga->pipe, &ds); + } + return svga->depthstencil_disable; +} + + static enum pipe_error emit_rss_vgpu10(struct svga_context *svga, unsigned dirty) { @@ -394,45 +409,67 @@ emit_rss_vgpu10(struct svga_context *svga, unsigned dirty) } } - if (dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_STENCIL_REF)) { - const struct svga_depth_stencil_state *curr = svga->curr.depth; - unsigned curr_ref = svga->curr.stencil_ref.ref_value[0]; + if (svga->disable_rasterizer) { + if (!svga->state.hw_draw.rasterizer_discard) { + struct svga_depth_stencil_state *ds; - if (curr->id != svga->state.hw_draw.depth_stencil_id || - curr_ref != svga->state.hw_draw.stencil_ref) { - /* Set/bind the depth/stencil state object */ - ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, curr->id, - curr_ref); - if (ret != PIPE_OK) - return ret; - - svga->state.hw_draw.depth_stencil_id = curr->id; - svga->state.hw_draw.stencil_ref = curr_ref; + /* If rasterization is to be disabled, disable depth and stencil + * testing as well. + */ + ds = get_no_depth_stencil_test_state(svga); + if (ds->id != svga->state.hw_draw.depth_stencil_id) { + ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, ds->id, 0); + if (ret != PIPE_OK) + return ret; + + svga->state.hw_draw.depth_stencil_id = ds->id; + svga->state.hw_draw.stencil_ref = 0; + } + svga->state.hw_draw.rasterizer_discard = TRUE; + } + } else { + if ((dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_STENCIL_REF)) || + svga->state.hw_draw.rasterizer_discard) { + const struct svga_depth_stencil_state *curr = svga->curr.depth; + unsigned curr_ref = svga->curr.stencil_ref.ref_value[0]; + + if (curr->id != svga->state.hw_draw.depth_stencil_id || + curr_ref != svga->state.hw_draw.stencil_ref) { + /* Set/bind the depth/stencil state object */ + ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, curr->id, + curr_ref); + if (ret != PIPE_OK) + return ret; + + svga->state.hw_draw.depth_stencil_id = curr->id; + svga->state.hw_draw.stencil_ref = curr_ref; + } } - } - if (dirty & (SVGA_NEW_REDUCED_PRIMITIVE | SVGA_NEW_RAST)) { - const struct svga_rasterizer_state *rast; + if (dirty & (SVGA_NEW_REDUCED_PRIMITIVE | SVGA_NEW_RAST)) { + const struct svga_rasterizer_state *rast; - if (svga->curr.reduced_prim == PIPE_PRIM_POINTS && - svga->curr.gs && svga->curr.gs->wide_point) { + if (svga->curr.reduced_prim == PIPE_PRIM_POINTS && + svga->curr.gs && svga->curr.gs->wide_point) { - /* If we are drawing a point sprite, we will need to - * bind a non-culling rasterizer state object - */ - rast = get_no_cull_rasterizer_state(svga); - } - else { - rast = svga->curr.rast; - } + /* If we are drawing a point sprite, we will need to + * bind a non-culling rasterizer state object + */ + rast = get_no_cull_rasterizer_state(svga); + } + else { + rast = svga->curr.rast; + } - if (svga->state.hw_draw.rasterizer_id != rast->id) { - /* Set/bind the rasterizer state object */ - ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, rast->id); - if (ret != PIPE_OK) - return ret; - svga->state.hw_draw.rasterizer_id = rast->id; + if (svga->state.hw_draw.rasterizer_id != rast->id) { + /* Set/bind the rasterizer state object */ + ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, rast->id); + if (ret != PIPE_OK) + return ret; + svga->state.hw_draw.rasterizer_id = rast->id; + } } + svga->state.hw_draw.rasterizer_discard = FALSE; } return PIPE_OK; } @@ -461,6 +498,7 @@ struct svga_tracked_state svga_hw_rss = SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE | + SVGA_NEW_FS | SVGA_NEW_REDUCED_PRIMITIVE), emit_rss -- 2.30.2