[PATCH 2/5] wined3d: Create Vulkan images for texture resources.

Henri Verbeet hverbeet at codeweavers.com
Mon Apr 20 14:00:23 CDT 2020


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/context_vk.c      |  36 +++++++-
 dlls/wined3d/texture.c         | 160 ++++++++++++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |  15 ++++
 3 files changed, 205 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index b3239a4f9ee..35a0c655ef3 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -86,7 +86,7 @@ VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_cont
     return vk_memory;
 }
 
-static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
+struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
         unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
 {
     struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
@@ -198,7 +198,7 @@ static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_v
     return &retired->objects[retired->count++];
 }
 
-static void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
+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);
@@ -223,7 +223,7 @@ static void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context
     o->command_buffer_id = command_buffer_id;
 }
 
-static void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
+void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
         struct wined3d_allocator_block *block, uint64_t command_buffer_id)
 {
     struct wined3d_retired_object_vk *o;
@@ -271,6 +271,31 @@ static void wined3d_context_vk_destroy_buffer(struct wined3d_context_vk *context
     o->command_buffer_id = command_buffer_id;
 }
 
+void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk,
+        VkImage vk_image, 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(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
+        TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
+        return;
+    }
+
+    if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
+    {
+        ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
+        return;
+    }
+
+    o->type = WINED3D_RETIRED_IMAGE_VK;
+    o->u.vk_image = vk_image;
+    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)
 {
     TRACE("context_vk %p, bo %p.\n", context_vk, bo);
@@ -345,6 +370,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
                 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
                 break;
 
+            case WINED3D_RETIRED_IMAGE_VK:
+                VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
+                TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
+                break;
+
             default:
                 ERR("Unhandled object type %#x.\n", o->type);
                 break;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 85f09ee3489..66cee442ff9 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -4230,6 +4230,129 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context,
     FIXME("Not implemented.\n");
 }
 
