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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev