[PATCH 6/6] dxgi/tests: Enable for D3D12 all tests that can succeed.

Conor McCarthy cmccarthy at codeweavers.com
Mon Oct 7 23:13:54 CDT 2019


It is not yet possible to get an IDXGIAdapter in Wine's D3D12. This makes
most of the multithreadable tests unworkable at the moment.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 dlls/dxgi/tests/dxgi.c | 557 ++++++++++++++++++++++-------------------
 1 file changed, 293 insertions(+), 264 deletions(-)

diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index 7a1baa82..a3ac788d 100644
--- a/dlls/dxgi/tests/dxgi.c
+++ b/dlls/dxgi/tests/dxgi.c
@@ -291,6 +291,9 @@ static BOOL output_belongs_to_adapter(IDXGIOutput *output, IDXGIAdapter *adapter
     IDXGIOutput *o;
     HRESULT hr;
 
+    if (!adapter)
+        return FALSE;
+
     hr = IDXGIOutput_GetDesc(output, &output_desc);
     ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
 
@@ -737,6 +740,7 @@ static IDXGIAdapter *get_adapter_(unsigned int line, IUnknown *device, BOOL is_d
         hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory4, (void **)&factory4);
         ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#x.\n", hr);
         hr = IDXGIFactory4_EnumAdapterByLuid(factory4, luid, &IID_IDXGIAdapter, (void **)&adapter);
+        todo_wine
         ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#x.\n", hr);
         IDXGIFactory4_Release(factory4);
         IDXGIFactory_Release(factory);
@@ -1450,21 +1454,21 @@ struct refresh_rates
     BOOL denominator_should_pass;
 };
 
-static void test_create_swapchain(void)
+static void test_create_swapchain(IUnknown *device, BOOL is_d3d12)
 {
     struct swapchain_fullscreen_state initial_state, expected_state;
     unsigned int  i, expected_width, expected_height;
     DXGI_SWAP_CHAIN_DESC creation_desc, result_desc;
     DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
+    IUnknown *obj = device, *obj2, *parent;
+    ULONG refcount, expected_refcount = 0;
     DXGI_SWAP_CHAIN_DESC1 swapchain_desc;
-    IDXGIDevice *device, *bgra_device;
-    ULONG refcount, expected_refcount;
-    IUnknown *obj, *obj2, *parent;
+    IDXGIAdapter *adapter = NULL;
     IDXGISwapChain1 *swapchain1;
     RECT *expected_client_rect;
     IDXGISwapChain *swapchain;
+    IDXGIDevice *bgra_device;
     IDXGISurface1 *surface;
-    IDXGIAdapter *adapter;
     IDXGIFactory *factory;
     IDXGIOutput *target;
     BOOL fullscreen;
@@ -1480,11 +1484,7 @@ static void test_create_swapchain(void)
         { 0,  0,  TRUE, FALSE},
     };
 
-    if (!(device = create_device(0)))
-    {
-        skip("Failed to create device.\n");
-        return;
-    }
+    get_factory(device, is_d3d12, &factory);
 
     creation_desc.BufferDesc.Width = 800;
     creation_desc.BufferDesc.Height = 600;
@@ -1496,26 +1496,29 @@ static void test_create_swapchain(void)
     creation_desc.SampleDesc.Count = 1;
     creation_desc.SampleDesc.Quality = 0;
     creation_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    creation_desc.BufferCount = 1;
+    creation_desc.BufferCount = is_d3d12 ? 2 : 1;
     creation_desc.OutputWindow = NULL;
     creation_desc.Windowed = TRUE;
-    creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    creation_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
     creation_desc.Flags = 0;
 
-    hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
-    ok(hr == S_OK, "IDXGIDevice does not implement IUnknown.\n");
-
-    hr = IDXGIDevice_GetAdapter(device, &adapter);
-    ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr);
-
-    hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
-    ok(hr == S_OK, "Failed to get parent, hr %#x.\n", hr);
+    if (!is_d3d12)
+    {
+        hr = IDXGIDevice_QueryInterface((IDXGIDevice *)device, &IID_IUnknown, (void **)&obj);
+        ok(hr == S_OK, "IDXGIDevice does not implement IUnknown.\n");
 
-    expected_refcount = get_refcount(adapter);
-    refcount = get_refcount(factory);
-    ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
-    refcount = get_refcount(device);
-    ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+        hr = IDXGIDevice_GetAdapter((IDXGIDevice *)device, &adapter);
+        ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr);
+        expected_refcount = get_refcount(adapter);
+        refcount = get_refcount(factory);
+        ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+        refcount = get_refcount(device);
+        ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+    }
+    else
+    {
+        adapter = get_adapter(device, TRUE);
+    }
 
     creation_desc.OutputWindow = NULL;
     hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
@@ -1534,12 +1537,13 @@ static void test_create_swapchain(void)
     hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
     ok(hr == S_OK, "Failed to create swapchain, hr %#x.\n", hr);
 
