From: Stian Low <wineryyyyy@gmail.com> --- dlls/wined3d/adapter_vk.c | 19 ++++++++++++++ dlls/wined3d/swapchain.c | 36 +++++++++++++++++++++++++++ dlls/wined3d/view.c | 52 ++++++++++++++++++++++++++++++++++----- dlls/wined3d/wined3d_vk.h | 7 ++++++ 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 79014b4c331..bdb4b480d29 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1515,6 +1515,24 @@ static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); } +static void adapter_vk_destroy_swapchain_rendertarget_views(struct wined3d_rendertarget_view_vk *view_vk) +{ + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk, *swap_view_vk_next; + struct wined3d_resource *resource = view_vk->v.resource; + struct wined3d_swapchain *swapchain; + + if (!(swapchain = wined3d_swapchain_from_resource(resource))) + return; + + LIST_FOR_EACH_ENTRY_SAFE(swap_view_vk, swap_view_vk_next, &view_vk->swapchain_views, struct wined3d_swapchain_rendertarget_view_vk, entry) + { + wined3d_view_vk_destroy(resource->device, NULL, &swap_view_vk->vk_image_view, NULL, NULL, NULL, &view_vk->command_buffer_id, NULL); + list_remove(&swap_view_vk->entry); + free(swap_view_vk); + swap_view_vk = swap_view_vk_next; + } +} + static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) { struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view); @@ -1522,6 +1540,7 @@ static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_vie TRACE("view_vk %p.\n", view_vk); + adapter_vk_destroy_swapchain_rendertarget_views(view_vk); wined3d_rendertarget_view_cleanup(&view_vk->v); wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view, NULL, NULL, NULL, &view_vk->command_buffer_id, view_vk); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 05a4d225d91..4e056283e96 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1200,6 +1200,42 @@ static VkResult wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain return vr; } +static void wined3d_swapchain_rendertarget_view_vk_rotate(struct wined3d_swapchain *swapchain) +{ + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk; + struct wined3d_swapchain_rendertarget_view *swap_view; + struct wined3d_rendertarget_view_vk *view_vk; + VkImageView vk_image_view, vk_image_view_prev; + + if (!swapchain || swapchain->state.desc.backbuffer_count < 2) + return; + + LIST_FOR_EACH_ENTRY(swap_view, &swapchain->back_buffer_rendertarget_views, struct wined3d_swapchain_rendertarget_view, entry) + { + if (!swap_view->view) + { + FIXME("Skipping rotate for swap_view %p which should not occur.\n", swap_view); + continue; + } + + view_vk = wined3d_rendertarget_view_vk(swap_view->view); + if (!view_vk->vk_image_view) + { + FIXME("Skipping rotate for view_vk %p with vk_image_view 0 which should not occur.\n", view_vk); + continue; + } + + vk_image_view_prev = view_vk->vk_image_view; + LIST_FOR_EACH_ENTRY(swap_view_vk, &view_vk->swapchain_views, struct wined3d_swapchain_rendertarget_view_vk, entry) + { + vk_image_view = swap_view_vk->vk_image_view; + swap_view_vk->vk_image_view = vk_image_view_prev; + vk_image_view_prev = vk_image_view; + } + view_vk->vk_image_view = vk_image_view_prev; + } +} + static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context_vk *context_vk) { struct wined3d_texture_sub_resource *sub_resource; diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 004f9fca655..a8892a88b92 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -912,14 +912,18 @@ static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_v static void wined3d_render_target_view_vk_cs_init(void *object) { + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk; struct wined3d_rendertarget_view_vk *view_vk = object; struct wined3d_view_desc *desc = &view_vk->v.desc; + struct wined3d_swapchain_rendertarget_view *lview; const struct wined3d_format_vk *format_vk; struct wined3d_texture_vk *texture_vk; + struct wined3d_swapchain *swapchain; struct wined3d_resource *resource; struct wined3d_context *context; VkImageUsageFlags vk_usage = 0; uint32_t default_flags = 0; + unsigned int i, count; TRACE("view_vk %p.\n", view_vk); @@ -946,12 +950,6 @@ static void wined3d_render_target_view_vk_cs_init(void *object) return; } - if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1) - { - FIXME("Swapchain views not supported.\n"); - return; - } - if (resource->bind_flags & WINED3D_BIND_RENDER_TARGET) vk_usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) @@ -963,8 +961,49 @@ static void wined3d_render_target_view_vk_cs_init(void *object) context_release(context); if (!view_vk->vk_image_view) + { + ERR("Failed to create render target view for resource %p\n", resource); + /* TODO: flag for cleanup? */ + return; + } + + if (!(swapchain = swapchain_from_resource(resource))) return; + context = context_acquire(resource->device, NULL, 0); + count = swapchain->state.desc.backbuffer_count - 1; + for (i = 0; i < count; i++) + { + if (!(swap_view_vk = calloc(1, sizeof(*swap_view_vk)))) + { + ERR("Out of memory.\n"); + context_release(context); + return; + } + + list_add_head(&view_vk->swapchain_views, &swap_view_vk->entry); + texture_vk = wined3d_texture_vk(swapchain->back_buffers[i + 1]); + if ((swap_view_vk->vk_image_view = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context), + desc, texture_vk, format_vk, COLOR_FIXUP_IDENTITY, true, vk_usage))) + continue; + + ERR("Failed to create render target view for swapchain %p backbuffer[%u]\n", swapchain, i); + /* TODO: flag for cleanup? */ + break; + } + + context_release(context); + + if (!(lview = calloc(1, sizeof(*lview)))) + { + ERR("Out of memory.\n"); + /* TODO: flag for cleanup? */ + return; + } + + list_add_head(&swapchain->back_buffer_rendertarget_views, &lview->entry); + lview->view = &view_vk->v; + TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view)); } @@ -980,6 +1019,7 @@ HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *v if (FAILED(hr = wined3d_rendertarget_view_init(&view_vk->v, desc, resource, parent, parent_ops))) return hr; + list_init(&view_vk->swapchain_views); wined3d_cs_init_object(resource->device->cs, wined3d_render_target_view_vk_cs_init, view_vk); return hr; diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index 937a958760c..05ce14f153b 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -1031,12 +1031,19 @@ static inline void wined3d_resource_vk_barrier(struct wined3d_resource *resource wined3d_texture_vk_barrier(wined3d_texture_vk(texture_from_resource(resource)), context_vk, bind_mask); } +struct wined3d_swapchain_rendertarget_view_vk +{ + struct list entry; + VkImageView vk_image_view; +}; + struct wined3d_rendertarget_view_vk { struct wined3d_rendertarget_view v; VkImageView vk_image_view; uint64_t command_buffer_id; + struct list swapchain_views; }; static inline struct wined3d_rendertarget_view_vk *wined3d_rendertarget_view_vk( -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10567