[Mesa-dev] [PATCH] svga: only free sampler views from the context which created it

Brian Paul brianp at vmware.com
Mon Mar 4 18:51:59 UTC 2019


Some applications, like google-chrome, cause the state tracker to
destroy sampler/resource views from a context other than the one
which was used to create it.  Previously, we just leaked the view.

Now, when we're in this situation we declare the view a zombie and
add it to a list of zombie views associated with the context which
created the context.

VMware bug 2274734.
---
 src/gallium/drivers/svga/svga_context.c      | 69 ++++++++++++++++++++++++++++
 src/gallium/drivers/svga/svga_context.h      | 21 +++++++++
 src/gallium/drivers/svga/svga_pipe_sampler.c |  8 ++--
 3 files changed, 93 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c
index 7b3e9e8..2c51fa0 100644
--- a/src/gallium/drivers/svga/svga_context.c
+++ b/src/gallium/drivers/svga/svga_context.c
@@ -54,12 +54,74 @@ DEBUG_GET_ONCE_BOOL_OPTION(no_line_width, "SVGA_NO_LINE_WIDTH", FALSE);
 DEBUG_GET_ONCE_BOOL_OPTION(force_hw_line_stipple, "SVGA_FORCE_HW_LINE_STIPPLE", FALSE);
 
 
+/*
+ * In some circumstances (such as running google-chrome) the state
+ * tracker may try to delete a resource view from a context different
+ * than when it was created.  We don't want to do that.
+ * In that situation, svga_sampler_view_destroy() calls this function
+ * to save the view for later deletion.  The context here is expected
+ * to be the context which created the view.
+ */
+void
+svga_save_zombie_view(struct pipe_context *pipe,
+                      struct pipe_sampler_view *view)
+{
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_pipe_sampler_view *sv = svga_pipe_sampler_view(view);
+   struct svga_zombie_view_list *entry;
+
+   assert(view->context == pipe);
+
+   entry = MALLOC_STRUCT(svga_zombie_view_list);
+   if (!entry)
+      return;
+
+   entry->view = sv;
+
+   /* We need a mutex since this function may be called from one thread
+    * while free_zombie_resource_views() is called from another.
+    */
+   mtx_lock(&svga->zombie_view_mutex);
+   LIST_ADDTAIL(&entry->node, &svga->zombie_views);
+   mtx_unlock(&svga->zombie_view_mutex);
+}
+
+
+/*
+ * This function is called periodically (currently from svga_surfaces_flush)
+ * to free any resource views which the state tracker tried to free earlier,
+ * but did so from the wrong context.
+ */
+static void
+free_zombie_resource_views(struct svga_context *svga)
+{
+   struct pipe_context *pipe = &svga->pipe;
+   struct svga_zombie_view_list *entry, *next;
+
+   mtx_lock(&svga->zombie_view_mutex);
+
+   LIST_FOR_EACH_ENTRY_SAFE(entry, next, &svga->zombie_views, node) {
+      assert(entry->view->base.context == pipe);
+      pipe->sampler_view_destroy(pipe, &entry->view->base);
+      free(entry);
+      LIST_DEL(&entry->node);
+   }
+
+   assert(LIST_IS_EMPTY(&svga->zombie_views));
+
+   mtx_unlock(&svga->zombie_view_mutex);
+}
+
+
 static void
 svga_destroy(struct pipe_context *pipe)
 {
    struct svga_context *svga = svga_context(pipe);
    unsigned shader, i;
 
+   free_zombie_resource_views(svga);
+   mtx_destroy(&svga->zombie_view_mutex);
+
    /* free any alternate rasterizer states used for point sprite */
    for (i = 0; i < ARRAY_SIZE(svga->rasterizer_no_cull); i++) {
       if (svga->rasterizer_no_cull[i]) {
@@ -137,6 +199,8 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags)
       goto done;
 
    LIST_INITHEAD(&svga->dirty_buffers);
+   LIST_INITHEAD(&svga->zombie_views);
+   mtx_init(&svga->zombie_view_mutex, mtx_plain);
 
    svga->pipe.screen = screen;
    svga->pipe.priv = priv;
@@ -482,6 +546,11 @@ svga_surfaces_flush(struct svga_context *svga)
    svga_propagate_rendertargets(svga);
 
    SVGA_STATS_TIME_POP(svga_sws(svga));
+
+   /* We want to call this function periodically.  This seems to
+    * be a reasonable place to do so.
+    */
+   free_zombie_resource_views(svga);
 }
 
 
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index fc63ec3..4de81ac 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -231,6 +231,18 @@ svga_pipe_sampler_view(struct pipe_sampler_view *v)
 }
 
 
+/*
+ * For keeping a list of zombie sampler views.  A zombie sampler view is
+ * one that is supposed to be deleted, but the view's parent context is not
+ * the context passed to pipe_context::sampler_view_destroy().
+ */
+struct svga_zombie_view_list
+{
+   struct svga_pipe_sampler_view *view;
+   struct list_head node;  // there's a linked list of these structs
+};
+
+
 struct svga_velems_state {
    unsigned count;
    struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
@@ -536,6 +548,10 @@ struct svga_context
    /** List of buffers with queued transfers */
    struct list_head dirty_buffers;
 
+   /** List of zombie resource views */
+   struct list_head zombie_views;
+   mtx_t zombie_view_mutex;
+
    /** performance / info queries for HUD */
    struct {
       uint64_t num_draw_calls;          /**< SVGA_QUERY_DRAW_CALLS */
@@ -683,6 +699,11 @@ void svga_toggle_render_condition(struct svga_context *svga,
                                   boolean render_condition_enabled,
                                   boolean on);
 
+void
+svga_save_zombie_view(struct pipe_context *pipe,
+                      struct pipe_sampler_view *view);
+
+
 /***********************************************************************
  * Inline conversion functions.  These are better-typed than the
  * macros used previously:
diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c
index b32bb09..d303aad 100644
--- a/src/gallium/drivers/svga/svga_pipe_sampler.c
+++ b/src/gallium/drivers/svga/svga_pipe_sampler.c
@@ -408,12 +408,10 @@ svga_sampler_view_destroy(struct pipe_context *pipe,
       if (view->context != pipe) {
          /* The SVGA3D device will generate an error (and on Linux, cause
           * us to abort) if we try to destroy a shader resource view from
-          * a context other than the one it was created with.  Skip the
-          * SVGA3D_vgpu10_DestroyShaderResourceView() and leak the sampler
-          * view for now.  This should only sometimes happen when a shared
-          * texture is deleted.
+          * a context other than the one it was created with.
+          * Declare this a zombie view and attach it to the creating context.
           */
-         _debug_printf("context mismatch in %s\n", __func__);
+         svga_save_zombie_view(view->context, view);
       }
       else {
          enum pipe_error ret;
-- 
1.8.5.6



More information about the mesa-dev mailing list