-    refcount = get_refcount(adapter);
+    refcount = !adapter ? 0 : get_refcount(adapter);
     ok(refcount >= expected_refcount, "Got refcount %u, expected >= %u.\n", refcount, expected_refcount);
     refcount = get_refcount(factory);
-    todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
+    todo_wine ok(refcount == 5 || broken(refcount == 4), "Got unexpected refcount %u.\n", refcount);
     refcount = get_refcount(device);
-    ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
+    todo_wine_if(is_d3d12)
+    ok(refcount == (is_d3d12 ? 6 : 3), "Got unexpected refcount %u.\n", refcount);
 
     hr = IDXGISwapChain_GetDesc(swapchain, NULL);
     ok(hr == E_INVALIDARG, "GetDesc unexpectedly returned %#x.\n", hr);
@@ -1548,13 +1552,13 @@ static void test_create_swapchain(void)
     ok(hr == S_OK, "Failed to get parent,%#x.\n", hr);
     ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
     refcount = IUnknown_Release(parent);
-    todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
+    todo_wine ok(refcount == 5 || broken(refcount == 4), "Got unexpected refcount %u.\n", refcount);
 
     hr = IDXGISwapChain_GetParent(swapchain, &IID_IDXGIFactory, (void **)&parent);
     ok(hr == S_OK, "Failed to get parent,%#x.\n", hr);
     ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
     refcount = IUnknown_Release(parent);
-    todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
+    todo_wine ok(refcount == 5 || broken(refcount == 4), "Got unexpected refcount %u.\n", refcount);
 
     hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1);
     ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
@@ -1586,7 +1590,7 @@ static void test_create_swapchain(void)
     ok(!refcount, "Swapchain has %u references left.\n", refcount);
 
     refcount = get_refcount(factory);
-    ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+    ok(refcount == (is_d3d12 ? 1 : 2), "Got unexpected refcount %u.\n", refcount);
 
     for (i = 0; i < ARRAY_SIZE(refresh_list); ++i)
     {
@@ -1602,11 +1606,11 @@ static void test_create_swapchain(void)
         ok(result_desc.Windowed == creation_desc.Windowed, "Test %u: Got unexpected windowed %#x.\n",
                 i, result_desc.Windowed);
 
-        todo_wine_if (!refresh_list[i].numerator_should_pass)
+        todo_wine_if (!is_d3d12 && !refresh_list[i].numerator_should_pass)
             ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
                     "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
 
-        todo_wine_if (!refresh_list[i].denominator_should_pass)
+        todo_wine_if (!is_d3d12 && !refresh_list[i].denominator_should_pass)
             ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
                     "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
 
@@ -1700,11 +1704,11 @@ static void test_create_swapchain(void)
         if (result_desc.Windowed != creation_desc.Windowed)
             trace("Test %u: Failed to change fullscreen state.\n", i);
 
-        todo_wine_if (!refresh_list[i].numerator_should_pass)
+        todo_wine_if (!is_d3d12 && !refresh_list[i].numerator_should_pass)
             ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
                     "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
 
-        todo_wine_if (!refresh_list[i].denominator_should_pass)
+        todo_wine_if (!is_d3d12 && !refresh_list[i].denominator_should_pass)
             ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
                     "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
 
@@ -1724,6 +1728,7 @@ static void test_create_swapchain(void)
                     i, containing_output);
             IDXGIOutput_Release(containing_output);
 
+            todo_wine_if(is_d3d12)
             ok(output_belongs_to_adapter(target, adapter),
                     "Test %u: Output %p doesn't belong to adapter %p.\n",
                     i, target, adapter);
@@ -1763,19 +1768,22 @@ static void test_create_swapchain(void)
     creation_desc.Windowed = TRUE;
     creation_desc.Flags = 0;
     hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
