Module: wine Branch: master Commit: ce0f12acc9b97437c4c11d0d8e98302088b5b39c URL: https://source.winehq.org/git/wine.git/?a=commit;h=ce0f12acc9b97437c4c11d0d8...
Author: Zebediah Figura zfigura@codeweavers.com Date: Wed Nov 3 23:46:55 2021 -0500
wined3d: Protect access to the Vulkan wined3d_allocator with a mutex.
So that it can be accessed from the client thread.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/wined3d/adapter_vk.c | 9 ++++++++ dlls/wined3d/context_vk.c | 50 ++++++++++++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 11 ++++++++++ 3 files changed, 59 insertions(+), 11 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,26 +387,29 @@ 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; }
- slab->requested_memory_type = memory_type; - if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo)) + if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0) { - ERR("Failed to create slab bo.\n"); + wined3d_device_vk_allocator_unlock(device_vk); + ERR("Failed to add slab to available tree.\n"); heap_free(slab); return false; } - slab->map = ~0u;
- if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0) + slab->requested_memory_type = memory_type; + if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo)) { - ERR("Failed to add slab to available tree.\n"); - wined3d_context_vk_destroy_bo(context_vk, &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;
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,