[PATCH 4/5] wined3d: Create Vulkan image views for rendertarget views.

Henri Verbeet hverbeet at codeweavers.com
Mon Apr 27 10:48:46 CDT 2020


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/adapter_vk.c      |  59 ++++++++++++++-
 dlls/wined3d/context_vk.c      |  30 ++++++++
 dlls/wined3d/texture.c         |   4 +-
 dlls/wined3d/view.c            | 128 ++++++++++++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |   9 +++
 5 files changed, 226 insertions(+), 4 deletions(-)

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 16a23a5fec8..1641de78522 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -1200,6 +1200,63 @@ static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_des
     return hr;
 }
 
+struct wined3d_view_vk_destroy_ctx
+{
+    struct wined3d_device_vk *device_vk;
+    VkImageView *vk_image_view;
+    uint64_t *command_buffer_id;
+    void *object;
+    struct wined3d_view_vk_destroy_ctx *free;
+};
+
+static void wined3d_view_vk_destroy_object(void *object)
+{
+    struct wined3d_view_vk_destroy_ctx *ctx = object;
+    const struct wined3d_vk_info *vk_info;
+    struct wined3d_device_vk *device_vk;
+
+    device_vk = ctx->device_vk;
+    vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
+
+    if (ctx->vk_image_view)
+    {
+        struct wined3d_context *context;
+
+        if (!(context = context_acquire(&device_vk->d, NULL, 0)))
+        {
+            VK_CALL(vkDestroyImageView(device_vk->vk_device, *ctx->vk_image_view, NULL));
+            TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_image_view));
+        }
+        else
+        {
+            wined3d_context_vk_destroy_image_view(wined3d_context_vk(context),
+                    *ctx->vk_image_view, *ctx->command_buffer_id);
+            context_release(context);
+        }
+    }
+
+    heap_free(ctx->object);
+    heap_free(ctx->free);
+}
+
+static void wined3d_view_vk_destroy(struct wined3d_device *device,
+        VkImageView *vk_image_view, uint64_t *command_buffer_id, void *view_vk)
+{
+    struct wined3d_view_vk_destroy_ctx *ctx, c;
+
+    if (!(ctx = heap_alloc(sizeof(*ctx))))
+        ctx = &c;
+    ctx->device_vk = wined3d_device_vk(device);
+    ctx->vk_image_view = vk_image_view;
+    ctx->command_buffer_id = command_buffer_id;
+    ctx->object = view_vk;
+    ctx->free = ctx != &c ? ctx : NULL;
+
+    wined3d_cs_destroy_object(device->cs, wined3d_view_vk_destroy_object, ctx);
+    if (ctx == &c)
+        device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
+}
+
 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
 {
     struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
@@ -1215,7 +1272,7 @@ static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_vie
     if (swapchain_count)
         wined3d_device_incref(device);
     wined3d_rendertarget_view_cleanup(&view_vk->v);
-    wined3d_cs_destroy_object(device->cs, heap_free, view_vk);
+    wined3d_view_vk_destroy(device, &view_vk->vk_image_view, &view_vk->command_buffer_id, view_vk);
     if (swapchain_count)
         wined3d_device_decref(device);
 }
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 76aafa4c110..f5a321b076c 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -444,6 +444,31 @@ void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk,
     o->command_buffer_id = command_buffer_id;
 }
 
+void wined3d_context_vk_destroy_image_view(struct wined3d_context_vk *context_vk,
+        VkImageView vk_view, 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(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
+        TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
+        return;
+    }
+
+    if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
+    {
+        ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
+        return;
+    }
+
+    o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
+    o->u.vk_image_view = vk_view;
+    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)
 {
     size_t object_size, idx;
@@ -537,6 +562,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
                 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
                 break;
 
+            case WINED3D_RETIRED_IMAGE_VIEW_VK:
+                VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
+                TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
+                break;
+
             default:
                 ERR("Unhandled object type %#x.\n", o->type);
                 break;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 70acc5b1822..0e39ad55a8c 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -4830,7 +4830,7 @@ static BOOL wined3d_texture_vk_load_sysmem(struct wined3d_texture_vk *texture_vk
     return TRUE;
 }
 
-static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk,
+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;
@@ -4863,7 +4863,7 @@ static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *textur
     create_info.pNext = NULL;
 
     create_info.flags = 0;
-    if (wined3d_format_is_typeless(&format_vk->f))
+    if (wined3d_format_is_typeless(&format_vk->f) || texture_vk->t.swapchain)
         create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
 
     switch (resource->type)
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 093143c674f..438d9a8b18f 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -621,14 +621,140 @@ HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *v
     return hr;
 }
 