-    ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+    ok(hr == E_INVALIDARG || hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
 
     creation_desc.Windowed = FALSE;
     hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
-    ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
-
-    creation_desc.BufferCount = 2;
-    creation_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
-    hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
     ok(hr == E_INVALIDARG || hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
-    creation_desc.BufferCount = 1;
-    creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
 
+    /* BufferCount and SwapEffect are already set to these values in D3D12. */
+    if (!is_d3d12)
+    {
+        creation_desc.BufferCount = 2;
+        creation_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+        hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
+        ok(hr == E_INVALIDARG || hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
+        creation_desc.BufferCount = 1;
+        creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    }
     check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
 
     /* Test swapchain creation with backbuffer width and height equal to 0. */
@@ -1911,9 +1919,9 @@ static void test_create_swapchain(void)
     ok(hr == S_OK, "Failed to create swapchain, hr %#x.\n", hr);
     hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
     ok(hr == S_OK, "Failed to get swapchain desc, hr %#x.\n", hr);
-    todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
+    todo_wine_if(!is_d3d12) ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
             result_desc.BufferDesc.Width, expected_width);
-    todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
+    todo_wine_if(!is_d3d12) ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
             result_desc.BufferDesc.Height, expected_height);
     check_swapchain_fullscreen_state(swapchain, &expected_state);
     hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
@@ -1924,13 +1932,15 @@ static void test_create_swapchain(void)
     IDXGIOutput_Release(expected_state.target);
 
 done:
-    IUnknown_Release(obj);
-    refcount = IDXGIDevice_Release(device);
-    ok(!refcount, "Device has %u references left.\n", refcount);
-    refcount = IDXGIAdapter_Release(adapter);
-    ok(!refcount, "Adapter has %u references left.\n", refcount);
+    if (!is_d3d12)
+    {
+        IUnknown_Release(obj);
+        refcount = IDXGIAdapter_Release(adapter);
+        todo_wine
+        ok(refcount == 2 || broken(refcount == 1), "Adapter has %u references left.\n", refcount);
+    }
     refcount = IDXGIFactory_Release(factory);
-    ok(!refcount, "Factory has %u references left.\n", refcount);
+    ok(refcount == !is_d3d12, "Factory has %u references left.\n", refcount);
     check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
     DestroyWindow(creation_desc.OutputWindow);
 }
@@ -3008,16 +3018,14 @@ static void test_resize_target_wndproc(void)
     CloseHandle(thread_data.finished);
 }
 
-static void test_inexact_modes(void)
+static void test_inexact_modes(IUnknown *device, BOOL is_d3d12)
 {
     struct swapchain_fullscreen_state initial_state, expected_state;
     DXGI_SWAP_CHAIN_DESC swapchain_desc, result_desc;
+    unsigned int i, expected_width, expected_height;
     IDXGIOutput *output = NULL;
     IDXGISwapChain *swapchain;
     IDXGIFactory *factory;
-    IDXGIAdapter *adapter;
-    IDXGIDevice *device;
-    unsigned int i;
     ULONG refcount;
     HRESULT hr;
 
@@ -3032,17 +3040,7 @@ static void test_inexact_modes(void)
         {799, 601},
     };
 
-    if (!(device = create_device(0)))
-    {
-        skip("Failed to create device.\n");
-        return;
-    }
-
-    hr = IDXGIDevice_GetAdapter(device, &adapter);
-    ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
-
-    hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
-    ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
+    get_factory(device, is_d3d12, &factory);
 
     swapchain_desc.BufferDesc.Width = 800;
     swapchain_desc.BufferDesc.Height = 600;
@@ -3054,10 +3052,10 @@ static void test_inexact_modes(void)
     swapchain_desc.SampleDesc.Count = 1;
     swapchain_desc.SampleDesc.Quality = 0;
     swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    swapchain_desc.BufferCount = 1;
+    swapchain_desc.BufferCount = is_d3d12 ? 2 : 1;
     swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
     swapchain_desc.Windowed = FALSE;
-    swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
     swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
 
     memset(&initial_state, 0, sizeof(initial_state));
@@ -3105,10 +3103,12 @@ static void test_inexact_modes(void)
         check_swapchain_fullscreen_state(swapchain, &expected_state);
         hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
         ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
-        ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
-                result_desc.BufferDesc.Width, sizes[i].width);
-        ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
-                result_desc.BufferDesc.Height, sizes[i].height);
+        expected_width = is_d3d12 ? expected_state.fullscreen_state.client_rect.right : sizes[i].width;
+        expected_height = is_d3d12 ? expected_state.fullscreen_state.client_rect.bottom : sizes[i].height;
+        ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
+                result_desc.BufferDesc.Width, expected_width);
+        ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
+                result_desc.BufferDesc.Height, expected_height);
 
         hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
         ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
@@ -3176,11 +3176,8 @@ static void test_inexact_modes(void)
 done:
     if (output)
         IDXGIOutput_Release(output);
-    IDXGIAdapter_Release(adapter);
-    refcount = IDXGIDevice_Release(device);
-    ok(!refcount, "Device has %u references left.\n", refcount);
     refcount = IDXGIFactory_Release(factory);
-    ok(!refcount, "Factory has %u references left.\n", refcount);
+    ok(refcount == !is_d3d12, "Factory has %u references left.\n", refcount);
 }
 
 static void test_create_factory(void)
@@ -3780,22 +3777,21 @@ static void test_swapchain_resize(IUnknown *device, BOOL is_d3d12)
     ok(refcount == !is_d3d12, "Got unexpected refcount %u.\n", refcount);
 }
 
