[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