[PATCH v2 1/7] wined3d: Protect access to the Vulkan wined3d_allocator with a mutex.

Zebediah Figura zfigura at codeweavers.com
Wed Nov 3 23:46:55 CDT 2021


So that it can be accessed from the client thread.

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

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 02a359c4f07..cbf7c94fd3a 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -521,6 +521,10 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
         goto fail;
     }
 
+    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");
+
     *device = &device_vk->d;
 
     return WINED3D_OK;
@@ -538,6 +542,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 ad7b0a8ba86..54c5eb6bc24 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -313,27 +313,43 @@ static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct
     struct wined3d_allocator *allocator = &device_vk->allocator;
     struct wined3d_allocator_block *block;
 
+    wined3d_device_vk_allocator_lock(device_vk);
+
     if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
     {
         *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
+        wined3d_device_vk_allocator_unlock(device_vk);
         return NULL;
     }
 
     if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
     {
+        wined3d_device_vk_allocator_unlock(device_vk);
         *vk_memory = VK_NULL_HANDLE;
         return NULL;
     }
 
     *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
 
+    wined3d_device_vk_allocator_unlock(device_vk);
     return block;
 }
 
+static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block)
+{
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+
+    assert(block->chunk->allocator == &device_vk->allocator);
+    wined3d_device_vk_allocator_lock(device_vk);
+    wined3d_allocator_block_free(block);
+    wined3d_device_vk_allocator_unlock(device_vk);
+}
+
 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
         VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
 {
     const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
     const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
     struct wined3d_bo_slab_vk_key key;
     struct wined3d_bo_slab_vk *slab;
@@ -360,6 +376,8 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context
     key.usage = usage;
     key.size = 32 * object_size;
 
+    wined3d_device_vk_allocator_lock(device_vk);
+
     if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
     {
         slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
@@ -369,27 +387,30 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context
     {
         if (!(slab = heap_alloc_zero(sizeof(*slab))))
         {
+            wined3d_device_vk_allocator_unlock(device_vk);
             ERR("Failed to allocate bo slab.\n");
             return false;
         }
 
+        if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
+        {
+            wined3d_device_vk_allocator_unlock(device_vk);
+            ERR("Failed to add slab to available tree.\n");
+            heap_free(slab);
+            return false;
+        }
+
         slab->requested_memory_type = memory_type;
         if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
         {
+            wined3d_device_vk_allocator_unlock(device_vk);
             ERR("Failed to create slab bo.\n");
+            wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
             heap_free(slab);
             return false;
         }
         slab->map = ~0u;
 
-        if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
-        {
-            ERR("Failed to add slab to available tree.\n");
-            wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
-            heap_free(slab);
-            return false;
-        }
-
         TRACE("Created new bo slab %p.\n", slab);
     }
 
@@ -407,6 +428,8 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context
         }
     }
 
+    wined3d_device_vk_allocator_unlock(device_vk);
+
     *bo = slab->bo;
     bo->memory = NULL;
     bo->slab = slab;
@@ -480,7 +503,7 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic
     {
         ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
         if (bo->memory)
-            wined3d_allocator_block_free(bo->memory);
+            wined3d_context_vk_free_memory(context_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));
@@ -574,7 +597,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_context_vk_free_memory(context_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));
@@ -688,7 +711,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_context_vk_free_memory(context_vk, block);
         TRACE("Freed block %p.\n", block);
         return;
     }
@@ -707,11 +730,14 @@ void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *conte
 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
         SIZE_T idx, struct wined3d_context_vk *context_vk)
 {
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
     struct wined3d_bo_slab_vk_key key;
     struct wine_rb_entry *entry;
 
     TRACE("slab %p, idx %lu, context_vk %p.\n", slab, idx, context_vk);
 
+    wined3d_device_vk_allocator_lock(device_vk);
+
     if (!slab->map)
     {
         key.memory_type = slab->requested_memory_type;
@@ -729,6 +755,8 @@ static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
         }
     }
     slab->map |= 1u << idx;
+
+    wined3d_device_vk_allocator_unlock(device_vk);
 }
 
 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
@@ -1000,7 +1028,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_context_vk_free_memory(context_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 aa8974366a6..62b92ce7c34 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4084,6 +4084,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;
@@ -4094,6 +4095,16 @@ static inline struct wined3d_device_vk *wined3d_device_vk(struct wined3d_device
     return CONTAINING_RECORD(device, struct wined3d_device_vk, d);
 }
 
+static inline void wined3d_device_vk_allocator_lock(struct wined3d_device_vk *device_vk)
+{
+    EnterCriticalSection(&device_vk->allocator_cs);
+}
+
+static inline void wined3d_device_vk_allocator_unlock(struct wined3d_device_vk *device_vk)
+{
+    LeaveCriticalSection(&device_vk->allocator_cs);
+}
+
 bool wined3d_device_vk_create_null_resources(struct wined3d_device_vk *device_vk,
         struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
 bool wined3d_device_vk_create_null_views(struct wined3d_device_vk *device_vk,
-- 
2.33.0




More information about the wine-devel mailing list