svga: disable rasterization if rasterizer_discard is set or FS undefined
authorCharmaine Lee <charmainel@vmware.com>
Tue, 4 Apr 2017 18:47:49 +0000 (12:47 -0600)
committerBrian Paul <brianp@vmware.com>
Fri, 7 Apr 2017 19:46:43 +0000 (13:46 -0600)
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 <brianp@vmware.com>
src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_pipe_draw.c
src/gallium/drivers/svga/svga_pipe_rasterizer.c
src/gallium/drivers/svga/svga_state_fs.c
src/gallium/drivers/svga/svga_state_rss.c

index ec86073ccc9d0fae4012f7e83786c8d39b66d4da..04466fb7dee8735223c025935a7bee24c631bbc9 100644 (file)
@@ -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;
 
index 40966e9b52ec7bc3af14875408208c5136ce1267..2b95a7878702ea289be93fb95ae4d7bc8dc942e0 100644 (file)
@@ -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:
index 30524a0e3ec49a7a820c3efdf2b62d6f6c4dc1d4..eaf46811ff7f9d9971dbe92a9d965e758fd9812c 100644 (file)
 #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,
index 70d89f5cc639b421af8e9f32f2dae0bbd95f3eee..35351fc60801caf32e2722fd32c5beb63f32cd88 100644 (file)
@@ -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;
index 48987445025001e303ad1cfa0ad08099d8359bdd..07a3614d79d7b33124ac494701b57e67ce615f6e 100644 (file)
@@ -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
index e22268d5b8f46a3d57e8ab678e432e691eaee723..d04ef8d6dd94307f5f46425238472b88dcef8e8f 100644 (file)
@@ -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