[PATCH 1/5] wined3d: Create Vulkan buffers.

Henri Verbeet hverbeet at codeweavers.com
Fri Dec 13 15:31:11 CST 2019


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/adapter_vk.c      | 17 ++++++++++
 dlls/wined3d/buffer.c          | 66 ++++++++++++++++++++++++++++++++++++--
 dlls/wined3d/context.c         | 72 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h | 21 ++++++++++++
 4 files changed, 173 insertions(+), 3 deletions(-)

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 4ec68013017..7d501b4b08f 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -555,6 +555,23 @@ static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
     heap_free(swapchain);
 }
 
+unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
+        uint32_t memory_type_mask, VkMemoryPropertyFlags flags)
+{
+    const VkPhysicalDeviceMemoryProperties *memory_info = &adapter_vk->memory_properties;
+    unsigned int i;
+
+    for (i = 0; i < memory_info->memoryTypeCount; ++i)
+    {
+        if (!(memory_type_mask & (1u << i)))
+            continue;
+        if ((memory_info->memoryTypes[i].propertyFlags & flags) == flags)
+            return i;
+    }
+
+    return ~0u;
+}
+
 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
         const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 5da6aec4fb8..4f3c28fe0b1 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1554,6 +1554,44 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined
     return wined3d_buffer_init(&buffer_gl->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops);
 }
 
