[PATCH 02/15] wined3d: Track buffer usage.

Henri Verbeet hverbeet at codeweavers.com
Fri Apr 17 10:51:09 CDT 2020


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/adapter_vk.c      |   7 +-
 dlls/wined3d/context_vk.c      | 144 ++++++++++++++++++++++++++++++---
 dlls/wined3d/wined3d_private.h |  35 +++++++-
 3 files changed, 172 insertions(+), 14 deletions(-)

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 1773f26ae7f..e51eeccc02c 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -536,10 +536,13 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context,
             range.size = size;
             VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range));
         }
+
+        bo->command_buffer_id = context_vk->current_command_buffer.id;
     }
 
-    wined3d_context_vk_submit_command_buffer(context_vk);
-    wined3d_context_vk_wait_command_buffer(context_vk, context_vk->current_command_buffer.id - 1);
+    if (bo->command_buffer_id == context_vk->current_command_buffer.id)
+        wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
+    wined3d_context_vk_wait_command_buffer(context_vk, bo->command_buffer_id);
 
     if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory,
             (uintptr_t)data->addr, size, 0, &map_ptr))) < 0)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index b0e65231f25..3fa3ce8207f 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -88,24 +88,97 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic
     }
 
     bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
+    bo->command_buffer_id = 0;
+
+    TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
+            wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
 
     return TRUE;
 }
 
-void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
+static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
+{
+    struct wined3d_retired_objects_vk *retired = &context_vk->retired;
+    struct wined3d_retired_object_vk *o;
+
+    if (retired->free)
+    {
+        o = retired->free;
+        retired->free = o->u.next;
+        return o;
+    }
+
+    if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
+            retired->count + 1, sizeof(*retired->objects)))
+        return NULL;
+
+    return &retired->objects[retired->count++];
+}
+
+static void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
+        VkDeviceMemory vk_memory, uint64_t command_buffer_id)
 {
     struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+    struct wined3d_retired_object_vk *o;
+
+    if (context_vk->completed_command_buffer_id > command_buffer_id)
+    {
+        VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
+        TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
+        return;
+    }
 
-    VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
-    VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
+    if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
+    {
+        ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
+        return;
+    }
+
+    o->type = WINED3D_RETIRED_MEMORY_VK;
+    o->u.vk_memory = vk_memory;
+    o->command_buffer_id = command_buffer_id;
+}
+
+static void wined3d_context_vk_destroy_buffer(struct wined3d_context_vk *context_vk,
+        VkBuffer vk_buffer, uint64_t command_buffer_id)
+{
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+    const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+    struct wined3d_retired_object_vk *o;
+
+    if (context_vk->completed_command_buffer_id > command_buffer_id)
+    {
+        VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
+        TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
+        return;
+    }
+
+    if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
+    {
+        ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
+        return;
+    }
+
+    o->type = WINED3D_RETIRED_BUFFER_VK;
+    o->u.vk_buffer = vk_buffer;
+    o->command_buffer_id = command_buffer_id;
+}
+
+void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
+{
+    wined3d_context_vk_destroy_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
+    wined3d_context_vk_destroy_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
 }
 
 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk)
 {
     struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+    struct wined3d_retired_objects_vk *retired = &context_vk->retired;
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
     struct wined3d_command_buffer_vk *buffer;
+    struct wined3d_retired_object_vk *o;
+    uint64_t command_buffer_id;
     SIZE_T i = 0;
 
     while (i < context_vk->submitted.buffer_count)
@@ -127,6 +200,47 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
             context_vk->completed_command_buffer_id = buffer->id;
         *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
     }
+    command_buffer_id = context_vk->completed_command_buffer_id;
+
+    retired->free = NULL;
+    for (i = retired->count; i; --i)
+    {
+        o = &retired->objects[i - 1];
+
+        if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
+            continue;
+
+        switch (o->type)
+        {
+            case WINED3D_RETIRED_FREE_VK:
+                /* Nothing to do. */
+                break;
+
+            case WINED3D_RETIRED_MEMORY_VK:
+                VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
+                TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
+                break;
+
+            case WINED3D_RETIRED_BUFFER_VK:
+                VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
+                TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
+                break;
+
+            default:
+                ERR("Unhandled object type %#x.\n", o->type);
+                break;
+        }
+
+        if (i == retired->count)
+        {
+            --retired->count;
+            continue;
+        }
+
+        o->type = WINED3D_RETIRED_FREE_VK;
+        o->u.next = retired->free;
+        retired->free = o;
+    }
 }
 
 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
