Signed-off-by: Henri Verbeet hverbeet@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(