-static void test_swapchain_parameters(void)
+static void test_swapchain_parameters(IUnknown *device, BOOL is_d3d12)
 {
     DXGI_USAGE usage, expected_usage, broken_usage;
     D3D10_TEXTURE2D_DESC d3d10_texture_desc;
     D3D11_TEXTURE2D_DESC d3d11_texture_desc;
+    D3D12_RESOURCE_DESC d3d12_resource_desc;
     unsigned int expected_bind_flags;
     ID3D10Texture2D *d3d10_texture;
     ID3D11Texture2D *d3d11_texture;
+    ID3D12Resource *d3d12_resource;
     DXGI_SWAP_CHAIN_DESC desc;
     IDXGISwapChain *swapchain;
     IDXGIResource *resource;
-    IDXGIAdapter *adapter;
     IDXGIFactory *factory;
-    IDXGIDevice *device;
     unsigned int i, j;
-    ULONG refcount;
     IUnknown *obj;
     HWND window;
     HRESULT hr;
@@ -3805,71 +3801,71 @@ static void test_swapchain_parameters(void)
         BOOL windowed;
         UINT buffer_count;
         DXGI_SWAP_EFFECT swap_effect;
-        HRESULT hr, vista_hr;
+        HRESULT hr, vista_hr, d3d12_hr;
         UINT highest_accessible_buffer;
     }
     tests[] =
     {
-        {TRUE,   0, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   1, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                     0},
-        {TRUE,   2, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                     0},
-        {TRUE,   0, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   1, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                     0},
-        {TRUE,   2, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                     1},
-        {TRUE,   3, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                     2},
-        {TRUE,   0, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   1, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   2, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL,  1},
-        {TRUE,   3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL,  2},
-        {TRUE,   0, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   1, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   2, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   0, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   1, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,   2, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,  16, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                     0},
-        {TRUE,  16, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    15},
-        {TRUE,  16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, 15},
-        {TRUE,  16, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,  17, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,  17, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,  17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {TRUE,  17, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-
-        {FALSE,  0, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  1, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                     0},
-        {FALSE,  2, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                     0},
-        {FALSE,  0, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  1, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                     0},
-        {FALSE,  2, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                     1},
-        {FALSE,  3, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                     2},
-        {FALSE,  0, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  1, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  2, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL,  1},
-        {FALSE,  3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL,  2},
-        {FALSE,  0, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  1, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  2, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  0, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  1, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE,  2, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE, 16, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                     0},
-        {FALSE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    15},
-        {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, 15},
+        {TRUE,   0, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   1, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   2, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   0, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   1, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   2, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  1},
+        {TRUE,   3, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  2},
+        {TRUE,   0, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   1, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   2, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     1},
+        {TRUE,   3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     2},
+        {TRUE,   0, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   1, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   2, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     0},
+        {TRUE,   0, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   1, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,   2, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,  16, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,  16, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL, 15},
+        {TRUE,  16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                    15},
+        {TRUE,  16, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     0},
+        {TRUE,  17, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,  17, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,  17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {TRUE,  17, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+
+        {FALSE,  0, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  1, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  2, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  0, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  1, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  2, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  1},
+        {FALSE,  3, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  2},
+        {FALSE,  0, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  1, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  2, 2 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     1},
+        {FALSE,  3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     2},
+        {FALSE,  0, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  1, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  2, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                     0},
+        {FALSE,  0, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  1, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE,  2, 5 /* undefined */,                DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE, 16, DXGI_SWAP_EFFECT_DISCARD,         S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL,      S_OK,                    S_OK,                    DXGI_ERROR_INVALID_CALL, 15},
+        {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK,                    DXGI_ERROR_INVALID_CALL, S_OK,                    15},
         /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
          * process. Disable it for now.
         {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD,    S_OK,                    DXGI_ERROR_INVALID_CALL,  0},
          */
-        {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
-        {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD,         DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL,      DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
+        {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD,    DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL,  0},
     };
     static const DXGI_USAGE usage_tests[] =
     {
@@ -3885,21 +3881,20 @@ static void test_swapchain_parameters(void)
         DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_DISCARD_ON_PRESENT,
     };
 
-    if (!(device = create_device(0)))
-    {
-        skip("Failed to create device.\n");
-        return;
-    }
+    get_factory(device, is_d3d12, &factory);
     window = create_window();
 
-    hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
-    ok(hr == S_OK, "IDXGIDevice does not implement IUnknown.\n");
-
-    hr = IDXGIDevice_GetAdapter(device, &adapter);
-    ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr);
-    hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
-    ok(hr == S_OK, "Failed to get parent, hr %#x.\n", hr);
-    IDXGIAdapter_Release(adapter);
+    if (is_d3d12)
+    {
+        obj = device;
+        hr = ID3D12CommandQueue_QueryInterface((ID3D12CommandQueue *)device, &IID_IUnknown, (void **)&obj);
+        ok(hr == S_OK, "ID3D12CommandQueue does not implement IUnknown.\n");
+    }
+    else
+    {
+        hr = IDXGIDevice_QueryInterface((IDXGIDevice *)device, &IID_IUnknown, (void **)&obj);
+        ok(hr == S_OK, "IDXGIDevice does not implement IUnknown.\n");
+    }
 
     for (i = 0; i < ARRAY_SIZE(tests); ++i)
     {
@@ -3916,36 +3911,57 @@ static void test_swapchain_parameters(void)
         desc.SwapEffect = tests[i].swap_effect;
 
         hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
-        ok(hr == tests[i].hr || broken(hr == tests[i].vista_hr)
+        ok(hr == (is_d3d12 ? tests[i].d3d12_hr : tests[i].hr) || broken(hr == tests[i].vista_hr)
                 || (SUCCEEDED(tests[i].hr) && hr == DXGI_STATUS_OCCLUDED),
                 "Got unexpected hr %#x, test %u.\n", hr, i);
         if (FAILED(hr))
             continue;
 
-        hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
-        todo_wine ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
-        if (FAILED(hr))
+        if (!is_d3d12)
         {
-            hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
-            ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
+            hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
+            todo_wine ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
+            if (FAILED(hr))
+            {
+                hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+                ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
 
-            IDXGISwapChain_Release(swapchain);
-            continue;
+                IDXGISwapChain_Release(swapchain);
+                continue;
+            }
+
+            expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+            if (tests[i].swap_effect == DXGI_SWAP_EFFECT_DISCARD)
+                expected_usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
+            hr = IDXGIResource_GetUsage(resource, &usage);
+            ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
+            ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
+
+            IDXGIResource_Release(resource);
         }
+        else
+        {
+            hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D12Resource, (void **)&d3d12_resource);
+            ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
+            if (FAILED(hr))
+            {
+                hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+                ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
 
-        expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
-        if (tests[i].swap_effect == DXGI_SWAP_EFFECT_DISCARD)
-            expected_usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
-        hr = IDXGIResource_GetUsage(resource, &usage);
-        ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
-        ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
+                IDXGISwapChain_Release(swapchain);
+                continue;
+            }
 
-        IDXGIResource_Release(resource);
+            d3d12_resource_desc = ID3D12Resource_GetDesc(d3d12_resource);
+            ok(d3d12_resource_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, "D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET not set, test %u.\n", i);
+
+            ID3D12Resource_Release(d3d12_resource);
+        }
 
         hr = IDXGISwapChain_GetDesc(swapchain, &desc);
         ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
 
-        for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
+        if (!is_d3d12) for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
         {
             hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
             ok(SUCCEEDED(hr), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr, i, j);
@@ -3980,8 +3996,29 @@ static void test_swapchain_parameters(void)
 
             IDXGIResource_Release(resource);
         }
-        hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
-        ok(hr == DXGI_ERROR_INVALID_CALL, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
+        else for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
+        {
+            hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_ID3D12Resource, (void **)&d3d12_resource);
+            ok(SUCCEEDED(hr), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr, i, j);
+            d3d12_resource_desc = ID3D12Resource_GetDesc(d3d12_resource);
+            ok(d3d12_resource_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
+                    "D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET not set, test %u.\n", i);
+
+            ID3D12Resource_Release(d3d12_resource);
+        }
+        if (!is_d3d12)
+        {
+            hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
+            ok(hr == DXGI_ERROR_INVALID_CALL, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
+        }
+        else
+        {
+            hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_ID3D12Resource, (void **)&d3d12_resource);
+            ok(hr == (tests[i].swap_effect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ? DXGI_ERROR_INVALID_CALL : tests[i].d3d12_hr),
+                    "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
+            if (SUCCEEDED(hr))
+                ID3D12Resource_Release(d3d12_resource);
+        }
 
         hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
         ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
@@ -3992,6 +4029,11 @@ static void test_swapchain_parameters(void)
     for (i = 0; i < ARRAY_SIZE(usage_tests); ++i)
     {
         usage = usage_tests[i];
+        if (usage & DXGI_USAGE_DISCARD_ON_PRESENT)
+        {
+            skip("DXGI_USAGE_DISCARD_ON_PRESENT is not valid in D3D12.\n");
+            continue;
+        }
 
         memset(&desc, 0, sizeof(desc));
         desc.BufferDesc.Width = registry_mode.dmPelsWidth;
@@ -3999,16 +4041,16 @@ static void test_swapchain_parameters(void)
         desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
         desc.SampleDesc.Count = 1;
         desc.BufferUsage = usage;
-        desc.BufferCount = 1;
+        desc.BufferCount = is_d3d12 ? 2 : 1;
         desc.OutputWindow = window;
         desc.Windowed = TRUE;
-        desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+        desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
         hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
         ok(hr == S_OK, "Got unexpected hr %#x, test %u.\n", hr, i);
 
         hr = IDXGISwapChain_GetDesc(swapchain, &desc);
         ok(hr == S_OK, "Failed to get swapchain desc, hr %#x, test %u.\n", hr, i);
-        todo_wine_if(usage & ~(DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT))
+        todo_wine_if(!is_d3d12 && (usage & ~(DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT)))
         ok(desc.BufferUsage == usage, "Got usage %#x, expected %#x, test %u.\n", desc.BufferUsage, usage, i);
 
         expected_bind_flags = 0;
@@ -4017,42 +4059,64 @@ static void test_swapchain_parameters(void)
         if (usage & DXGI_USAGE_SHADER_INPUT)
             expected_bind_flags |= D3D11_BIND_SHADER_RESOURCE;
 
-        hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&d3d10_texture);
-        ok(hr == S_OK, "Failed to get d3d10 texture, hr %#x, test %u.\n", hr, i);
-        ID3D10Texture2D_GetDesc(d3d10_texture, &d3d10_texture_desc);
-        ok(d3d10_texture_desc.BindFlags == expected_bind_flags,
-                "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
-                d3d10_texture_desc.BindFlags, expected_bind_flags, i);
-        ID3D10Texture2D_Release(d3d10_texture);
-
-        hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D11Texture2D, (void **)&d3d11_texture);
-        ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Failed to get d3d11 texture, hr %#x, test %u.\n", hr, i);
-        if (SUCCEEDED(hr))
+        if (!is_d3d12)
         {
-            ID3D11Texture2D_GetDesc(d3d11_texture, &d3d11_texture_desc);
-            ok(d3d11_texture_desc.BindFlags == expected_bind_flags,
-                    "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
-                    d3d11_texture_desc.BindFlags, expected_bind_flags, i);
-            ID3D11Texture2D_Release(d3d11_texture);
-        }
+            hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&d3d10_texture);
+            ok(hr == S_OK, "Failed to get d3d10 texture, hr %#x, test %u.\n", hr, i);
+            ID3D10Texture2D_GetDesc(d3d10_texture, &d3d10_texture_desc);
+            ok(d3d10_texture_desc.BindFlags == expected_bind_flags,
+                    "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
+                    d3d10_texture_desc.BindFlags, expected_bind_flags, i);
+            ID3D10Texture2D_Release(d3d10_texture);
+
+            hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D11Texture2D, (void **)&d3d11_texture);
+            ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Failed to get d3d11 texture, hr %#x, test %u.\n", hr, i);
+            if (SUCCEEDED(hr))
+            {
+                ID3D11Texture2D_GetDesc(d3d11_texture, &d3d11_texture_desc);
+                ok(d3d11_texture_desc.BindFlags == expected_bind_flags,
+                        "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
+                        d3d11_texture_desc.BindFlags, expected_bind_flags, i);
+                ID3D11Texture2D_Release(d3d11_texture);
+            }
 
-        hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
-        todo_wine ok(hr == S_OK, "Failed to get buffer, hr %#x, test %u.\n", hr, i);
-        if (FAILED(hr))
+            hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
+            todo_wine ok(hr == S_OK, "Failed to get buffer, hr %#x, test %u.\n", hr, i);
+            if (FAILED(hr))
+            {
+                IDXGISwapChain_Release(swapchain);
+                continue;
+            }
+            expected_usage = usage | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_DISCARD_ON_PRESENT;
+            hr = IDXGIResource_GetUsage(resource, &usage);
+            ok(hr == S_OK, "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
+            ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
+            IDXGIResource_Release(resource);
+        }
+        else
         {
-            IDXGISwapChain_Release(swapchain);
-            continue;
+            hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D12Resource, (void **)&d3d12_resource);
+            ok(hr == S_OK, "Failed to get buffer, hr %#x, test %u.\n", hr, i);
+            if (FAILED(hr))
+            {
+                IDXGISwapChain_Release(swapchain);
+                continue;
+            }
+            d3d12_resource_desc = ID3D12Resource_GetDesc(d3d12_resource);
+            ok(d3d12_resource_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, "D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET not set, test %u.\n", i);
+            ID3D12Resource_Release(d3d12_resource);
         }
-        expected_usage = usage | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_DISCARD_ON_PRESENT;
-        hr = IDXGIResource_GetUsage(resource, &usage);
-        ok(hr == S_OK, "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
-        ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
-        IDXGIResource_Release(resource);
 
         IDXGISwapChain_Release(swapchain);
     }
 
     /* multisampling */
+    if (is_d3d12)
+    {
+        skip("Multisampled render targets are resolved explicitly in D3D12.\n");
+        goto done;
+    }
+
     memset(&desc, 0, sizeof(desc));
     desc.BufferDesc.Width = registry_mode.dmPelsWidth;
     desc.BufferDesc.Height = registry_mode.dmPelsHeight;
@@ -4068,7 +4132,7 @@ static void test_swapchain_parameters(void)
     desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
     hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
     ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
-    if (check_multisample_quality_levels(device, desc.BufferDesc.Format, desc.SampleDesc.Count))
+    if (check_multisample_quality_levels((IDXGIDevice *)device, desc.BufferDesc.Format, desc.SampleDesc.Count))
     {
         desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
         hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
@@ -4084,10 +4148,9 @@ static void test_swapchain_parameters(void)
         skip("Multisampling not supported for DXGI_FORMAT_R8G8B8A8_UNORM.\n");
     }
 
+done:
     IDXGIFactory_Release(factory);
     IUnknown_Release(obj);
-    refcount = IDXGIDevice_Release(device);
-    ok(!refcount, "Device has %u references left.\n", refcount);
     DestroyWindow(window);
 }
 
@@ -4857,14 +4920,12 @@ static LRESULT CALLBACK test_wndproc(HWND hwnd, unsigned int message, WPARAM wpa
     return DefWindowProcA(hwnd, message, wparam, lparam);
 }
 
-static void test_swapchain_window_messages(void)
+static void test_swapchain_window_messages(IUnknown *device, BOOL is_d3d12)
 {
     DXGI_SWAP_CHAIN_DESC swapchain_desc;
     IDXGISwapChain *swapchain;
     DXGI_MODE_DESC mode_desc;
     IDXGIFactory *factory;
-    IDXGIAdapter *adapter;
-    IDXGIDevice *device;
     ULONG refcount;
     WNDCLASSA wc;
     HWND window;
@@ -4926,11 +4987,7 @@ static void test_swapchain_window_messages(void)
         {0,                    FALSE, 0},
     };
 
-    if (!(device = create_device(0)))
-    {
-        skip("Failed to create device.\n");
-        return;
-    }
+    get_factory(device, is_d3d12, &factory);
 
     memset(&wc, 0, sizeof(wc));
     wc.lpfnWndProc = test_wndproc;
@@ -4939,12 +4996,6 @@ static void test_swapchain_window_messages(void)
     window = CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
     ok(!!window, "Failed to create window.\n");
 
-    hr = IDXGIDevice_GetAdapter(device, &adapter);
-    ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr);
-    hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
-    ok(hr == S_OK, "Failed to get parent, hr %#x.\n", hr);
-    IDXGIAdapter_Release(adapter);
-
     swapchain_desc.BufferDesc.Width = 800;
     swapchain_desc.BufferDesc.Height = 600;
     swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
@@ -4955,10 +5006,10 @@ static void test_swapchain_window_messages(void)
     swapchain_desc.SampleDesc.Count = 1;
     swapchain_desc.SampleDesc.Quality = 0;
     swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    swapchain_desc.BufferCount = 1;
+    swapchain_desc.BufferCount = is_d3d12 ? 2 : 1;
     swapchain_desc.OutputWindow = window;
     swapchain_desc.Windowed = TRUE;
-    swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
     swapchain_desc.Flags = 0;
 
     /* create swapchain */
@@ -5051,22 +5102,18 @@ done:
     ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
     DestroyWindow(window);
 
-    refcount = IDXGIDevice_Release(device);
-    ok(!refcount, "Device has %u references left.\n", refcount);
     refcount = IDXGIFactory_Release(factory);
-    ok(!refcount, "Factory has %u references left.\n", refcount);
+    ok(refcount == !is_d3d12, "Factory has %u references left.\n", refcount);
 
     UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL));
 }
 