@@ -147,6 +261,8 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
     context_vk->completed_command_buffer_id = buffer->id;
     wined3d_context_vk_cleanup_resources(context_vk);
     heap_free(context_vk->submitted.buffers);
+    heap_free(context_vk->retired.objects);
+
     wined3d_context_cleanup(&context_vk->c);
 }
 
@@ -199,7 +315,9 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk
     return buffer->vk_command_buffer;
 }
 
-void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk)
+void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
+        unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
+        unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
 {
     struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
@@ -208,7 +326,10 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
     VkSubmitInfo submit_info;
     VkResult vr;
 
-    TRACE("context_vk %p.\n", context_vk);
+    TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
+            "signal_semaphore_count %u, signal_semaphores %p.\n",
+            context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
+            signal_semaphore_count, signal_semaphores);
 
     buffer = &context_vk->current_command_buffer;
     if (!buffer->vk_command_buffer)
@@ -227,13 +348,13 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
 
     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     submit_info.pNext = NULL;
-    submit_info.waitSemaphoreCount = 0;
-    submit_info.pWaitSemaphores = NULL;
-    submit_info.pWaitDstStageMask = NULL;
+    submit_info.waitSemaphoreCount = wait_semaphore_count;
+    submit_info.pWaitSemaphores = wait_semaphores;
+    submit_info.pWaitDstStageMask = wait_stages;
     submit_info.commandBufferCount = 1;
     submit_info.pCommandBuffers = &buffer->vk_command_buffer;
-    submit_info.signalSemaphoreCount = 0;
-    submit_info.pSignalSemaphores = NULL;
+    submit_info.signalSemaphoreCount = signal_semaphore_count;
+    submit_info.pSignalSemaphores = signal_semaphores;
 
     if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
         ERR("Failed to submit command buffer %p, vr %s.\n",
@@ -262,7 +383,8 @@ void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_v
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
     SIZE_T i;
 
-    if (id <= context_vk->completed_command_buffer_id)
+    if (id <= context_vk->completed_command_buffer_id
+            || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
         return;
 
     for (i = 0; i < context_vk->submitted.buffer_count; ++i)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f2b3cd9548e..fe44a6edb0c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1523,6 +1523,8 @@ struct wined3d_bo_vk
     VkDeviceMemory vk_memory;
 
     VkMemoryPropertyFlags memory_type;
+
+    uint64_t command_buffer_id;
 };
 
 struct wined3d_bo_address
@@ -2182,6 +2184,33 @@ struct wined3d_command_buffer_vk
     VkFence vk_fence;
 };
 
+enum wined3d_retired_object_type_vk
+{
+    WINED3D_RETIRED_FREE_VK,
+    WINED3D_RETIRED_MEMORY_VK,
+    WINED3D_RETIRED_BUFFER_VK,
+};
+
+struct wined3d_retired_object_vk
+{
+    enum wined3d_retired_object_type_vk type;
+    union
+    {
+        struct wined3d_retired_object_vk *next;
+        VkDeviceMemory vk_memory;
+        VkBuffer vk_buffer;
+    } u;
+    uint64_t command_buffer_id;
+};
+
+struct wined3d_retired_objects_vk
+{
+    struct wined3d_retired_object_vk *objects;
+    struct wined3d_retired_object_vk *free;
+    SIZE_T size;
+    SIZE_T count;
+};
+
 struct wined3d_context_vk
 {
     struct wined3d_context c;
@@ -2198,6 +2227,8 @@ struct wined3d_context_vk
         SIZE_T buffers_size;
         SIZE_T buffer_count;
     } submitted;
+
+    struct wined3d_retired_objects_vk retired;
 };
 
 static inline struct wined3d_context_vk *wined3d_context_vk(struct wined3d_context *context)
@@ -2213,7 +2244,9 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk,
 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
-void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
+void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
+        unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
+        unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores) DECLSPEC_HIDDEN;
 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id) DECLSPEC_HIDDEN;
 
 typedef void (*APPLYSTATEFUNC)(struct wined3d_context *ctx, const struct wined3d_state *state, DWORD state_id);
-- 
2.20.1




More information about the wine-devel mailing list