+static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk,
+        struct wined3d_context_vk *context_vk)
+{
+    const struct wined3d_format_vk *format_vk;
+    VkMemoryRequirements memory_requirements;
+    const struct wined3d_vk_info *vk_info;
+    struct wined3d_adapter_vk *adapter_vk;
+    struct wined3d_device_vk *device_vk;
+    struct wined3d_resource *resource;
+    VkImageCreateInfo create_info;
+    unsigned int memory_type_idx;
+    VkResult vr;
+
+    if (texture_vk->t.flags & WINED3D_TEXTURE_RGB_ALLOCATED)
+        return TRUE;
+
+    resource = &texture_vk->t.resource;
+    device_vk = wined3d_device_vk(resource->device);
+    adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
+    format_vk = wined3d_format_vk(resource->format);
+    vk_info = context_vk->vk_info;
+
+    create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    create_info.pNext = NULL;
+
+    create_info.flags = 0;
+    if (wined3d_format_is_typeless(&format_vk->f))
+        create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+    switch (resource->type)
+    {
+        case WINED3D_RTYPE_TEXTURE_1D:
+            create_info.imageType = VK_IMAGE_TYPE_1D;
+            break;
+        case WINED3D_RTYPE_TEXTURE_2D:
+            create_info.imageType = VK_IMAGE_TYPE_2D;
+            if (texture_vk->t.layer_count >= 6 && resource->width == resource->height)
+                create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+            break;
+        case WINED3D_RTYPE_TEXTURE_3D:
+            create_info.imageType = VK_IMAGE_TYPE_3D;
+            if (resource->bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_UNORDERED_ACCESS))
+                create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
+            break;
+        default:
+            ERR("Invalid resource type %s.\n", debug_d3dresourcetype(resource->type));
+            create_info.imageType = VK_IMAGE_TYPE_2D;
+            break;
+    }
+
+    create_info.format = format_vk->vk_format;
+    create_info.extent.width = resource->width;
+    create_info.extent.height = resource->height;
+    create_info.extent.depth = resource->depth;
+    create_info.mipLevels = texture_vk->t.level_count;
+    create_info.arrayLayers = texture_vk->t.layer_count;
+    create_info.samples = max(1, wined3d_resource_get_sample_count(resource));
+    create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+
+    create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    if (resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE)
+        create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+    if (resource->bind_flags & WINED3D_BIND_RENDER_TARGET)
+        create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+    if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
+        create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+    if (resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS)
+        create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
+
+    create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    create_info.queueFamilyIndexCount = 0;
+    create_info.pQueueFamilyIndices = NULL;
+    create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    if ((vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &texture_vk->vk_image))) < 0)
+    {
+        ERR("Failed to create Vulkan image, vr %s.\n", wined3d_debug_vkresult(vr));
+        return FALSE;
+    }
+
+    VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, texture_vk->vk_image, &memory_requirements));
+
+    memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
+            memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+    if (memory_type_idx == ~0u)
+    {
+        ERR("Failed to find suitable memory type.\n");
+        VK_CALL(vkDestroyImage(device_vk->vk_device, texture_vk->vk_image, NULL));
+        texture_vk->vk_image = VK_NULL_HANDLE;
+        return FALSE;
+    }
+
+    texture_vk->memory = wined3d_context_vk_allocate_memory(context_vk,
+            memory_type_idx, memory_requirements.size, &texture_vk->vk_memory);
+    if (!texture_vk->vk_memory)
+    {
+        ERR("Failed to allocate image memory.\n");
+        VK_CALL(vkDestroyImage(device_vk->vk_device, texture_vk->vk_image, NULL));
+        texture_vk->vk_image = VK_NULL_HANDLE;
+        return FALSE;
+    }
+
+    if ((vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, texture_vk->vk_image,
+            texture_vk->vk_memory, texture_vk->memory ? texture_vk->memory->offset : 0))) < 0)
+    {
+        WARN("Failed to bind memory, vr %s.\n", wined3d_debug_vkresult(vr));
+        if (texture_vk->memory)
+            wined3d_allocator_block_free(texture_vk->memory);
+        else
+            VK_CALL(vkFreeMemory(device_vk->vk_device, texture_vk->vk_memory, NULL));
+        texture_vk->vk_memory = VK_NULL_HANDLE;
+        VK_CALL(vkDestroyImage(device_vk->vk_device, texture_vk->vk_image, NULL));
+        texture_vk->vk_image = VK_NULL_HANDLE;
+        return FALSE;
+    }
+
+    texture_vk->t.flags |= WINED3D_TEXTURE_RGB_ALLOCATED;
+
+    TRACE("Created image 0x%s, memory 0x%s for texture %p.\n",
+            wine_dbgstr_longlong(texture_vk->vk_image), wine_dbgstr_longlong(texture_vk->vk_memory), texture_vk);
+
+    return TRUE;
+}
+
 static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location)
 {
@@ -4244,8 +4367,7 @@ static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture,
             return TRUE;
 
         case WINED3D_LOCATION_TEXTURE_RGB:
-            /* The Vulkan image is created during resource creation. */
-            return TRUE;
+            return wined3d_texture_vk_prepare_texture(wined3d_texture_vk(texture), wined3d_context_vk(context));
 
         default:
             FIXME("Unhandled location %s.\n", wined3d_debug_location(location));
@@ -4264,7 +4386,39 @@ static BOOL wined3d_texture_vk_load_location(struct wined3d_texture *texture,
 static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture,
         struct wined3d_context *context, unsigned int location)
 {
-    FIXME("texture %p, context %p, location %s.\n", texture, context, wined3d_debug_location(location));
+    struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
+    struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
+
+    TRACE("texture %p, context %p, location %s.\n", texture, context, wined3d_debug_location(location));
+
+    switch (location)
+    {
+        case WINED3D_LOCATION_TEXTURE_RGB:
+            if (texture_vk->vk_image)
+            {
+                wined3d_context_vk_destroy_image(context_vk, texture_vk->vk_image, texture_vk->command_buffer_id);
+                texture_vk->vk_image = VK_NULL_HANDLE;
+                if (texture_vk->memory)
+                    wined3d_context_vk_destroy_allocator_block(context_vk,
+                            texture_vk->memory, texture_vk->command_buffer_id);
+                else
+                    wined3d_context_vk_destroy_memory(context_vk,
+                            texture_vk->vk_memory, texture_vk->command_buffer_id);
+                texture_vk->vk_memory = VK_NULL_HANDLE;
+                texture_vk->memory = NULL;
+            }
+            break;
+
+        case WINED3D_LOCATION_BUFFER:
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+        case WINED3D_LOCATION_RB_MULTISAMPLE:
+        case WINED3D_LOCATION_RB_RESOLVED:
+            break;
+
+        default:
+            ERR("Unhandled location %s.\n", wined3d_debug_location(location));
+            break;
+    }
 }
 
 static const struct wined3d_texture_ops wined3d_texture_vk_ops =
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 7e78cb60df5..de07c5909aa 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2195,6 +2195,7 @@ enum wined3d_retired_object_type_vk
     WINED3D_RETIRED_MEMORY_VK,
     WINED3D_RETIRED_ALLOCATOR_BLOCK_VK,
     WINED3D_RETIRED_BUFFER_VK,
+    WINED3D_RETIRED_IMAGE_VK,
 };
 
 struct wined3d_retired_object_vk
@@ -2206,6 +2207,7 @@ struct wined3d_retired_object_vk
         VkDeviceMemory vk_memory;
         struct wined3d_allocator_block *block;
         VkBuffer vk_buffer;
+        VkImage vk_image;
     } u;
     uint64_t command_buffer_id;
 };
@@ -2243,13 +2245,21 @@ static inline struct wined3d_context_vk *wined3d_context_vk(struct wined3d_conte
     return CONTAINING_RECORD(context, struct wined3d_context_vk, c);
 }
 
+struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
+        unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory) DECLSPEC_HIDDEN;
 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
         unsigned int pool, size_t size) DECLSPEC_HIDDEN;
 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_allocator_block(struct wined3d_context_vk *context_vk,
+        struct wined3d_allocator_block *block, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk,
         const struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN;
+void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk,
+        VkImage vk_image, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
+void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
+        VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
 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;
@@ -3944,6 +3954,11 @@ void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl *t
 struct wined3d_texture_vk
 {
     struct wined3d_texture t;
+
+    VkImage vk_image;
+    struct wined3d_allocator_block *memory;
+    VkDeviceMemory vk_memory;
+    uint64_t command_buffer_id;
 };
 
 static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_texture *texture)
-- 
2.20.1




More information about the wine-devel mailing list