[PATCH v4 2/2] vkd3d: Don't allow concurrent writes to descriptors.

Derek Lesho dlesho at codeweavers.com
Wed Sep 18 15:58:18 CDT 2019


In D3D12 it is legal to concurrently overwrite descriptors, we can't handle that.
This patch locks descriptors that share an underlying view from being written to
at the same time.

Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
v4: Instead of locking descriptors and moving lock pointers to the destination
descriptors, this version ensures that the minimal amount of descriptors are
grouped synchronized by storing the locks in vkd3d_view instead.  My initial testing
shows this allows us to spend half as much time waiting as in v3, and a fourth as
much time waiting as an implementation that locks the whole heap on write.
---
 libs/vkd3d/resource.c      | 307 ++++++++++++++++++++++++++-----------
 libs/vkd3d/vkd3d_private.h |   5 +-
 2 files changed, 219 insertions(+), 93 deletions(-)

diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 463f373..a43f6fa 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -1881,6 +1881,7 @@ static struct vkd3d_view *vkd3d_view_create(void)
     if ((view = vkd3d_malloc(sizeof(*view))))
     {
         view->refcount = 1;
+        pthread_spin_init(&view->lock, PTHREAD_PROCESS_PRIVATE);
         view->vk_counter_view = VK_NULL_HANDLE;
     }
     return view;
@@ -1891,25 +1892,24 @@ void vkd3d_view_incref(struct vkd3d_view *view)
     InterlockedIncrement(&view->refcount);
 }
 
