Mesa (master): swr: fix crash in swr_update_derived following st/ mesa state changes

Tim Rowley torowley at kemper.freedesktop.org
Thu Mar 2 19:44:23 UTC 2017


Module: Mesa
Branch: master
Commit: a7b8d50bcb56b5d093aee24a722f2a5288b79b14
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a7b8d50bcb56b5d093aee24a722f2a5288b79b14

Author: Bruce Cherniak <bruce.cherniak at intel.com>
Date:   Wed Mar  1 22:58:36 2017 -0600

swr: fix crash in swr_update_derived following st/mesa state changes

Recent change to st/mesa state update logic caused major regressions to
swr validation code.

swr uses the same validation logic (swr_update_derived) for both draw
and Clear calls.  New st/mesa state update logic results in certain state
objects not being set/bound during Clear.  This was causing null ptr
exceptions.  Creation of static dummy state objects allows setting these
pointers during Clear validation, without interfering with relevant state
validation.

Once fixed, new logic also highlighted an error in dirty bit checking for
fragment shader and clip validation.

(The alternative is to have a simplified validation routine for Clear.
Which may do that at some point.)

Reviewed-by: Tim Rowley <timothy.o.rowley at intel.com>

---

 src/gallium/drivers/swr/swr_shader.cpp |  6 +++++
 src/gallium/drivers/swr/swr_state.cpp  | 43 +++++++++++++++++++++++++++++++---
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/swr/swr_shader.cpp b/src/gallium/drivers/swr/swr_shader.cpp
index 676938c..9169f6d 100644
--- a/src/gallium/drivers/swr/swr_shader.cpp
+++ b/src/gallium/drivers/swr/swr_shader.cpp
@@ -366,6 +366,9 @@ BuilderSWR::CompileVS(struct swr_context *ctx, swr_jit_vs_key &key)
 PFN_VERTEX_FUNC
 swr_compile_vs(struct swr_context *ctx, swr_jit_vs_key &key)
 {
+   if (!ctx->vs->pipe.tokens)
+      return NULL;
+
    BuilderSWR builder(
       reinterpret_cast<JitManager *>(swr_screen(ctx->pipe.screen)->hJitMgr),
       "VS");
@@ -726,6 +729,9 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
 PFN_PIXEL_KERNEL
 swr_compile_fs(struct swr_context *ctx, swr_jit_fs_key &key)
 {
+   if (!ctx->fs->pipe.tokens)
+      return NULL;
+
    BuilderSWR builder(
       reinterpret_cast<JitManager *>(swr_screen(ctx->pipe.screen)->hJitMgr),
       "FS");
diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp
index 5e3d58d..e1f1734 100644
--- a/src/gallium/drivers/swr/swr_state.cpp
+++ b/src/gallium/drivers/swr/swr_state.cpp
@@ -914,6 +914,39 @@ swr_update_derived(struct pipe_context *pipe,
    struct swr_context *ctx = swr_context(pipe);
    struct swr_screen *screen = swr_screen(pipe->screen);
 
+   /* When called from swr_clear (p_draw_info = null), set any null
+    * state-objects to the dummy state objects to prevent nullptr dereference
+    * in validation below.
+    *
+    * Important that this remains static for zero initialization.  These
+    * aren't meant to be proper state objects, just empty structs. They will
+    * not be written to.
+    *
+    * Shaders can't be part of the union since they contain std::unordered_map
+    */
+   static struct {
+      union {
+         struct pipe_rasterizer_state rasterizer;
+         struct pipe_depth_stencil_alpha_state depth_stencil;
+         struct swr_blend_state blend;
+      } state;
+      struct swr_vertex_shader vs;
+      struct swr_fragment_shader fs;
+   } swr_dummy;
+
+   if (!p_draw_info) {
+      if (!ctx->rasterizer)
+         ctx->rasterizer = &swr_dummy.state.rasterizer;
+      if (!ctx->depth_stencil)
+         ctx->depth_stencil = &swr_dummy.state.depth_stencil;
+      if (!ctx->blend)
+         ctx->blend = &swr_dummy.state.blend;
+      if (!ctx->vs)
+         ctx->vs = &swr_dummy.vs;
+      if (!ctx->fs)
+         ctx->fs = &swr_dummy.fs;
+   }
+
    /* Update screen->pipe to current pipe context. */
    if (screen->pipe != pipe)
       screen->pipe = pipe;
@@ -1236,8 +1269,12 @@ swr_update_derived(struct pipe_context *pipe,
    }
 
    /* FragmentShader */
-   if (ctx->dirty & (SWR_NEW_FS | SWR_NEW_SAMPLER | SWR_NEW_SAMPLER_VIEW
-                     | SWR_NEW_RASTERIZER | SWR_NEW_FRAMEBUFFER)) {
+   if (ctx->dirty & (SWR_NEW_FS |
+                     SWR_NEW_VS |
+                     SWR_NEW_RASTERIZER |
+                     SWR_NEW_SAMPLER |
+                     SWR_NEW_SAMPLER_VIEW |
+                     SWR_NEW_FRAMEBUFFER)) {
       swr_jit_fs_key key;
       swr_generate_fs_key(key, ctx, ctx->fs);
       auto search = ctx->fs->map.find(key);
@@ -1505,7 +1542,7 @@ swr_update_derived(struct pipe_context *pipe,
       }
    }
 
-   if (ctx->dirty & SWR_NEW_CLIP) {
+   if (ctx->dirty & (SWR_NEW_CLIP | SWR_NEW_RASTERIZER | SWR_NEW_VS)) {
       // shader exporting clip distances overrides all user clip planes
       if (ctx->rasterizer->clip_plane_enable &&
           !ctx->vs->info.base.num_written_clipdistance)




More information about the mesa-commit mailing list