Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2018
- 62 participants
- 701 discussions
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/ddraw/tests/ddraw1.c | 128 +++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw2.c | 128 +++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw4.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw7.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 528 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index c767d3a38d3e..39e7d109438b 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -9046,6 +9046,133 @@ static void test_blt_z_alpha(void)
DestroyWindow(window);
}
+static void test_cross_device_blt(void)
+{
+ IDirectDrawSurface *surface, *surface2, *sysmem_surface;
+ IDirect3DDevice *device, *device2;
+ IDirectDraw *ddraw, *ddraw2;
+ DDSURFACEDESC surface_desc;
+ HWND window, window2;
+ ULONG refcount;
+ D3DCOLOR color;
+ DDBLTFX fx;
+ HRESULT hr;
+
+ window = create_window();
+ ddraw = create_ddraw();
+ if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirectDraw_Release(ddraw);
+ DestroyWindow(window);
+ return;
+ }
+
+ window2 = create_window();
+ ddraw2 = create_ddraw();
+ if (!(device2 = create_device(ddraw2, window2, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirectDraw_Release(ddraw2);
+ IDirect3DDevice_Release(device);
+ IDirectDraw_Release(ddraw);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+ return;
+ }
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
+ U5(surface_desc).dwBackBufferCount = 2;
+ hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+ surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
+ U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00007c00;
+ U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x000003e0;
+ U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000001f;
+ hr = IDirectDraw_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ U5(fx).dwFillColor = 0xff0000ff;
+ hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+ hr = IDirectDrawSurface_IsLost(sysmem_surface);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface_Release(surface2);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface_Release(surface);
+ IDirectDrawSurface_Release(surface2);
+ IDirectDrawSurface_Release(sysmem_surface);
+ refcount = IDirect3DDevice_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ refcount = IDirect3DDevice_Release(device2);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ IDirectDraw_Release(ddraw);
+ IDirectDraw_Release(ddraw2);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+}
+
static void test_getdc(void)
{
IDirectDrawSurface *surface, *surface2, *tmp;
@@ -11677,6 +11804,7 @@ START_TEST(ddraw1)
test_overlay_rect();
test_blt();
test_blt_z_alpha();
+ test_cross_device_blt();
test_getdc();
test_transform_vertices();
test_display_mode_surface_pixel_format();
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 794f90b94005..9e2107cda43c 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -10159,6 +10159,133 @@ static void test_blt_z_alpha(void)
DestroyWindow(window);
}
+static void test_cross_device_blt(void)
+{
+ IDirectDrawSurface *surface, *surface2, *sysmem_surface;
+ IDirect3DDevice2 *device, *device2;
+ IDirectDraw2 *ddraw, *ddraw2;
+ DDSURFACEDESC surface_desc;
+ HWND window, window2;
+ ULONG refcount;
+ D3DCOLOR color;
+ DDBLTFX fx;
+ HRESULT hr;
+
+ window = create_window();
+ ddraw = create_ddraw();
+ if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirectDraw2_Release(ddraw);
+ DestroyWindow(window);
+ return;
+ }
+
+ window2 = create_window();
+ ddraw2 = create_ddraw();
+ if (!(device2 = create_device(ddraw2, window2, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirectDraw2_Release(ddraw2);
+ IDirect3DDevice2_Release(device);
+ IDirectDraw2_Release(ddraw);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+ return;
+ }
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
+ U5(surface_desc).dwBackBufferCount = 2;
+ hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+ surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
+ U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00007c00;
+ U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x000003e0;
+ U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000001f;
+ hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ U5(fx).dwFillColor = 0xff0000ff;
+ hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+ hr = IDirectDrawSurface_IsLost(sysmem_surface);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface_Release(surface2);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface_Release(surface);
+ IDirectDrawSurface_Release(surface2);
+ IDirectDrawSurface_Release(sysmem_surface);
+ refcount = IDirect3DDevice2_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ refcount = IDirect3DDevice2_Release(device2);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ IDirectDraw2_Release(ddraw);
+ IDirectDraw2_Release(ddraw2);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+}
+
static void test_getdc(void)
{
IDirectDrawSurface *surface, *surface2, *tmp;
@@ -12966,6 +13093,7 @@ START_TEST(ddraw2)
test_overlay_rect();
test_blt();
test_blt_z_alpha();
+ test_cross_device_blt();
test_getdc();
test_draw_primitive();
test_edge_antialiasing_blending();
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 172d99d16707..cc77eea4a99f 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -11615,6 +11615,141 @@ static void test_blt_z_alpha(void)
DestroyWindow(window);
}
+static void test_cross_device_blt(void)
+{
+ IDirectDrawSurface4 *surface, *surface2, *sysmem_surface;
+ IDirect3DDevice3 *device, *device2;
+ IDirectDraw4 *ddraw, *ddraw2;
+ DDSURFACEDESC2 surface_desc;
+ HWND window, window2;
+ IDirect3D3 *d3d;
+ ULONG refcount;
+ D3DCOLOR color;
+ DDBLTFX fx;
+ HRESULT hr;
+
+ window = create_window();
+ if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
+ {
+ skip("Failed to create a 3D device.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ window2 = create_window();
+ if (!(device2 = create_device(window2, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirect3DDevice3_Release(device);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+ return;
+ }
+
+ hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
+ hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
+ IDirect3D3_Release(d3d);
+
+ hr = IDirect3DDevice3_GetDirect3D(device2, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
+ hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw2);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
+ IDirect3D3_Release(d3d);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
+ U5(surface_desc).dwBackBufferCount = 2;
+ hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+ surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
+ U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00007c00;
+ U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x000003e0;
+ U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000001f;
+ hr = IDirectDraw4_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ U5(fx).dwFillColor = 0xff0000ff;
+ hr = IDirectDrawSurface4_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_IsLost(sysmem_surface);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface4_Release(surface2);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw4_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface4_Release(surface);
+ IDirectDrawSurface4_Release(surface2);
+ IDirectDrawSurface4_Release(sysmem_surface);
+ IDirectDraw4_Release(ddraw);
+ IDirectDraw4_Release(ddraw2);
+ refcount = IDirect3DDevice3_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ refcount = IDirect3DDevice3_Release(device2);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+}
+
static void test_color_clamping(void)
{
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
@@ -15060,6 +15195,7 @@ START_TEST(ddraw4)
test_overlay_rect();
test_blt();
test_blt_z_alpha();
+ test_cross_device_blt();
test_color_clamping();
test_getdc();
test_draw_primitive();
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 35a45c034566..501c9a184e28 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -11581,6 +11581,141 @@ static void test_blt_z_alpha(void)
DestroyWindow(window);
}
+static void test_cross_device_blt(void)
+{
+ IDirectDrawSurface7 *surface, *surface2, *sysmem_surface;
+ IDirect3DDevice7 *device, *device2;
+ IDirectDraw7 *ddraw, *ddraw2;
+ DDSURFACEDESC2 surface_desc;
+ HWND window, window2;
+ IDirect3D7 *d3d;
+ ULONG refcount;
+ D3DCOLOR color;
+ DDBLTFX fx;
+ HRESULT hr;
+
+ window = create_window();
+ if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
+ {
+ skip("Failed to create a 3D device.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ window2 = create_window();
+ if (!(device2 = create_device(window2, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirect3DDevice7_Release(device);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+ return;
+ }
+
+ hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
+ hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
+ IDirect3D7_Release(d3d);
+
+ hr = IDirect3DDevice7_GetDirect3D(device2, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
+ hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw2);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
+ IDirect3D7_Release(d3d);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
+ U5(surface_desc).dwBackBufferCount = 2;
+ hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+ surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
+ U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00007c00;
+ U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x000003e0;
+ U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000001f;
+ hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ U5(fx).dwFillColor = 0xff0000ff;
+ hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+ hr = IDirectDrawSurface7_IsLost(sysmem_surface);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface7_Release(surface2);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ surface_desc.dwWidth = 640;
+ surface_desc.dwHeight = 480;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDFLIP_WAIT, NULL);
+ todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
+ color = get_surface_color(sysmem_surface, 320, 240);
+ todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
+
+ IDirectDrawSurface7_Release(surface);
+ IDirectDrawSurface7_Release(surface2);
+ IDirectDrawSurface7_Release(sysmem_surface);
+ IDirectDraw7_Release(ddraw);
+ IDirectDraw7_Release(ddraw2);
+ refcount = IDirect3DDevice7_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ refcount = IDirect3DDevice7_Release(device2);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+ DestroyWindow(window2);
+}
+
static void test_color_clamping(void)
{
static D3DMATRIX mat =
@@ -14384,6 +14519,7 @@ START_TEST(ddraw7)
test_overlay_rect();
test_blt();
test_blt_z_alpha();
+ test_cross_device_blt();
test_color_clamping();
test_getdc();
test_draw_primitive();
--
2.16.4
3
3
DirectDraw tests show that cross-device blits are supposed to work for
limited cases between system memory surfaces. However, cross-device
blits are unsafe in wined3d, especially with CSMT enabled.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45382
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
FWIW, the games affected by this bug shouldn't use cross-device blits at
all. Cross-device blits happen between a surface created by our
amstream implementation, and the bug doesn't occur with native amstream.
---
dlls/wined3d/texture.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c316906a9576..634992714d02 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -3097,6 +3097,12 @@ HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned
return WINED3DERR_INVALIDCALL;
}
+ if (dst_texture->resource.device != src_texture->resource.device)
+ {
+ FIXME("Rejecting cross-device blit.\n");
+ return E_NOTIMPL;
+ }
+
wined3d_cs_emit_blt_sub_resource(dst_texture->resource.device->cs, &dst_texture->resource, dst_sub_resource_idx,
&dst_box, &src_texture->resource, src_sub_resource_idx, &src_box, flags, fx, filter);
--
2.16.4
2
1
09 Aug '18
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/dxgi/tests/device.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/dxgi/tests/device.c b/dlls/dxgi/tests/device.c
index 6e14010f5c33..81b231a4d36f 100644
--- a/dlls/dxgi/tests/device.c
+++ b/dlls/dxgi/tests/device.c
@@ -37,6 +37,7 @@ static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory);
static HRESULT (WINAPI *pCreateDXGIFactory2)(UINT flags, REFIID iid, void **factory);
static PFN_D3D12_CREATE_DEVICE pD3D12CreateDevice;
+static PFN_D3D12_GET_DEBUG_INTERFACE pD3D12GetDebugInterface;
static ULONG get_refcount(IUnknown *iface)
{
@@ -4042,7 +4043,9 @@ static void run_on_d3d12(void (*test_func)(IUnknown *device, BOOL is_d3d12))
START_TEST(device)
{
HMODULE dxgi_module, d3d12_module;
+ BOOL enable_debug_layer = FALSE;
unsigned int argc, i;
+ ID3D12Debug *debug;
char **argv;
dxgi_module = GetModuleHandleA("dxgi.dll");
@@ -4055,7 +4058,9 @@ START_TEST(device)
argc = winetest_get_mainargs(&argv);
for (i = 2; i < argc; ++i)
{
- if (!strcmp(argv[i], "--warp"))
+ if (!strcmp(argv[i], "--validate"))
+ enable_debug_layer = TRUE;
+ else if (!strcmp(argv[i], "--warp"))
use_warp_adapter = TRUE;
else if (!strcmp(argv[i], "--adapter") && i + 1 < argc)
use_adapter_idx = atoi(argv[++i]);
@@ -4091,6 +4096,13 @@ START_TEST(device)
}
pD3D12CreateDevice = (void *)GetProcAddress(d3d12_module, "D3D12CreateDevice");
+ pD3D12GetDebugInterface = (void *)GetProcAddress(d3d12_module, "D3D12GetDebugInterface");
+
+ if (enable_debug_layer && SUCCEEDED(pD3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug)))
+ {
+ ID3D12Debug_EnableDebugLayer(debug);
+ ID3D12Debug_Release(debug);
+ }
run_on_d3d12(test_swapchain_backbuffer_index);
--
2.16.4
2
1
[PATCH 10/11] include/d3d12: Add PFN_D3D12_GET_DEBUG_INTERFACE declaration.
by Józef Kucia 09 Aug '18
by Józef Kucia 09 Aug '18
09 Aug '18
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
include/d3d12.idl | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/d3d12.idl b/include/d3d12.idl
index 43e9c2dca3bb..6f515e6ad6d1 100644
--- a/include/d3d12.idl
+++ b/include/d3d12.idl
@@ -2177,4 +2177,6 @@ typedef HRESULT (__stdcall *PFN_D3D12_CREATE_DEVICE)(IUnknown *adapter,
[local] HRESULT __stdcall D3D12CreateDevice(IUnknown *adapter,
D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device);
+typedef HRESULT (__stdcall *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID iid, void **debug);
+
[local] HRESULT __stdcall D3D12GetDebugInterface(REFIID iid, void **debug);
--
2.16.4
2
1
[PATCH 09/11] dxgi/tests: Make sure that command queue is idle before destroying it.
by Józef Kucia 09 Aug '18
by Józef Kucia 09 Aug '18
09 Aug '18
Fixes invalid Direct3D 12 API usage.
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/dxgi/tests/device.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/dlls/dxgi/tests/device.c b/dlls/dxgi/tests/device.c
index 124c5a43d6e9..6e14010f5c33 100644
--- a/dlls/dxgi/tests/device.c
+++ b/dlls/dxgi/tests/device.c
@@ -502,6 +502,47 @@ static ID3D12CommandQueue *create_d3d12_direct_queue(ID3D12Device *device)
return queue;
}
+static HRESULT wait_for_fence(ID3D12Fence *fence, UINT64 value)
+{
+ HANDLE event;
+ HRESULT hr;
+ DWORD ret;
+
+ if (ID3D12Fence_GetCompletedValue(fence) >= value)
+ return S_OK;
+
+ if (!(event = CreateEventA(NULL, FALSE, FALSE, NULL)))
+ return E_FAIL;
+
+ if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(fence, value, event)))
+ {
+ CloseHandle(event);
+ return hr;
+ }
+
+ ret = WaitForSingleObject(event, INFINITE);
+ CloseHandle(event);
+ return ret == WAIT_OBJECT_0 ? S_OK : E_FAIL;
+}
+
+#define wait_queue_idle(a, b) wait_queue_idle_(__LINE__, a, b)
+static void wait_queue_idle_(unsigned int line, ID3D12Device *device, ID3D12CommandQueue *queue)
+{
+ ID3D12Fence *fence;
+ HRESULT hr;
+
+ hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
+ &IID_ID3D12Fence, (void **)&fence);
+ ok_(__FILE__, line)(hr == S_OK, "Failed to create fence, hr %#x.\n", hr);
+
+ hr = ID3D12CommandQueue_Signal(queue, fence, 1);
+ ok_(__FILE__, line)(hr == S_OK, "Failed to signal fence, hr %#x.\n", hr);
+ hr = wait_for_fence(fence, 1);
+ ok_(__FILE__, line)(hr == S_OK, "Failed to wait for fence, hr %#x.\n", hr);
+
+ ID3D12Fence_Release(fence);
+}
+
#define get_factory(a, b, c) get_factory_(__LINE__, a, b, c)
static void get_factory_(unsigned int line, IUnknown *device, BOOL is_d3d12, IDXGIFactory **factory)
{
@@ -3990,6 +4031,8 @@ static void run_on_d3d12(void (*test_func)(IUnknown *device, BOOL is_d3d12))
test_func((IUnknown *)queue, TRUE);
+ wait_queue_idle(device, queue);
+
refcount = ID3D12CommandQueue_Release(queue);
ok(!refcount, "Command queue has %u references left.\n", refcount);
refcount = ID3D12Device_Release(device);
--
2.16.4
2
1
09 Aug '18
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/d3d12/tests/d3d12.c | 187 +++++++++++++++++++++++++++++++++++------------
1 file changed, 139 insertions(+), 48 deletions(-)
diff --git a/dlls/d3d12/tests/d3d12.c b/dlls/d3d12/tests/d3d12.c
index 99641be0f683..2e2e69be0adc 100644
--- a/dlls/d3d12/tests/d3d12.c
+++ b/dlls/d3d12/tests/d3d12.c
@@ -177,28 +177,33 @@ static HRESULT create_root_signature(ID3D12Device *device, const D3D12_ROOT_SIGN
return hr;
}
-#define create_empty_root_signature(device, flags) create_empty_root_signature_(__LINE__, device, flags)
-static ID3D12RootSignature *create_empty_root_signature_(unsigned int line,
- ID3D12Device *device, D3D12_ROOT_SIGNATURE_FLAGS flags)
+static ID3D12RootSignature *create_default_root_signature(ID3D12Device *device)
{
D3D12_ROOT_SIGNATURE_DESC root_signature_desc;
ID3D12RootSignature *root_signature = NULL;
+ D3D12_ROOT_PARAMETER root_parameters[1];
HRESULT hr;
- root_signature_desc.NumParameters = 0;
- root_signature_desc.pParameters = NULL;
+ root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+ root_parameters[0].Constants.ShaderRegister = 0;
+ root_parameters[0].Constants.RegisterSpace = 0;
+ root_parameters[0].Constants.Num32BitValues = 4;
+ root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+
+ root_signature_desc.NumParameters = ARRAY_SIZE(root_parameters);
+ root_signature_desc.pParameters = root_parameters;
root_signature_desc.NumStaticSamplers = 0;
root_signature_desc.pStaticSamplers = NULL;
- root_signature_desc.Flags = flags;
+ root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
- ok_(__FILE__, line)(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
+ ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
return root_signature;
}
-#define create_pipeline_state(a, b, c) create_pipeline_state_(__LINE__, a, b, c)
+#define create_pipeline_state(a, b, c, d) create_pipeline_state_(__LINE__, a, b, c, d)
static ID3D12PipelineState *create_pipeline_state_(unsigned int line, ID3D12Device *device,
- ID3D12RootSignature *root_signature, DXGI_FORMAT rt_format)
+ ID3D12RootSignature *root_signature, DXGI_FORMAT rt_format, const D3D12_SHADER_BYTECODE *ps)
{
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_state_desc;
ID3D12PipelineState *pipeline_state;
@@ -244,12 +249,15 @@ static ID3D12PipelineState *create_pipeline_state_(unsigned int line, ID3D12Devi
0x0000000f, 0x0100086a, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000,
0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e,
};
- static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)};
+ static const D3D12_SHADER_BYTECODE default_ps = {ps_code, sizeof(ps_code)};
+
+ if (!ps)
+ ps = &default_ps;
memset(&pipeline_state_desc, 0, sizeof(pipeline_state_desc));
pipeline_state_desc.pRootSignature = root_signature;
pipeline_state_desc.VS = vs;
- pipeline_state_desc.PS = ps;
+ pipeline_state_desc.PS = *ps;
pipeline_state_desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
pipeline_state_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
pipeline_state_desc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
@@ -265,6 +273,24 @@ static ID3D12PipelineState *create_pipeline_state_(unsigned int line, ID3D12Devi
return pipeline_state;
}
+#define reset_command_list(a, b) reset_command_list_(__LINE__, a, b)
+static void reset_command_list_(unsigned int line,
+ ID3D12GraphicsCommandList *list, ID3D12CommandAllocator *allocator)
+{
+ HRESULT hr;
+
+ hr = ID3D12CommandAllocator_Reset(allocator);
+ ok_(__FILE__, line)(hr == S_OK, "Failed to reset command allocator, hr %#x.\n", hr);
+ hr = ID3D12GraphicsCommandList_Reset(list, allocator, NULL);
+ ok_(__FILE__, line)(hr == S_OK, "Failed to reset command list, hr %#x.\n", hr);
+}
+
+struct test_context_desc
+{
+ BOOL no_pipeline;
+ const D3D12_SHADER_BYTECODE *ps;
+};
+
struct test_context
{
ID3D12Device *device;
@@ -326,8 +352,9 @@ static void create_render_target_(unsigned int line, struct test_context *contex
ID3D12Device_CreateRenderTargetView(context->device, *render_target, NULL, *rtv);
}
-#define init_test_context(context) init_test_context_(__LINE__, context)
-static BOOL init_test_context_(unsigned int line, struct test_context *context)
+#define init_test_context(a, b) init_test_context_(__LINE__, a, b)
+static BOOL init_test_context_(unsigned int line, struct test_context *context,
+ const struct test_context_desc *desc)
{
D3D12_COMMAND_QUEUE_DESC command_queue_desc;
D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc;
@@ -376,11 +403,14 @@ static BOOL init_test_context_(unsigned int line, struct test_context *context)
SetRect(&context->scissor_rect, 0, 0,
context->render_target_desc.Width, context->render_target_desc.Height);
- context->root_signature = create_empty_root_signature_(line,
- device, D3D12_ROOT_SIGNATURE_FLAG_NONE);
+ context->root_signature = create_default_root_signature(device);
+
+ if (desc && desc->no_pipeline)
+ return TRUE;
context->pipeline_state = create_pipeline_state_(line, device,
- context->root_signature, context->render_target_desc.Format);
+ context->root_signature, context->render_target_desc.Format,
+ desc ? desc->ps : NULL);
return TRUE;
}
@@ -516,7 +546,7 @@ static HWND create_window(DWORD style)
}
static IDXGISwapChain3 *create_swapchain(ID3D12CommandQueue *queue, HWND window,
- unsigned int width, unsigned int height)
+ DXGI_FORMAT format, unsigned int width, unsigned int height)
{
IDXGISwapChain1 *swapchain1;
DXGI_SWAP_CHAIN_DESC1 desc;
@@ -529,7 +559,7 @@ static IDXGISwapChain3 *create_swapchain(ID3D12CommandQueue *queue, HWND window,
desc.Width = width;
desc.Height = height;
- desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc.Format = format;
desc.Stereo = FALSE;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
@@ -735,7 +765,7 @@ static void test_draw(void)
struct test_context context;
ID3D12CommandQueue *queue;
- if (!init_test_context(&context))
+ if (!init_test_context(&context, NULL))
return;
command_list = context.list;
queue = context.queue;
@@ -762,54 +792,115 @@ static void test_swapchain_draw(void)
{
static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f};
ID3D12GraphicsCommandList *command_list;
+ struct test_context_desc desc;
struct test_context context;
ID3D12Resource *backbuffer;
IDXGISwapChain3 *swapchain;
ID3D12CommandQueue *queue;
- unsigned int index;
+ unsigned int i, index;
+ ID3D12Device *device;
ULONG refcount;
HWND window;
HRESULT hr;
RECT rect;
BOOL ret;
- if (!init_test_context(&context))
+ static const DWORD ps_code[] =
+ {
+#if 0
+ float4 color;
+
+ float4 main() : SV_Target
+ {
+ return color;
+ }
+#endif
+ 0x43425844, 0x69e703c1, 0xf0db50aa, 0x9af7ae76, 0x623b93f7, 0x00000001, 0x000000bc, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
+ 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000044, 0x00000050, 0x00000011,
+ 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
+ 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
+ };
+ static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)};
+
+ static const struct
+ {
+ DXGI_FORMAT format;
+ float input[4];
+ unsigned int color;
+ }
+ tests[] =
+ {
+ {DXGI_FORMAT_B8G8R8A8_UNORM, {1.0f, 0.0f, 0.0f, 1.0f}, 0xffff0000},
+ {DXGI_FORMAT_B8G8R8A8_UNORM, {0.0f, 1.0f, 0.0f, 1.0f}, 0xff00ff00},
+ {DXGI_FORMAT_R8G8B8A8_UNORM, {1.0f, 0.0f, 0.0f, 1.0f}, 0xff0000ff},
+ {DXGI_FORMAT_R8G8B8A8_UNORM, {0.0f, 1.0f, 0.0f, 1.0f}, 0xff00ff00},
+ };
+
+ desc.no_pipeline = TRUE;
+ if (!init_test_context(&context, &desc))
return;
+ device = context.device;
command_list = context.list;
queue = context.queue;
- window = create_window(0);
+ window = create_window(WS_VISIBLE);
ret = GetClientRect(window, &rect);
ok(ret, "Failed to get client rect.\n");
set_viewport(&context.viewport, 0.0f, 0.0f, rect.right, rect.bottom, 0.0f, 1.0f);
- swapchain = create_swapchain(queue, window, rect.right, rect.bottom);
- index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
- hr = IDXGISwapChain3_GetBuffer(swapchain, index, &IID_ID3D12Resource, (void **)&backbuffer);
- ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", index, hr);
- ID3D12Device_CreateRenderTargetView(context.device, backbuffer, NULL, context.rtv);
-
- transition_sub_resource_state(command_list, backbuffer, 0,
- D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
-
- ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, FALSE, NULL);
- ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature);
- ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state);
- ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport);
- ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &rect);
- ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
-
- transition_sub_resource_state(command_list, backbuffer, 0,
- D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
-
- check_sub_resource_uint(backbuffer, 0, queue, command_list, 0xff00ff00, 0);
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ context.pipeline_state = create_pipeline_state(device,
+ context.root_signature, tests[i].format, &ps);
+
+ swapchain = create_swapchain(queue, window, tests[i].format, rect.right, rect.bottom);
+ index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
+ hr = IDXGISwapChain3_GetBuffer(swapchain, index, &IID_ID3D12Resource, (void **)&backbuffer);
+ ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", index, hr);
+ ID3D12Device_CreateRenderTargetView(device, backbuffer, NULL, context.rtv);
+
+ transition_sub_resource_state(command_list, backbuffer, 0,
+ D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
+
+ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
+
+ ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, FALSE, NULL);
+ ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature);
+ ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state);
+ ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport);
+ ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &rect);
+ ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0, 4, tests[i].input, 0);
+ ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
+
+ transition_sub_resource_state(command_list, backbuffer, 0,
+ D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ check_sub_resource_uint(backbuffer, 0, queue, command_list, tests[i].color, 0);
+
+ reset_command_list(command_list, context.allocator);
+ transition_sub_resource_state(command_list, backbuffer, 0,
+ D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT);
+ hr = ID3D12GraphicsCommandList_Close(command_list);
+ ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr);
+ exec_command_list(queue, command_list);
+
+ hr = IDXGISwapChain3_Present(swapchain, 0, 0);
+ ok(hr == S_OK, "Failed to present, hr %#x.\n", hr);
+
+ wait_queue_idle(device, queue);
+
+ refcount = ID3D12Resource_Release(backbuffer);
+ ok(!refcount, "Backbuffer has %u references left.\n", refcount);
+ refcount = IDXGISwapChain3_Release(swapchain);
+ ok(!refcount, "Swapchain has %u references left.\n", refcount);
+ ID3D12PipelineState_Release(context.pipeline_state);
+ context.pipeline_state = NULL;
+
+ reset_command_list(command_list, context.allocator);
+ }
- refcount = ID3D12Resource_Release(backbuffer);
- ok(!refcount, "Backbuffer has %u references left.\n", refcount);
- refcount = IDXGISwapChain3_Release(swapchain);
- ok(!refcount, "Swapchain has %u references left.\n", refcount);
DestroyWindow(window);
destroy_test_context(&context);
}
--
2.16.4
2
1
[PATCH 07/11] dxgi: Blit user buffers to Vulkan swapchain buffers while presenting.
by Józef Kucia 09 Aug '18
by Józef Kucia 09 Aug '18
09 Aug '18
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/dxgi/swapchain.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 260 insertions(+), 22 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index ad7d02a4aefc..241db3b10b10 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -826,16 +826,25 @@ static PFN_vkd3d_resource_incref vkd3d_resource_incref;
struct dxgi_vk_funcs
{
PFN_vkAcquireNextImageKHR p_vkAcquireNextImageKHR;
+ PFN_vkAllocateCommandBuffers p_vkAllocateCommandBuffers;
PFN_vkAllocateMemory p_vkAllocateMemory;
+ PFN_vkBeginCommandBuffer p_vkBeginCommandBuffer;
PFN_vkBindImageMemory p_vkBindImageMemory;
+ PFN_vkCmdBlitImage p_vkCmdBlitImage;
+ PFN_vkCmdPipelineBarrier p_vkCmdPipelineBarrier;
+ PFN_vkCreateCommandPool p_vkCreateCommandPool;
PFN_vkCreateFence p_vkCreateFence;
PFN_vkCreateImage p_vkCreateImage;
+ PFN_vkCreateSemaphore p_vkCreateSemaphore;
PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR;
PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR;
+ PFN_vkDestroyCommandPool p_vkDestroyCommandPool;
PFN_vkDestroyFence p_vkDestroyFence;
PFN_vkDestroyImage p_vkDestroyImage;
+ PFN_vkDestroySemaphore p_vkDestroySemaphore;
PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR;
PFN_vkDestroySwapchainKHR p_vkDestroySwapchainKHR;
+ PFN_vkEndCommandBuffer p_vkEndCommandBuffer;
PFN_vkFreeMemory p_vkFreeMemory;
PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr;
PFN_vkGetImageMemoryRequirements p_vkGetImageMemoryRequirements;
@@ -848,6 +857,7 @@ struct dxgi_vk_funcs
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR p_vkGetPhysicalDeviceWin32PresentationSupportKHR;
PFN_vkGetSwapchainImagesKHR p_vkGetSwapchainImagesKHR;
PFN_vkQueuePresentKHR p_vkQueuePresentKHR;
+ PFN_vkQueueSubmit p_vkQueueSubmit;
PFN_vkQueueWaitIdle p_vkQueueWaitIdle;
PFN_vkResetFences p_vkResetFences;
PFN_vkWaitForFences p_vkWaitForFences;
@@ -881,7 +891,10 @@ struct d3d12_swapchain
VkDevice vk_device;
VkPhysicalDevice vk_physical_device;
VkDeviceMemory vk_memory;
+ VkCommandPool vk_cmd_pool;
VkImage vk_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;
@@ -970,7 +983,10 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
vkd3d_resource_decref(swapchain->buffers[i]);
if (swapchain->vk_device)
+ {
vk_funcs->p_vkDestroyImage(swapchain->vk_device, swapchain->vk_images[i], NULL);
+ vk_funcs->p_vkDestroySemaphore(swapchain->vk_device, swapchain->vk_semaphores[i], NULL);
+ }
}
if (swapchain->vk_device)
@@ -979,6 +995,7 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
vk_funcs->p_vkDestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL);
vk_funcs->p_vkFreeMemory(swapchain->vk_device, swapchain->vk_memory, NULL);
+ vk_funcs->p_vkDestroyCommandPool(swapchain->vk_device, swapchain->vk_cmd_pool, NULL);
}
if (swapchain->vk_instance)
@@ -1262,13 +1279,59 @@ static HRESULT d3d12_swapchain_acquire_next_image(struct d3d12_swapchain *swapch
return S_OK;
}
+static HRESULT d3d12_swapchain_blit_buffer(struct d3d12_swapchain *swapchain, VkQueue vk_queue)
+{
+ const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ VkSubmitInfo submit_info;
+ VkResult 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 = &swapchain->vk_cmd_buffers[swapchain->current_buffer_index];
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &swapchain->vk_semaphores[swapchain->current_buffer_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 hresult_from_vk_result(vr);
+}
+
+static HRESULT d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain, VkQueue vk_queue)
+{
+ const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ VkPresentInfoKHR present_info;
+ VkResult vr;
+
+ present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ present_info.pNext = NULL;
+ present_info.waitSemaphoreCount = 0;
+ present_info.pWaitSemaphores = NULL;
+ present_info.swapchainCount = 1;
+ present_info.pSwapchains = &swapchain->vk_swapchain;
+ present_info.pImageIndices = &swapchain->current_buffer_index;
+ present_info.pResults = NULL;
+
+ if (swapchain->vk_semaphores[swapchain->current_buffer_index])
+ {
+ present_info.waitSemaphoreCount = 1;
+ present_info.pWaitSemaphores = &swapchain->vk_semaphores[swapchain->current_buffer_index];
+ }
+
+ if ((vr = vk_funcs->p_vkQueuePresentKHR(vk_queue, &present_info)) < 0)
+ ERR("Failed to queue present, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+}
+
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_Present1(IDXGISwapChain3 *iface,
UINT sync_interval, UINT flags, const DXGI_PRESENT_PARAMETERS *present_parameters)
{
struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
- const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
- VkPresentInfoKHR present_desc;
VkQueue vk_queue;
+ HRESULT hr;
TRACE("iface %p, sync_interval %u, flags %#x, present_parameters %p.\n",
iface, sync_interval, flags, present_parameters);
@@ -1292,21 +1355,27 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_Present1(IDXGISwapChain3 *iface
if (present_parameters)
FIXME("Ignored present parameters %p.\n", present_parameters);
- present_desc.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- present_desc.pNext = NULL;
- present_desc.waitSemaphoreCount = 0;
- present_desc.pWaitSemaphores = NULL;
- present_desc.swapchainCount = 1;
- present_desc.pSwapchains = &swapchain->vk_swapchain;
- present_desc.pImageIndices = &swapchain->current_buffer_index;
- present_desc.pResults = NULL;
-
if (!(vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue)))
{
ERR("Failed to acquire Vulkan queue.\n");
return E_FAIL;
}
- vk_funcs->p_vkQueuePresentKHR(vk_queue, &present_desc);
+
+ if (swapchain->vk_images[swapchain->current_buffer_index])
+ {
+ if (FAILED(hr = d3d12_swapchain_blit_buffer(swapchain, vk_queue)))
+ {
+ vkd3d_release_vk_queue(swapchain->command_queue);
+ return hr;
+ }
+ }
+
+ if (FAILED(hr = d3d12_swapchain_queue_present(swapchain, vk_queue)))
+ {
+ vkd3d_release_vk_queue(swapchain->command_queue);
+ return hr;
+ }
+
vkd3d_release_vk_queue(swapchain->command_queue);
return d3d12_swapchain_acquire_next_image(swapchain);
@@ -1601,14 +1670,24 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkInstance vk_instance, Vk
return FALSE; \
}
LOAD_DEVICE_PFN(vkAcquireNextImageKHR)
+ LOAD_DEVICE_PFN(vkAllocateCommandBuffers)
LOAD_DEVICE_PFN(vkAllocateMemory)
+ LOAD_DEVICE_PFN(vkBeginCommandBuffer)
LOAD_DEVICE_PFN(vkBindImageMemory)
+ LOAD_DEVICE_PFN(vkCmdBlitImage)
+ LOAD_DEVICE_PFN(vkCmdPipelineBarrier)
+ LOAD_DEVICE_PFN(vkCreateCommandPool)
LOAD_DEVICE_PFN(vkCreateFence)
LOAD_DEVICE_PFN(vkCreateImage)
+ LOAD_DEVICE_PFN(vkCreateSemaphore)
+ LOAD_DEVICE_PFN(vkDestroyCommandPool)
LOAD_DEVICE_PFN(vkDestroyFence)
LOAD_DEVICE_PFN(vkDestroyImage)
+ LOAD_DEVICE_PFN(vkDestroySemaphore)
+ LOAD_DEVICE_PFN(vkEndCommandBuffer)
LOAD_DEVICE_PFN(vkFreeMemory)
LOAD_DEVICE_PFN(vkGetImageMemoryRequirements)
+ LOAD_DEVICE_PFN(vkQueueSubmit)
LOAD_DEVICE_PFN(vkQueueWaitIdle)
LOAD_DEVICE_PFN(vkResetFences)
LOAD_DEVICE_PFN(vkWaitForFences)
@@ -1809,16 +1888,154 @@ static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapc
return S_OK;
}
+static void vk_cmd_image_barrier(const struct dxgi_vk_funcs *vk_funcs, VkCommandBuffer cmd_buffer,
+ VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
+ VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask,
+ VkImageLayout old_layout, VkImageLayout new_layout, VkImage image)
+{
+ VkImageMemoryBarrier barrier;
+
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = NULL;
+ barrier.srcAccessMask = src_access_mask;
+ barrier.dstAccessMask = dst_access_mask;
+ barrier.oldLayout = old_layout;
+ barrier.newLayout = new_layout;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = image;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+ vk_funcs->p_vkCmdPipelineBarrier(cmd_buffer,
+ src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier);
+}
+
+static HRESULT d3d12_swapchain_prepare_command_buffers(struct d3d12_swapchain *swapchain,
+ const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, uint32_t queue_family_index,
+ VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS])
+{
+ const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ VkDevice vk_device = swapchain->vk_device;
+ VkCommandBufferAllocateInfo allocate_info;
+ VkSemaphoreCreateInfo semaphore_info;
+ VkCommandBufferBeginInfo begin_info;
+ VkCommandPoolCreateInfo pool_info;
+ VkImageBlit blit;
+ unsigned int i;
+ VkResult vr;
+
+ pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ pool_info.pNext = NULL;
+ pool_info.flags = 0;
+ pool_info.queueFamilyIndex = queue_family_index;
+
+ if ((vr = vk_funcs->p_vkCreateCommandPool(vk_device, &pool_info,
+ NULL, &swapchain->vk_cmd_pool)) < 0)
+ {
+ WARN("Failed to create command pool, vr %d.\n", vr);
+ swapchain->vk_cmd_pool = VK_NULL_HANDLE;
+ return hresult_from_vk_result(vr);
+ }
+
+ allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocate_info.pNext = NULL;
+ allocate_info.commandPool = swapchain->vk_cmd_pool;
+ allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocate_info.commandBufferCount = swapchain->buffer_count;
+
+ if ((vr = vk_funcs->p_vkAllocateCommandBuffers(vk_device, &allocate_info,
+ swapchain->vk_cmd_buffers)) < 0)
+ {
+ WARN("Failed to allocate command buffers, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ for (i = 0; i < swapchain->buffer_count; ++i)
+ {
+ VkCommandBuffer vk_cmd_buffer = swapchain->vk_cmd_buffers[i];
+
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.pNext = NULL;
+ begin_info.flags = 0;
+ begin_info.pInheritanceInfo = NULL;
+
+ if ((vr = vk_funcs->p_vkBeginCommandBuffer(vk_cmd_buffer, &begin_info)) < 0)
+ {
+ WARN("Failed to begin command buffer, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ vk_cmd_image_barrier(vk_funcs, vk_cmd_buffer,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, VK_ACCESS_TRANSFER_WRITE_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ vk_swapchain_images[i]);
+
+ blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ blit.srcSubresource.mipLevel = 0;
+ blit.srcSubresource.baseArrayLayer = 0;
+ blit.srcSubresource.layerCount = 1;
+ blit.srcOffsets[0].x = 0;
+ blit.srcOffsets[0].y = 0;
+ blit.srcOffsets[0].z = 0;
+ blit.srcOffsets[1].x = swapchain_desc->Width;
+ blit.srcOffsets[1].y = swapchain_desc->Height;
+ blit.srcOffsets[1].z = 1;
+ blit.dstSubresource = blit.srcSubresource;
+ blit.dstOffsets[0] = blit.srcOffsets[0];
+ blit.dstOffsets[1] = blit.srcOffsets[1];
+
+ vk_funcs->p_vkCmdBlitImage(vk_cmd_buffer,
+ swapchain->vk_images[i], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vk_swapchain_images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1, &blit, VK_FILTER_NEAREST);
+
+ vk_cmd_image_barrier(vk_funcs, vk_cmd_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_ACCESS_TRANSFER_WRITE_BIT, 0,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ vk_swapchain_images[i]);
+
+ if ((vr = vk_funcs->p_vkEndCommandBuffer(vk_cmd_buffer)) < 0)
+ {
+ WARN("Failed to end command buffer, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+ }
+
+ for (i = 0; i < swapchain->buffer_count; ++i)
+ {
+ semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphore_info.pNext = NULL;
+ semaphore_info.flags = 0;
+
+ if ((vr = vk_funcs->p_vkCreateSemaphore(vk_device, &semaphore_info,
+ NULL, &swapchain->vk_semaphores[i])) < 0)
+ {
+ WARN("Failed to create semaphore, vr %d.\n", vr);
+ swapchain->vk_semaphores[i] = VK_NULL_HANDLE;
+ return hresult_from_vk_result(vr);
+ }
+ }
+
+ return S_OK;
+}
+
static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
- ID3D12Device *device, const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc,
- VkFormat vk_swapchain_format, VkFormat vk_format)
+ ID3D12Device *device, ID3D12CommandQueue *queue,
+ const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat vk_swapchain_format, VkFormat vk_format)
{
const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
struct vkd3d_image_resource_create_info resource_info;
VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain;
- VkImage vk_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkDevice vk_device = swapchain->vk_device;
- uint32_t image_count;
+ uint32_t image_count, queue_family_index;
+ D3D12_COMMAND_QUEUE_DESC queue_desc;
unsigned int i;
VkResult vr;
HRESULT hr;
@@ -1830,10 +2047,11 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
}
if (image_count != swapchain_desc->BufferCount)
FIXME("Got %u swapchain images, expected %u.\n", image_count, swapchain_desc->BufferCount);
- if (image_count > ARRAY_SIZE(vk_images))
+ if (image_count > ARRAY_SIZE(vk_swapchain_images))
return E_FAIL;
swapchain->buffer_count = image_count;
- if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images)) < 0)
+ if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain,
+ &image_count, vk_swapchain_images)) < 0)
{
WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
return hresult_from_vk_result(vr);
@@ -1853,21 +2071,41 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
- resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
if (vk_swapchain_format != vk_format)
{
+ queue_desc = ID3D12CommandQueue_GetDesc(queue);
+ if (queue_desc.Type != D3D12_COMMAND_LIST_TYPE_DIRECT)
+ {
+ /* vkCmdBlitImage() is only supported for Graphics queues. */
+ FIXME("Format conversion not implemented for command queue type %#x.\n", queue_desc.Type);
+ return E_NOTIMPL;
+ }
+ queue_family_index = vkd3d_get_vk_queue_family_index(queue);
+
TRACE("Creating user swapchain buffers for format conversion.\n");
if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, swapchain_desc, vk_format)))
return hr;
- resource_info.present_state = D3D12_RESOURCE_STATE_COPY_SOURCE;
+ if (FAILED(hr = d3d12_swapchain_prepare_command_buffers(swapchain, swapchain_desc,
+ queue_family_index, vk_swapchain_images)))
+ return hr;
}
for (i = 0; i < swapchain->buffer_count; ++i)
{
- resource_info.vk_image = swapchain->vk_images[i] ? swapchain->vk_images[i] : vk_images[i];
+ if (swapchain->vk_images[i])
+ {
+ resource_info.vk_image = swapchain->vk_images[i];
+ resource_info.present_state = D3D12_RESOURCE_STATE_COPY_SOURCE;
+ }
+ else
+ {
+ resource_info.vk_image = vk_swapchain_images[i];
+ resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
+ }
+
if (FAILED(hr = vkd3d_create_image_resource(device, &resource_info, &swapchain->buffers[i])))
{
WARN("Failed to create vkd3d resource for Vulkan image %u, hr %#x.\n", i, hr);
@@ -2071,7 +2309,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
}
swapchain->vk_fence = vk_fence;
- if (FAILED(hr = d3d12_swapchain_create_buffers(swapchain, device,
+ if (FAILED(hr = d3d12_swapchain_create_buffers(swapchain, device, queue,
swapchain_desc, vk_swapchain_format, vk_format)))
{
d3d12_swapchain_destroy(swapchain);
--
2.16.4
2
1
[PATCH 06/11] dxgi: Create user images for swapchain formats not supported by Vulkan.
by Józef Kucia 09 Aug '18
by Józef Kucia 09 Aug '18
09 Aug '18
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/dxgi/swapchain.c | 222 +++++++++++++++++++++++++++++++++++++++++++----
dlls/dxgi/tests/device.c | 3 +-
2 files changed, 208 insertions(+), 17 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 07329b115079..ad7d02a4aefc 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -826,14 +826,21 @@ static PFN_vkd3d_resource_incref vkd3d_resource_incref;
struct dxgi_vk_funcs
{
PFN_vkAcquireNextImageKHR p_vkAcquireNextImageKHR;
+ PFN_vkAllocateMemory p_vkAllocateMemory;
+ PFN_vkBindImageMemory p_vkBindImageMemory;
PFN_vkCreateFence p_vkCreateFence;
+ PFN_vkCreateImage p_vkCreateImage;
PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR;
PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR;
PFN_vkDestroyFence p_vkDestroyFence;
+ PFN_vkDestroyImage p_vkDestroyImage;
PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR;
PFN_vkDestroySwapchainKHR p_vkDestroySwapchainKHR;
+ PFN_vkFreeMemory p_vkFreeMemory;
PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr;
+ PFN_vkGetImageMemoryRequirements p_vkGetImageMemoryRequirements;
PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr;
+ PFN_vkGetPhysicalDeviceMemoryProperties p_vkGetPhysicalDeviceMemoryProperties;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR p_vkGetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR p_vkGetPhysicalDeviceSurfacePresentModesKHR;
@@ -872,6 +879,9 @@ struct d3d12_swapchain
VkFence vk_fence;
VkInstance vk_instance;
VkDevice vk_device;
+ VkPhysicalDevice vk_physical_device;
+ VkDeviceMemory vk_memory;
+ VkImage vk_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
ID3D12Resource *buffers[DXGI_MAX_SWAP_CHAIN_BUFFERS];
unsigned int buffer_count;
@@ -958,12 +968,17 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
{
if (swapchain->buffers[i])
vkd3d_resource_decref(swapchain->buffers[i]);
+
+ if (swapchain->vk_device)
+ vk_funcs->p_vkDestroyImage(swapchain->vk_device, swapchain->vk_images[i], NULL);
}
if (swapchain->vk_device)
{
vk_funcs->p_vkDestroyFence(swapchain->vk_device, swapchain->vk_fence, NULL);
vk_funcs->p_vkDestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL);
+
+ vk_funcs->p_vkFreeMemory(swapchain->vk_device, swapchain->vk_memory, NULL);
}
if (swapchain->vk_instance)
@@ -1546,7 +1561,7 @@ static BOOL init_vkd3d(void)
return !!vkd3d_handle;
}
-static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkDevice vk_device)
+static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkInstance vk_instance, VkDevice vk_device)
{
const struct vulkan_funcs *vk;
@@ -1570,6 +1585,15 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkDevice vk_device)
dxgi->p_vkGetSwapchainImagesKHR = vk->p_vkGetSwapchainImagesKHR;
dxgi->p_vkQueuePresentKHR = vk->p_vkQueuePresentKHR;
+#define LOAD_INSTANCE_PFN(name) \
+ if (!(dxgi->p_##name = vk->p_vkGetInstanceProcAddr(vk_instance, #name))) \
+ { \
+ ERR("Failed to get instance proc "#name".\n"); \
+ return FALSE; \
+ }
+ LOAD_INSTANCE_PFN(vkGetPhysicalDeviceMemoryProperties)
+#undef LOAD_INSTANCE_PFN
+
#define LOAD_DEVICE_PFN(name) \
if (!(dxgi->p_##name = vk->p_vkGetDeviceProcAddr(vk_device, #name))) \
{ \
@@ -1577,8 +1601,14 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkDevice vk_device)
return FALSE; \
}
LOAD_DEVICE_PFN(vkAcquireNextImageKHR)
+ LOAD_DEVICE_PFN(vkAllocateMemory)
+ LOAD_DEVICE_PFN(vkBindImageMemory)
LOAD_DEVICE_PFN(vkCreateFence)
+ LOAD_DEVICE_PFN(vkCreateImage)
LOAD_DEVICE_PFN(vkDestroyFence)
+ LOAD_DEVICE_PFN(vkDestroyImage)
+ LOAD_DEVICE_PFN(vkFreeMemory)
+ LOAD_DEVICE_PFN(vkGetImageMemoryRequirements)
LOAD_DEVICE_PFN(vkQueueWaitIdle)
LOAD_DEVICE_PFN(vkResetFences)
LOAD_DEVICE_PFN(vkWaitForFences)
@@ -1600,8 +1630,6 @@ static HRESULT select_vk_format(const struct dxgi_vk_funcs *vk_funcs,
*vk_format = VK_FORMAT_UNDEFINED;
format = vkd3d_get_vk_format(swapchain_desc->Format);
- if (format == VK_FORMAT_UNDEFINED)
- return DXGI_ERROR_INVALID_CALL;
vr = vk_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL);
if (vr < 0 || !format_count)
@@ -1626,20 +1654,164 @@ static HRESULT select_vk_format(const struct dxgi_vk_funcs *vk_funcs,
if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
break;
}
+ if (i == format_count)
+ {
+ /* Try to create a swapchain with format conversion. */
+ WARN("Failed to find Vulkan swapchain format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
+ for (i = 0; i < format_count; ++i)
+ {
+ if (formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+ {
+ format = formats[i].format;
+ break;
+ }
+ }
+ }
heap_free(formats);
-
if (i == format_count)
{
- FIXME("Failed to find suitable format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
- return DXGI_ERROR_INVALID_CALL;
+ FIXME("Failed to find Vulkan swapchain format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
+ return DXGI_ERROR_UNSUPPORTED;
}
+ TRACE("Using Vulkan swapchain format %#x.\n", format);
+
*vk_format = format;
return S_OK;
}
+static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format)
+{
+ switch (vk_format)
+ {
+ case VK_FORMAT_B8G8R8A8_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
+ case VK_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM;
+ case VK_FORMAT_R8G8B8A8_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ case VK_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM;
+ default:
+ FIXME("Unhandled format %#x.\n", vk_format);
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+static HRESULT vk_select_memory_type(const struct dxgi_vk_funcs *vk_funcs,
+ VkPhysicalDevice vk_physical_device, uint32_t memory_type_mask,
+ VkMemoryPropertyFlags flags, uint32_t *memory_type_index)
+{
+ VkPhysicalDeviceMemoryProperties memory_properties;
+ unsigned int i;
+
+ vk_funcs->p_vkGetPhysicalDeviceMemoryProperties(vk_physical_device, &memory_properties);
+ for (i = 0; i < memory_properties.memoryTypeCount; ++i)
+ {
+ if (!(memory_type_mask & (1u << i)))
+ continue;
+
+ if ((memory_properties.memoryTypes[i].propertyFlags & flags) == flags)
+ {
+ *memory_type_index = i;
+ return S_OK;
+ }
+ }
+
+ FIXME("Failed to find memory type (allowed types %#x).\n", memory_type_mask);
+ return E_FAIL;
+}
+
+static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain,
+ const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat vk_format)
+{
+ const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ VkDeviceSize image_offset[DXGI_MAX_SWAP_CHAIN_BUFFERS];
+ VkDevice vk_device = swapchain->vk_device;
+ VkMemoryAllocateInfo allocate_info;
+ VkMemoryRequirements requirements;
+ VkImageCreateInfo image_info;
+ uint32_t memory_type_mask;
+ VkDeviceSize memory_size;
+ unsigned int i;
+ VkResult vr;
+ HRESULT hr;
+
+ memset(&image_info, 0, sizeof(image_info));
+ 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.extent.width = swapchain_desc->Width;
+ image_info.extent.height = swapchain_desc->Height;
+ image_info.extent.depth = 1;
+ image_info.mipLevels = 1;
+ image_info.arrayLayers = 1;
+ image_info.samples = VK_SAMPLE_COUNT_1_BIT;
+ image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+ | VK_IMAGE_USAGE_TRANSFER_DST_BIT
+ | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ image_info.queueFamilyIndexCount = 0;
+ image_info.pQueueFamilyIndices = NULL;
+ image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ for (i = 0; i < swapchain->buffer_count; ++i)
+ {
+ if ((vr = vk_funcs->p_vkCreateImage(vk_device, &image_info, NULL, &swapchain->vk_images[i])) < 0)
+ {
+ WARN("Failed to create Vulkan image, vr %d.\n", vr);
+ swapchain->vk_images[i] = VK_NULL_HANDLE;
+ return hresult_from_vk_result(vr);
+ }
+ }
+
+ memory_size = 0;
+ memory_type_mask = ~0u;
+ for (i = 0; i < swapchain->buffer_count; ++i)
+ {
+ vk_funcs->p_vkGetImageMemoryRequirements(vk_device, swapchain->vk_images[i], &requirements);
+
+ TRACE("Size %s, alignment %s, memory types %#x.\n",
+ wine_dbgstr_longlong(requirements.size), wine_dbgstr_longlong(requirements.alignment),
+ requirements.memoryTypeBits);
+
+ image_offset[i] = (memory_size + (requirements.alignment - 1)) & ~(requirements.alignment - 1);
+ memory_size = image_offset[i] + requirements.size;
+
+ memory_type_mask &= requirements.memoryTypeBits;
+ }
+
+ TRACE("Allocating %s bytes for user images.\n", wine_dbgstr_longlong(memory_size));
+
+ allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocate_info.pNext = NULL;
+ allocate_info.allocationSize = memory_size;
+
+ if (FAILED(hr = vk_select_memory_type(vk_funcs, swapchain->vk_physical_device,
+ memory_type_mask, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_info.memoryTypeIndex)))
+ return hr;
+
+ if ((vr = vk_funcs->p_vkAllocateMemory(vk_device, &allocate_info, NULL, &swapchain->vk_memory)) < 0)
+ {
+ WARN("Failed to allocate device memory, vr %d.\n", vr);
+ swapchain->vk_memory = VK_NULL_HANDLE;
+ return hresult_from_vk_result(vr);
+ }
+
+ for (i = 0; i < swapchain->buffer_count; ++i)
+ {
+ if ((vr = vk_funcs->p_vkBindImageMemory(vk_device, swapchain->vk_images[i],
+ swapchain->vk_memory, image_offset[i])) < 0)
+ {
+ WARN("Failed to bind image memory, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+ }
+
+ return S_OK;
+}
+
static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
- ID3D12Device *device, const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc)
+ ID3D12Device *device, const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc,
+ VkFormat vk_swapchain_format, VkFormat vk_format)
{
const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
struct vkd3d_image_resource_create_info resource_info;
@@ -1675,16 +1847,27 @@ 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 = swapchain_desc->Format;
+ resource_info.desc.Format = dxgi_format_from_vk_format(vk_format);
resource_info.desc.SampleDesc.Count = 1;
resource_info.desc.SampleDesc.Quality = 0;
resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
- for (i = 0; i < image_count; ++i)
+
+ if (vk_swapchain_format != vk_format)
{
- resource_info.vk_image = vk_images[i];
+ TRACE("Creating user swapchain buffers for format conversion.\n");
+
+ if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, swapchain_desc, vk_format)))
+ return hr;
+
+ resource_info.present_state = D3D12_RESOURCE_STATE_COPY_SOURCE;
+ }
+
+ for (i = 0; i < swapchain->buffer_count; ++i)
+ {
+ resource_info.vk_image = swapchain->vk_images[i] ? swapchain->vk_images[i] : vk_images[i];
if (FAILED(hr = vkd3d_create_image_resource(device, &resource_info, &swapchain->buffers[i])))
{
WARN("Failed to create vkd3d resource for Vulkan image %u, hr %#x.\n", i, hr);
@@ -1707,6 +1890,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
struct VkWin32SurfaceCreateInfoKHR surface_desc;
VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE;
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
+ VkFormat vk_swapchain_format, vk_format;
VkSurfaceCapabilitiesKHR surface_caps;
VkPhysicalDevice vk_physical_device;
VkFence vk_fence = VK_NULL_HANDLE;
@@ -1716,7 +1900,6 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
VkInstance vk_instance;
VkBool32 supported;
VkDevice vk_device;
- VkFormat vk_format;
VkResult vr;
HRESULT hr;
@@ -1744,6 +1927,12 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
return DXGI_ERROR_UNSUPPORTED;
}
+ if (!(vk_format = vkd3d_get_vk_format(swapchain_desc->Format)))
+ {
+ WARN("Invalid format %#x.\n", swapchain_desc->Format);
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
if (swapchain_desc->BufferUsage && swapchain_desc->BufferUsage != DXGI_USAGE_RENDER_TARGET_OUTPUT)
FIXME("Ignoring buffer usage %#x.\n", swapchain_desc->BufferUsage);
if (swapchain_desc->Scaling != DXGI_SCALING_STRETCH)
@@ -1767,8 +1956,9 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
swapchain->vk_instance = vk_instance;
swapchain->vk_device = vk_device;
+ swapchain->vk_physical_device = vk_physical_device;
- if (!init_vk_funcs(&swapchain->vk_funcs, vk_device))
+ if (!init_vk_funcs(&swapchain->vk_funcs, vk_instance, vk_device))
return E_FAIL;
wined3d_private_store_init(&swapchain->private_store);
@@ -1795,7 +1985,8 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
return DXGI_ERROR_UNSUPPORTED;
}
- if (FAILED(hr = select_vk_format(vk_funcs, vk_physical_device, vk_surface, swapchain_desc, &vk_format)))
+ if (FAILED(hr = select_vk_format(vk_funcs, vk_physical_device,
+ vk_surface, swapchain_desc, &vk_swapchain_format)))
{
d3d12_swapchain_destroy(swapchain);
return hr;
@@ -1847,7 +2038,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
vk_swapchain_desc.flags = 0;
vk_swapchain_desc.surface = vk_surface;
vk_swapchain_desc.minImageCount = swapchain_desc->BufferCount;
- vk_swapchain_desc.imageFormat = vk_format;
+ vk_swapchain_desc.imageFormat = vk_swapchain_format;
vk_swapchain_desc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
vk_swapchain_desc.imageExtent.width = swapchain_desc->Width;
vk_swapchain_desc.imageExtent.height = swapchain_desc->Height;
@@ -1880,7 +2071,8 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
}
swapchain->vk_fence = vk_fence;
- if (FAILED(hr = d3d12_swapchain_create_buffers(swapchain, device, swapchain_desc)))
+ if (FAILED(hr = d3d12_swapchain_create_buffers(swapchain, device,
+ swapchain_desc, vk_swapchain_format, vk_format)))
{
d3d12_swapchain_destroy(swapchain);
return hr;
diff --git a/dlls/dxgi/tests/device.c b/dlls/dxgi/tests/device.c
index 2e68511137a7..124c5a43d6e9 100644
--- a/dlls/dxgi/tests/device.c
+++ b/dlls/dxgi/tests/device.c
@@ -3645,9 +3645,8 @@ static void test_swapchain_backbuffer_index(IUnknown *device, BOOL is_d3d12)
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
swapchain_desc.SwapEffect = tests[i].swap_effect;
- expected_hr = !is_d3d12 || tests[i].supported_in_d3d12 ? S_OK : DXGI_ERROR_INVALID_CALL;
+ expected_hr = is_d3d12 && !tests[i].supported_in_d3d12 ? DXGI_ERROR_INVALID_CALL : S_OK;
hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
- todo_wine_if(is_d3d12 && tests[i].supported_in_d3d12)
ok(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
if (FAILED(hr))
continue;
--
2.16.4
2
1
09 Aug '18
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/dxgi/swapchain.c | 113 +++++++++++++++++++++++++++-----------------------
1 file changed, 62 insertions(+), 51 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index f222568865fd..07329b115079 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -1638,15 +1638,73 @@ static HRESULT select_vk_format(const struct dxgi_vk_funcs *vk_funcs,
return S_OK;
}
+static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
+ ID3D12Device *device, const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc)
+{
+ const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ struct vkd3d_image_resource_create_info resource_info;
+ VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain;
+ VkImage vk_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
+ VkDevice vk_device = swapchain->vk_device;
+ uint32_t image_count;
+ 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 != swapchain_desc->BufferCount)
+ FIXME("Got %u swapchain images, expected %u.\n", image_count, swapchain_desc->BufferCount);
+ if (image_count > ARRAY_SIZE(vk_images))
+ return E_FAIL;
+ swapchain->buffer_count = image_count;
+ if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images)) < 0)
+ {
+ WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ resource_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO;
+ resource_info.next = NULL;
+ resource_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resource_info.desc.Alignment = 0;
+ resource_info.desc.Width = swapchain_desc->Width;
+ resource_info.desc.Height = swapchain_desc->Height;
+ resource_info.desc.DepthOrArraySize = 1;
+ resource_info.desc.MipLevels = 1;
+ resource_info.desc.Format = swapchain_desc->Format;
+ resource_info.desc.SampleDesc.Count = 1;
+ resource_info.desc.SampleDesc.Quality = 0;
+ resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
+ resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
+ for (i = 0; i < image_count; ++i)
+ {
+ resource_info.vk_image = vk_images[i];
+ if (FAILED(hr = vkd3d_create_image_resource(device, &resource_info, &swapchain->buffers[i])))
+ {
+ WARN("Failed to create vkd3d resource for Vulkan image %u, hr %#x.\n", i, hr);
+ return hr;
+ }
+
+ vkd3d_resource_incref(swapchain->buffers[i]);
+ ID3D12Resource_Release(swapchain->buffers[i]);
+ }
+
+ return S_OK;
+}
+
static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGIFactory *factory,
ID3D12Device *device, ID3D12CommandQueue *queue, HWND window,
const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc)
{
const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
- struct vkd3d_image_resource_create_info resource_info;
struct VkSwapchainCreateInfoKHR vk_swapchain_desc;
struct VkWin32SurfaceCreateInfoKHR surface_desc;
- VkImage vk_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE;
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkSurfaceCapabilitiesKHR surface_caps;
@@ -1654,7 +1712,6 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
VkFence vk_fence = VK_NULL_HANDLE;
VkFenceCreateInfo fence_desc;
uint32_t queue_family_index;
- unsigned int image_count, i;
VkImageUsageFlags usage;
VkInstance vk_instance;
VkBool32 supported;
@@ -1823,25 +1880,10 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
}
swapchain->vk_fence = vk_fence;
- if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0)
+ if (FAILED(hr = d3d12_swapchain_create_buffers(swapchain, device, swapchain_desc)))
{
- WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
d3d12_swapchain_destroy(swapchain);
- return hresult_from_vk_result(vr);
- }
- if (image_count != swapchain_desc->BufferCount)
- FIXME("Got %u swapchain images, expected %u.\n", image_count, swapchain_desc->BufferCount);
- if (image_count > ARRAY_SIZE(vk_images))
- {
- d3d12_swapchain_destroy(swapchain);
- return E_FAIL;
- }
- swapchain->buffer_count = image_count;
- if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images)) < 0)
- {
- WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
- d3d12_swapchain_destroy(swapchain);
- return hresult_from_vk_result(vr);
+ return hr;
}
if (FAILED(hr = d3d12_swapchain_acquire_next_image(swapchain)))
@@ -1851,37 +1893,6 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
return hr;
}
- resource_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO;
- resource_info.next = NULL;
- resource_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- resource_info.desc.Alignment = 0;
- resource_info.desc.Width = swapchain_desc->Width;
- resource_info.desc.Height = swapchain_desc->Height;
- resource_info.desc.DepthOrArraySize = 1;
- resource_info.desc.MipLevels = 1;
- resource_info.desc.Format = swapchain_desc->Format;
- resource_info.desc.SampleDesc.Count = 1;
- resource_info.desc.SampleDesc.Quality = 0;
- resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
- resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
- resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
- for (i = 0; i < image_count; ++i)
- {
- resource_info.vk_image = vk_images[i];
- if (SUCCEEDED(hr = vkd3d_create_image_resource(device, &resource_info, &swapchain->buffers[i])))
- {
- vkd3d_resource_incref(swapchain->buffers[i]);
- ID3D12Resource_Release(swapchain->buffers[i]);
- }
- else
- {
- ERR("Failed to create vkd3d resource for Vulkan image %u, hr %#x.\n", i, hr);
- d3d12_swapchain_destroy(swapchain);
- return hr;
- }
- }
-
ID3D12CommandQueue_AddRef(swapchain->command_queue = queue);
ID3D12Device_AddRef(swapchain->device = device);
IWineDXGIFactory_AddRef(swapchain->factory = factory);
--
2.16.4
2
1
[PATCH 04/11] dxgi: Wait for Vulkan queue to become idle before destroying swapchain.
by Józef Kucia 09 Aug '18
by Józef Kucia 09 Aug '18
09 Aug '18
Direct3D 12 debug layers do not complain when a swapchain is destroyed
immediately after Present().
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/dxgi/swapchain.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 7a305554dbeb..f222568865fd 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -826,8 +826,10 @@ static PFN_vkd3d_resource_incref vkd3d_resource_incref;
struct dxgi_vk_funcs
{
PFN_vkAcquireNextImageKHR p_vkAcquireNextImageKHR;
+ PFN_vkCreateFence p_vkCreateFence;
PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR;
PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR;
+ PFN_vkDestroyFence p_vkDestroyFence;
PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR;
PFN_vkDestroySwapchainKHR p_vkDestroySwapchainKHR;
PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr;
@@ -839,10 +841,9 @@ struct dxgi_vk_funcs
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR p_vkGetPhysicalDeviceWin32PresentationSupportKHR;
PFN_vkGetSwapchainImagesKHR p_vkGetSwapchainImagesKHR;
PFN_vkQueuePresentKHR p_vkQueuePresentKHR;
- PFN_vkCreateFence p_vkCreateFence;
- PFN_vkWaitForFences p_vkWaitForFences;
+ PFN_vkQueueWaitIdle p_vkQueueWaitIdle;
PFN_vkResetFences p_vkResetFences;
- PFN_vkDestroyFence p_vkDestroyFence;
+ PFN_vkWaitForFences p_vkWaitForFences;
};
static HRESULT hresult_from_vk_result(VkResult vr)
@@ -929,10 +930,25 @@ static ULONG STDMETHODCALLTYPE d3d12_swapchain_AddRef(IDXGISwapChain3 *iface)
static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
{
const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+ VkQueue vk_queue;
unsigned int i;
if (swapchain->command_queue)
+ {
+ if ((vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue)))
+ {
+ vk_funcs->p_vkQueueWaitIdle(vk_queue);
+
+ vkd3d_release_vk_queue(swapchain->command_queue);
+ }
+ else
+ {
+ WARN("Failed to acquire Vulkan queue.\n");
+ }
+
ID3D12CommandQueue_Release(swapchain->command_queue);
+ }
+
if (swapchain->factory)
IWineDXGIFactory_Release(swapchain->factory);
@@ -1563,6 +1579,7 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkDevice vk_device)
LOAD_DEVICE_PFN(vkAcquireNextImageKHR)
LOAD_DEVICE_PFN(vkCreateFence)
LOAD_DEVICE_PFN(vkDestroyFence)
+ LOAD_DEVICE_PFN(vkQueueWaitIdle)
LOAD_DEVICE_PFN(vkResetFences)
LOAD_DEVICE_PFN(vkWaitForFences)
#undef LOAD_DEVICE_PFN
--
2.16.4
2
1