-static void vkd3d_view_decref_descriptor(struct vkd3d_view *view,
-        const struct d3d12_desc *descriptor, struct d3d12_device *device)
+int vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device)
 {
     const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
     ULONG refcount = InterlockedDecrement(&view->refcount);
 
     if (refcount)
-        return;
+        return true;
 
     TRACE("Destroying view %p.\n", view);
 
-    if (!descriptor)
+    if (view->type == VKD3D_DESCRIPTOR_MAGIC_RTV || view->type == VKD3D_DESCRIPTOR_MAGIC_DSV)
     {
         VK_CALL(vkDestroyImageView(device->vk_device, view->u.vk_image_view, NULL));
     }
-    else if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SRV || descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV)
+    else if (view->type == VKD3D_DESCRIPTOR_MAGIC_SRV || view->type == VKD3D_DESCRIPTOR_MAGIC_UAV)
     {
-        if (descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
-                || descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
+        if (view->vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
+                || view->vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
             VK_CALL(vkDestroyBufferView(device->vk_device, view->u.vk_buffer_view, NULL));
         else
             VK_CALL(vkDestroyImageView(device->vk_device, view->u.vk_image_view, NULL));
@@ -1917,17 +1917,16 @@ static void vkd3d_view_decref_descriptor(struct vkd3d_view *view,
         if (view->vk_counter_view)
             VK_CALL(vkDestroyBufferView(device->vk_device, view->vk_counter_view, NULL));
     }
-    else if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
+    else if (view->type == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
     {
         VK_CALL(vkDestroySampler(device->vk_device, view->u.vk_sampler, NULL));
     }
 
-    vkd3d_free(view);
-}
+    pthread_spin_unlock(&view->lock);
+    pthread_spin_destroy(&view->lock);
 
-void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device)
-{
-    vkd3d_view_decref_descriptor(view, NULL, device);
+    vkd3d_free(view);
+    return false;
 }
 
 static void d3d12_desc_destroy(struct d3d12_desc *descriptor,
@@ -1938,19 +1937,41 @@ static void d3d12_desc_destroy(struct d3d12_desc *descriptor,
             || descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV
             || descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
     {
-        vkd3d_view_decref_descriptor(descriptor->u.view, descriptor, device);
+        vkd3d_view_decref(descriptor->u.view, device);
     }
+}
+
+static struct vkd3d_view *d3d12_desc_grab_view(struct d3d12_desc *desc, struct d3d12_device *device)
+{
+    pthread_spinlock_t *lock = NULL;
 
-    memset(descriptor, 0, sizeof(*descriptor));
+    while (desc->magic && desc->magic != VKD3D_DESCRIPTOR_MAGIC_CBV)
+    {
+        if (!(pthread_spin_trylock(lock = &desc->u.view->lock)))
+        {
+            /* we successfully acquired the lock */
+            vkd3d_view_incref(desc->u.view);
+            return desc->u.view;
+        }
+
+        /* if we can't acquire it right away, wait for it then try again w/ the new view pointer */
+        pthread_spin_lock(lock);
+        pthread_spin_unlock(lock);
+    }
+    
+    return NULL;
 }
 
 void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src,
         struct d3d12_device *device)
 {
+    struct vkd3d_view *dst_view;
+
     assert(dst != src);
 
-    d3d12_desc_destroy(dst, device);
+    dst_view = d3d12_desc_grab_view(dst, device);
 
+    d3d12_desc_destroy(dst, device);
     *dst = *src;
 
     if (src->magic == VKD3D_DESCRIPTOR_MAGIC_SRV
@@ -1959,6 +1980,10 @@ void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src,
     {
         vkd3d_view_incref(src->u.view);
     }
+
+    if (dst_view)
+        if (vkd3d_view_decref(dst_view, device))
+            pthread_spin_unlock(&dst_view->lock);
 }
 
 static VkDeviceSize vkd3d_get_required_texel_buffer_alignment(const struct d3d12_device *device,
@@ -2322,22 +2347,22 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
 {
     struct VkDescriptorBufferInfo *buffer_info;
     struct d3d12_resource *resource;
-
-    d3d12_desc_destroy(descriptor, device);
+    struct d3d12_desc new_desc = {};
+    struct vkd3d_view *prev_view;
 
     if (!desc)
     {
         WARN("Constant buffer desc is NULL.\n");
-        return;
+        goto done;
     }
 
     if (desc->SizeInBytes & (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1))
     {
         WARN("Size is not %u bytes aligned.\n", D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
-        return;
+        goto done;
     }
 
-    buffer_info = &descriptor->u.vk_cbv_info;
+    buffer_info = &new_desc.u.vk_cbv_info;
     if (desc->BufferLocation)
     {
         resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, desc->BufferLocation);
@@ -2353,8 +2378,18 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
         buffer_info->range = VKD3D_NULL_BUFFER_SIZE;
     }
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_CBV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+    new_desc.magic = VKD3D_DESCRIPTOR_MAGIC_CBV;
+    new_desc.vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+
+    done:
+    prev_view = d3d12_desc_grab_view(descriptor, device);
+
+    d3d12_desc_destroy(descriptor, device);
+    *descriptor = new_desc;
+
+    if (prev_view)
+        if (vkd3d_view_decref(prev_view, device))
+            pthread_spin_unlock(&prev_view->lock);
 }
 
 static unsigned int vkd3d_view_flags_from_d3d12_buffer_srv_flags(D3D12_BUFFER_SRV_FLAGS flags)
@@ -2425,8 +2460,8 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor,
     if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
         return;
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+    descriptor->magic = view->type = VKD3D_DESCRIPTOR_MAGIC_SRV;
+    descriptor->vk_descriptor_type = view->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
     descriptor->u.view = view;
 }
 
@@ -2455,8 +2490,8 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
             desc->u.Buffer.StructureByteStride, flags, &view))
         return;
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+    descriptor->magic = view->type = VKD3D_DESCRIPTOR_MAGIC_SRV;
+    descriptor->vk_descriptor_type = view->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
     descriptor->u.view = view;
 }
 
@@ -2465,24 +2500,23 @@ void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
         const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
 {
     struct vkd3d_texture_view_desc vkd3d_desc;
-    struct vkd3d_view *view;
-
-    d3d12_desc_destroy(descriptor, device);
+    struct vkd3d_view *view, *prev_view;
+    struct d3d12_desc new_desc = {};
 
     if (!resource)
     {
-        vkd3d_create_null_srv(descriptor, device, desc);
-        return;
+        vkd3d_create_null_srv(&new_desc, device, desc);
+        goto done;
     }
 
     if (d3d12_resource_is_buffer(resource))
     {
-        vkd3d_create_buffer_srv(descriptor, device, resource, desc);
-        return;
+        vkd3d_create_buffer_srv(&new_desc, device, resource, desc);
+        goto done;
     }
 
     if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
-        return;
+        goto done;
 
     vkd3d_desc.miplevel_count = VK_REMAINING_MIP_LEVELS;
     vkd3d_desc.allowed_swizzle = true;
@@ -2559,11 +2593,21 @@ void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
     }
 
     if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
