wined3d: Decrement reference count and take the lock atomically for cached objects.
Samplers, blend states, rasterizer states and depth stencil states can be retrieved from the cache in struct d3d_device even after the reference count reaches zero, causing memory corruption. Signed-off-by: Jan Sikorski <jsikorski@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1886b3d322
commit
996728315a
|
@ -34,13 +34,12 @@ ULONG CDECL wined3d_sampler_incref(struct wined3d_sampler *sampler)
|
||||||
|
|
||||||
ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler)
|
ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler)
|
||||||
{
|
{
|
||||||
ULONG refcount = InterlockedDecrement(&sampler->refcount);
|
ULONG refcount = wined3d_atomic_decrement_mutex_lock(&sampler->refcount);
|
||||||
|
|
||||||
TRACE("%p decreasing refcount to %u.\n", sampler, refcount);
|
TRACE("%p decreasing refcount to %u.\n", sampler, refcount);
|
||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
wined3d_mutex_lock();
|
|
||||||
sampler->parent_ops->wined3d_object_destroyed(sampler->parent);
|
sampler->parent_ops->wined3d_object_destroyed(sampler->parent);
|
||||||
sampler->device->adapter->adapter_ops->adapter_destroy_sampler(sampler);
|
sampler->device->adapter->adapter_ops->adapter_destroy_sampler(sampler);
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
|
|
@ -51,14 +51,13 @@ static void wined3d_blend_state_destroy_object(void *object)
|
||||||
|
|
||||||
ULONG CDECL wined3d_blend_state_decref(struct wined3d_blend_state *state)
|
ULONG CDECL wined3d_blend_state_decref(struct wined3d_blend_state *state)
|
||||||
{
|
{
|
||||||
ULONG refcount = InterlockedDecrement(&state->refcount);
|
ULONG refcount = wined3d_atomic_decrement_mutex_lock(&state->refcount);
|
||||||
struct wined3d_device *device = state->device;
|
struct wined3d_device *device = state->device;
|
||||||
|
|
||||||
TRACE("%p decreasing refcount to %u.\n", state, refcount);
|
TRACE("%p decreasing refcount to %u.\n", state, refcount);
|
||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
wined3d_mutex_lock();
|
|
||||||
state->parent_ops->wined3d_object_destroyed(state->parent);
|
state->parent_ops->wined3d_object_destroyed(state->parent);
|
||||||
wined3d_cs_destroy_object(device->cs, wined3d_blend_state_destroy_object, state);
|
wined3d_cs_destroy_object(device->cs, wined3d_blend_state_destroy_object, state);
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
@ -127,14 +126,13 @@ static void wined3d_depth_stencil_state_destroy_object(void *object)
|
||||||
|
|
||||||
ULONG CDECL wined3d_depth_stencil_state_decref(struct wined3d_depth_stencil_state *state)
|
ULONG CDECL wined3d_depth_stencil_state_decref(struct wined3d_depth_stencil_state *state)
|
||||||
{
|
{
|
||||||
ULONG refcount = InterlockedDecrement(&state->refcount);
|
ULONG refcount = wined3d_atomic_decrement_mutex_lock(&state->refcount);
|
||||||
struct wined3d_device *device = state->device;
|
struct wined3d_device *device = state->device;
|
||||||
|
|
||||||
TRACE("%p decreasing refcount to %u.\n", state, refcount);
|
TRACE("%p decreasing refcount to %u.\n", state, refcount);
|
||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
wined3d_mutex_lock();
|
|
||||||
state->parent_ops->wined3d_object_destroyed(state->parent);
|
state->parent_ops->wined3d_object_destroyed(state->parent);
|
||||||
wined3d_cs_destroy_object(device->cs, wined3d_depth_stencil_state_destroy_object, state);
|
wined3d_cs_destroy_object(device->cs, wined3d_depth_stencil_state_destroy_object, state);
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
@ -192,14 +190,13 @@ static void wined3d_rasterizer_state_destroy_object(void *object)
|
||||||
|
|
||||||
ULONG CDECL wined3d_rasterizer_state_decref(struct wined3d_rasterizer_state *state)
|
ULONG CDECL wined3d_rasterizer_state_decref(struct wined3d_rasterizer_state *state)
|
||||||
{
|
{
|
||||||
ULONG refcount = InterlockedDecrement(&state->refcount);
|
ULONG refcount = wined3d_atomic_decrement_mutex_lock(&state->refcount);
|
||||||
struct wined3d_device *device = state->device;
|
struct wined3d_device *device = state->device;
|
||||||
|
|
||||||
TRACE("%p decreasing refcount to %u.\n", state, refcount);
|
TRACE("%p decreasing refcount to %u.\n", state, refcount);
|
||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
wined3d_mutex_lock();
|
|
||||||
state->parent_ops->wined3d_object_destroyed(state->parent);
|
state->parent_ops->wined3d_object_destroyed(state->parent);
|
||||||
wined3d_cs_destroy_object(device->cs, wined3d_rasterizer_state_destroy_object, state);
|
wined3d_cs_destroy_object(device->cs, wined3d_rasterizer_state_destroy_object, state);
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
|
|
@ -4155,6 +4155,26 @@ const char *wined3d_debug_view_desc(const struct wined3d_view_desc *d,
|
||||||
const struct wined3d_resource *resource) DECLSPEC_HIDDEN;
|
const struct wined3d_resource *resource) DECLSPEC_HIDDEN;
|
||||||
const char *wined3d_debug_vkresult(VkResult vr) DECLSPEC_HIDDEN;
|
const char *wined3d_debug_vkresult(VkResult vr) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
static inline ULONG wined3d_atomic_decrement_mutex_lock(volatile LONG *refcount)
|
||||||
|
{
|
||||||
|
ULONG count, old_count = *refcount;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((count = old_count) == 1)
|
||||||
|
{
|
||||||
|
wined3d_mutex_lock();
|
||||||
|
count = InterlockedDecrement(refcount);
|
||||||
|
if (count) wined3d_mutex_unlock();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_count = InterlockedCompareExchange(refcount, count - 1, count);
|
||||||
|
}
|
||||||
|
while (old_count != count);
|
||||||
|
|
||||||
|
return count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct wined3d_client_resource
|
struct wined3d_client_resource
|
||||||
{
|
{
|
||||||
/* The resource's persistently mapped address, which we may use to perform
|
/* The resource's persistently mapped address, which we may use to perform
|
||||||
|
|
Loading…
Reference in New Issue