+static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buffer_vk,
+        struct wined3d_context_vk *context_vk)
+{
+    struct wined3d_resource *resource = &buffer_vk->b.resource;
+    uint32_t bind_flags = resource->bind_flags;
+    VkMemoryPropertyFlags memory_type;
+    VkBufferUsageFlags usage;
+
+    usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+    if (bind_flags & WINED3D_BIND_VERTEX_BUFFER)
+        usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+    if (bind_flags & WINED3D_BIND_INDEX_BUFFER)
+        usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+    if (bind_flags & WINED3D_BIND_CONSTANT_BUFFER)
+        usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+    if (bind_flags & WINED3D_BIND_SHADER_RESOURCE)
+        usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+    if (bind_flags & WINED3D_BIND_UNORDERED_ACCESS)
+        usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+    if (bind_flags & WINED3D_BIND_INDIRECT_BUFFER)
+        usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
+    if (bind_flags & (WINED3D_BIND_STREAM_OUTPUT | WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL))
+        FIXME("Ignoring some bind flags %#x.\n", bind_flags);
+    memory_type = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+            | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+            | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+    if (!(wined3d_context_vk_create_bo(context_vk, resource->size, usage, memory_type, &buffer_vk->bo)))
+    {
+        WARN("Failed to create Vulkan buffer.\n");
+        return FALSE;
+    }
+
+    buffer_vk->b.buffer_object = (uintptr_t)&buffer_vk->bo;
+    buffer_invalidate_bo_range(&buffer_vk->b, 0, 0);
+
+    return TRUE;
+}
+
 static BOOL wined3d_buffer_vk_prepare_location(struct wined3d_buffer *buffer,
         struct wined3d_context *context, unsigned int location)
 {
@@ -1563,8 +1601,10 @@ static BOOL wined3d_buffer_vk_prepare_location(struct wined3d_buffer *buffer,
             return wined3d_resource_prepare_sysmem(&buffer->resource);
 
         case WINED3D_LOCATION_BUFFER:
-            /* The Vulkan buffer is created during resource creation. */
-            return TRUE;
+            if (buffer->buffer_object)
+                return TRUE;
+
+            return wined3d_buffer_vk_create_buffer_object(wined3d_buffer_vk(buffer), wined3d_context_vk(context));
 
         default:
             FIXME("Unhandled location %s.\n", wined3d_debug_location(location));
@@ -1575,7 +1615,24 @@ static BOOL wined3d_buffer_vk_prepare_location(struct wined3d_buffer *buffer,
 static void wined3d_buffer_vk_unload_location(struct wined3d_buffer *buffer,
         struct wined3d_context *context, unsigned int location)
 {
-    FIXME("buffer %p, context %p, location %s.\n", buffer, context, wined3d_debug_location(location));
+    struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
+    struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
+
+    TRACE("buffer %p, context %p, location %s.\n", buffer, context, wined3d_debug_location(location));
+
+    switch (location)
+    {
+        case WINED3D_LOCATION_BUFFER:
+            wined3d_context_vk_destroy_bo(context_vk, &buffer_vk->bo);
+            buffer_vk->bo.vk_buffer = VK_NULL_HANDLE;
+            buffer_vk->bo.vk_memory = VK_NULL_HANDLE;
+            buffer_vk->b.buffer_object = 0u;
+            break;
+
+        default:
+            ERR("Unhandled location %s.\n", wined3d_debug_location(location));
+            break;
+    }
 }
 
 static void wined3d_buffer_vk_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context,
@@ -1605,6 +1662,9 @@ HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined
     TRACE("buffer_vk %p, device %p, desc %p, data %p, parent %p, parent_ops %p.\n",
             buffer_vk, device, desc, data, parent, parent_ops);
 
+    if (desc->access & WINED3D_RESOURCE_ACCESS_GPU)
+        buffer_vk->b.flags |= WINED3D_BUFFER_USE_BO;
+
     return wined3d_buffer_init(&buffer_vk->b, device, desc, data, parent, parent_ops, &wined3d_buffer_vk_ops);
 }
 
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 95769014af6..5d88d4463f9 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1493,6 +1493,74 @@ static void wined3d_context_gl_cleanup(struct wined3d_context_gl *context_gl)
     wined3d_context_cleanup(&context_gl->c);
 }
 
+BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
+        VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
+{
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+    const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+    VkMemoryRequirements memory_requirements;
+    struct wined3d_adapter_vk *adapter_vk;
+    VkMemoryAllocateInfo allocate_info;
+    VkBufferCreateInfo create_info;
+    VkResult vr;
+
+    adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
+
+    create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+    create_info.pNext = NULL;
+    create_info.flags = 0;
+    create_info.size = size;
+    create_info.usage = usage;
+    create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    create_info.queueFamilyIndexCount = 0;
+    create_info.pQueueFamilyIndices = NULL;
+
+    if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
+    {
+        ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
+        return FALSE;
+    }
+
+    VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
+
+    allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+    allocate_info.pNext = NULL;
+    allocate_info.allocationSize = memory_requirements.size;
+    allocate_info.memoryTypeIndex = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
+            memory_requirements.memoryTypeBits, memory_type);
+    if (allocate_info.memoryTypeIndex == ~0u)
+    {
+        ERR("Failed to find suitable memory type.\n");
+        VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
+        return FALSE;
+    }
+    if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &bo->vk_memory))) < 0)
+    {
+        ERR("Failed to allocate buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
+        VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
+        return FALSE;
+    }
+
+    if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer, bo->vk_memory, 0))) < 0)
+    {
+        ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
+        VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
+        VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
+{
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+    const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+
+    VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
+    VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
+}
+
 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
 {
     wined3d_context_cleanup(&context_vk->c);
@@ -2344,9 +2412,13 @@ fail:
 
 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
 {
+    struct wined3d_adapter_vk *adapter_vk;
+
     TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
 
     wined3d_context_init(&context_vk->c, swapchain);
+    adapter_vk = wined3d_adapter_vk(swapchain->device->adapter);
+    context_vk->vk_info = &adapter_vk->vk_info;
 
     return WINED3D_OK;
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 21f17736ec7..583d970eca8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1512,6 +1512,12 @@ do {                                                                \
 #define checkGLcall(A) do {} while(0)
 #endif
 
+struct wined3d_bo_vk
+{
+    VkBuffer vk_buffer;
+    VkDeviceMemory vk_memory;
+};
+
 struct wined3d_bo_address
 {
     UINT_PTR buffer_object;
@@ -2155,9 +2161,20 @@ void wined3d_context_gl_update_stream_sources(struct wined3d_context_gl *context
 struct wined3d_context_vk
 {
     struct wined3d_context c;
+
+    const struct wined3d_vk_info *vk_info;
 };
 
+static inline struct wined3d_context_vk *wined3d_context_vk(struct wined3d_context *context)
+{
+    return CONTAINING_RECORD(context, struct wined3d_context_vk, c);
+}
+
 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
+BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
+        VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN;
+void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk,
+        const struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN;
 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 
@@ -2929,6 +2946,8 @@ static inline struct wined3d_adapter_vk *wined3d_adapter_vk(struct wined3d_adapt
 
 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
         unsigned int wined3d_creation_flags) DECLSPEC_HIDDEN;
+unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
+        uint32_t memory_type_mask, VkMemoryPropertyFlags flags) DECLSPEC_HIDDEN;
 
 struct wined3d_caps_gl_ctx
 {
@@ -4208,6 +4227,8 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined
 struct wined3d_buffer_vk
 {
     struct wined3d_buffer b;
+
+    struct wined3d_bo_vk bo;
 };
 
 static inline struct wined3d_buffer_vk *wined3d_buffer_vk(struct wined3d_buffer *buffer)
-- 
2.11.0




More information about the wine-devel mailing list