-static void test_swapchain_window_styles(void)
+static void test_swapchain_window_styles(IUnknown *device, BOOL is_d3d12)
 {
     LONG style, exstyle, fullscreen_style, fullscreen_exstyle;
     DXGI_SWAP_CHAIN_DESC swapchain_desc;
     IDXGISwapChain *swapchain;
     IDXGIFactory *factory;
-    IDXGIAdapter *adapter;
-    IDXGIDevice *device;
     ULONG refcount;
     unsigned int i;
     HRESULT hr;
@@ -5094,17 +5141,7 @@ static void test_swapchain_window_styles(void)
          WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE},
     };
 
-    if (!(device = create_device(0)))
-    {
-        skip("Failed to create device.\n");
-        return;
-    }
-
-    hr = IDXGIDevice_GetAdapter(device, &adapter);
-    ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr);
-    hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
-    ok(hr == S_OK, "Failed to get parent, hr %#x.\n", hr);
-    IDXGIAdapter_Release(adapter);
+    get_factory(device, is_d3d12, &factory);
 
     swapchain_desc.BufferDesc.Width = 800;
     swapchain_desc.BufferDesc.Height = 600;
@@ -5116,9 +5153,9 @@ static void test_swapchain_window_styles(void)
     swapchain_desc.SampleDesc.Count = 1;
     swapchain_desc.SampleDesc.Quality = 0;
     swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    swapchain_desc.BufferCount = 1;
