The D3D12 swapchain code is currently quite messy, probably because it was originally designed around the direct usage of the Vulkan swapchain images, then the support for user buffers was added, and the original design was later phased out. Currently the internal state can be divided in two different sets of objects: the "D3D12 side", which is visible to the `IDXGISwapChain` client and must be preserved at all times (except on the client's request, i.e., when `UpdateBuffers()` is called) and the "Vulkan side" which is private and can be destroyed and recreated more or less transparently (in case the Vulkan swapchain goes out of date or some settings are updated).
This MR begins the process of de-intertwining the helpers that act on one or the other sides, so that the structure of the code is made clearer. The full patch set is at https://gitlab.winehq.org/giomasce/wine/-/commits/chianti.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 0ba9db96108..aabbb9943c3 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1044,26 +1044,37 @@ struct d3d12_swapchain struct wined3d_swapchain_state *state; struct wined3d_swapchain_state_parent state_parent;
- VkSwapchainKHR vk_swapchain; VkSurfaceKHR vk_surface; VkFence vk_fence; VkInstance vk_instance; VkDevice vk_device; VkPhysicalDevice vk_physical_device; + + /* D3D12 side of the swapchain: these objects are visible to the + * IDXGISwapChain client, so they must never be recreated, except + * when ResizeBuffers*() is called. */ + unsigned int buffer_count; VkDeviceMemory vk_memory; - VkCommandPool vk_cmd_pool; VkImage vk_images[DXGI_MAX_SWAP_CHAIN_BUFFERS]; + ID3D12Resource *buffers[DXGI_MAX_SWAP_CHAIN_BUFFERS]; + unsigned int current_buffer_index; + + /* Vulkan side of the swapchain: these objects are also destroyed + * and recreated when the Vulkan swapchain becomes out of date or + * when the synchronization interval is changed; this operation + * should be transparent to the IDXGISwapChain client (except for + * timings: recreating the Vulkan swapchain creates a noticeable + * delay, unfortunately). */ + VkSwapchainKHR vk_swapchain; + VkCommandPool vk_cmd_pool; VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS]; VkCommandBuffer vk_cmd_buffers[DXGI_MAX_SWAP_CHAIN_BUFFERS]; VkSemaphore vk_semaphores[DXGI_MAX_SWAP_CHAIN_BUFFERS]; - ID3D12Resource *buffers[DXGI_MAX_SWAP_CHAIN_BUFFERS]; - unsigned int buffer_count; unsigned int vk_swapchain_width; unsigned int vk_swapchain_height; VkPresentModeKHR present_mode; - uint32_t vk_image_index; - unsigned int current_buffer_index; + struct dxgi_vk_funcs vk_funcs;
ID3D12CommandQueue *command_queue;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index aabbb9943c3..4aa0066cf32 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1454,7 +1454,7 @@ static VkResult d3d12_swapchain_record_swapchain_blit(struct d3d12_swapchain *sw return vr; }
-static HRESULT d3d12_swapchain_prepare_command_buffers(struct d3d12_swapchain *swapchain, +static HRESULT d3d12_swapchain_create_command_buffers(struct d3d12_swapchain *swapchain, uint32_t queue_family_index) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; @@ -1548,7 +1548,7 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain, if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, vk_format))) return hr;
- if (FAILED(hr = d3d12_swapchain_prepare_command_buffers(swapchain, queue_family_index))) + if (FAILED(hr = d3d12_swapchain_create_command_buffers(swapchain, queue_family_index))) return hr;
if (swapchain->buffers[0])
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 4aa0066cf32..7d368c88687 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1073,6 +1073,8 @@ struct d3d12_swapchain unsigned int vk_swapchain_width; unsigned int vk_swapchain_height; VkPresentModeKHR present_mode; + VkFormat vk_format; + uint32_t vk_image_index;
struct dxgi_vk_funcs vk_funcs; @@ -1255,7 +1257,7 @@ static BOOL d3d12_swapchain_is_present_mode_supported(struct d3d12_swapchain *sw return supported; }
-static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain, VkFormat vk_format) +static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; VkDeviceSize image_offset[DXGI_MAX_SWAP_CHAIN_BUFFERS]; @@ -1276,7 +1278,7 @@ static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapc image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; image_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = vk_format; + image_info.format = swapchain->vk_format; image_info.extent.width = swapchain->desc.Width; image_info.extent.height = swapchain->desc.Height; image_info.extent.depth = 1; @@ -1511,8 +1513,7 @@ static HRESULT d3d12_swapchain_create_command_buffers(struct d3d12_swapchain *sw return S_OK; }
-static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain, - VkFormat vk_swapchain_format, VkFormat vk_format) +static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; struct vkd3d_image_resource_create_info resource_info; @@ -1545,7 +1546,7 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
queue_family_index = vkd3d_get_vk_queue_family_index(queue);
- if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, vk_format))) + if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain))) return hr;
if (FAILED(hr = d3d12_swapchain_create_command_buffers(swapchain, queue_family_index))) @@ -1562,7 +1563,7 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain, resource_info.desc.Height = swapchain->desc.Height; resource_info.desc.DepthOrArraySize = 1; resource_info.desc.MipLevels = 1; - resource_info.desc.Format = dxgi_format_from_vk_format(vk_format); + resource_info.desc.Format = dxgi_format_from_vk_format(swapchain->vk_format); resource_info.desc.SampleDesc.Count = 1; resource_info.desc.SampleDesc.Quality = 0; resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; @@ -1671,15 +1672,15 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; VkSwapchainCreateInfoKHR vk_swapchain_desc; VkDevice vk_device = swapchain->vk_device; - VkFormat vk_format, vk_swapchain_format; unsigned int width, height, image_count; VkSurfaceCapabilitiesKHR surface_caps; + VkFormat vk_swapchain_format; VkSwapchainKHR vk_swapchain; VkImageUsageFlags usage; VkResult vr; HRESULT hr;
- if (!(vk_format = vkd3d_get_vk_format(swapchain->desc.Format))) + if (!(swapchain->vk_format = vkd3d_get_vk_format(swapchain->desc.Format))) { WARN("Invalid format %#x.\n", swapchain->desc.Format); return DXGI_ERROR_INVALID_CALL; @@ -1776,7 +1777,7 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s
swapchain->vk_image_index = INVALID_VK_IMAGE_INDEX;
- return d3d12_swapchain_create_buffers(swapchain, vk_swapchain_format, vk_format); + return d3d12_swapchain_create_buffers(swapchain); }
static inline struct d3d12_swapchain *d3d12_swapchain_from_IDXGISwapChain4(IDXGISwapChain4 *iface)
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 73 ++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 33 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 7d368c88687..deb7e50026d 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1513,45 +1513,13 @@ static HRESULT d3d12_swapchain_create_command_buffers(struct d3d12_swapchain *sw return S_OK; }
-static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain) +static HRESULT d3d12_swapchain_create_image_resources(struct d3d12_swapchain *swapchain) { - const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; struct vkd3d_image_resource_create_info resource_info; - VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain; - ID3D12CommandQueue *queue = swapchain->command_queue; - VkDevice vk_device = swapchain->vk_device; ID3D12Device *device = swapchain->device; - uint32_t image_count, queue_family_index; unsigned int i; - VkResult vr; HRESULT hr;
- if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0) - { - WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); - return hresult_from_vk_result(vr); - } - if (image_count > ARRAY_SIZE(swapchain->vk_swapchain_images)) - { - FIXME("Unsupported Vulkan swapchain image count %u.\n", image_count); - return E_FAIL; - } - swapchain->buffer_count = image_count; - if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, - &image_count, swapchain->vk_swapchain_images)) < 0) - { - WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); - return hresult_from_vk_result(vr); - } - - queue_family_index = vkd3d_get_vk_queue_family_index(queue); - - if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain))) - return hr; - - if (FAILED(hr = d3d12_swapchain_create_command_buffers(swapchain, queue_family_index))) - return hr; - if (swapchain->buffers[0]) return S_OK;
@@ -1588,6 +1556,45 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain) return S_OK; }
+static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain) +{ + const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; + VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain; + ID3D12CommandQueue *queue = swapchain->command_queue; + VkDevice vk_device = swapchain->vk_device; + uint32_t image_count, queue_family_index; + VkResult vr; + HRESULT hr; + + if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0) + { + WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); + return hresult_from_vk_result(vr); + } + if (image_count > ARRAY_SIZE(swapchain->vk_swapchain_images)) + { + FIXME("Unsupported Vulkan swapchain image count %u.\n", image_count); + return E_FAIL; + } + swapchain->buffer_count = image_count; + if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, + &image_count, swapchain->vk_swapchain_images)) < 0) + { + WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); + return hresult_from_vk_result(vr); + } + + queue_family_index = vkd3d_get_vk_queue_family_index(queue); + + if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain))) + return hr; + + if (FAILED(hr = d3d12_swapchain_create_command_buffers(swapchain, queue_family_index))) + return hr; + + return d3d12_swapchain_create_image_resources(swapchain); +} + static VkResult d3d12_swapchain_acquire_next_vulkan_image(struct d3d12_swapchain *swapchain) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index deb7e50026d..1d86e79d5e5 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1687,12 +1687,6 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s VkResult vr; HRESULT hr;
- if (!(swapchain->vk_format = vkd3d_get_vk_format(swapchain->desc.Format))) - { - WARN("Invalid format %#x.\n", swapchain->desc.Format); - return DXGI_ERROR_INVALID_CALL; - } - if (FAILED(hr = select_vk_format(vk_funcs, vk_physical_device, swapchain->vk_surface, &swapchain->desc, &vk_swapchain_format))) return hr; @@ -1784,6 +1778,22 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s
swapchain->vk_image_index = INVALID_VK_IMAGE_INDEX;
+ return S_OK; +} + +static HRESULT d3d12_swapchain_create_resources(struct d3d12_swapchain *swapchain) +{ + HRESULT hr; + + if (!(swapchain->vk_format = vkd3d_get_vk_format(swapchain->desc.Format))) + { + WARN("Invalid format %#x.\n", swapchain->desc.Format); + return DXGI_ERROR_INVALID_CALL; + } + + if (FAILED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain))) + return hr; + return d3d12_swapchain_create_buffers(swapchain); }
@@ -1970,7 +1980,7 @@ static HRESULT d3d12_swapchain_set_sync_interval(struct d3d12_swapchain *swapcha
d3d12_swapchain_destroy_buffers(swapchain, FALSE); swapchain->present_mode = present_mode; - return d3d12_swapchain_create_vulkan_swapchain(swapchain); + return d3d12_swapchain_create_resources(swapchain); }
static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain, VkQueue vk_queue) @@ -2077,7 +2087,7 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain, TRACE("Recreating Vulkan swapchain.\n");
d3d12_swapchain_destroy_buffers(swapchain, FALSE); - if (FAILED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain))) + if (FAILED(hr = d3d12_swapchain_create_resources(swapchain))) return hr;
if (!(vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue))) @@ -2356,7 +2366,7 @@ static HRESULT d3d12_swapchain_resize_buffers(struct d3d12_swapchain *swapchain,
d3d12_swapchain_destroy_buffers(swapchain, TRUE); swapchain->desc = new_desc; - return d3d12_swapchain_create_vulkan_swapchain(swapchain); + return d3d12_swapchain_create_resources(swapchain); }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeBuffers(IDXGISwapChain4 *iface, @@ -3038,7 +3048,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI ID3D12CommandQueue_AddRef(swapchain->command_queue = queue); ID3D12Device_AddRef(swapchain->device = device);
- if (FAILED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain))) + if (FAILED(hr = d3d12_swapchain_create_resources(swapchain))) { d3d12_swapchain_destroy(swapchain); return hr;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 1d86e79d5e5..0b8d09d8b96 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1558,32 +1558,10 @@ static HRESULT d3d12_swapchain_create_image_resources(struct d3d12_swapchain *sw
static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain) { - const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; - VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain; ID3D12CommandQueue *queue = swapchain->command_queue; - VkDevice vk_device = swapchain->vk_device; - uint32_t image_count, queue_family_index; - VkResult vr; + uint32_t queue_family_index; HRESULT hr;
- if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0) - { - WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); - return hresult_from_vk_result(vr); - } - if (image_count > ARRAY_SIZE(swapchain->vk_swapchain_images)) - { - FIXME("Unsupported Vulkan swapchain image count %u.\n", image_count); - return E_FAIL; - } - swapchain->buffer_count = image_count; - if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, - &image_count, swapchain->vk_swapchain_images)) < 0) - { - WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); - return hresult_from_vk_result(vr); - } - queue_family_index = vkd3d_get_vk_queue_family_index(queue);
if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain))) @@ -1772,6 +1750,24 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s if (swapchain->vk_swapchain) vk_funcs->p_vkDestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL);
+ if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0) + { + WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); + return hresult_from_vk_result(vr); + } + if (image_count > ARRAY_SIZE(swapchain->vk_swapchain_images)) + { + FIXME("Unsupported Vulkan swapchain image count %u.\n", image_count); + return E_FAIL; + } + swapchain->buffer_count = image_count; + if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, + &image_count, swapchain->vk_swapchain_images)) < 0) + { + WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr); + return hresult_from_vk_result(vr); + } + swapchain->vk_swapchain = vk_swapchain; swapchain->vk_swapchain_width = width; swapchain->vk_swapchain_height = height;
This merge request was approved by Zebediah Figura.