From b78f02922d392de34c1a060788c245a336d699ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Wed, 27 Feb 2019 16:05:00 +0100 Subject: [PATCH] dxgi: Implement 0 sync interval for D3D12 swapchains. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/dxgi/swapchain.c | 101 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 06fb7ef89a2..fb55820cb88 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -892,6 +892,7 @@ struct d3d12_swapchain unsigned int buffer_count; unsigned int vk_swapchain_width; unsigned int vk_swapchain_height; + VkPresentModeKHR present_mode; uint32_t current_buffer_index; struct dxgi_vk_funcs vk_funcs; @@ -1021,6 +1022,51 @@ static HRESULT vk_select_memory_type(const struct dxgi_vk_funcs *vk_funcs, return E_FAIL; } +static BOOL d3d12_swapchain_is_present_mode_supported(struct d3d12_swapchain *swapchain, + VkPresentModeKHR present_mode) +{ + VkPhysicalDevice vk_physical_device = swapchain->vk_physical_device; + const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; + VkPresentModeKHR *modes; + uint32_t count, i; + BOOL supported; + VkResult vr; + + if (present_mode == VK_PRESENT_MODE_FIFO_KHR) + return TRUE; + + if ((vr = vk_funcs->p_vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical_device, + swapchain->vk_surface, &count, NULL)) < 0) + { + WARN("Failed to get count of available present modes, vr %d.\n", vr); + return FALSE; + } + + supported = FALSE; + + if (!(modes = heap_calloc(count, sizeof(*modes)))) + return FALSE; + if ((vr = vk_funcs->p_vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical_device, + swapchain->vk_surface, &count, modes)) >= 0) + { + for (i = 0; i < count; ++i) + { + if (modes[i] == present_mode) + { + supported = TRUE; + break; + } + } + } + else + { + WARN("Failed to get available present modes, vr %d.\n", vr); + } + heap_free(modes); + + return supported; +} + static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain, VkFormat vk_format) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; @@ -1527,7 +1573,7 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s vk_swapchain_desc.pQueueFamilyIndices = NULL; vk_swapchain_desc.preTransform = surface_caps.currentTransform; vk_swapchain_desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - vk_swapchain_desc.presentMode = VK_PRESENT_MODE_FIFO_KHR; + vk_swapchain_desc.presentMode = swapchain->present_mode; vk_swapchain_desc.clipped = VK_TRUE; vk_swapchain_desc.oldSwapchain = swapchain->vk_swapchain; if ((vr = vk_funcs->p_vkCreateSwapchainKHR(vk_device, &vk_swapchain_desc, NULL, &vk_swapchain)) < 0) @@ -1922,6 +1968,52 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetCoreWindow(IDXGISwapChain3 * return DXGI_ERROR_INVALID_CALL; } +static HRESULT d3d12_swapchain_set_sync_interval(struct d3d12_swapchain *swapchain, + unsigned int sync_interval) +{ + VkPresentModeKHR present_mode; + HRESULT hr; + + switch (sync_interval) + { + case 0: + present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; + break; + default: + FIXME("Unsupported sync interval %u.\n", sync_interval); + case 1: + present_mode = VK_PRESENT_MODE_FIFO_KHR; + break; + } + + if (swapchain->present_mode == present_mode) + return S_OK; + + if (!swapchain->vk_images[swapchain->current_buffer_index]) + { + FIXME("Cannot recreate swapchain without user images.\n"); + return S_OK; + } + + if (!d3d12_swapchain_is_present_mode_supported(swapchain, present_mode)) + { + FIXME("Vulkan present mode %#x is not supported.\n", present_mode); + return S_OK; + } + + d3d12_swapchain_destroy_buffers(swapchain, FALSE); + + swapchain->present_mode = present_mode; + + if (FAILED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain))) + { + ERR("Failed to recreate Vulkan swapchain, hr %#x.\n", hr); + return hr; + } + + return d3d12_swapchain_acquire_next_image(swapchain); +} + static VkResult d3d12_swapchain_blit_buffer(struct d3d12_swapchain *swapchain, VkQueue vk_queue) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; @@ -1989,8 +2081,6 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_Present1(IDXGISwapChain3 *iface WARN("Invalid sync interval %u.\n", sync_interval); return DXGI_ERROR_INVALID_CALL; } - if (sync_interval != 1) - FIXME("Ignoring sync interval %u.\n", sync_interval); if (flags & ~DXGI_PRESENT_TEST) FIXME("Unimplemented flags %#x.\n", flags); @@ -2003,6 +2093,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_Present1(IDXGISwapChain3 *iface if (present_parameters) FIXME("Ignored present parameters %p.\n", present_parameters); + if (FAILED(hr = d3d12_swapchain_set_sync_interval(swapchain, sync_interval))) + return hr; + if (!(vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue))) { ERR("Failed to acquire Vulkan queue.\n"); @@ -2391,6 +2484,8 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI swapchain->desc = *swapchain_desc; swapchain->fullscreen_desc = *fullscreen_desc; + swapchain->present_mode = VK_PRESENT_MODE_FIFO_KHR; + switch (swapchain_desc->SwapEffect) { case DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL: