st/mesa: implement "zombie" sampler views (v2)

When st_texture_release_all_sampler_views() is called the texture may
have sampler views belonging to several contexts.  If we unreference a
sampler view and its refcount hits zero, we need to be sure to destroy
the sampler view with the same context which created it.

This was not the case with the previous code which used
pipe_sampler_view_release().  That function could end up freeing a
sampler view with a context different than the one which created it.
In the case of the VMware svga driver, we detected this but leaked the
sampler view.  This led to a crash with google-chrome when the kernel
module had too many sampler views.  VMware bug 2274734.

Alternately, if we try to delete a sampler view with the correct
context, we may be "reaching into" a context which is active on
another thread.  That's not safe.

To fix these issues this patch adds a per-context list of "zombie"
sampler views.  These are views which are to be freed at some point
when the context is active.  Other contexts may safely add sampler
views to the zombie list at any time (it's mutex protected).  This
avoids the context/view ownership mix-ups we had before.

Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos
a few Linux games.  If anyone can recomment some other multi-threaded,
multi-context GL apps to test, please let me know.

v2: avoid potential race issue by always adding sampler views to the
zombie list if the view's context doesn't match the current context,
ignoring the refcount.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: Neha Bhende <bhenden@vmware.com>
Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
Brian Paul
2019-03-12 09:13:00 -06:00
parent e547a1ccb5
commit 593e36f956
5 changed files with 131 additions and 4 deletions

View File

@@ -150,6 +150,7 @@ found:
sv->glsl130_or_later = glsl130_or_later;
sv->srgb_skip_decode = srgb_skip_decode;
sv->view = view;
sv->st = st;
out:
simple_mtx_unlock(&stObj->validate_mutex);
@@ -213,8 +214,6 @@ void
st_texture_release_all_sampler_views(struct st_context *st,
struct st_texture_object *stObj)
{
GLuint i;
/* TODO: This happens while a texture is deleted, because the Driver API
* is asymmetric: the driver allocates the texture object memory, but
* mesa/main frees it.
@@ -224,8 +223,21 @@ st_texture_release_all_sampler_views(struct st_context *st,
simple_mtx_lock(&stObj->validate_mutex);
struct st_sampler_views *views = stObj->sampler_views;
for (i = 0; i < views->count; ++i)
pipe_sampler_view_release(st->pipe, &views->views[i].view);
for (unsigned i = 0; i < views->count; ++i) {
struct st_sampler_view *stsv = &views->views[i];
if (stsv->view) {
if (stsv->st != st) {
/* Transfer this reference to the zombie list. It will
* likely be freed when the zombie list is freed.
*/
st_save_zombie_sampler_view(stsv->st, stsv->view);
stsv->view = NULL;
} else {
pipe_sampler_view_reference(&stsv->view, NULL);
}
}
}
views->count = 0;
simple_mtx_unlock(&stObj->validate_mutex);
}
@@ -241,6 +253,7 @@ st_delete_texture_sampler_views(struct st_context *st,
st_texture_release_all_sampler_views(st, stObj);
/* Free the container of the current per-context sampler views */
assert(stObj->sampler_views->count == 0);
free(stObj->sampler_views);
stObj->sampler_views = NULL;