[PATCH 5/8] wined3d: Protect access to the Vulkan wined3d_allocator with a critical section.

Zebediah Figura zfigura at codeweavers.com
Tue Nov 2 18:20:10 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/wined3d/adapter_vk.c      |  9 +++++++++
 dlls/wined3d/context_vk.c      | 31 +++++++++++++++++++++++++++----
 dlls/wined3d/wined3d_private.h |  1 +
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 218b7dc74ba..020a70b4ed4 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -517,6 +517,10 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
 #undef VK_DEVICE_EXT_PFN
 #undef VK_DEVICE_PFN
 
+    InitializeCriticalSection(&device_vk->allocator_cs);
+    if (device_vk->allocator_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1)
+        device_vk->allocator_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wined3d_device_vk.allocator_cs");
+
     if (!wined3d_allocator_init(&device_vk->allocator,
             adapter_vk->memory_properties.memoryTypeCount, &wined3d_allocator_vk_ops))
     {
@@ -551,6 +555,11 @@ static void adapter_vk_destroy_device(struct wined3d_device *device)
 
     wined3d_device_cleanup(&device_vk->d);
     wined3d_allocator_cleanup(&device_vk->allocator);
+
+    if (device_vk->allocator_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1)
+        device_vk->allocator_cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection(&device_vk->allocator_cs);
+
     VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
     heap_free(device_vk);
 }
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index a6a2ea8a44b..21239bd74b9 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -312,23 +312,36 @@ static struct wined3d_allocator_block *wined3d_device_vk_allocate_memory(struct
     struct wined3d_allocator *allocator = &device_vk->allocator;
     struct wined3d_allocator_block *block;
 
+    EnterCriticalSection(&device_vk->allocator_cs);
+
     if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
     {
         *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
+        LeaveCriticalSection(&device_vk->allocator_cs);
         return NULL;
     }
 
     if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
     {
+        LeaveCriticalSection(&device_vk->allocator_cs);
         *vk_memory = VK_NULL_HANDLE;
         return NULL;
     }
 
     *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
 
+    LeaveCriticalSection(&device_vk->allocator_cs);
     return block;
 }
 
+static void wined3d_device_vk_free_memory(struct wined3d_device_vk *device_vk, struct wined3d_allocator_block *block)
+{
+    assert(block->chunk->allocator == &device_vk->allocator);
+    EnterCriticalSection(&device_vk->allocator_cs);
+    wined3d_allocator_block_free(block);
+    LeaveCriticalSection(&device_vk->allocator_cs);
+}
+
 static bool wined3d_device_vk_create_slab_bo(struct wined3d_device_vk *device_vk, struct wined3d_context_vk *context_vk,
         VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
 {
@@ -359,6 +372,8 @@ static bool wined3d_device_vk_create_slab_bo(struct wined3d_device_vk *device_vk
     key.usage = usage;
     key.size = 32 * object_size;
 
+    EnterCriticalSection(&device_vk->allocator_cs);
+
     if ((entry = wine_rb_get(&device_vk->bo_slab_available, &key)))
     {
         slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
@@ -368,6 +383,7 @@ static bool wined3d_device_vk_create_slab_bo(struct wined3d_device_vk *device_vk
     {
         if (!(slab = heap_alloc_zero(sizeof(*slab))))
         {
+            LeaveCriticalSection(&device_vk->allocator_cs);
             ERR("Failed to allocate bo slab.\n");
             return false;
         }
@@ -375,6 +391,7 @@ static bool wined3d_device_vk_create_slab_bo(struct wined3d_device_vk *device_vk
         slab->requested_memory_type = memory_type;
         if (!wined3d_device_vk_create_bo(device_vk, context_vk, key.size, usage, memory_type, &slab->bo))
         {
+            LeaveCriticalSection(&device_vk->allocator_cs);
             ERR("Failed to create slab bo.\n");
             heap_free(slab);
             return false;
@@ -406,6 +423,8 @@ static bool wined3d_device_vk_create_slab_bo(struct wined3d_device_vk *device_vk
         }
     }
 
+    LeaveCriticalSection(&device_vk->allocator_cs);
+
     *bo = slab->bo;
     bo->memory = NULL;
     bo->slab = slab;
@@ -478,7 +497,7 @@ BOOL wined3d_device_vk_create_bo(struct wined3d_device_vk *device_vk, struct win
     {
         ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
         if (bo->memory)
-            wined3d_allocator_block_free(bo->memory);
+            wined3d_device_vk_free_memory(device_vk, bo->memory);
         else
             VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
         VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
@@ -572,7 +591,7 @@ BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkIm
     {
         VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
         if (image->memory)
-            wined3d_allocator_block_free(image->memory);
+            wined3d_device_vk_free_memory(device_vk, image->memory);
         else
             VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL));
         ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr));
@@ -686,7 +705,7 @@ void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *conte
 
     if (context_vk->completed_command_buffer_id > command_buffer_id)
     {
-        wined3d_allocator_block_free(block);
+        wined3d_device_vk_free_memory(wined3d_device_vk(context_vk->c.device), block);
         TRACE("Freed block %p.\n", block);
         return;
     }
@@ -711,6 +730,8 @@ static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
 
     TRACE("slab %p, idx %lu, context_vk %p.\n", slab, idx, context_vk);
 
+    EnterCriticalSection(&device_vk->allocator_cs);
+
     if (!slab->map)
     {
         key.memory_type = slab->requested_memory_type;
@@ -728,6 +749,8 @@ static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
         }
     }
     slab->map |= 1u << idx;
+
+    LeaveCriticalSection(&device_vk->allocator_cs);
 }
 
 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
@@ -999,7 +1022,7 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
 
             case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
                 TRACE("Destroying block %p.\n", o->u.block);
-                wined3d_allocator_block_free(o->u.block);
+                wined3d_device_vk_free_memory(device_vk, o->u.block);
                 break;
 
             case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d8b16c0d074..21b4ef2e103 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4081,6 +4081,7 @@ struct wined3d_device_vk
     struct wined3d_null_resources_vk null_resources_vk;
     struct wined3d_null_views_vk null_views_vk;
 
+    CRITICAL_SECTION allocator_cs;
     struct wined3d_allocator allocator;
 
     struct wined3d_uav_clear_state_vk uav_clear_state;
-- 
2.33.0




More information about the wine-devel mailing list