wined3d: Avoid accessing the bo_user list from outside the command stream thread (Valgrind).

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2021-04-29 19:06:02 +02:00 committed by Alexandre Julliard
parent f4de92a4ed
commit 7e64eba5b3
2 changed files with 68 additions and 78 deletions

View File

@ -4755,6 +4755,7 @@ struct wined3d_view_gl_destroy_ctx
{
struct wined3d_device *device;
const struct wined3d_gl_view *gl_view;
struct wined3d_bo_user *bo_user;
struct wined3d_bo_gl *counter_bo;
void *object;
struct wined3d_view_gl_destroy_ctx *free;
@ -4787,13 +4788,15 @@ static void wined3d_view_gl_destroy_object(void *object)
checkGLcall("delete resources");
context_release(context);
}
if (ctx->bo_user)
list_remove(&ctx->bo_user->entry);
heap_free(ctx->object);
heap_free(ctx->free);
}
static void wined3d_view_gl_destroy(struct wined3d_device *device,
const struct wined3d_gl_view *gl_view, struct wined3d_bo_gl *counter_bo, void *object)
static void wined3d_view_gl_destroy(struct wined3d_device *device, const struct wined3d_gl_view *gl_view,
struct wined3d_bo_user *bo_user, struct wined3d_bo_gl *counter_bo, void *object)
{
struct wined3d_view_gl_destroy_ctx *ctx, c;
@ -4801,6 +4804,7 @@ static void wined3d_view_gl_destroy(struct wined3d_device *device,
ctx = &c;
ctx->device = device;
ctx->gl_view = gl_view;
ctx->bo_user = bo_user;
ctx->counter_bo = counter_bo;
ctx->object = object;
ctx->free = ctx != &c ? ctx : NULL;
@ -4813,21 +4817,16 @@ static void wined3d_view_gl_destroy(struct wined3d_device *device,
static void adapter_gl_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
{
struct wined3d_rendertarget_view_gl *view_gl = wined3d_rendertarget_view_gl(view);
struct wined3d_device *device = view_gl->v.resource->device;
unsigned int swapchain_count = device->swapchain_count;
struct wined3d_resource *resource = view_gl->v.resource;
TRACE("view_gl %p.\n", view_gl);
/* Take a reference to the device, in case releasing the view's resource
* would cause the device to be destroyed. However, swapchain resources
* don't take a reference to the device, and we wouldn't want to increment
* the refcount on a device that's in the process of being destroyed. */
if (swapchain_count)
wined3d_device_incref(device);
/* Take a reference to the resource, in case releasing the resource
* would cause the device to be destroyed. */
wined3d_resource_incref(resource);
wined3d_rendertarget_view_cleanup(&view_gl->v);
wined3d_view_gl_destroy(device, &view_gl->gl_view, NULL, view_gl);
if (swapchain_count)
wined3d_device_decref(device);
wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, NULL, NULL, view_gl);
wined3d_resource_decref(resource);
}
static HRESULT adapter_gl_create_shader_resource_view(const struct wined3d_view_desc *desc,
@ -4859,22 +4858,20 @@ static HRESULT adapter_gl_create_shader_resource_view(const struct wined3d_view_
static void adapter_gl_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
{
struct wined3d_shader_resource_view_gl *view_gl = wined3d_shader_resource_view_gl(view);
struct wined3d_device *device = view_gl->v.resource->device;
unsigned int swapchain_count = device->swapchain_count;
struct wined3d_resource *resource = view_gl->v.resource;
TRACE("view_gl %p.\n", view_gl);
/* Take a reference to the device, in case releasing the view's resource
* would cause the device to be destroyed. However, swapchain resources
* don't take a reference to the device, and we wouldn't want to increment
* the refcount on a device that's in the process of being destroyed. */
if (swapchain_count)
wined3d_device_incref(device);
list_remove(&view_gl->bo_user.entry);
/* Take a reference to the resource. There are two reasons for this:
* - Releasing the resource could in turn cause the device to be
* destroyed, but we still need the device for
* wined3d_view_vk_destroy().
* - We shouldn't free buffer resources until after we've removed the
* view from its bo_user list. */
wined3d_resource_incref(resource);
wined3d_shader_resource_view_cleanup(&view_gl->v);
wined3d_view_gl_destroy(device, &view_gl->gl_view, NULL, view_gl);
if (swapchain_count)
wined3d_device_decref(device);
wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, NULL, view_gl);
wined3d_resource_decref(resource);
}
static HRESULT adapter_gl_create_unordered_access_view(const struct wined3d_view_desc *desc,
@ -4906,22 +4903,20 @@ static HRESULT adapter_gl_create_unordered_access_view(const struct wined3d_view
static void adapter_gl_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
{
struct wined3d_unordered_access_view_gl *view_gl = wined3d_unordered_access_view_gl(view);
struct wined3d_device *device = view_gl->v.resource->device;
unsigned int swapchain_count = device->swapchain_count;
struct wined3d_resource *resource = view_gl->v.resource;
TRACE("view_gl %p.\n", view_gl);
/* Take a reference to the device, in case releasing the view's resource
* would cause the device to be destroyed. However, swapchain resources
* don't take a reference to the device, and we wouldn't want to increment
* the refcount on a device that's in the process of being destroyed. */
if (swapchain_count)
wined3d_device_incref(device);
list_remove(&view_gl->bo_user.entry);
/* Take a reference to the resource. There are two reasons for this:
* - Releasing the resource could in turn cause the device to be
* destroyed, but we still need the device for
* wined3d_view_vk_destroy().
* - We shouldn't free buffer resources until after we've removed the
* view from its bo_user list. */
wined3d_resource_incref(resource);
wined3d_unordered_access_view_cleanup(&view_gl->v);
wined3d_view_gl_destroy(device, &view_gl->gl_view, &view_gl->counter_bo, view_gl);
if (swapchain_count)
wined3d_device_decref(device);
wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, &view_gl->counter_bo, view_gl);
wined3d_resource_decref(resource);
}
static HRESULT adapter_gl_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,

View File

@ -1304,6 +1304,7 @@ struct wined3d_view_vk_destroy_ctx
struct wined3d_device_vk *device_vk;
VkBufferView *vk_buffer_view;
VkImageView *vk_image_view;
struct wined3d_bo_user *bo_user;
struct wined3d_bo_vk *vk_counter_bo;
VkBufferView *vk_counter_view;
uint64_t *command_buffer_id;
@ -1350,6 +1351,8 @@ static void wined3d_view_vk_destroy_object(void *object)
TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_image_view));
}
}
if (ctx->bo_user)
list_remove(&ctx->bo_user->entry);
if (ctx->vk_counter_bo && ctx->vk_counter_bo->vk_buffer)
wined3d_context_vk_destroy_bo(wined3d_context_vk(context), ctx->vk_counter_bo);
if (ctx->vk_counter_view)
@ -1374,7 +1377,7 @@ static void wined3d_view_vk_destroy_object(void *object)
}
static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView *vk_buffer_view,
VkImageView *vk_image_view, struct wined3d_bo_vk *vk_counter_bo,
VkImageView *vk_image_view, struct wined3d_bo_user *bo_user, struct wined3d_bo_vk *vk_counter_bo,
VkBufferView *vk_counter_view, uint64_t *command_buffer_id, void *view_vk)
{
struct wined3d_view_vk_destroy_ctx *ctx, c;
@ -1384,6 +1387,7 @@ static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView
ctx->device_vk = wined3d_device_vk(device);
ctx->vk_buffer_view = vk_buffer_view;
ctx->vk_image_view = vk_image_view;
ctx->bo_user = bo_user;
ctx->vk_counter_bo = vk_counter_bo;
ctx->vk_counter_view = vk_counter_view;
ctx->command_buffer_id = command_buffer_id;
@ -1398,22 +1402,17 @@ static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView
static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
{
struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
struct wined3d_device *device = view_vk->v.resource->device;
unsigned int swapchain_count = device->swapchain_count;
struct wined3d_resource *resource = view_vk->v.resource;
TRACE("view_vk %p.\n", view_vk);
/* Take a reference to the device, in case releasing the view's resource
* would cause the device to be destroyed. However, swapchain resources
* don't take a reference to the device, and we wouldn't want to increment
* the refcount on a device that's in the process of being destroyed. */
if (swapchain_count)
wined3d_device_incref(device);
/* Take a reference to the resource, in case releasing the resource
* would cause the device to be destroyed. */
wined3d_resource_incref(resource);
wined3d_rendertarget_view_cleanup(&view_vk->v);
wined3d_view_vk_destroy(device, NULL, &view_vk->vk_image_view,
NULL, NULL, &view_vk->command_buffer_id, view_vk);
if (swapchain_count)
wined3d_device_decref(device);
wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view,
NULL, NULL, NULL, &view_vk->command_buffer_id, view_vk);
wined3d_resource_decref(resource);
}
static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
@ -1445,30 +1444,28 @@ static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_
static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
{
struct wined3d_shader_resource_view_vk *srv_vk = wined3d_shader_resource_view_vk(view);
struct wined3d_device *device = srv_vk->v.resource->device;
unsigned int swapchain_count = device->swapchain_count;
struct wined3d_resource *resource = srv_vk->v.resource;
struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
VkBufferView *vk_buffer_view = NULL;
VkImageView *vk_image_view = NULL;
TRACE("srv_vk %p.\n", srv_vk);
/* Take a reference to the device, in case releasing the view's resource
* would cause the device to be destroyed. However, swapchain resources
* don't take a reference to the device, and we wouldn't want to increment
* the refcount on a device that's in the process of being destroyed. */
if (swapchain_count)
wined3d_device_incref(device);
if (srv_vk->v.resource->type == WINED3D_RTYPE_BUFFER)
/* Take a reference to the resource. There are two reasons for this:
* - Releasing the resource could in turn cause the device to be
* destroyed, but we still need the device for
* wined3d_view_vk_destroy().
* - We shouldn't free buffer resources until after we've removed the
* view from its bo_user list. */
wined3d_resource_incref(resource);
if (resource->type == WINED3D_RTYPE_BUFFER)
vk_buffer_view = &view_vk->u.vk_buffer_view;
else
vk_image_view = &view_vk->u.vk_image_info.imageView;
list_remove(&view_vk->bo_user.entry);
wined3d_shader_resource_view_cleanup(&srv_vk->v);
wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view,
NULL, NULL, &view_vk->command_buffer_id, srv_vk);
if (swapchain_count)
wined3d_device_decref(device);
wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view,
&view_vk->bo_user, NULL, NULL, &view_vk->command_buffer_id, srv_vk);
wined3d_resource_decref(resource);
}
static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
@ -1500,30 +1497,28 @@ static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view
static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
{
struct wined3d_unordered_access_view_vk *uav_vk = wined3d_unordered_access_view_vk(view);
struct wined3d_device *device = uav_vk->v.resource->device;
unsigned int swapchain_count = device->swapchain_count;
struct wined3d_resource *resource = uav_vk->v.resource;
struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
VkBufferView *vk_buffer_view = NULL;
VkImageView *vk_image_view = NULL;
TRACE("uav_vk %p.\n", uav_vk);
/* Take a reference to the device, in case releasing the view's resource
* would cause the device to be destroyed. However, swapchain resources
* don't take a reference to the device, and we wouldn't want to increment
* the refcount on a device that's in the process of being destroyed. */
if (swapchain_count)
wined3d_device_incref(device);
if (uav_vk->v.resource->type == WINED3D_RTYPE_BUFFER)
/* Take a reference to the resource. There are two reasons for this:
* - Releasing the resource could in turn cause the device to be
* destroyed, but we still need the device for
* wined3d_view_vk_destroy().
* - We shouldn't free buffer resources until after we've removed the
* view from its bo_user list. */
wined3d_resource_incref(resource);
if (resource->type == WINED3D_RTYPE_BUFFER)
vk_buffer_view = &view_vk->u.vk_buffer_view;
else
vk_image_view = &view_vk->u.vk_image_info.imageView;
list_remove(&view_vk->bo_user.entry);
wined3d_unordered_access_view_cleanup(&uav_vk->v);
wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view, &uav_vk->counter_bo,
&uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk);
if (swapchain_count)
wined3d_device_decref(device);
wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view, &view_vk->bo_user,
&uav_vk->counter_bo, &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk);
wined3d_resource_decref(resource);
}
static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,