-        return;
+        goto done;
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
-    descriptor->u.view = view;
+    new_desc.magic = view->type = VKD3D_DESCRIPTOR_MAGIC_SRV;
+    new_desc.vk_descriptor_type = view->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+    new_desc.u.view = view;
+
+    done:
+    prev_view = d3d12_desc_grab_view(descriptor, device);
+
+    d3d12_desc_destroy(descriptor, device);
+    *descriptor = new_desc;
+
+    if (prev_view)
+        if (vkd3d_view_decref(prev_view, device))
+            pthread_spin_unlock(&prev_view->lock);
 }
 
 static unsigned int vkd3d_view_flags_from_d3d12_buffer_uav_flags(D3D12_BUFFER_UAV_FLAGS flags)
@@ -2634,8 +2678,8 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor,
     if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
         return;
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+    descriptor->magic = view->type = VKD3D_DESCRIPTOR_MAGIC_UAV;
+    descriptor->vk_descriptor_type = view->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
     descriptor->u.view = view;
 }
 
@@ -2667,8 +2711,8 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
             desc->u.Buffer.StructureByteStride, flags, &view))
         return;
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+    descriptor->magic = view->type = VKD3D_DESCRIPTOR_MAGIC_UAV;
+    descriptor->vk_descriptor_type = view->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
     descriptor->u.view = view;
 
     if (counter_resource)
@@ -2685,6 +2729,7 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
             WARN("Failed to create counter buffer view.\n");
             view->vk_counter_view = VK_NULL_HANDLE;
             d3d12_desc_destroy(descriptor, device);
+            memset(descriptor, 0, sizeof(*descriptor));
         }
     }
 
@@ -2747,8 +2792,8 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
     if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
         return;
 
-    descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
-    descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+    descriptor->magic = view->type = VKD3D_DESCRIPTOR_MAGIC_UAV;
+    descriptor->vk_descriptor_type = view->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
     descriptor->u.view = view;
 
     descriptor->uav.texture.vk_aspect_mask = vkd3d_desc.format->vk_aspect_mask;
@@ -2761,26 +2806,37 @@ void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *d
         struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
         const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
 {
-    d3d12_desc_destroy(descriptor, device);
+    struct d3d12_desc new_desc = {};
+    struct vkd3d_view *prev_view;
 
     if (!resource)
     {
         if (counter_resource)
             FIXME("Ignoring counter resource %p.\n", counter_resource);
-        vkd3d_create_null_uav(descriptor, device, desc);
-        return;
+        vkd3d_create_null_uav(&new_desc, device, desc);
+        goto done;
     }
 
     if (d3d12_resource_is_buffer(resource))
     {
-        vkd3d_create_buffer_uav(descriptor, device, resource, counter_resource, desc);
+        vkd3d_create_buffer_uav(&new_desc, device, resource, counter_resource, desc);
     }
     else
     {
         if (counter_resource)
             FIXME("Unexpected counter resource for texture view.\n");
-        vkd3d_create_texture_uav(descriptor, device, resource, desc);
+        vkd3d_create_texture_uav(&new_desc, device, resource, desc);
     }
+
+    done:
+    prev_view = d3d12_desc_grab_view(descriptor, device);
+
+    d3d12_desc_destroy(descriptor, device);
+    *descriptor = new_desc;
+
+    if (prev_view)
+        if (vkd3d_view_decref(prev_view, device))
+            pthread_spin_unlock(&prev_view->lock);
 }
 
 bool vkd3d_create_raw_buffer_view(struct d3d12_device *device,
@@ -2887,14 +2943,13 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f
 void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
         struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc)
 {
-    struct vkd3d_view *view;
-
-    d3d12_desc_destroy(sampler, device);
+    struct vkd3d_view *view, *prev_view;
+    struct d3d12_desc new_sampler = {};
 
     if (!desc)
     {
         WARN("NULL sampler desc.\n");
-        return;
+        goto done;
     }
 
     if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
@@ -2904,19 +2959,29 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
                 desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]);
 
     if (!(view = vkd3d_view_create()))