+    swapchain_desc.BufferCount = is_d3d12 ? 2 : 1;
     swapchain_desc.Windowed = TRUE;
-    swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
     swapchain_desc.Flags = 0;
 
     for (i = 0; i < ARRAY_SIZE(tests); ++i)
@@ -5192,10 +5229,8 @@ static void test_swapchain_window_styles(void)
         DestroyWindow(swapchain_desc.OutputWindow);
     }
 
-    refcount = IDXGIDevice_Release(device);
-    ok(!refcount, "Device has %u references left.\n", refcount);
     refcount = IDXGIFactory_Release(factory);
-    ok(!refcount, "Factory has %u references left.\n", refcount);
+    ok(refcount == !is_d3d12, "Factory has %u references left.\n", refcount);
 }
 
 static void test_gamma_control(void)
@@ -5310,15 +5345,13 @@ done:
     ok(!refcount, "Factory has %u references left.\n", refcount);
 }
 
-static void test_window_association(void)
+static void test_window_association(IUnknown *device, BOOL is_d3d12)
 {
     DXGI_SWAP_CHAIN_DESC swapchain_desc;
     LONG_PTR original_wndproc, wndproc;
     IDXGIFactory *factory, *factory2;
     IDXGISwapChain *swapchain;
     IDXGIOutput *output;
-    IDXGIAdapter *adapter;
-    IDXGIDevice *device;
     HWND hwnd, hwnd2;
     BOOL fullscreen;
     unsigned int i;
@@ -5355,12 +5388,6 @@ static void test_window_association(void)
         {0, FALSE}
     };
 