+static VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags)
+{
+    switch (type)
+    {
+        case WINED3D_RTYPE_TEXTURE_1D:
+            if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
+                return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+            else
+                return VK_IMAGE_VIEW_TYPE_1D;
+
+        case WINED3D_RTYPE_TEXTURE_2D:
+            if (flags & WINED3D_VIEW_TEXTURE_CUBE)
+            {
+                if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
+                    return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+                else
+                    return VK_IMAGE_VIEW_TYPE_CUBE;
+            }
+            if (flags & WINED3D_VIEW_TEXTURE_ARRAY)
+                return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+            else
+                return VK_IMAGE_VIEW_TYPE_2D;
+
+        case WINED3D_RTYPE_TEXTURE_3D:
+            return VK_IMAGE_VIEW_TYPE_3D;
+
+        default:
+            ERR("Unhandled resource type %s.\n", debug_d3dresourcetype(type));
+            return ~0u;
+    }
+}
+
+static void wined3d_render_target_view_vk_cs_init(void *object)
+{
+    struct wined3d_rendertarget_view_vk *view_vk = object;
+    struct wined3d_view_desc *desc = &view_vk->v.desc;
+    const struct wined3d_format_vk *format_vk;
+    struct VkImageViewCreateInfo create_info;
+    const struct wined3d_vk_info *vk_info;
+    struct wined3d_texture_vk *texture_vk;
+    struct wined3d_device_vk *device_vk;
+    struct wined3d_resource *resource;
+    struct wined3d_context *context;
+    uint32_t default_flags = 0;
+    VkResult vr;
+
+    resource = view_vk->v.resource;
+    if (resource->type == WINED3D_RTYPE_BUFFER)
+    {
+        FIXME("Buffer views not implemented.\n");
+        return;
+    }
+
+    texture_vk = wined3d_texture_vk(texture_from_resource(resource));
+    format_vk = wined3d_format_vk(view_vk->v.format);
+
+    if (texture_vk->t.layer_count > 1)
+        default_flags |= WINED3D_VIEW_TEXTURE_ARRAY;
+
+    if (resource->format->id == format_vk->f.id && desc->flags == default_flags
+            && !desc->u.texture.level_idx && desc->u.texture.level_count == texture_vk->t.level_count
+            && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture_vk->t.layer_count
+            && !is_stencil_view_format(&format_vk->f) && resource->type != WINED3D_RTYPE_TEXTURE_3D
+            && is_identity_fixup(format_vk->f.color_fixup))
+    {
+        TRACE("Creating identity render target view.\n");
+        return;
+    }
+
+    if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1)
+    {
+        FIXME("Swapchain views not supported.\n");
+        return;
+    }
+
+    device_vk = wined3d_device_vk(resource->device);
+    context = context_acquire(&device_vk->d, NULL, 0);
+    vk_info = wined3d_context_vk(context)->vk_info;
+
+    if (!wined3d_texture_vk_prepare_texture(texture_vk, wined3d_context_vk(context)))
+    {
+        ERR("Failed to prepare texture.\n");
+        context_release(context);
+        return;
+    }
+
+    create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+    create_info.pNext = NULL;
+    create_info.flags = 0;
+    create_info.image = texture_vk->vk_image;
+    create_info.viewType = vk_image_view_type_from_wined3d(resource->type, desc->flags);
+    if (create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
+    {
+        if (desc->u.texture.layer_count > 1)
+            create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+        else
+            create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+    }
+    create_info.format = format_vk->vk_format;
+    create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+    create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+    create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+    create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+    create_info.subresourceRange.aspectMask = vk_aspect_mask_from_format(&format_vk->f);
+    create_info.subresourceRange.baseMipLevel = desc->u.texture.level_idx;
+    create_info.subresourceRange.levelCount = desc->u.texture.level_count;
+    create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
+    create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
+    if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, NULL, &view_vk->vk_image_view))) < 0)
+    {
+        ERR("Failed to create Vulkan image view, vr %d.\n", vr);
+        context_release(context);
+        return;
+    }
+    TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view));
+
+    context_release(context);
+}
+
 HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk,
         const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
         void *parent, const struct wined3d_parent_ops *parent_ops)
 {
+    HRESULT hr;
+
     TRACE("view_vk %p, desc %s, resource %p, parent %p, parent_ops %p.\n",
             view_vk, wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops);
 
-    return wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops);
+    if (FAILED(hr = wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops)))
+        return hr;
+
+    wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_vk_cs_init, view_vk);
+
+    return hr;
 }
 
 HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *desc,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 2faeca4b35d..43bdb26c936 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2228,6 +2228,7 @@ enum wined3d_retired_object_type_vk
     WINED3D_RETIRED_BO_SLAB_SLICE_VK,
     WINED3D_RETIRED_BUFFER_VK,
     WINED3D_RETIRED_IMAGE_VK,
+    WINED3D_RETIRED_IMAGE_VIEW_VK,
 };
 
 struct wined3d_retired_object_vk
@@ -2245,6 +2246,7 @@ struct wined3d_retired_object_vk
         } slice;
         VkBuffer vk_buffer;
         VkImage vk_image;
+        VkImageView vk_image_view;
     } u;
     uint64_t command_buffer_id;
 };
@@ -2296,6 +2298,8 @@ 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_image_view(struct wined3d_context_vk *context_vk,
+        VkImageView vk_view, 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;
@@ -4002,6 +4006,8 @@ static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_textu
 HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wined3d_device *device,
         const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
         uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk,
+        struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
 
 struct wined3d_renderbuffer_entry
 {
@@ -4499,6 +4505,9 @@ HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *v
 struct wined3d_rendertarget_view_vk
 {
     struct wined3d_rendertarget_view v;
+
+    VkImageView vk_image_view;
+    uint64_t command_buffer_id;
 };
 
 static inline struct wined3d_rendertarget_view_vk *wined3d_rendertarget_view_vk(
-- 
2.20.1




More information about the wine-devel mailing list