From dd03e37f9fdd8e5264a60308f28e07f05d9a26f7 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 24 Jan 2020 19:32:03 +0330 Subject: [PATCH] wined3d: Create Vulkan buffers. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- 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 458343ce4a4..7d66fab0a26 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)