-    if (!(device = create_device(0)))
-    {
-        skip("Failed to create device.\n");
-        return;
-    }
-
     swapchain_desc.BufferDesc.Width = 640;
     swapchain_desc.BufferDesc.Height = 480;
     swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
@@ -5371,10 +5398,10 @@ static void test_window_association(void)
     swapchain_desc.SampleDesc.Count = 1;
     swapchain_desc.SampleDesc.Quality = 0;
     swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    swapchain_desc.BufferCount = 1;
+    swapchain_desc.BufferCount = is_d3d12 ? 2 : 1;
     swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
     swapchain_desc.Windowed = TRUE;
-    swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
     swapchain_desc.Flags = 0;
 
     original_wndproc = GetWindowLongPtrW(swapchain_desc.OutputWindow, GWLP_WNDPROC);
@@ -5383,11 +5410,7 @@ static void test_window_association(void)
     hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory2);
     ok(hr == S_OK, "Failed to create DXGI factory, hr %#x.\n", hr);
 
-    hr = IDXGIDevice_GetAdapter(device, &adapter);
-    ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-    hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
-    ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-    refcount = IDXGIAdapter_Release(adapter);
+    get_factory(device, is_d3d12, &factory);
 
     hr = IDXGIFactory_GetWindowAssociation(factory, NULL);
     ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
