-- v3: dxgi: Reset the back buffer index to zero on ResizeBuffers(). dxgi/tests: Test that ResizeBuffers() resets the back buffer index to zero. dxgi: Always assume that a D3D12 swapchain always uses user images. dxgi: Immediately error out when creating a D3D12 swapchain on a non-immediate queue. dxgi/tests: Test that D3D12 swapchains can only be created on direct command queues.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/tests/dxgi.c | 82 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index e0465b90ed0..f8b60c241af 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -776,13 +776,13 @@ static ID3D12Device *create_d3d12_device(void) return device; }
-static ID3D12CommandQueue *create_d3d12_direct_queue(ID3D12Device *device) +static ID3D12CommandQueue *create_d3d12_queue(ID3D12Device *device, D3D12_COMMAND_LIST_TYPE type) { D3D12_COMMAND_QUEUE_DESC command_queue_desc; ID3D12CommandQueue *queue; HRESULT hr;
- command_queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + command_queue_desc.Type = type; command_queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; command_queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; command_queue_desc.NodeMask = 0; @@ -7610,7 +7610,7 @@ static void run_on_d3d12(void (*test_func)(IUnknown *device, BOOL is_d3d12)) return; }
- queue = create_d3d12_direct_queue(device); + queue = create_d3d12_queue(device, D3D12_COMMAND_LIST_TYPE_DIRECT);
test_func((IUnknown *)queue, TRUE);
@@ -7622,6 +7622,80 @@ static void run_on_d3d12(void (*test_func)(IUnknown *device, BOOL is_d3d12)) ok(!refcount, "Device has %lu references left.\n", refcount); }
+static void test_invalid_command_queue_types(void) +{ + static const enum D3D12_COMMAND_LIST_TYPE queue_types[] = + { + D3D12_COMMAND_LIST_TYPE_COMPUTE, + D3D12_COMMAND_LIST_TYPE_COPY, + }; + + DXGI_SWAP_CHAIN_DESC swapchain_desc; + ID3D12CommandQueue *queue; + IDXGISwapChain *swapchain; + IDXGIFactory *factory; + ID3D12Device *device; + IUnknown *queue_unk; + RECT client_rect; + ULONG refcount; + unsigned int i; + HWND window; + HRESULT hr; + BOOL ret; + + if (!(device = create_d3d12_device())) + { + skip("Failed to create Direct3D 12 device.\n"); + return; + } + + window = create_window(); + ret = GetClientRect(window, &client_rect); + ok(ret, "Failed to get client rect.\n"); + + for (i = 0; i < ARRAY_SIZE(queue_types); ++i) + { + queue = create_d3d12_queue(device, queue_types[i]); + hr = ID3D12CommandQueue_QueryInterface(queue, &IID_IUnknown, (void **)&queue_unk); + ok(hr == S_OK, "Got unexpected hr %lx.\n", hr); + + get_factory(queue_unk, TRUE, &factory); + + swapchain_desc.BufferDesc.Width = 640; + swapchain_desc.BufferDesc.Height = 480; + swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; + swapchain_desc.BufferDesc.RefreshRate.Denominator = 1; + swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapchain_desc.SampleDesc.Count = 1; + swapchain_desc.SampleDesc.Quality = 0; + swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchain_desc.BufferCount = 2; + swapchain_desc.OutputWindow = window; + swapchain_desc.Windowed = TRUE; + swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapchain_desc.Flags = 0; + + hr = IDXGIFactory_CreateSwapChain(factory, queue_unk, &swapchain_desc, &swapchain); + todo_wine + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + + wait_queue_idle(device, queue); + + IDXGIFactory_Release(factory); + + IUnknown_Release(queue_unk); + refcount = ID3D12CommandQueue_Release(queue); + ok(!refcount, "Command queue has %lu references left.\n", refcount); + } + + DestroyWindow(window); + + refcount = ID3D12Device_Release(device); + ok(!refcount, "Device has %lu references left.\n", refcount); +} + START_TEST(dxgi) { HMODULE dxgi_module, d3d11_module, d3d12_module, gdi32_module; @@ -7721,6 +7795,8 @@ START_TEST(dxgi) ID3D12Debug_Release(debug); }
+ test_invalid_command_queue_types(); + run_on_d3d12(test_set_fullscreen); run_on_d3d12(test_resize_target); run_on_d3d12(test_swapchain_resize);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 5 +++++ dlls/dxgi/tests/dxgi.c | 1 - 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 9677142e0af..a665342812a 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -3071,6 +3071,7 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu IDXGISwapChain1 **swapchain) { DXGI_SWAP_CHAIN_FULLSCREEN_DESC default_fullscreen_desc; + struct D3D12_COMMAND_QUEUE_DESC queue_desc; struct d3d12_swapchain *object; ID3D12Device *device; HRESULT hr; @@ -3078,6 +3079,10 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu if (swapchain_desc->Format == DXGI_FORMAT_UNKNOWN) return DXGI_ERROR_INVALID_CALL;
+ queue_desc = ID3D12CommandQueue_GetDesc(queue); + if (queue_desc.Type != D3D12_COMMAND_LIST_TYPE_DIRECT) + return DXGI_ERROR_INVALID_CALL; + if (!fullscreen_desc) { memset(&default_fullscreen_desc, 0, sizeof(default_fullscreen_desc)); diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index f8b60c241af..75d1fe6e901 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -7678,7 +7678,6 @@ static void test_invalid_command_queue_types(void) swapchain_desc.Flags = 0;
hr = IDXGIFactory_CreateSwapChain(factory, queue_unk, &swapchain_desc, &swapchain); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
wait_queue_idle(device, queue);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 184 +++++++++++------------------------------- 1 file changed, 45 insertions(+), 139 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index a665342812a..35551ab1c7e 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1184,11 +1184,6 @@ static BOOL d3d12_swapchain_is_present_mode_supported(struct d3d12_swapchain *sw return supported; }
-static BOOL d3d12_swapchain_has_user_images(struct d3d12_swapchain *swapchain) -{ - return !!swapchain->vk_images[0]; -} - static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain, VkFormat vk_format) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; @@ -1203,7 +1198,7 @@ static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapc VkResult vr; HRESULT hr;
- if (d3d12_swapchain_has_user_images(swapchain)) + if (swapchain->vk_images[0]) return S_OK;
memset(&image_info, 0, sizeof(image_info)); @@ -1455,7 +1450,6 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain, VkDevice vk_device = swapchain->vk_device; ID3D12Device *device = swapchain->device; uint32_t image_count, queue_family_index; - D3D12_COMMAND_QUEUE_DESC queue_desc; unsigned int i; VkResult vr; HRESULT hr; @@ -1493,31 +1487,13 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain, resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
- queue_desc = ID3D12CommandQueue_GetDesc(queue); - if (queue_desc.Type != D3D12_COMMAND_LIST_TYPE_DIRECT) - { - /* vkCmdBlitImage() is only supported for graphics queues. */ - FIXME("Swapchain blit not implemented for command queue type %#x.\n", queue_desc.Type); - if (vk_swapchain_format != vk_format) - return E_NOTIMPL; - if (image_count != swapchain->desc.BufferCount) - { - FIXME("Got %u swapchain images, expected %u.\n", image_count, swapchain->desc.BufferCount); - return E_NOTIMPL; - } - } queue_family_index = vkd3d_get_vk_queue_family_index(queue);
- if (queue_desc.Type == D3D12_COMMAND_LIST_TYPE_DIRECT) - { - TRACE("Creating user swapchain buffers.\n"); - - if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, vk_format))) - return hr; + 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))) - return hr; - } + if (FAILED(hr = d3d12_swapchain_prepare_command_buffers(swapchain, queue_family_index))) + return hr;
if (swapchain->buffers[0]) return S_OK; @@ -1575,23 +1551,6 @@ static VkResult d3d12_swapchain_acquire_next_vulkan_image(struct d3d12_swapchain return vr; }
-static VkResult d3d12_swapchain_acquire_next_back_buffer(struct d3d12_swapchain *swapchain) -{ - VkResult vr; - - /* If we don't have user images, we need to acquire a Vulkan image in order - * to get the correct value for the current back buffer index. */ - if (d3d12_swapchain_has_user_images(swapchain)) - return VK_SUCCESS; - - if ((vr = d3d12_swapchain_acquire_next_vulkan_image(swapchain)) >= 0) - swapchain->current_buffer_index = swapchain->vk_image_index; - else - ERR("Failed to acquire Vulkan image, vr %d.\n", vr); - - return vr; -} - static void d3d12_swapchain_destroy_buffers(struct d3d12_swapchain *swapchain, BOOL destroy_user_buffers) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; @@ -1614,7 +1573,7 @@ static void d3d12_swapchain_destroy_buffers(struct d3d12_swapchain *swapchain, B
for (i = 0; i < swapchain->desc.BufferCount; ++i) { - if (swapchain->buffers[i] && (destroy_user_buffers || !d3d12_swapchain_has_user_images(swapchain))) + if (swapchain->buffers[i] && (destroy_user_buffers || !swapchain->vk_images[0])) { vkd3d_resource_decref(swapchain->buffers[i]); swapchain->buffers[i] = NULL; @@ -1757,24 +1716,6 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s return d3d12_swapchain_create_buffers(swapchain, vk_swapchain_format, vk_format); }
-static HRESULT d3d12_swapchain_recreate_vulkan_swapchain(struct d3d12_swapchain *swapchain) -{ - VkResult vr; - HRESULT hr; - - if (SUCCEEDED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain))) - { - vr = d3d12_swapchain_acquire_next_back_buffer(swapchain); - hr = hresult_from_vk_result(vr); - } - else - { - ERR("Failed to recreate Vulkan swapchain, hr %#lx.\n", hr); - } - - return hr; -} - static inline struct d3d12_swapchain *d3d12_swapchain_from_IDXGISwapChain4(IDXGISwapChain4 *iface) { return CONTAINING_RECORD(iface, struct d3d12_swapchain, IDXGISwapChain4_iface); @@ -1950,12 +1891,6 @@ static HRESULT d3d12_swapchain_set_sync_interval(struct d3d12_swapchain *swapcha if (swapchain->present_mode == present_mode) return S_OK;
- if (!d3d12_swapchain_has_user_images(swapchain)) - { - 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); @@ -1964,14 +1899,17 @@ 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_recreate_vulkan_swapchain(swapchain); + return d3d12_swapchain_create_vulkan_swapchain(swapchain); }
static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain, VkQueue vk_queue) { const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs; VkPresentInfoKHR present_info; + VkCommandBuffer vk_cmd_buffer; VkSubmitInfo submit_info; + VkImage vk_dst_image; + VkImage vk_src_image; VkResult vr;
if (swapchain->vk_image_index == INVALID_VK_IMAGE_INDEX) @@ -1982,6 +1920,36 @@ static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain,
assert(swapchain->vk_image_index < swapchain->buffer_count);
+ vk_cmd_buffer = swapchain->vk_cmd_buffers[swapchain->vk_image_index]; + vk_dst_image = swapchain->vk_swapchain_images[swapchain->vk_image_index]; + vk_src_image = swapchain->vk_images[swapchain->current_buffer_index]; + + if ((vr = vk_funcs->p_vkResetCommandBuffer(vk_cmd_buffer, 0)) < 0) + { + ERR("Failed to reset command buffer, vr %d.\n", vr); + return vr; + } + + if ((vr = d3d12_swapchain_record_swapchain_blit(swapchain, + vk_cmd_buffer, vk_dst_image, vk_src_image)) < 0 ) + return vr; + + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = NULL; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = NULL; + submit_info.pWaitDstStageMask = NULL; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &vk_cmd_buffer; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &swapchain->vk_semaphores[swapchain->vk_image_index]; + + if ((vr = vk_funcs->p_vkQueueSubmit(vk_queue, 1, &submit_info, VK_NULL_HANDLE)) < 0) + { + ERR("Failed to blit swapchain buffer, vr %d.\n", vr); + return vr; + } + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.pNext = NULL; present_info.waitSemaphoreCount = 0; @@ -1990,43 +1958,8 @@ static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain, present_info.pSwapchains = &swapchain->vk_swapchain; present_info.pImageIndices = &swapchain->vk_image_index; present_info.pResults = NULL; - - if (d3d12_swapchain_has_user_images(swapchain)) - { - /* blit */ - VkCommandBuffer vk_cmd_buffer = swapchain->vk_cmd_buffers[swapchain->vk_image_index]; - VkImage vk_dst_image = swapchain->vk_swapchain_images[swapchain->vk_image_index]; - VkImage vk_src_image = swapchain->vk_images[swapchain->current_buffer_index]; - - if ((vr = vk_funcs->p_vkResetCommandBuffer(vk_cmd_buffer, 0)) < 0) - { - ERR("Failed to reset command buffer, vr %d.\n", vr); - return vr; - } - - if ((vr = d3d12_swapchain_record_swapchain_blit(swapchain, - vk_cmd_buffer, vk_dst_image, vk_src_image)) < 0 ) - return vr; - - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = NULL; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = NULL; - submit_info.pWaitDstStageMask = NULL; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &vk_cmd_buffer; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &swapchain->vk_semaphores[swapchain->vk_image_index]; - - if ((vr = vk_funcs->p_vkQueueSubmit(vk_queue, 1, &submit_info, VK_NULL_HANDLE)) < 0) - { - ERR("Failed to blit swapchain buffer, vr %d.\n", vr); - return vr; - } - - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &swapchain->vk_semaphores[swapchain->vk_image_index]; - } + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &swapchain->vk_semaphores[swapchain->vk_image_index];
if ((vr = vk_funcs->p_vkQueuePresentKHR(vk_queue, &present_info)) >= 0) swapchain->vk_image_index = INVALID_VK_IMAGE_INDEX; @@ -2070,16 +2003,10 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain, { vkd3d_release_vk_queue(swapchain->command_queue);
- if (!d3d12_swapchain_has_user_images(swapchain)) - { - FIXME("Cannot recreate swapchain without user images.\n"); - return DXGI_STATUS_MODE_CHANGED; - } - TRACE("Recreating Vulkan swapchain.\n");
d3d12_swapchain_destroy_buffers(swapchain, FALSE); - if (FAILED(hr = d3d12_swapchain_recreate_vulkan_swapchain(swapchain))) + if (FAILED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain))) return hr;
if (!(vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue))) @@ -2119,23 +2046,7 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain, }
swapchain->current_buffer_index = (swapchain->current_buffer_index + 1) % swapchain->desc.BufferCount; - vr = d3d12_swapchain_acquire_next_back_buffer(swapchain); - if (vr == VK_ERROR_OUT_OF_DATE_KHR) - { - if (!d3d12_swapchain_has_user_images(swapchain)) - { - FIXME("Cannot recreate swapchain without user images.\n"); - return DXGI_STATUS_MODE_CHANGED; - } - - TRACE("Recreating Vulkan swapchain.\n"); - - d3d12_swapchain_destroy_buffers(swapchain, FALSE); - return d3d12_swapchain_recreate_vulkan_swapchain(swapchain); - } - if (vr < 0) - ERR("Failed to acquire next Vulkan image, vr %d.\n", vr); - return hresult_from_vk_result(vr); + return S_OK; }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_Present(IDXGISwapChain4 *iface, UINT sync_interval, UINT flags) @@ -2352,7 +2263,7 @@ static HRESULT d3d12_swapchain_resize_buffers(struct d3d12_swapchain *swapchain,
d3d12_swapchain_destroy_buffers(swapchain, TRUE); swapchain->desc = new_desc; - return d3d12_swapchain_recreate_vulkan_swapchain(swapchain); + return d3d12_swapchain_create_vulkan_swapchain(swapchain); }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeBuffers(IDXGISwapChain4 *iface, @@ -3033,11 +2944,6 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI swapchain->vk_fence = vk_fence;
swapchain->current_buffer_index = 0; - if ((vr = d3d12_swapchain_acquire_next_back_buffer(swapchain)) < 0) - { - d3d12_swapchain_destroy(swapchain); - return hresult_from_vk_result(vr); - }
if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) {
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/tests/dxgi.c | 49 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 75d1fe6e901..6334c66d5c0 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -4941,7 +4941,6 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12) swapchain_desc.SampleDesc.Count = 1; swapchain_desc.SampleDesc.Quality = 0; swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapchain_desc.BufferCount = 4; swapchain_desc.OutputWindow = create_window(); swapchain_desc.Windowed = TRUE; swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; @@ -4954,6 +4953,7 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12)
for (i = 0; i < ARRAY_SIZE(swap_effects); ++i) { + swapchain_desc.BufferCount = 4; swapchain_desc.SwapEffect = swap_effects[i]; expected_hr = is_d3d12 && !is_flip_model(swap_effects[i]) ? DXGI_ERROR_INVALID_CALL : S_OK; hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain); @@ -4969,10 +4969,55 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12) goto done; }
- for (j = 0; j < 2 * swapchain_desc.BufferCount; ++j) + for (j = 0; j < 2 * swapchain_desc.BufferCount + 2; ++j) + { + index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); + expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; + ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); + hr = IDXGISwapChain3_Present(swapchain3, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + + swapchain_desc.BufferCount = 3; + hr = IDXGISwapChain_ResizeBuffers(swapchain, swapchain_desc.BufferCount, + rect.right, rect.bottom, DXGI_FORMAT_UNKNOWN, swapchain_desc.Flags); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* The back buffer index restarts from 0. */ + for (j = 0; j < swapchain_desc.BufferCount + 2; ++j) + { + index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); + expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; + todo_wine_if(is_d3d12) + ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); + hr = IDXGISwapChain3_Present(swapchain3, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + + hr = IDXGISwapChain_ResizeBuffers(swapchain, swapchain_desc.BufferCount, + rect.right, rect.bottom, DXGI_FORMAT_UNKNOWN, swapchain_desc.Flags); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* Even when not really changing the buffer count. */ + for (j = 0; j < swapchain_desc.BufferCount + 1; ++j) + { + index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); + expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; + todo_wine_if(is_d3d12) + ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); + hr = IDXGISwapChain3_Present(swapchain3, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + + hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, + rect.right, rect.bottom, DXGI_FORMAT_UNKNOWN, swapchain_desc.Flags); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + for (j = 0; j < swapchain_desc.BufferCount + 2; ++j) { index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; + todo_wine_if(is_d3d12) ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); hr = IDXGISwapChain3_Present(swapchain3, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 2 ++ dlls/dxgi/tests/dxgi.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 35551ab1c7e..d4cef5cc586 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2257,6 +2257,8 @@ static HRESULT d3d12_swapchain_resize_buffers(struct d3d12_swapchain *swapchain, if (!dxgi_validate_swapchain_desc(&new_desc)) return DXGI_ERROR_INVALID_CALL;
+ swapchain->current_buffer_index = 0; + if (desc->Width == new_desc.Width && desc->Height == new_desc.Height && desc->Format == new_desc.Format && desc->BufferCount == new_desc.BufferCount) return S_OK; diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 6334c66d5c0..44b7b2d9ac8 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -4988,7 +4988,6 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12) { index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; - todo_wine_if(is_d3d12) ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); hr = IDXGISwapChain3_Present(swapchain3, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); @@ -5003,7 +5002,6 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12) { index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; - todo_wine_if(is_d3d12) ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); hr = IDXGISwapChain3_Present(swapchain3, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); @@ -5017,7 +5015,6 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12) { index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3); expected_index = is_d3d12 ? j % swapchain_desc.BufferCount : 0; - todo_wine_if(is_d3d12) ok(index == expected_index, "Got back buffer index %u, expected %u.\n", index, expected_index); hr = IDXGISwapChain3_Present(swapchain3, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
It might not be a bad idea to test command list types that are supposed to succeed as well, to avoid the CreateSwapChain() call failing due to e.g. an unsupported swapchain_desc parameter.
Creating a swap chain on a direct command queue is already well tested in many other places. Here I think it would complicate the control flow without adding much useful signal.
It wouldn't so much be to test swapchain creation on a direct command queue per se, but rather to show that the reason swapchain creation fails on the other queue types is the queue type, instead of e.g. an unsupported backbuffer format or backbuffer count. I.e., increasing the confidence that the test is testing what we think it's testing.
Should this perhaps be a d3d12 test instead?
You mean it should use the `run_on_d3d12()` helper? I figured that was just for tests that could make sense for both D3D10 and D3D12. This doesn't make sense on D3D10, because the swapchain is not created from a command queue, so I thought it would be pointless to use that helper. But if you prefer to use it, it's not difficult to adapt it.
No, I mean a test in dlls/d3d12/tests/d3d12.c. As you say, this test is fairly specific to d3d12 and doesn't make much sense for d3d10/11.
That said, the argument that this is mainly testing code in dlls/dxgi instead of code in dlls/d3d12 is certainly valid too. The d3d12 tests do already have a create_command_queue() helper that takes a queue type as parameter though.
(For what it's worth, neither of these points would be blockers for me if you disagree; I just think they're worth considering.)