-        return;
+        goto done;
 
     if (d3d12_create_sampler(device, desc->Filter, desc->AddressU,
             desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
             desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->u.vk_sampler) < 0)
     {
         vkd3d_free(view);
-        return;
+        goto done;
     }
 
-    sampler->magic = VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
-    sampler->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLER;
-    sampler->u.view = view;
+    new_sampler.magic = view->type = VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
+    new_sampler.vk_descriptor_type = view->vk_descriptor_type =  VK_DESCRIPTOR_TYPE_SAMPLER;
+    new_sampler.u.view = view;
+
+    done:
+    prev_view = d3d12_desc_grab_view(sampler, device);
+
+    d3d12_desc_destroy(sampler, device);
+    *sampler = new_sampler;
+
+    if (prev_view)
+        if (vkd3d_view_decref(prev_view, device))
+            pthread_spin_unlock(&prev_view->lock);
 }
 
 HRESULT vkd3d_create_static_sampler(struct d3d12_device *device,
@@ -2942,30 +3007,49 @@ static void d3d12_rtv_desc_destroy(struct d3d12_rtv_desc *rtv, struct d3d12_devi
         return;
 
     vkd3d_view_decref(rtv->view, device);
-    memset(rtv, 0, sizeof(*rtv));
+}
+
+static struct vkd3d_view *d3d12_rtv_desc_grab_view(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device)
+{
+    pthread_spinlock_t *lock;
+
+    while (rtv_desc->view)
+    {
+        if (!(pthread_spin_trylock(lock = &rtv_desc->view->lock)))
+        {
+            /* we successfully picked up the lock */
+            vkd3d_view_incref(rtv_desc->view);
+            return rtv_desc->view;
+        }
+
+        /* if we can't acquire it right away, wait for it then try again w/ the new view pointer */
+        pthread_spin_lock(lock);
+        pthread_spin_unlock(lock);
+    }
+    
+    return NULL;
 }
 
 void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device,
         struct d3d12_resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc)
 {
     struct vkd3d_texture_view_desc vkd3d_desc;
-    struct vkd3d_view *view;
-
-    d3d12_rtv_desc_destroy(rtv_desc, device);
+    struct vkd3d_view *view, *prev_view;
+    struct d3d12_rtv_desc new_rtv_desc = {};
 
     if (!resource)
     {
         FIXME("NULL resource RTV not implemented.\n");
-        return;
+        goto done;
     }
 
     if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
-        return;
+        goto done;
 
     if (vkd3d_desc.format->vk_aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
     {
         WARN("Trying to create RTV for depth/stencil format %#x.\n", vkd3d_desc.format->dxgi_format);
-        return;
+        goto done;
     }
 
     if (desc)
@@ -3013,16 +3097,26 @@ void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_dev
     assert(d3d12_resource_is_texture(resource));
 
     if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
-        return;
+        goto done;
+
+    new_rtv_desc.magic = view->type = VKD3D_DESCRIPTOR_MAGIC_RTV;
+    new_rtv_desc.sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
+    new_rtv_desc.format = vkd3d_desc.format;
+    new_rtv_desc.width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
+    new_rtv_desc.height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
+    new_rtv_desc.layer_count = vkd3d_desc.layer_count;
+    new_rtv_desc.view = view;
+    new_rtv_desc.resource = resource;
+
+    done:
+    prev_view = d3d12_rtv_desc_grab_view(rtv_desc, device);
 
-    rtv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_RTV;
-    rtv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
-    rtv_desc->format = vkd3d_desc.format;
-    rtv_desc->width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
-    rtv_desc->height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
-    rtv_desc->layer_count = vkd3d_desc.layer_count;
-    rtv_desc->view = view;
-    rtv_desc->resource = resource;
+    d3d12_rtv_desc_destroy(rtv_desc, device);
+    *rtv_desc = new_rtv_desc;
+
+    if (prev_view)
+        if (vkd3d_view_decref(prev_view, device))
+            pthread_spin_unlock(&prev_view->lock);
 }
 
 /* DSVs */
@@ -3032,36 +3126,55 @@ static void d3d12_dsv_desc_destroy(struct d3d12_dsv_desc *dsv, struct d3d12_devi
         return;
 
     vkd3d_view_decref(dsv->view, device);
-    memset(dsv, 0, sizeof(*dsv));
+}
+
+static struct vkd3d_view *d3d12_dsv_desc_grab_view(struct d3d12_dsv_desc *dsv_desc, struct d3d12_device *device)
+{
+    pthread_spinlock_t *lock;
+    
+    while (dsv_desc->view)
+    {
+        if (!(pthread_spin_trylock(lock = &dsv_desc->view->lock)))
+        {
+            /* we successfully picked up the lock */
+            vkd3d_view_incref(dsv_desc->view);
+            return dsv_desc->view;
+        }
+
+        /* if we can't acquire it right away, wait for it then try again w/ the new view pointer */
+        pthread_spin_lock(lock);
+        pthread_spin_unlock(lock);
+    }
+    
+    return NULL;
 }
 
 void d3d12_dsv_desc_create_dsv(struct d3d12_dsv_desc *dsv_desc, struct d3d12_device *device,
         struct d3d12_resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc)
 {
     struct vkd3d_texture_view_desc vkd3d_desc;
-    struct vkd3d_view *view;
-
-    d3d12_dsv_desc_destroy(dsv_desc, device);
+    struct vkd3d_view *view, *prev_view;
+    struct d3d12_dsv_desc new_dsv_desc = {};
 
     if (!resource)
     {
         FIXME("NULL resource DSV not implemented.\n");
-        return;
+        goto done;
     }
 
     if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
     {
         WARN("Cannot create DSV for 3D texture.\n");
-        return;
+        goto done;
     }
 
     if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
-        return;
+        goto done;
 
     if (!(vkd3d_desc.format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
     {
         WARN("Trying to create DSV for format %#x.\n", vkd3d_desc.format->dxgi_format);
-        return;
+        goto done;
     }
 
     if (desc)
@@ -3096,16 +3209,26 @@ void d3d12_dsv_desc_create_dsv(struct d3d12_dsv_desc *dsv_desc, struct d3d12_dev
     assert(d3d12_resource_is_texture(resource));
 
     if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
-        return;
+        goto done;
+
+    new_dsv_desc.magic = view->type = VKD3D_DESCRIPTOR_MAGIC_DSV;
+    new_dsv_desc.sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
+    new_dsv_desc.format = vkd3d_desc.format;
+    new_dsv_desc.width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
+    new_dsv_desc.height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
+    new_dsv_desc.layer_count = vkd3d_desc.layer_count;
+    new_dsv_desc.view = view;
+    new_dsv_desc.resource = resource;
+
+    done:
+    prev_view = d3d12_dsv_desc_grab_view(dsv_desc, device);
+
+    d3d12_dsv_desc_destroy(dsv_desc, device);
+    *dsv_desc = new_dsv_desc;
 
-    dsv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_DSV;
-    dsv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
-    dsv_desc->format = vkd3d_desc.format;
-    dsv_desc->width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
-    dsv_desc->height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
-    dsv_desc->layer_count = vkd3d_desc.layer_count;
-    dsv_desc->view = view;
-    dsv_desc->resource = resource;
+    if (prev_view)
+        if (vkd3d_view_decref(prev_view, device))
+            pthread_spin_unlock(&prev_view->lock);
 }
 
 /* ID3D12DescriptorHeap */
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index bd9670e..3c4daff 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -451,6 +451,9 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device,
 struct vkd3d_view
 {
     LONG refcount;
+    pthread_spinlock_t lock;
+    uint32_t type;
+    VkDescriptorType vk_descriptor_type;
     union
     {
         VkBufferView vk_buffer_view;
@@ -460,7 +463,7 @@ struct vkd3d_view
     VkBufferView vk_counter_view;
 };
 
-void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device) DECLSPEC_HIDDEN;
+int vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device) DECLSPEC_HIDDEN;
 void vkd3d_view_incref(struct vkd3d_view *view) DECLSPEC_HIDDEN;
 
 struct d3d12_desc
-- 
2.23.0




More information about the wine-devel mailing list