@@ -5463,6 +5486,7 @@ static void test_window_association(void)
             output = NULL;
             hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &output);
             ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
+            todo_wine_if(is_d3d12 && tests[i].expect_fullscreen)
             ok(fullscreen == tests[i].expect_fullscreen
                     || broken(tests[i].broken_d3d10 && fullscreen),
                     "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
@@ -5487,10 +5511,8 @@ static void test_window_association(void)
     ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
     DestroyWindow(swapchain_desc.OutputWindow);
 
-    refcount = IDXGIDevice_Release(device);
-    ok(!refcount, "Device has %u references left.\n", refcount);
     refcount = IDXGIFactory_Release(factory);
-    ok(!refcount, "Factory has %u references left.\n", refcount);
+    ok(refcount == !is_d3d12, "Factory has %u references left.\n", refcount);
 }
 
 static void test_output_ownership(IUnknown *device, BOOL is_d3d12)
@@ -5730,14 +5752,15 @@ START_TEST(dxgi)
     run_queued_tests();
 
     /* These tests use full-screen swapchains, so shouldn't run in parallel. */
-    test_create_swapchain();
+    run_on_d3d10(test_create_swapchain);
     test_default_fullscreen_target_output();
-    test_inexact_modes();
+    run_on_d3d10(test_inexact_modes);
+    /* IDXGIOutput_GetGammaControlCapabilities is not available on D3D12. */
     test_gamma_control();
-    test_swapchain_parameters();
-    test_swapchain_window_messages();
-    test_swapchain_window_styles();
-    test_window_association();
+    run_on_d3d10(test_swapchain_parameters);
+    run_on_d3d10(test_swapchain_window_messages);
+    run_on_d3d10(test_swapchain_window_styles);
+    run_on_d3d10(test_window_association);
     run_on_d3d10(test_set_fullscreen);
     run_on_d3d10(test_resize_target);
     run_on_d3d10(test_swapchain_resize);
@@ -5761,6 +5784,12 @@ START_TEST(dxgi)
         ID3D12Debug_Release(debug);
     }
 
+    run_on_d3d12(test_create_swapchain);
+    run_on_d3d12(test_inexact_modes);
+    run_on_d3d12(test_swapchain_parameters);
+    run_on_d3d12(test_swapchain_window_messages);
+    run_on_d3d12(test_swapchain_window_styles);
+    run_on_d3d12(test_window_association);
     run_on_d3d12(test_set_fullscreen);
     run_on_d3d12(test_resize_target);
     run_on_d3d12(test_swapchain_resize);
-- 
2.23.0




More information about the wine-devel mailing list