From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/Makefile.in | 2 +- dlls/win32u/tests/d3dkmt.c | 569 ++++++++++++++++++++++++++++++++++ 2 files changed, 570 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/tests/Makefile.in b/dlls/win32u/tests/Makefile.in index 541812f754c..6e9e3d441df 100644 --- a/dlls/win32u/tests/Makefile.in +++ b/dlls/win32u/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = win32u.dll -IMPORTS = imm32 user32 gdi32 dwmapi setupapi win32u +IMPORTS = imm32 user32 gdi32 dwmapi setupapi d3d9 win32u
SOURCES = \ d3dkmt.c \ diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 5385c25a9d0..c1d286b0676 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -20,6 +20,7 @@
#include <stdarg.h>
+#define COBJMACROS #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -35,12 +36,32 @@ #include "devpkey.h" #include "cfgmgr32.h"
+#include "d3d9.h" +#include "dxgi1_3.h" #include "wine/test.h"
+#define D3DUSAGE_SURFACE 0x8000000 +#define D3DUSAGE_LOCKABLE 0x4000000 +#define D3DUSAGE_OFFSCREEN 0x0400000 + static const WCHAR display1W[] = L"\\.\DISPLAY1";
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+static const LUID luid_zero; +const GUID GUID_NULL = {0}; + +static const char *debugstr_luid( const LUID *luid ) +{ + if (!luid) return "(null)"; + return wine_dbg_sprintf( "%04lx:%04lx", luid->LowPart, luid->HighPart ); +} + +static BOOL luid_equals( const LUID *a, const LUID *b ) +{ + return a->HighPart == b->HighPart && a->LowPart == b->LowPart; +} + static const char *debugstr_ok( const char *cond ) { int c, n = 0; @@ -61,11 +82,22 @@ static const char *debugstr_ok( const char *cond ) t v = (r); \ ok( v op (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ } while (0) +#define ok_i4( r, op, e ) ok_ex( r, op, e, int, "%i" ) #define ok_u4( r, op, e ) ok_ex( r, op, e, UINT, "%u" ) #define ok_x4( r, op, e ) ok_ex( r, op, e, UINT, "%#x" ) #define ok_u1( r, op, e ) ok_ex( r, op, e, unsigned char, "%u" ) #define ok_ptr( r, op, e ) ok_ex( r, op, e, const void *, "%p" ) + +#define ok_ret( e, r ) ok_ex( r, ==, e, UINT_PTR, "%Iu, error %ld", GetLastError() ) +#define ok_ref( e, r ) ok_ex( r, ==, e, LONG, "%ld" ) +#define ok_hr( e, r ) ok_ex( r, ==, e, HRESULT, "%#lx" ) #define ok_nt( e, r ) ok_ex( r, ==, e, NTSTATUS, "%#lx" ) +#define ok_vk( e, r ) ok_ex( r, ==, e, VkResult, "%d" ) + +static BOOL is_d3dkmt_handle( HANDLE handle ) +{ + return (ULONG_PTR)handle & 0xc0000000; +}
#define run_in_process( a ) run_in_process_( __FILE__, __LINE__, a ) static void run_in_process_( const char *file, int line, const char *args ) @@ -154,6 +186,257 @@ static void _check_object_name( unsigned line, HANDLE handle, const WCHAR *expec debugstr_w(str->Buffer), debugstr_w(expected_name) ); }
+struct dxgi_runtime_desc +{ + UINT size; + UINT version; + UINT width; + UINT height; + DXGI_FORMAT format; + UINT unknown_0; + UINT unknown_1; + UINT keyed_mutex; + D3DKMT_HANDLE mutex_handle; + D3DKMT_HANDLE sync_handle; + UINT nt_shared; + UINT unknown_2; + UINT unknown_3; + UINT unknown_4; +}; + +#define check_dxgi_runtime_desc( a, b ) check_dxgi_runtime_desc_( a, b, FALSE ) +static void check_dxgi_runtime_desc_( struct dxgi_runtime_desc *desc, const struct dxgi_runtime_desc *expect, BOOL d3d12 ) +{ + ok_x4( desc->size, ==, expect->size ); + ok_x4( desc->version, ==, expect->version ); + ok_x4( desc->width, ==, expect->width ); + ok_x4( desc->height, ==, expect->height ); + ok_x4( desc->format, ==, expect->format ); + if (expect->version == 1) ok_x4( desc->unknown_0, ==, 1 ); + else if (!d3d12) ok_x4( desc->unknown_0, ==, 0 ); + ok_x4( desc->unknown_1, ==, 0 ); + ok_x4( desc->keyed_mutex, ==, expect->keyed_mutex ); + if (desc->keyed_mutex) check_d3dkmt_global( desc->mutex_handle ); + if (desc->keyed_mutex) check_d3dkmt_global( desc->sync_handle ); + ok_x4( desc->nt_shared, ==, expect->nt_shared ); + ok_x4( desc->unknown_2, ==, 0 ); + ok_x4( desc->unknown_3, ==, 0 ); + if (!d3d12) ok_x4( desc->unknown_4, ==, 0 ); +} + +struct d3d9_runtime_desc +{ + struct dxgi_runtime_desc dxgi; + D3DFORMAT format; + D3DRESOURCETYPE type; + UINT usage; + union + { + struct + { + UINT unknown_0; + UINT width; + UINT height; + UINT levels; + UINT depth; + } texture; + struct + { + UINT unknown_0; + UINT unknown_1; + UINT unknown_2; + UINT width; + UINT height; + } surface; + struct + { + UINT unknown_0; + UINT width; + UINT format; + UINT unknown_1; + UINT unknown_2; + } buffer; + }; +}; + +C_ASSERT( sizeof(struct d3d9_runtime_desc) == 0x58 ); + +static void check_d3d9_runtime_desc( struct d3d9_runtime_desc *desc, const struct d3d9_runtime_desc *expect ) +{ + check_dxgi_runtime_desc( &desc->dxgi, &expect->dxgi ); + + ok_x4( desc->format, ==, expect->format ); + ok_x4( desc->type, ==, expect->type ); + ok_x4( desc->usage, ==, expect->usage ); + switch (desc->type) + { + case D3DRTYPE_TEXTURE: + ok_x4( desc->texture.unknown_0, ==, 0 ); + ok_x4( desc->texture.width, ==, expect->dxgi.width ); + ok_x4( desc->texture.height, ==, expect->dxgi.height ); + ok_x4( desc->texture.levels, ==, 1 ); + ok_x4( desc->texture.depth, ==, 0 ); + break; + case D3DRTYPE_CUBETEXTURE: + ok_x4( desc->texture.unknown_0, ==, 0 ); + ok_x4( desc->texture.width, ==, expect->dxgi.width ); + ok_x4( desc->texture.height, ==, expect->dxgi.width ); + ok_x4( desc->texture.levels, ==, 1 ); + ok_x4( desc->texture.depth, ==, 0 ); + break; + case D3DRTYPE_VOLUMETEXTURE: + ok_x4( desc->texture.unknown_0, ==, 0 ); + ok_x4( desc->texture.width, ==, expect->dxgi.width ); + ok_x4( desc->texture.height, ==, expect->dxgi.height ); + ok_x4( desc->texture.levels, ==, 1 ); + ok_x4( desc->texture.depth, ==, expect->texture.depth ); + break; + case D3DRTYPE_SURFACE: + ok_x4( desc->surface.unknown_0, ==, 0 ); + ok_x4( desc->surface.unknown_1, ==, 0 ); + ok_x4( desc->surface.unknown_2, ==, 0 ); + ok_x4( desc->surface.width, ==, expect->dxgi.width ); + ok_x4( desc->surface.height, ==, expect->dxgi.height ); + break; + case D3DRTYPE_VERTEXBUFFER: + case D3DRTYPE_INDEXBUFFER: + ok_x4( desc->buffer.unknown_0, ==, 0 ); + ok_x4( desc->buffer.width, ==, expect->dxgi.width ); + ok_x4( desc->buffer.format, ==, expect->buffer.format ); + ok_x4( desc->buffer.unknown_1, ==, 0 ); + ok_x4( desc->buffer.unknown_2, ==, 0 ); + break; + default: + ok( 0, "unexpected\n" ); + break; + } +} + +static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_global, UINT size, char *buffer ) +{ + D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE query_nt = {0}; + D3DKMT_OPENADAPTERFROMLUID open_adapter = {0}; + D3DKMT_OPENRESOURCEFROMNTHANDLE open_nt = {0}; + D3DDDI_OPENALLOCATIONINFO2 open_alloc = {0}; + D3DKMT_DESTROYDEVICE destroy_device = {0}; + D3DKMT_CREATEDEVICE create_device = {0}; + D3DKMT_CLOSEADAPTER close_adapter = {0}; + D3DKMT_DESTROYALLOCATION destroy = {0}; + D3DKMT_QUERYRESOURCEINFO query = {0}; + D3DKMT_OPENRESOURCE open = {0}; + + char resource_data[0x100] = {0}; + char driver_data[0x4000] = {0}; + D3DKMT_HANDLE resource; + NTSTATUS status; + + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) return; + + open_adapter.AdapterLuid = luid; + status = D3DKMTOpenAdapterFromLuid(&open_adapter); + ok_nt( status, STATUS_SUCCESS ); + check_d3dkmt_local(open_adapter.hAdapter, NULL); + create_device.hAdapter = open_adapter.hAdapter; + status = D3DKMTCreateDevice(&create_device); + ok_nt( status, STATUS_SUCCESS ); + check_d3dkmt_local(create_device.hDevice, NULL); + + if (expect_global) check_d3dkmt_global( (UINT_PTR)handle ); + else check_object_type( handle, L"DxgkSharedResource" ); + + if (is_d3dkmt_handle( handle )) + { + memset( buffer, 0xcd, size ); + query.hDevice = create_device.hDevice; + query.hGlobalShare = HandleToUlong( handle ); + query.pPrivateRuntimeData = buffer; + query.PrivateRuntimeDataSize = size; + status = D3DKMTQueryResourceInfo( &query ); + ok_nt( STATUS_SUCCESS, status ); + if (size) ok_u4( query.PrivateRuntimeDataSize, ==, size ); + else ok( query.PrivateRuntimeDataSize == 0 || query.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query.PrivateRuntimeDataSize ); + ok_u4( query.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); + ok_u4( query.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); + ok_u4( query.NumAllocations, ==, 1 ); + if (size) ok_u1( *buffer, ==, 0xcd ); + + memset( buffer, 0xcd, size ); + open.hDevice = query.hDevice; + open.hGlobalShare = query.hGlobalShare; + open.NumAllocations = 1; + open.pOpenAllocationInfo2 = &open_alloc; + open.pPrivateRuntimeData = buffer; + open.PrivateRuntimeDataSize = query.PrivateRuntimeDataSize; + open.pResourcePrivateDriverData = resource_data; + open.ResourcePrivateDriverDataSize = query.ResourcePrivateDriverDataSize; + open.pTotalPrivateDriverDataBuffer = driver_data; + open.TotalPrivateDriverDataBufferSize = query.TotalPrivateDriverDataSize; + status = D3DKMTOpenResource2( &open ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open.hResource, NULL ); + if (size) ok_u4( open.PrivateRuntimeDataSize, ==, size ); + else ok( open.PrivateRuntimeDataSize == 0 || open.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open.PrivateRuntimeDataSize ); + ok_u4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); + ok_u4( open.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); + ok_u4( open.NumAllocations, ==, 1 ); + check_d3dkmt_local( open_alloc.hAllocation, NULL ); + + resource = open.hResource; + } + else + { + memset( buffer, 0xcd, size ); + query_nt.hDevice = create_device.hDevice; + query_nt.hNtHandle = handle; + query_nt.pPrivateRuntimeData = buffer; + query_nt.PrivateRuntimeDataSize = size; + status = D3DKMTQueryResourceInfoFromNtHandle( &query_nt ); + ok_nt( STATUS_SUCCESS, status ); + if (size) ok_u4( query_nt.PrivateRuntimeDataSize, ==, size ); + else ok( query_nt.PrivateRuntimeDataSize == 0 || query_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query_nt.PrivateRuntimeDataSize ); + ok_u4( query_nt.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); + ok_u4( query_nt.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); + ok_u4( query_nt.NumAllocations, ==, 1 ); + if (size) ok_u1( *buffer, ==, 0xcd ); + + memset( buffer, 0xcd, size ); + open_nt.hDevice = query_nt.hDevice; + open_nt.hNtHandle = query_nt.hNtHandle; + open_nt.NumAllocations = 1; + open_nt.pOpenAllocationInfo2 = &open_alloc; + open_nt.pPrivateRuntimeData = buffer; + open_nt.PrivateRuntimeDataSize = query_nt.PrivateRuntimeDataSize; + open_nt.pResourcePrivateDriverData = resource_data; + open_nt.ResourcePrivateDriverDataSize = query_nt.ResourcePrivateDriverDataSize; + open_nt.pTotalPrivateDriverDataBuffer = driver_data; + open_nt.TotalPrivateDriverDataBufferSize = query_nt.TotalPrivateDriverDataSize; + status = D3DKMTOpenResourceFromNtHandle( &open_nt ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_nt.hResource, NULL ); + if (size) ok_u4( open_nt.PrivateRuntimeDataSize, ==, size ); + else ok( open_nt.PrivateRuntimeDataSize == 0 || open_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open_nt.PrivateRuntimeDataSize ); + ok_u4( open_nt.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); + ok_u4( open_nt.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); + ok_u4( open_nt.NumAllocations, ==, 1 ); + todo_wine check_d3dkmt_local( open_alloc.hAllocation, NULL ); + + resource = open_nt.hResource; + } + + destroy.hDevice = create_device.hDevice; + destroy.hResource = resource; + status = D3DKMTDestroyAllocation( &destroy ); + ok_nt( STATUS_SUCCESS, status ); + + destroy_device.hDevice = create_device.hDevice; + status = D3DKMTDestroyDevice(&destroy_device); + ok_nt( status, STATUS_SUCCESS ); + close_adapter.hAdapter = open_adapter.hAdapter; + status = D3DKMTCloseAdapter(&close_adapter); + ok_nt( status, STATUS_SUCCESS ); +} + static BOOL get_primary_adapter_name( WCHAR *name ) { DISPLAY_DEVICEW dd; @@ -2663,6 +2946,291 @@ static void test_D3DKMTShareObjects( void ) ok_nt( STATUS_SUCCESS, status ); }
+static IDirect3DDevice9Ex *create_d3d9ex_device( HWND hwnd, LUID *luid, BOOL *stencil_broken ) +{ + D3DPRESENT_PARAMETERS params = {0}; + D3DADAPTER_IDENTIFIER9 adapter_id; + IDirect3DDevice9Ex *device; + IDirect3D9Ex *d3d; + LUID adapter_luid; + UINT i, count; + HRESULT hr; + + hr = Direct3DCreate9Ex( D3D_SDK_VERSION, &d3d ); + ok_hr( S_OK, hr ); + count = IDirect3D9Ex_GetAdapterCount( d3d ); + ok_u4( count, >, 0 ); + + for (i = 0; i < count; i++) + { + hr = IDirect3D9Ex_GetAdapterLUID( d3d, i, &adapter_luid ); + ok_hr( S_OK, hr ); + + if (luid_equals( luid, &luid_zero )) *luid = adapter_luid; + if (luid_equals( luid, &adapter_luid )) break; + } + ok( i < count, "d3d9ex adapter not found\n" ); + + hr = IDirect3D9Ex_GetAdapterIdentifier( d3d, i, 0, &adapter_id ); + ok_hr( S_OK, hr ); + if (stencil_broken) *stencil_broken = adapter_id.VendorId == 0x1002; + + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.hDeviceWindow = hwnd; + params.Windowed = TRUE; + hr = IDirect3D9Ex_CreateDeviceEx( d3d, i, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, NULL, &device ); + ok_hr( S_OK, hr ); + IDirect3D9Ex_Release( d3d ); + + return device; +} + +static void test_shared_resources(void) +{ + IDirect3DDevice9Ex *d3d9_exp, *d3d9_imp; + BOOL stencil_broken; + LUID luid = {0}; + HRESULT hr; + HWND hwnd; + MSG msg; + + hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 100, 100, 200, 200, NULL, NULL, NULL, NULL ); + ok_ptr( hwnd, !=, NULL ); + while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); + + d3d9_exp = create_d3d9ex_device( hwnd, &luid, &stencil_broken ); + ok_ptr( d3d9_exp, !=, NULL ); + d3d9_imp = create_d3d9ex_device( hwnd, &luid, NULL ); + ok_ptr( d3d9_imp, !=, NULL ); + + trace( "adapter luid %s\n", debugstr_luid( &luid ) ); + +#define MAKETEST(api, dim, idx) (((api & 7) << 7) | ((dim & 7) << 4) | (idx & 15)) +#define GET_API(test) ((test >> 7) & 7) +#define GET_DIM(test) ((test >> 4) & 7) + + for (UINT test = 0; test <= MAKETEST(7,7,0xf); test++) + { + static const UINT resource_size = 0x100000, array_1d = 0x20, width_2d = 0x40, height_3d = 0x20, width_cube = 0x40; + const UINT width_3d = width_2d, depth_3d = resource_size / 4 / width_2d / height_3d; + const UINT height_2d = resource_size / 4 / width_2d; + const UINT width_1d = resource_size / 4 / array_1d; + + C_ASSERT( width_cube * width_cube * width_cube * 4 == resource_size ); + C_ASSERT( width_1d * array_1d * 4 == resource_size ); + C_ASSERT( width_2d * height_2d * 4 == resource_size ); + C_ASSERT( width_3d * height_3d * depth_3d * 4 == resource_size ); + + char runtime_desc[0x1000] = {0}; + IUnknown *export = NULL; + HANDLE handle = NULL; + + winetest_push_context( "%u:%u:%u", GET_API(test), GET_DIM(test), test & 15 ); + + switch (test) + { + case MAKETEST(0, 0, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = resource_size / (4 * sizeof(float)), .height = 1, .format = DXGI_FORMAT_UNKNOWN}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_VERTEXDATA, .type = D3DRTYPE_VERTEXBUFFER, .usage = D3DUSAGE_LOCKABLE, .buffer.format = D3DFVF_XYZ}; + hr = IDirect3DDevice9Ex_CreateVertexBuffer( d3d9_exp, dxgi.width, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, + (IDirect3DVertexBuffer9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 0, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = resource_size / 2, .height = 1, .format = DXGI_FORMAT_UNKNOWN}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_INDEX16, .type = D3DRTYPE_INDEXBUFFER, .usage = D3DUSAGE_LOCKABLE}; + hr = IDirect3DDevice9Ex_CreateIndexBuffer( d3d9_exp, dxgi.width, 0, desc.format, D3DPOOL_DEFAULT, + (IDirect3DIndexBuffer9 **)&export, &handle ); + ok( hr == S_OK || broken( hr == D3DERR_NOTAVAILABLE ), "got %#lx\n", hr ); + if (hr != S_OK) break; + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_TEXTURE, .usage = D3DUSAGE_SURFACE}; + hr = IDirect3DDevice9Ex_CreateTexture( d3d9_exp, dxgi.width, dxgi.height, 1, 0, desc.format, D3DPOOL_DEFAULT, + (IDirect3DTexture9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_TEXTURE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_LOCKABLE | D3DUSAGE_DYNAMIC}; + hr = IDirect3DDevice9Ex_CreateTexture( d3d9_exp, dxgi.width, dxgi.height, 1, D3DUSAGE_DYNAMIC, desc.format, D3DPOOL_DEFAULT, + (IDirect3DTexture9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 2): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_TEXTURE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_RENDERTARGET}; + hr = IDirect3DDevice9Ex_CreateTexture( d3d9_exp, dxgi.width, dxgi.height, 1, D3DUSAGE_RENDERTARGET, desc.format, D3DPOOL_DEFAULT, + (IDirect3DTexture9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 3): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_RENDERTARGET}; + hr = IDirect3DDevice9Ex_CreateRenderTarget( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DMULTISAMPLE_NONE, 0, + FALSE, (IDirect3DSurface9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 4): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_LOCKABLE | D3DUSAGE_RENDERTARGET}; + hr = IDirect3DDevice9Ex_CreateRenderTarget( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DMULTISAMPLE_NONE, 0, + TRUE, (IDirect3DSurface9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 5): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_D24_UNORM_S8_UINT}; + struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_D24S8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_DEPTHSTENCIL}; + hr = IDirect3DDevice9Ex_CreateDepthStencilSurface( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DMULTISAMPLE_NONE, 0, + FALSE, (IDirect3DSurface9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + if (stencil_broken) { desc.dxgi.format = 0; desc.format = D3DFMT_D24S8 - 1; } + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 6): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_LOCKABLE | D3DUSAGE_OFFSCREEN}; + hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DPOOL_DEFAULT, + (IDirect3DSurface9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 7): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_RENDERTARGET}; + hr = IDirect3DDevice9Ex_CreateRenderTargetEx( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DMULTISAMPLE_NONE, 0, + FALSE, (IDirect3DSurface9 **)&export, &handle, 0 ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 8): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_B8G8R8A8_UNORM}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_LOCKABLE | D3DUSAGE_OFFSCREEN}; + hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DPOOL_DEFAULT, + (IDirect3DSurface9 **)&export, &handle, 0 ); + todo_wine ok_hr( S_OK, hr ); + todo_wine todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 2, 9): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_D24_UNORM_S8_UINT}; + struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_D24S8, .type = D3DRTYPE_SURFACE, .usage = D3DUSAGE_SURFACE | D3DUSAGE_DEPTHSTENCIL}; + hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx( d3d9_exp, dxgi.width, dxgi.height, desc.format, D3DMULTISAMPLE_NONE, 0, + FALSE, (IDirect3DSurface9 **)&export, &handle, 0 ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + if (stencil_broken) { desc.dxgi.format = 0; desc.format = D3DFMT_D24S8 - 1; } + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 3, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_3d, .height = height_3d, .format = DXGI_FORMAT_UNKNOWN}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_VOLUMETEXTURE, .usage = D3DUSAGE_SURFACE, .texture.depth = depth_3d}; + hr = IDirect3DDevice9Ex_CreateVolumeTexture( d3d9_exp, dxgi.width, dxgi.height, desc.texture.depth, 1, 0, desc.format, D3DPOOL_DEFAULT, + (IDirect3DVolumeTexture9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(0, 3, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x58, .version = 1, .width = width_cube, .height = width_cube, .format = DXGI_FORMAT_UNKNOWN}; + const struct d3d9_runtime_desc desc = {.dxgi = dxgi, .format = D3DFMT_A8R8G8B8, .type = D3DRTYPE_CUBETEXTURE, .usage = D3DUSAGE_SURFACE}; + hr = IDirect3DDevice9Ex_CreateCubeTexture( d3d9_exp, dxgi.width, 1, 0, desc.format, D3DPOOL_DEFAULT, + (IDirect3DCubeTexture9 **)&export, &handle ); + ok_hr( S_OK, hr ); + todo_wine ok_ptr( handle, !=, NULL ); + if (!handle) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); + break; + } + } + + if (handle && !is_d3dkmt_handle( handle )) CloseHandle( handle ); + if (export) ok_ref( 0, IUnknown_Release( export ) ); + winetest_pop_context(); + } + +#undef GET_DIM +#undef GET_API +#undef MAKETEST + + ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_imp ) ); + ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_exp ) ); + DestroyWindow( hwnd ); +} + START_TEST( d3dkmt ) { char **argv; @@ -2692,4 +3260,5 @@ START_TEST( d3dkmt ) test_D3DKMTCreateKeyedMutex(); test_D3DKMTCreateAllocation(); test_D3DKMTShareObjects(); + test_shared_resources(); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 86 +++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index c1d286b0676..71c1cf8d574 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -3023,7 +3023,7 @@ static void test_shared_resources(void) C_ASSERT( width_3d * height_3d * depth_3d * 4 == resource_size );
char runtime_desc[0x1000] = {0}; - IUnknown *export = NULL; + IUnknown *export = NULL, *import = NULL; HANDLE handle = NULL;
winetest_push_context( "%u:%u:%u", GET_API(test), GET_DIM(test), test & 15 ); @@ -3216,7 +3216,91 @@ static void test_shared_resources(void) break; } } + if (!handle) goto skip_tests;
+ if (d3d9_imp) + { + const struct d3d9_runtime_desc *desc = (struct d3d9_runtime_desc *)runtime_desc; + + hr = IDirect3DDevice9Ex_CreateTexture( d3d9_imp, width_2d, height_2d, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_TEXTURE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->usage != D3DUSAGE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateVolumeTexture( d3d9_imp, width_3d, height_3d, depth_3d, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_VOLUMETEXTURE) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateCubeTexture( d3d9_imp, width_cube, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_CUBETEXTURE) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateVertexBuffer( d3d9_imp, resource_size / (4 * sizeof(float)), 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, (IDirect3DVertexBuffer9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_VERTEXBUFFER) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateIndexBuffer( d3d9_imp, resource_size / 2, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, (IDirect3DIndexBuffer9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_INDEXBUFFER) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateRenderTarget( d3d9_imp, width_2d, height_2d, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (!(desc->usage & D3DUSAGE_RENDERTARGET)) todo_wine ok_hr( E_INVALIDARG, hr ); + else if ((desc->usage & D3DUSAGE_LOCKABLE)) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateDepthStencilSurface( d3d9_imp, width_2d, height_2d, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (!(desc->usage & D3DUSAGE_DEPTHSTENCIL)) todo_wine ok_hr( E_INVALIDARG, hr ); + else if ((desc->usage & D3DUSAGE_LOCKABLE)) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface( d3d9_imp, width_2d, height_2d, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&import, &handle ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (!(desc->usage & D3DUSAGE_OFFSCREEN)) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateRenderTargetEx( d3d9_imp, width_2d, height_2d, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&import, &handle, 0 ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (!(desc->usage & D3DUSAGE_RENDERTARGET)) todo_wine ok_hr( E_INVALIDARG, hr ); + else if ((desc->usage & D3DUSAGE_LOCKABLE)) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx( d3d9_imp, width_2d, height_2d, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&import, &handle, 0 ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (!(desc->usage & D3DUSAGE_OFFSCREEN)) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx( d3d9_imp, width_2d, height_2d, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&import, &handle, 0 ); + if (desc->dxgi.version != 1) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->type != D3DRTYPE_SURFACE) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (!(desc->usage & D3DUSAGE_DEPTHSTENCIL)) todo_wine ok_hr( E_INVALIDARG, hr ); + else if ((desc->usage & D3DUSAGE_LOCKABLE)) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + } + +skip_tests: if (handle && !is_d3dkmt_handle( handle )) CloseHandle( handle ); if (export) ok_ref( 0, IUnknown_Release( export ) ); winetest_pop_context();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/Makefile.in | 2 +- dlls/win32u/tests/d3dkmt.c | 274 +++++++++++++++++++++++++++++++++- 2 files changed, 272 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/tests/Makefile.in b/dlls/win32u/tests/Makefile.in index 6e9e3d441df..0e7618b8458 100644 --- a/dlls/win32u/tests/Makefile.in +++ b/dlls/win32u/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = win32u.dll -IMPORTS = imm32 user32 gdi32 dwmapi setupapi d3d9 win32u +IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 win32u
SOURCES = \ d3dkmt.c \ diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 71c1cf8d574..43044c3363e 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -38,6 +38,7 @@
#include "d3d9.h" #include "dxgi1_3.h" +#include "wine/wgl.h" #include "wine/test.h"
#define D3DUSAGE_SURFACE 0x8000000 @@ -2973,7 +2974,7 @@ static IDirect3DDevice9Ex *create_d3d9ex_device( HWND hwnd, LUID *luid, BOOL *st
hr = IDirect3D9Ex_GetAdapterIdentifier( d3d, i, 0, &adapter_id ); ok_hr( S_OK, hr ); - if (stencil_broken) *stencil_broken = adapter_id.VendorId == 0x1002; + if (stencil_broken) *stencil_broken = !winetest_platform_is_wine && adapter_id.VendorId == 0x1002;
params.SwapEffect = D3DSWAPEFFECT_DISCARD; params.hDeviceWindow = hwnd; @@ -2986,9 +2987,180 @@ static IDirect3DDevice9Ex *create_d3d9ex_device( HWND hwnd, LUID *luid, BOOL *st return device; }
+C_ASSERT( sizeof(GUID) == GL_UUID_SIZE_EXT ); +C_ASSERT( sizeof(LUID) == GL_LUID_SIZE_EXT ); + +struct opengl_device +{ + HWND hwnd; + HDC hdc; + HGLRC rc; + BOOL broken; +}; + +static void destroy_opengl_device( struct opengl_device *dev ) +{ + UINT ret; + + ret = wglMakeCurrent( dev->hdc, NULL ); + ok_u4( ret, !=, 0 ); + ret = wglDeleteContext( dev->rc ); + ok_u4( ret, !=, 0 ); + ret = ReleaseDC( dev->hwnd, dev->hdc ); + ok_u4( ret, !=, 0 ); + + free( dev ); +} + +static const char *find_opengl_extension( const char *extensions, const char *name ) +{ + size_t len = strlen( name ); + const char *ptr; + if (!(ptr = strstr( extensions, name ))) return NULL; + if (ptr != extensions && ptr[-1] != ' ') return NULL; + if (ptr[len] != 0 && ptr[len] != ' ') return NULL; + return ptr; +} + +static struct opengl_device *create_opengl_device( HWND hwnd, LUID *luid ) +{ + static const PIXELFORMATDESCRIPTOR pfd = {.dwFlags = PFD_DRAW_TO_WINDOW, .cColorBits = 24, .cRedBits = 8}; + + PFN_glGetUnsignedBytevEXT p_glGetUnsignedBytevEXT; + PFN_glGetUnsignedBytei_vEXT p_glGetUnsignedBytei_vEXT; + + const char *extensions, *ptr; + struct opengl_device *dev; + int format, count; + GUID guid; + BOOL ret; + + dev = calloc( 1, sizeof(*dev) ); + ok_ptr( dev, !=, NULL ); + + dev->hwnd = hwnd; + dev->hdc = GetWindowDC( hwnd ); + ok_ptr( dev->hdc, !=, NULL ); + + format = ChoosePixelFormat( dev->hdc, &pfd ); + ok_u4( format, !=, 0 ); + SetPixelFormat( dev->hdc, format, &pfd ); + + dev->rc = wglCreateContext( dev->hdc ); + ok_ptr( dev->rc, !=, NULL ); + ret = wglMakeCurrent( dev->hdc, dev->rc ); + ok_u4( ret, !=, 0 ); + + p_glGetUnsignedBytevEXT = (void *)wglGetProcAddress( "glGetUnsignedBytevEXT" ); + if (!p_glGetUnsignedBytevEXT) + { + destroy_opengl_device( dev ); + return NULL; + } + p_glGetUnsignedBytei_vEXT = (void *)wglGetProcAddress( "glGetUnsignedBytei_vEXT" ); + ok_ptr( p_glGetUnsignedBytei_vEXT, !=, NULL ); + + extensions = (char *)glGetString( GL_EXTENSIONS ); + ok_x4( glGetError(), ==, 0 ); + ok_ptr( extensions, !=, NULL ); + + ptr = find_opengl_extension( extensions, "GL_EXT_memory_object" ); + ok_ptr( ptr, !=, NULL ); + ptr = find_opengl_extension( extensions, "GL_EXT_memory_object_win32" ); + todo_wine ok_ptr( ptr, !=, NULL ); + ptr = find_opengl_extension( extensions, "GL_EXT_semaphore" ); + todo_wine ok_ptr( ptr, !=, NULL ); + ptr = find_opengl_extension( extensions, "GL_EXT_semaphore_win32" ); + todo_wine ok_ptr( ptr, !=, NULL ); + ptr = find_opengl_extension( extensions, "GL_EXT_win32_keyed_mutex" ); + dev->broken = !winetest_platform_is_wine && ptr == NULL; /* missing on AMD, as is support for importing D3D handles */ + + count = 0; + glGetIntegerv( GL_NUM_DEVICE_UUIDS_EXT, &count ); + ok_x4( glGetError(), ==, 0 ); + ok_u4( count, ==, 1 ); + + for (int i = 0; i < count; i++) + { + memset( &guid, 0, sizeof(guid) ); + p_glGetUnsignedBytei_vEXT( GL_DEVICE_UUID_EXT, i, (GLubyte *)&guid ); + ok_x4( glGetError(), ==, 0 ); + ok( !IsEqualGUID( &GUID_NULL, &guid ), "got GL_DEVICE_UUID_EXT[%u] %s\n", i, debugstr_guid( &guid ) ); + } + + memset( &guid, 0, sizeof(guid) ); + p_glGetUnsignedBytevEXT( GL_DRIVER_UUID_EXT, (GLubyte *)&guid ); + ok_x4( glGetError(), ==, 0 ); + ok( !IsEqualGUID( &GUID_NULL, &guid ), "got GL_DRIVER_UUID_EXT %s\n", debugstr_guid( &guid ) ); + + if (!winetest_platform_is_wine) /* crashes in host drivers */ + { + LUID device_luid = {0}; + unsigned int nodes = 0; + + p_glGetUnsignedBytevEXT( GL_DEVICE_LUID_EXT, (GLubyte *)&device_luid ); + if (!dev->broken) ok_x4( glGetError(), ==, 0 ); + else ok_x4( glGetError(), ==, GL_INVALID_ENUM ); + + glGetIntegerv( GL_DEVICE_NODE_MASK_EXT, (GLint *)&nodes ); + if (!dev->broken) ok_x4( glGetError(), ==, 0 ); + else ok_x4( glGetError(), ==, GL_INVALID_ENUM ); + if (!dev->broken) ok_u4( nodes, !=, 0 ); + + if (luid_equals( luid, &luid_zero )) *luid = device_luid; + } + + return dev; +} + +static void import_opengl_image( struct opengl_device *dev, UINT width, UINT height, UINT depth, UINT bpp, + const WCHAR *name, HANDLE handle, UINT handle_type ) +{ + PFN_glCreateMemoryObjectsEXT p_glCreateMemoryObjectsEXT; + PFN_glDeleteMemoryObjectsEXT p_glDeleteMemoryObjectsEXT; + GLuint memory; + + UINT ret; + + if (dev->broken && handle_type != GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT && handle_type != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT) + { + win_skip( "Skipping unsupported handle types\n" ); + return; + } + + ret = wglMakeCurrent( dev->hdc, dev->rc ); + todo_wine_if( ret == 0 ) ok_u4( ret, !=, 0 ); + + p_glCreateMemoryObjectsEXT = (void *)wglGetProcAddress( "glCreateMemoryObjectsEXT" ); + ok_ptr( p_glCreateMemoryObjectsEXT, !=, NULL ); + p_glDeleteMemoryObjectsEXT = (void *)wglGetProcAddress( "glDeleteMemoryObjectsEXT" ); + ok_ptr( p_glDeleteMemoryObjectsEXT, !=, NULL ); + + if (name) + { + PFN_glImportMemoryWin32NameEXT p_glImportMemoryWin32NameEXT = (void *)wglGetProcAddress( "glImportMemoryWin32NameEXT" ); + ok_ptr( p_glImportMemoryWin32NameEXT, !=, NULL ); + + p_glCreateMemoryObjectsEXT( 1, &memory ); + p_glImportMemoryWin32NameEXT( memory, width * height * depth * bpp, handle_type, name ); + p_glDeleteMemoryObjectsEXT( 1, &memory ); + } + else + { + PFN_glImportMemoryWin32HandleEXT p_glImportMemoryWin32HandleEXT = (void *)wglGetProcAddress( "glImportMemoryWin32HandleEXT" ); + todo_wine ok_ptr( p_glImportMemoryWin32HandleEXT, !=, NULL ); + if (!p_glImportMemoryWin32HandleEXT) return; + + p_glCreateMemoryObjectsEXT( 1, &memory ); + p_glImportMemoryWin32HandleEXT( memory, width * height * depth * bpp, handle_type, handle ); + p_glDeleteMemoryObjectsEXT( 1, &memory ); + } +} + static void test_shared_resources(void) { IDirect3DDevice9Ex *d3d9_exp, *d3d9_imp; + struct opengl_device *opengl_imp; BOOL stencil_broken; LUID luid = {0}; HRESULT hr; @@ -2999,13 +3171,20 @@ static void test_shared_resources(void) ok_ptr( hwnd, !=, NULL ); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
+ if (!(opengl_imp = create_opengl_device( hwnd, &luid ))) + { + win_skip( "Skipping tests on software renderer\n" ); + DestroyWindow( hwnd ); + return; + } + + trace( "adapter luid %s\n", debugstr_luid( &luid ) ); + d3d9_exp = create_d3d9ex_device( hwnd, &luid, &stencil_broken ); ok_ptr( d3d9_exp, !=, NULL ); d3d9_imp = create_d3d9ex_device( hwnd, &luid, NULL ); ok_ptr( d3d9_imp, !=, NULL );
- trace( "adapter luid %s\n", debugstr_luid( &luid ) ); - #define MAKETEST(api, dim, idx) (((api & 7) << 7) | ((dim & 7) << 4) | (idx & 15)) #define GET_API(test) ((test >> 7) & 7) #define GET_DIM(test) ((test >> 4) & 7) @@ -3024,6 +3203,7 @@ static void test_shared_resources(void)
char runtime_desc[0x1000] = {0}; IUnknown *export = NULL, *import = NULL; + const WCHAR *name = NULL; HANDLE handle = NULL;
winetest_push_context( "%u:%u:%u", GET_API(test), GET_DIM(test), test & 15 ); @@ -3300,6 +3480,93 @@ static void test_shared_resources(void) if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); }
+ if (opengl_imp->broken ? (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 0, 1)) : + (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 3, 1))) + { + todo_wine win_skip( "Skipping broken OpenGL/Vulkan import tests\n" ); + goto skip_tests; + } + + if (opengl_imp) + { + if (is_d3dkmt_handle( handle )) + { + switch (GET_DIM(test)) + { + case 0: + import_opengl_image( opengl_imp, resource_size, 1, 1, 1, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, resource_size, 1, 1, 1, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + case 1: + import_opengl_image( opengl_imp, width_1d, 1, array_1d, 4, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_1d, 1, array_1d, 4, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + case 2: + import_opengl_image( opengl_imp, width_2d, height_2d, 1, 4, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_2d, height_2d, 1, 4, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + case 3: + import_opengl_image( opengl_imp, width_3d, height_3d, depth_3d, 4, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_3d, height_3d, depth_3d, 4, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + } + } + else + { + switch (GET_DIM(test)) + { + case 0: + import_opengl_image( opengl_imp, resource_size, 1, 1, 1, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, resource_size, 1, 1, 1, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, resource_size, 1, 1, 1, name, handle, GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, resource_size, 1, 1, 1, name, handle, GL_HANDLE_TYPE_D3D12_RESOURCE_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + case 1: + import_opengl_image( opengl_imp, width_1d, 1, array_1d, 4, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_1d, 1, array_1d, 4, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_1d, 1, array_1d, 4, name, handle, GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_1d, 1, array_1d, 4, name, handle, GL_HANDLE_TYPE_D3D12_RESOURCE_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + case 2: + import_opengl_image( opengl_imp, width_2d, height_2d, 1, 4, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_2d, height_2d, 1, 4, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_2d, height_2d, 1, 4, name, handle, GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_2d, height_2d, 1, 4, name, handle, GL_HANDLE_TYPE_D3D12_RESOURCE_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + case 3: + import_opengl_image( opengl_imp, width_3d, height_3d, depth_3d, 4, name, handle, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_3d, height_3d, depth_3d, 4, name, handle, GL_HANDLE_TYPE_D3D11_IMAGE_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_3d, height_3d, depth_3d, 4, name, handle, GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT ); + ok_x4( glGetError(), ==, 0 ); + import_opengl_image( opengl_imp, width_3d, height_3d, depth_3d, 4, name, handle, GL_HANDLE_TYPE_D3D12_RESOURCE_EXT ); + ok_x4( glGetError(), ==, 0 ); + break; + } + } + } + skip_tests: if (handle && !is_d3dkmt_handle( handle )) CloseHandle( handle ); if (export) ok_ref( 0, IUnknown_Release( export ) ); @@ -3312,6 +3579,7 @@ skip_tests:
ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_imp ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_exp ) ); + destroy_opengl_device( opengl_imp ); DestroyWindow( hwnd ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/Makefile.in | 2 +- dlls/win32u/tests/d3dkmt.c | 264 ++++++++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/tests/Makefile.in b/dlls/win32u/tests/Makefile.in index 0e7618b8458..a9c57c1991c 100644 --- a/dlls/win32u/tests/Makefile.in +++ b/dlls/win32u/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = win32u.dll -IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 win32u +IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 dxgi d3d10 win32u
SOURCES = \ d3dkmt.c \ diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 43044c3363e..814e7421fab 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -38,6 +38,7 @@
#include "d3d9.h" #include "dxgi1_3.h" +#include "d3d11_1.h" #include "wine/wgl.h" #include "wine/test.h"
@@ -313,6 +314,81 @@ static void check_d3d9_runtime_desc( struct d3d9_runtime_desc *desc, const struc } }
+struct d3d11_runtime_desc +{ + struct dxgi_runtime_desc dxgi; + D3D11_RESOURCE_DIMENSION dimension; + union + { + D3D10_BUFFER_DESC d3d10_buf; + D3D10_TEXTURE1D_DESC d3d10_1d; + D3D10_TEXTURE2D_DESC d3d10_2d; + D3D10_TEXTURE3D_DESC d3d10_3d; + D3D11_BUFFER_DESC d3d11_buf; + D3D11_TEXTURE1D_DESC d3d11_1d; + D3D11_TEXTURE2D_DESC d3d11_2d; + D3D11_TEXTURE3D_DESC d3d11_3d; + }; +}; + +C_ASSERT( sizeof(struct d3d11_runtime_desc) == 0x68 ); + +#define check_d3d11_runtime_desc( a, b ) check_d3d11_runtime_desc_( a, b, FALSE ) +static void check_d3d11_runtime_desc_( struct d3d11_runtime_desc *desc, const struct d3d11_runtime_desc *expect, BOOL d3d12 ) +{ + check_dxgi_runtime_desc_( &desc->dxgi, &expect->dxgi, d3d12 ); + + ok_x4( desc->dimension, ==, expect->dimension ); + switch (desc->dimension) + { + case D3D11_RESOURCE_DIMENSION_BUFFER: + ok_x4( desc->d3d11_buf.ByteWidth, ==, expect->d3d11_buf.ByteWidth ); + ok_x4( desc->d3d11_buf.Usage, ==, expect->d3d11_buf.Usage ); + ok_x4( desc->d3d11_buf.BindFlags, ==, expect->d3d11_buf.BindFlags ); + ok_x4( desc->d3d11_buf.CPUAccessFlags, ==, expect->d3d11_buf.CPUAccessFlags ); + ok_x4( desc->d3d11_buf.MiscFlags, ==, expect->d3d11_buf.MiscFlags ); + ok_x4( desc->d3d11_buf.StructureByteStride, ==, expect->d3d11_buf.StructureByteStride ); + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + ok_x4( desc->d3d11_1d.Width, ==, expect->d3d11_1d.Width ); + ok_x4( desc->d3d11_1d.MipLevels, ==, expect->d3d11_1d.MipLevels ); + ok_x4( desc->d3d11_1d.ArraySize, ==, expect->d3d11_1d.ArraySize ); + ok_x4( desc->d3d11_1d.Format, ==, expect->d3d11_1d.Format ); + ok_x4( desc->d3d11_1d.Usage, ==, expect->d3d11_1d.Usage ); + ok_x4( desc->d3d11_1d.BindFlags, ==, expect->d3d11_1d.BindFlags ); + ok_x4( desc->d3d11_1d.CPUAccessFlags, ==, expect->d3d11_1d.CPUAccessFlags ); + ok_x4( desc->d3d11_1d.MiscFlags, ==, expect->d3d11_1d.MiscFlags ); + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + ok_x4( desc->d3d11_2d.Width, ==, expect->d3d11_2d.Width ); + ok_x4( desc->d3d11_2d.Height, ==, expect->d3d11_2d.Height ); + ok_x4( desc->d3d11_2d.MipLevels, ==, expect->d3d11_2d.MipLevels ); + ok_x4( desc->d3d11_2d.ArraySize, ==, expect->d3d11_2d.ArraySize ); + ok_x4( desc->d3d11_2d.Format, ==, expect->d3d11_2d.Format ); + ok_x4( desc->d3d11_2d.SampleDesc.Count, ==, expect->d3d11_2d.SampleDesc.Count ); + ok_x4( desc->d3d11_2d.SampleDesc.Quality, ==, expect->d3d11_2d.SampleDesc.Quality ); + ok_x4( desc->d3d11_2d.Usage, ==, expect->d3d11_2d.Usage ); + ok_x4( desc->d3d11_2d.BindFlags, ==, expect->d3d11_2d.BindFlags ); + ok_x4( desc->d3d11_2d.CPUAccessFlags, ==, expect->d3d11_2d.CPUAccessFlags ); + ok_x4( desc->d3d11_2d.MiscFlags, ==, expect->d3d11_2d.MiscFlags ); + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + ok_x4( desc->d3d11_3d.Width, ==, expect->d3d11_3d.Width ); + ok_x4( desc->d3d11_3d.Height, ==, expect->d3d11_3d.Height ); + ok_x4( desc->d3d11_3d.Depth, ==, expect->d3d11_3d.Depth ); + ok_x4( desc->d3d11_3d.MipLevels, ==, expect->d3d11_3d.MipLevels ); + ok_x4( desc->d3d11_3d.Format, ==, expect->d3d11_3d.Format ); + ok_x4( desc->d3d11_3d.Usage, ==, expect->d3d11_3d.Usage ); + ok_x4( desc->d3d11_3d.BindFlags, ==, expect->d3d11_3d.BindFlags ); + ok_x4( desc->d3d11_3d.CPUAccessFlags, ==, expect->d3d11_3d.CPUAccessFlags ); + ok_x4( desc->d3d11_3d.MiscFlags, ==, expect->d3d11_3d.MiscFlags ); + break; + default: + ok( 0, "unexpected\n" ); + break; + } +} + static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_global, UINT size, char *buffer ) { D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE query_nt = {0}; @@ -2987,6 +3063,24 @@ static IDirect3DDevice9Ex *create_d3d9ex_device( HWND hwnd, LUID *luid, BOOL *st return device; }
+static IDXGIAdapter *create_dxgi_adapter( IDXGIFactory3 *dxgi, LUID *luid ) +{ + IDXGIAdapter *adapter = NULL; + DXGI_ADAPTER_DESC desc; + + for (UINT i = 0; SUCCEEDED(IDXGIFactory3_EnumAdapters( dxgi, i, &adapter )); i++) + { + IDXGIAdapter_GetDesc( adapter, &desc ); + if (luid_equals( luid, &luid_zero )) *luid = desc.AdapterLuid; + if (luid_equals( luid, &desc.AdapterLuid )) break; + IDXGIAdapter_Release( adapter ); + adapter = NULL; + } + + ok_ptr( adapter, !=, NULL ); + return adapter; +} + C_ASSERT( sizeof(GUID) == GL_UUID_SIZE_EXT ); C_ASSERT( sizeof(LUID) == GL_LUID_SIZE_EXT );
@@ -3157,10 +3251,39 @@ static void import_opengl_image( struct opengl_device *dev, UINT width, UINT hei } }
+static HRESULT get_dxgi_global_handle( IUnknown *obj, HANDLE *handle ) +{ + IDXGIResource *res; + HRESULT hr; + + hr = IUnknown_QueryInterface( obj, &IID_IDXGIResource, (void **)&res ); + ok_hr( S_OK, hr ); + hr = IDXGIResource_GetSharedHandle( res, handle ); + IDXGIResource_Release( res ); + + return hr; +} + +static HRESULT get_dxgi_shared_handle( IUnknown *obj, const WCHAR *name, HANDLE *handle ) +{ + IDXGIResource1 *res; + HRESULT hr; + + hr = IUnknown_QueryInterface( obj, &IID_IDXGIResource1, (void **)&res ); + ok_hr( S_OK, hr ); + hr = IDXGIResource1_CreateSharedHandle( res, NULL, GENERIC_ALL, name, handle ); + IDXGIResource1_Release( res ); + + return hr; +} + static void test_shared_resources(void) { IDirect3DDevice9Ex *d3d9_exp, *d3d9_imp; + ID3D10Device *d3d10_exp, *d3d10_imp; struct opengl_device *opengl_imp; + IDXGIAdapter *adapter; + IDXGIFactory3 *dxgi; BOOL stencil_broken; LUID luid = {0}; HRESULT hr; @@ -3185,6 +3308,21 @@ static void test_shared_resources(void) d3d9_imp = create_d3d9ex_device( hwnd, &luid, NULL ); ok_ptr( d3d9_imp, !=, NULL );
+ hr = CreateDXGIFactory1( &IID_IDXGIFactory3, (void **)&dxgi ); + ok_hr( S_OK, hr ); + + adapter = create_dxgi_adapter( dxgi, &luid ); + ok_ptr( adapter, !=, NULL ); + + hr = D3D10CreateDevice( adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT, + D3D10_SDK_VERSION, &d3d10_imp ); + ok_hr( S_OK, hr ); + hr = D3D10CreateDevice( adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT, + D3D10_SDK_VERSION, &d3d10_exp ); + ok_hr( S_OK, hr ); + + IDXGIAdapter_Release( adapter ); + #define MAKETEST(api, dim, idx) (((api & 7) << 7) | ((dim & 7) << 4) | (idx & 15)) #define GET_API(test) ((test >> 7) & 7) #define GET_DIM(test) ((test >> 4) & 7) @@ -3395,9 +3533,113 @@ static void test_shared_resources(void) check_d3d9_runtime_desc( (struct d3d9_runtime_desc *)runtime_desc, &desc ); break; } + + case MAKETEST(1, 0, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_BUFFER, .d3d10_buf = { + .ByteWidth = resource_size, .Usage = D3D10_USAGE_DEFAULT, .BindFlags = D3D10_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D10_CPU_ACCESS_READ, + .MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX, + }}; + hr = ID3D10Device_CreateBuffer( d3d10_exp, &desc.d3d10_buf, NULL, (ID3D10Buffer **)&export ); + ok_hr( E_INVALIDARG, hr ); + if (!export) break; + hr = get_dxgi_shared_handle( export, NULL, &handle ); + ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, (struct d3d11_runtime_desc *)&desc ); + break; + } + case MAKETEST(1, 1, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE1D, .d3d10_1d = { + .Width = width_1d, .MipLevels = 1, .ArraySize = array_1d, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Usage = D3D10_USAGE_DEFAULT, .BindFlags = D3D10_BIND_RENDER_TARGET, .CPUAccessFlags = D3D10_CPU_ACCESS_READ, + .MiscFlags = D3D10_RESOURCE_MISC_SHARED, + }}; + hr = ID3D10Device_CreateTexture1D( d3d10_exp, &desc.d3d10_1d, NULL, (ID3D10Texture1D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, (struct d3d11_runtime_desc *)&desc ); + break; + } + case MAKETEST(1, 2, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d10_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D10_USAGE_DEFAULT, .BindFlags = D3D10_BIND_RENDER_TARGET, .CPUAccessFlags = D3D10_CPU_ACCESS_READ, + .MiscFlags = D3D10_RESOURCE_MISC_SHARED, + }}; + hr = ID3D10Device_CreateTexture2D( d3d10_exp, &desc.d3d10_2d, NULL, (ID3D10Texture2D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, (struct d3d11_runtime_desc *)&desc ); + break; + } + case MAKETEST(1, 2, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .keyed_mutex = 1}; + struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d10_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D10_USAGE_DEFAULT, .BindFlags = D3D10_BIND_RENDER_TARGET, .CPUAccessFlags = D3D10_CPU_ACCESS_READ, + .MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX, + }}; + hr = ID3D10Device_CreateTexture2D( d3d10_exp, &desc.d3d10_2d, NULL, (ID3D10Texture2D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + desc.d3d11_2d.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; /* flag gets updated to the d3d11 version */ + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, (struct d3d11_runtime_desc *)&desc ); + break; + } + case MAKETEST(1, 3, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D, .d3d10_3d = { + .Width = width_3d, .Height = height_3d, .Depth = depth_3d, .MipLevels = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Usage = D3D10_USAGE_DEFAULT, .BindFlags = D3D10_BIND_RENDER_TARGET, .CPUAccessFlags = D3D10_CPU_ACCESS_READ, + .MiscFlags = D3D10_RESOURCE_MISC_SHARED, + }}; + hr = ID3D10Device_CreateTexture3D( d3d10_exp, &desc.d3d10_3d, NULL, (ID3D10Texture3D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, (struct d3d11_runtime_desc *)&desc ); + break; + } } if (!handle) goto skip_tests;
+ if (name) + { + WCHAR path[MAX_PATH]; + swprintf( path, ARRAY_SIZE(path), L"\Sessions\1\BaseNamedObjects\%s", name ); + check_object_name( handle, path ); + } + if (d3d9_imp) { const struct d3d9_runtime_desc *desc = (struct d3d9_runtime_desc *)runtime_desc; @@ -3480,6 +3722,25 @@ static void test_shared_resources(void) if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); }
+ if (dxgi) + { + LUID adapter_luid = {0}; + hr = IDXGIFactory3_GetSharedResourceAdapterLuid( dxgi, handle, &adapter_luid ); + todo_wine ok_hr( S_OK, hr ); + todo_wine ok( luid_equals( &luid, &adapter_luid ), "got %s\n", debugstr_luid( &adapter_luid ) ); + } + + if (d3d10_imp) + { + const struct d3d11_runtime_desc *desc = (struct d3d11_runtime_desc *)runtime_desc; + + hr = ID3D10Device_OpenSharedResource( d3d10_imp, handle, &IID_ID3D10Resource, (void **)&import ); + if (!is_d3dkmt_handle( handle )) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->dxgi.version != 4) ok_hr( E_INVALIDARG, hr ); + else todo_wine ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + } + if (opengl_imp->broken ? (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 0, 1)) : (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 3, 1))) { @@ -3577,6 +3838,9 @@ skip_tests: #undef GET_API #undef MAKETEST
+ if (d3d10_imp) ok_ref( 0, ID3D10Device_Release( d3d10_imp ) ); + if (d3d10_exp) ok_ref( 0, ID3D10Device_Release( d3d10_exp ) ); + ok_ref( 0, IDXGIFactory3_Release( dxgi ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_imp ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_exp ) ); destroy_opengl_device( opengl_imp );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/Makefile.in | 2 +- dlls/win32u/tests/d3dkmt.c | 236 +++++++++++++++++++++++++++++++++- 2 files changed, 235 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/tests/Makefile.in b/dlls/win32u/tests/Makefile.in index a9c57c1991c..20b54bdaa5c 100644 --- a/dlls/win32u/tests/Makefile.in +++ b/dlls/win32u/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = win32u.dll -IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 dxgi d3d10 win32u +IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 dxgi d3d10 d3d11 win32u
SOURCES = \ d3dkmt.c \ diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 814e7421fab..0adad01fa86 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -3081,6 +3081,24 @@ static IDXGIAdapter *create_dxgi_adapter( IDXGIFactory3 *dxgi, LUID *luid ) return adapter; }
+static ID3D11Device1 *create_d3d11_device( IDXGIAdapter *adapter ) +{ + D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; + ID3D11Device1 *device1; + ID3D11Device *device; + HRESULT hr; + + hr = D3D11CreateDevice( adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, &feature_level, 1, + D3D11_SDK_VERSION, &device, NULL, NULL ); + ok_hr( S_OK, hr ); + + hr = ID3D11Device_QueryInterface( device, &IID_ID3D11Device1, (void **)&device1 ); + ok_hr( S_OK, hr ); + ID3D11Device_Release( device ); + + return device1; +} + C_ASSERT( sizeof(GUID) == GL_UUID_SIZE_EXT ); C_ASSERT( sizeof(LUID) == GL_LUID_SIZE_EXT );
@@ -3233,7 +3251,8 @@ static void import_opengl_image( struct opengl_device *dev, UINT width, UINT hei if (name) { PFN_glImportMemoryWin32NameEXT p_glImportMemoryWin32NameEXT = (void *)wglGetProcAddress( "glImportMemoryWin32NameEXT" ); - ok_ptr( p_glImportMemoryWin32NameEXT, !=, NULL ); + todo_wine ok_ptr( p_glImportMemoryWin32NameEXT, !=, NULL ); + if (!p_glImportMemoryWin32NameEXT) return;
p_glCreateMemoryObjectsEXT( 1, &memory ); p_glImportMemoryWin32NameEXT( memory, width * height * depth * bpp, handle_type, name ); @@ -3280,6 +3299,7 @@ static HRESULT get_dxgi_shared_handle( IUnknown *obj, const WCHAR *name, HANDLE static void test_shared_resources(void) { IDirect3DDevice9Ex *d3d9_exp, *d3d9_imp; + ID3D11Device1 *d3d11_exp, *d3d11_imp; ID3D10Device *d3d10_exp, *d3d10_imp; struct opengl_device *opengl_imp; IDXGIAdapter *adapter; @@ -3321,6 +3341,11 @@ static void test_shared_resources(void) D3D10_SDK_VERSION, &d3d10_exp ); ok_hr( S_OK, hr );
+ d3d11_imp = create_d3d11_device( adapter ); + ok_ptr( d3d11_imp, !=, NULL ); + d3d11_exp = create_d3d11_device( adapter ); + ok_ptr( d3d11_exp, !=, NULL ); + IDXGIAdapter_Release( adapter );
#define MAKETEST(api, dim, idx) (((api & 7) << 7) | ((dim & 7) << 4) | (idx & 15)) @@ -3630,6 +3655,179 @@ static void test_shared_resources(void) check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, (struct d3d11_runtime_desc *)&desc ); break; } + + case MAKETEST(2, 0, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_BUFFER, .d3d11_buf = { + .ByteWidth = resource_size, .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, + }}; + hr = ID3D11Device1_CreateBuffer( d3d11_exp, &desc.d3d11_buf, NULL, (ID3D11Buffer **)&export ); + todo_wine ok_hr( E_INVALIDARG, hr ); + if (!export) break; + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 1, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE1D, .d3d11_1d = { + .Width = width_1d, .MipLevels = 1, .ArraySize = array_1d, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED, + }}; + hr = ID3D11Device1_CreateTexture1D( d3d11_exp, &desc.d3d11_1d, NULL, (ID3D11Texture1D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 1, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .keyed_mutex = 1}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE1D, .d3d11_1d = { + .Width = width_1d, .MipLevels = 1, .ArraySize = array_1d, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, + }}; + hr = ID3D11Device1_CreateTexture1D( d3d11_exp, &desc.d3d11_1d, NULL, (ID3D11Texture1D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 2, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d11_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED, + }}; + hr = ID3D11Device1_CreateTexture2D( d3d11_exp, &desc.d3d11_2d, NULL, (ID3D11Texture2D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 2, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .nt_shared = 1}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d11_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE, + }}; + hr = ID3D11Device1_CreateTexture2D( d3d11_exp, &desc.d3d11_2d, NULL, (ID3D11Texture2D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 2, 2): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .keyed_mutex = 1}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d11_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, + }}; + hr = ID3D11Device1_CreateTexture2D( d3d11_exp, &desc.d3d11_2d, NULL, (ID3D11Texture2D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 2, 3): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .nt_shared = 1}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d11_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE, + }}; + name = L"__winetest_d3d11_image"; + hr = ID3D11Device1_CreateTexture2D( d3d11_exp, &desc.d3d11_2d, NULL, (ID3D11Texture2D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_shared_handle( export, name, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 3, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D, .d3d11_3d = { + .Width = width_3d, .Height = height_3d, .Depth = depth_3d, .MipLevels = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED, + }}; + hr = ID3D11Device1_CreateTexture3D( d3d11_exp, &desc.d3d11_3d, NULL, (ID3D11Texture3D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(2, 3, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .keyed_mutex = 1}; + const struct d3d11_runtime_desc desc = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D, .d3d11_3d = { + .Width = width_3d, .Height = height_3d, .Depth = depth_3d, .MipLevels = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = D3D11_CPU_ACCESS_READ, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, + }}; + hr = ID3D11Device1_CreateTexture3D( d3d11_exp, &desc.d3d11_3d, NULL, (ID3D11Texture3D **)&export ); + ok_hr( S_OK, hr ); + hr = get_dxgi_shared_handle( export, NULL, &handle ); + todo_wine ok_hr( E_INVALIDARG, hr ); + hr = get_dxgi_global_handle( export, &handle ); + todo_wine ok_hr( S_OK, hr ); + if (hr != S_OK) break; + get_d3dkmt_resource_desc( luid, handle, TRUE, sizeof(desc), runtime_desc ); + check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); + break; + } } if (!handle) goto skip_tests;
@@ -3637,7 +3835,7 @@ static void test_shared_resources(void) { WCHAR path[MAX_PATH]; swprintf( path, ARRAY_SIZE(path), L"\Sessions\1\BaseNamedObjects\%s", name ); - check_object_name( handle, path ); + todo_wine check_object_name( handle, path ); }
if (d3d9_imp) @@ -3741,6 +3939,38 @@ static void test_shared_resources(void) if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); }
+ if (d3d11_imp) + { + const struct dxgi_runtime_desc *desc = (struct dxgi_runtime_desc *)runtime_desc; + + hr = ID3D11Device1_OpenSharedResource( d3d11_imp, handle, &IID_ID3D11Resource, (void **)&import ); + if (!is_d3dkmt_handle( handle )) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->version == 1) + { + const struct d3d9_runtime_desc *d3d9_desc = (struct d3d9_runtime_desc *)runtime_desc; + if (d3d9_desc->type != D3DRTYPE_TEXTURE && d3d9_desc->type != D3DRTYPE_SURFACE) ok_hr( E_INVALIDARG, hr ); + else if (d3d9_desc->usage & D3DUSAGE_DEPTHSTENCIL) ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + } + else if (desc->version != 4) ok_hr( E_INVALIDARG, hr ); + else todo_wine ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + hr = ID3D11Device1_OpenSharedResource1( d3d11_imp, handle, &IID_ID3D11Resource, (void **)&import ); + if (is_d3dkmt_handle( handle )) todo_wine ok_hr( E_INVALIDARG, hr ); + else if (desc->version == 4) todo_wine ok_hr( S_OK, hr ); + else if (!desc->format) todo_wine ok_hr( E_INVALIDARG, hr ); + else ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + + if (name) + { + hr = ID3D11Device1_OpenSharedResourceByName( d3d11_imp, name, GENERIC_ALL, &IID_ID3D11Resource, (void **)&import ); + todo_wine ok_hr( S_OK, hr ); + if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); + } + } + if (opengl_imp->broken ? (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 0, 1)) : (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 3, 1))) { @@ -3838,6 +4068,8 @@ skip_tests: #undef GET_API #undef MAKETEST
+ if (d3d11_imp) ok_ref( 0, ID3D11Device1_Release( d3d11_imp ) ); + if (d3d11_exp) ok_ref( 0, ID3D11Device1_Release( d3d11_exp ) ); if (d3d10_imp) ok_ref( 0, ID3D10Device_Release( d3d10_imp ) ); if (d3d10_exp) ok_ref( 0, ID3D10Device_Release( d3d10_exp ) ); ok_ref( 0, IDXGIFactory3_Release( dxgi ) );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/Makefile.in | 2 +- dlls/win32u/tests/d3dkmt.c | 281 +++++++++++++++++++++++++++++++++- 2 files changed, 277 insertions(+), 6 deletions(-)
diff --git a/dlls/win32u/tests/Makefile.in b/dlls/win32u/tests/Makefile.in index 20b54bdaa5c..e668c844f64 100644 --- a/dlls/win32u/tests/Makefile.in +++ b/dlls/win32u/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = win32u.dll -IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 dxgi d3d10 d3d11 win32u +IMPORTS = imm32 user32 gdi32 dwmapi setupapi opengl32 d3d9 dxgi d3d10 d3d11 d3d12 win32u
SOURCES = \ d3dkmt.c \ diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 0adad01fa86..251888dff2e 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -39,6 +39,8 @@ #include "d3d9.h" #include "dxgi1_3.h" #include "d3d11_1.h" +#include "d3d12.h" + #include "wine/wgl.h" #include "wine/test.h"
@@ -389,6 +391,48 @@ static void check_d3d11_runtime_desc_( struct d3d11_runtime_desc *desc, const st } }
+struct d3d12_runtime_desc +{ + struct d3d11_runtime_desc d3d11; + UINT unknown_5[4]; + UINT resource_size; + UINT unknown_6[7]; + UINT resource_align; + UINT unknown_7[9]; + union + { + D3D12_RESOURCE_DESC desc; + D3D12_RESOURCE_DESC1 desc1; + }; + UINT64 unknown_8[1]; +}; + +C_ASSERT( sizeof(struct d3d12_runtime_desc) == 0x108 ); +C_ASSERT( offsetof(struct d3d12_runtime_desc, unknown_5) == sizeof(struct d3d11_runtime_desc) ); + +static void check_d3d12_runtime_desc( struct d3d12_runtime_desc *desc, const struct d3d12_runtime_desc *expect ) +{ + if (desc->d3d11.dxgi.version == 4) check_d3d11_runtime_desc_( &desc->d3d11, &expect->d3d11, TRUE ); + else check_dxgi_runtime_desc_( &desc->d3d11.dxgi, &expect->d3d11.dxgi, TRUE ); + + ok_x4( desc->desc.Dimension, ==, expect->desc.Dimension ); + ok_x4( desc->desc.Alignment, ==, expect->resource_align ); + ok_x4( desc->desc.Width, ==, expect->desc.Width ); + ok_x4( desc->desc.Height, ==, expect->desc.Height ); + ok_x4( desc->desc.DepthOrArraySize, ==, expect->desc.DepthOrArraySize ); + ok_x4( desc->desc.MipLevels, ==, expect->desc.MipLevels ); + ok_x4( desc->desc.Format, ==, expect->desc.Format ); + ok_x4( desc->desc.SampleDesc.Count, ==, expect->desc.SampleDesc.Count ); + ok_x4( desc->desc.SampleDesc.Quality, ==, expect->desc.SampleDesc.Quality ); + ok_x4( desc->desc.Layout, ==, expect->desc.Layout ); + ok_x4( desc->desc.Flags, ==, expect->desc.Flags ); + ok_x4( desc->desc1.SamplerFeedbackMipRegion.Width, ==, expect->desc1.SamplerFeedbackMipRegion.Width ); + ok_x4( desc->desc1.SamplerFeedbackMipRegion.Height, ==, expect->desc1.SamplerFeedbackMipRegion.Height ); + ok_x4( desc->desc1.SamplerFeedbackMipRegion.Depth, ==, expect->desc1.SamplerFeedbackMipRegion.Depth ); + ok_x4( desc->resource_size, ==, expect->resource_size ); + ok_x4( desc->resource_align, ==, expect->resource_align ); +} + static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_global, UINT size, char *buffer ) { D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE query_nt = {0}; @@ -3296,14 +3340,28 @@ static HRESULT get_dxgi_shared_handle( IUnknown *obj, const WCHAR *name, HANDLE return hr; }
+static HRESULT get_d3d12_shared_handle( ID3D12Device *d3d12, IUnknown *obj, const WCHAR *name, HANDLE *handle ) +{ + ID3D12DeviceChild *child; + HRESULT hr; + + hr = IUnknown_QueryInterface( obj, &IID_ID3D12DeviceChild, (void **)&child ); + ok_hr( S_OK, hr ); + hr = ID3D12Device_CreateSharedHandle( d3d12, child, NULL, GENERIC_ALL, name, handle ); + ID3D12DeviceChild_Release( child ); + + return hr; +} + static void test_shared_resources(void) { - IDirect3DDevice9Ex *d3d9_exp, *d3d9_imp; - ID3D11Device1 *d3d11_exp, *d3d11_imp; - ID3D10Device *d3d10_exp, *d3d10_imp; - struct opengl_device *opengl_imp; + struct opengl_device *opengl_imp = NULL; + IDirect3DDevice9Ex *d3d9_exp = NULL, *d3d9_imp = NULL; + ID3D11Device1 *d3d11_exp = NULL, *d3d11_imp = NULL; + ID3D10Device *d3d10_exp = NULL, *d3d10_imp = NULL; + ID3D12Device *d3d12_exp = NULL, *d3d12_imp = NULL; + IDXGIFactory3 *dxgi = NULL; IDXGIAdapter *adapter; - IDXGIFactory3 *dxgi; BOOL stencil_broken; LUID luid = {0}; HRESULT hr; @@ -3346,6 +3404,13 @@ static void test_shared_resources(void) d3d11_exp = create_d3d11_device( adapter ); ok_ptr( d3d11_exp, !=, NULL );
+ hr = D3D12CreateDevice( (IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, + &IID_ID3D12Device, (void **)&d3d12_imp ); + todo_wine ok_hr( S_OK, hr ); + hr = D3D12CreateDevice( (IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, + &IID_ID3D12Device, (void **)&d3d12_exp ); + todo_wine ok_hr( S_OK, hr ); + IDXGIAdapter_Release( adapter );
#define MAKETEST(api, dim, idx) (((api & 7) << 7) | ((dim & 7) << 4) | (idx & 15)) @@ -3828,6 +3893,190 @@ static void test_shared_resources(void) check_d3d11_runtime_desc( (struct d3d11_runtime_desc *)runtime_desc, &desc ); break; } + + case MAKETEST(3, 0, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1}; + const struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER, .Width = resource_size, .Height = 1, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_UNKNOWN, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + .Flags = D3D12_RESOURCE_FLAG_NONE, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 1, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1}; + struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D, .Width = width_1d, .Height = 1, .DepthOrArraySize = array_1d, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_NONE, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + if (!opengl_imp->broken) desc.resource_size = 0x800000; /* each plane is aligned on NVIDIA */ + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 2, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1}; + const struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, .Width = width_2d, .Height = height_2d, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_NONE, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 2, 1): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1}; + const struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, .Width = width_2d, .Height = height_2d, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 2, 2): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_R8G8B8A8_UNORM}; + const struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, .Width = width_2d, .Height = height_2d, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 2, 3): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_R8G8B8A8_UNORM, .nt_shared = 1}; + const struct d3d11_runtime_desc d3d11 = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d11_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = 0, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE, + }}; + const struct d3d12_runtime_desc desc = {.d3d11 = d3d11, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, .Width = width_2d, .Height = height_2d, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 2, 4): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1}; + const struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, .Width = width_2d, .Height = height_2d, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_NONE, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 2, 5): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .version = 4, .width = width_2d, .height = height_2d, .format = DXGI_FORMAT_R8G8B8A8_UNORM, .nt_shared = 1}; + const struct d3d11_runtime_desc d3d11 = {.dxgi = dxgi, .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, .d3d11_2d = { + .Width = width_2d, .Height = height_2d, .MipLevels = 1, .ArraySize = 1, .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = 0, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE, + }}; + const struct d3d12_runtime_desc desc = {.d3d11 = d3d11, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, .Width = width_2d, .Height = height_2d, .DepthOrArraySize = 1, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + name = L"__winetest_d3d12_image"; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, name, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } + case MAKETEST(3, 3, 0): + { + const struct dxgi_runtime_desc dxgi = {.size = 0x68, .nt_shared = 1}; + const struct d3d12_runtime_desc desc = {.d3d11.dxgi = dxgi, .resource_size = resource_size, .resource_align = 0x10000, .desc = { + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D, .Width = width_3d, .Height = height_3d, .DepthOrArraySize = depth_3d, .MipLevels = 1, + .Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = D3D12_RESOURCE_FLAG_NONE, + }}; + D3D12_HEAP_PROPERTIES heap_props = {.Type = D3D12_HEAP_TYPE_DEFAULT}; + if (!d3d12_exp) break; + hr = ID3D12Device_CreateCommittedResource( d3d12_exp, &heap_props, D3D12_HEAP_FLAG_SHARED, &desc.desc, D3D12_RESOURCE_STATE_COMMON, + NULL, &IID_ID3D12Resource, (void **)&export ); + ok_hr( S_OK, hr ); + hr = get_d3d12_shared_handle( d3d12_exp, export, NULL, &handle ); + ok_hr( S_OK, hr ); + get_d3dkmt_resource_desc( luid, handle, FALSE, sizeof(desc), runtime_desc ); + check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); + break; + } } if (!handle) goto skip_tests;
@@ -3971,6 +4220,26 @@ static void test_shared_resources(void) } }
+ if (d3d12_imp) + { + hr = ID3D12Device_OpenSharedHandle( d3d12_imp, handle, &IID_ID3D12Resource, (void **)&import ); + ok_hr( S_OK, hr ); + if (import) ok_ref( 0, IUnknown_Release( import ) ); + + if (name) + { + HANDLE other; + + hr = ID3D12Device_OpenSharedHandleByName( d3d12_imp, name, GENERIC_ALL, &other ); + ok_hr( S_OK, hr ); + hr = ID3D12Device_OpenSharedHandle( d3d12_imp, other, &IID_ID3D12Resource, (void **)&import ); + ok_hr( S_OK, hr ); + CloseHandle( other ); + + if (import) ok_ref( 0, IUnknown_Release( import ) ); + } + } + if (opengl_imp->broken ? (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 0, 1)) : (test == MAKETEST(0, 0, 0) || test == MAKETEST(0, 3, 1))) { @@ -4068,6 +4337,8 @@ skip_tests: #undef GET_API #undef MAKETEST
+ if (d3d12_imp) ID3D12Device_Release( d3d12_imp ); + if (d3d12_exp) ok_ref( 0, ID3D12Device_Release( d3d12_exp ) ); if (d3d11_imp) ok_ref( 0, ID3D11Device1_Release( d3d11_imp ) ); if (d3d11_exp) ok_ref( 0, ID3D11Device1_Release( d3d11_exp ) ); if (d3d10_imp) ok_ref( 0, ID3D10Device_Release( d3d10_imp ) );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 511 ++++++++++++++++++++++++++++++++++++- 1 file changed, 503 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 251888dff2e..3e423702fcb 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -41,6 +41,7 @@ #include "d3d11_1.h" #include "d3d12.h"
+#include "wine/vulkan.h" #include "wine/wgl.h" #include "wine/test.h"
@@ -52,6 +53,9 @@ static const WCHAR display1W[] = L"\\.\DISPLAY1";
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+static PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; +static PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr; + static const LUID luid_zero; const GUID GUID_NULL = {0};
@@ -476,7 +480,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob status = D3DKMTQueryResourceInfo( &query ); ok_nt( STATUS_SUCCESS, status ); if (size) ok_u4( query.PrivateRuntimeDataSize, ==, size ); - else ok( query.PrivateRuntimeDataSize == 0 || query.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query.PrivateRuntimeDataSize ); + else todo_wine ok( query.PrivateRuntimeDataSize == 0 || query.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query.PrivateRuntimeDataSize ); ok_u4( query.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query.NumAllocations, ==, 1 ); @@ -497,7 +501,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( open.hResource, NULL ); if (size) ok_u4( open.PrivateRuntimeDataSize, ==, size ); - else ok( open.PrivateRuntimeDataSize == 0 || open.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open.PrivateRuntimeDataSize ); + else todo_wine ok( open.PrivateRuntimeDataSize == 0 || open.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open.PrivateRuntimeDataSize ); ok_u4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_u4( open.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( open.NumAllocations, ==, 1 ); @@ -515,7 +519,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob status = D3DKMTQueryResourceInfoFromNtHandle( &query_nt ); ok_nt( STATUS_SUCCESS, status ); if (size) ok_u4( query_nt.PrivateRuntimeDataSize, ==, size ); - else ok( query_nt.PrivateRuntimeDataSize == 0 || query_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query_nt.PrivateRuntimeDataSize ); + else todo_wine ok( query_nt.PrivateRuntimeDataSize == 0 || query_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query_nt.PrivateRuntimeDataSize ); ok_u4( query_nt.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query_nt.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query_nt.NumAllocations, ==, 1 ); @@ -536,7 +540,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( open_nt.hResource, NULL ); if (size) ok_u4( open_nt.PrivateRuntimeDataSize, ==, size ); - else ok( open_nt.PrivateRuntimeDataSize == 0 || open_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open_nt.PrivateRuntimeDataSize ); + else todo_wine ok( open_nt.PrivateRuntimeDataSize == 0 || open_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open_nt.PrivateRuntimeDataSize ); ok_u4( open_nt.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_u4( open_nt.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( open_nt.NumAllocations, ==, 1 ); @@ -3143,6 +3147,446 @@ static ID3D11Device1 *create_d3d11_device( IDXGIAdapter *adapter ) return device1; }
+struct vulkan_device +{ + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; +}; + +struct vulkan_buffer +{ + VkBuffer buffer; + VkDeviceMemory memory; +}; + +struct vulkan_image +{ + VkImage image; + VkDeviceMemory memory; +}; + +static VkResult create_vulkan_instance( uint32_t extension_count, const char *const *extensions, + VkInstance *instance ) +{ + VkInstanceCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; + VkApplicationInfo app_info = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO}; + PFN_vkCreateInstance p_vkCreateInstance; + HMODULE vulkan; + + if (!(vulkan = LoadLibraryW( L"vulkan-1" ))) return VK_ERROR_INITIALIZATION_FAILED; + if (!(p_vkCreateInstance = (void *)GetProcAddress( vulkan, "vkCreateInstance" ))) return 0; + if (!(p_vkGetInstanceProcAddr = (void *)GetProcAddress( vulkan, "vkGetInstanceProcAddr" ))) return 0; + if (!(p_vkGetDeviceProcAddr = (void *)GetProcAddress( vulkan, "vkGetDeviceProcAddr" ))) return 0; + + app_info.apiVersion = VK_API_VERSION_1_1; + create_info.pApplicationInfo = &app_info; + create_info.enabledExtensionCount = extension_count; + create_info.ppEnabledExtensionNames = extensions; + + return p_vkCreateInstance( &create_info, NULL, instance ); +} + +static void get_vulkan_physical_device_luid( VkInstance instance, VkPhysicalDevice physical_device, LUID *luid ) +{ + PFN_vkGetPhysicalDeviceProperties2 p_vkGetPhysicalDeviceProperties2; + + VkPhysicalDeviceIDProperties id_props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES}; + VkPhysicalDeviceVulkan11Properties vk11_props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES, .pNext = &id_props}; + VkPhysicalDeviceProperties2 props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &vk11_props}; + + if (!(p_vkGetPhysicalDeviceProperties2 = (void *)p_vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceProperties2" ))) return; + + p_vkGetPhysicalDeviceProperties2( physical_device, &props ); + ok_u4( props.properties.apiVersion, !=, 0 ); + ok_u4( props.properties.driverVersion, !=, 0 ); + ok_u4( props.properties.vendorID, !=, 0 ); + todo_wine ok_u4( props.properties.deviceID, !=, 0 ); + ok_u4( props.properties.deviceType, !=, 0 ); + + ok( !IsEqualGUID( &GUID_NULL, (GUID *)id_props.deviceUUID ), "got deviceUUID %s\n", debugstr_guid( (GUID *)id_props.deviceUUID ) ); + ok( !IsEqualGUID( &GUID_NULL, (GUID *)id_props.driverUUID ), "got driverUUID %s\n", debugstr_guid( (GUID *)id_props.driverUUID ) ); + ok( !luid_equals( &luid_zero, (LUID *)id_props.deviceLUID ), "got deviceLUID %s\n", debugstr_luid( (LUID *)id_props.deviceLUID ) ); + ok_u4( id_props.deviceNodeMask, ==, 1 ); + ok_u4( id_props.deviceLUIDValid, ==, 1 ); + + ok( !IsEqualGUID( &GUID_NULL, (GUID *)vk11_props.deviceUUID ), "got deviceUUID %s\n", debugstr_guid( (GUID *)vk11_props.deviceUUID ) ); + ok( !IsEqualGUID( &GUID_NULL, (GUID *)vk11_props.driverUUID ), "got driverUUID %s\n", debugstr_guid( (GUID *)vk11_props.driverUUID ) ); + ok( !luid_equals( &luid_zero, (LUID *)vk11_props.deviceLUID ), "got deviceLUID %s\n", debugstr_luid( (LUID *)vk11_props.deviceLUID ) ); + ok_u4( vk11_props.deviceNodeMask, ==, 1 ); + ok_u4( vk11_props.deviceLUIDValid, ==, 1 ); + + *luid = *(LUID *)vk11_props.deviceLUID; +} + +static VkExternalMemoryHandleTypeFlags get_vulkan_external_image_types( VkInstance instance, VkPhysicalDevice physical_device, + VkExternalMemoryFeatureFlags feature_flags ) +{ + static const VkExternalMemoryHandleTypeFlagBits bits[] = + { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT, + }; + + VkPhysicalDeviceExternalImageFormatInfo external_info = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO}; + VkPhysicalDeviceImageFormatInfo2 format_info = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, .pNext = &external_info}; + + VkExternalImageFormatProperties external_props = {.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES}; + VkImageFormatProperties2 format_props = {.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &external_props}; + + PFN_vkGetPhysicalDeviceImageFormatProperties2 p_vkGetPhysicalDeviceImageFormatProperties2; + VkExternalMemoryHandleTypeFlags handle_types = 0; + VkResult vr; + + if (!(p_vkGetPhysicalDeviceImageFormatProperties2 = (void *)p_vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties2" ))) return 0; + + format_info.format = VK_FORMAT_R8G8B8A8_UNORM; + format_info.type = VK_IMAGE_TYPE_2D; + format_info.tiling = VK_IMAGE_TILING_OPTIMAL; + format_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + for (const VkExternalMemoryHandleTypeFlagBits *bit = bits; bit < bits + ARRAY_SIZE(bits); bit++) + { + winetest_push_context( "%#x", *bit ); + + external_info.handleType = *bit; + memset( &external_props.externalMemoryProperties, 0, sizeof(external_props.externalMemoryProperties) ); + vr = p_vkGetPhysicalDeviceImageFormatProperties2( physical_device, &format_info, &format_props ); + ok( vr == VK_SUCCESS || vr == VK_ERROR_FORMAT_NOT_SUPPORTED, "got %#x\n", vr ); + + if (!(~external_props.externalMemoryProperties.externalMemoryFeatures & feature_flags)) + { + ok_u4( external_props.externalMemoryProperties.compatibleHandleTypes, ==, external_info.handleType ); + handle_types |= external_info.handleType; + } + + winetest_pop_context(); + } + + return handle_types; +} + +static void destroy_vulkan_device( struct vulkan_device *dev ) +{ + if (dev->instance) + { + PFN_vkDestroyInstance p_vkDestroyInstance; + PFN_vkDestroyDevice p_vkDestroyDevice; + + p_vkDestroyDevice = (void *)p_vkGetDeviceProcAddr( dev->device, "vkDestroyDevice" ); + p_vkDestroyDevice( dev->device, NULL ); + + p_vkDestroyInstance = (void *)p_vkGetInstanceProcAddr( dev->instance, "vkDestroyInstance" ); + p_vkDestroyInstance( dev->instance, NULL ); + } + + free( dev ); +} + +static uint32_t get_vulkan_queue_family( VkInstance instance, VkPhysicalDevice physical_device ) +{ + PFN_vkGetPhysicalDeviceQueueFamilyProperties p_vkGetPhysicalDeviceQueueFamilyProperties; + + VkQueueFamilyProperties *props; + uint32_t i, count; + + p_vkGetPhysicalDeviceQueueFamilyProperties = (void *)p_vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceQueueFamilyProperties" ); + + p_vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &count, NULL ); + props = calloc( count, sizeof(*props) ); + ok_ptr( props, !=, NULL ); + p_vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &count, props ); + for (i = 0; i < count; ++i) if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) break; + free( props ); + + return i; +} + +static struct vulkan_device *create_vulkan_device( LUID *luid ) +{ + static const char *instance_extensions[] = + { + "VK_KHR_external_memory_capabilities", + "VK_KHR_get_physical_device_properties2", + }; + static const char *device_extensions[] = + { + "VK_KHR_get_memory_requirements2", + "VK_KHR_dedicated_allocation", + "VK_KHR_external_memory", + "VK_KHR_external_memory_win32", + }; + + VkDeviceQueueCreateInfo queue_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}; + VkDeviceCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; + + PFN_vkEnumeratePhysicalDevices p_vkEnumeratePhysicalDevices; + PFN_vkCreateDevice p_vkCreateDevice; + + VkPhysicalDevice *physical_devices; + struct vulkan_device *dev; + float priority = 0.0f; + uint32_t count; + VkResult vr; + + dev = calloc( 1, sizeof(*dev) ); + ok_ptr( dev, !=, NULL ); + + vr = create_vulkan_instance( ARRAY_SIZE(instance_extensions), instance_extensions, &dev->instance ); + if (vr != VK_SUCCESS) return NULL; + + p_vkEnumeratePhysicalDevices = (void *)p_vkGetInstanceProcAddr( dev->instance, "vkEnumeratePhysicalDevices" ); + vr = p_vkEnumeratePhysicalDevices( dev->instance, &count, NULL ); + ok_vk( VK_SUCCESS, vr ); + + physical_devices = calloc( count, sizeof(*physical_devices) ); + ok_ptr( physical_devices, !=, NULL ); + vr = p_vkEnumeratePhysicalDevices( dev->instance, &count, physical_devices ); + ok_vk( VK_SUCCESS, vr ); + + for (uint32_t i = 0; i < count; ++i) + { + static const VkExternalMemoryHandleTypeFlags expect_export_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + static const VkExternalMemoryHandleTypeFlags expect_import_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + VkExternalMemoryHandleTypeFlags types; + + winetest_push_context( "export" ); + types = get_vulkan_external_image_types( dev->instance, physical_devices[i], VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR ); + todo_wine ok( !(~types & expect_export_types), "got types %#x\n", types ); + winetest_pop_context(); + + winetest_push_context( "import" ); + types = get_vulkan_external_image_types( dev->instance, physical_devices[i], VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR ); + todo_wine ok( !(~types & expect_import_types), "got types %#x\n", types ); + winetest_pop_context(); + } + + for (uint32_t i = 0; i < count; ++i) + { + LUID device_luid; + + dev->physical_device = physical_devices[i]; + get_vulkan_physical_device_luid( dev->instance, physical_devices[i], &device_luid ); + if (luid_equals( luid, &luid_zero )) *luid = device_luid; + if (luid_equals( luid, &device_luid )) break; + dev->physical_device = VK_NULL_HANDLE; + } + ok_ptr( dev->physical_device, !=, VK_NULL_HANDLE ); + + free( physical_devices ); + + queue_info.queueFamilyIndex = get_vulkan_queue_family( dev->instance, dev->physical_device ); + queue_info.queueCount = 1; + queue_info.pQueuePriorities = &priority; + + create_info.enabledExtensionCount = ARRAY_SIZE(device_extensions); + create_info.ppEnabledExtensionNames = device_extensions; + create_info.queueCreateInfoCount = 1; + create_info.pQueueCreateInfos = &queue_info; + + p_vkCreateDevice = (void *)p_vkGetInstanceProcAddr( dev->instance, "vkCreateDevice" ); + vr = p_vkCreateDevice( dev->physical_device, &create_info, NULL, &dev->device ); + todo_wine ok_vk( VK_SUCCESS, vr ); + todo_wine ok_ptr( dev->device, !=, VK_NULL_HANDLE ); + if (dev->device == VK_NULL_HANDLE) + { + PFN_vkDestroyInstance p_vkDestroyInstance = (void *)p_vkGetInstanceProcAddr( dev->instance, "vkDestroyInstance" ); + p_vkDestroyInstance( dev->instance, NULL ); + free( dev ); + return NULL; + } + + return dev; +} + +static uint32_t find_vulkan_memory_type( VkInstance instance, VkPhysicalDevice physical_device, VkMemoryPropertyFlagBits flags, uint32_t mask ) +{ + PFN_vkGetPhysicalDeviceMemoryProperties p_vkGetPhysicalDeviceMemoryProperties; + VkPhysicalDeviceMemoryProperties properties = {0}; + unsigned int i; + + p_vkGetPhysicalDeviceMemoryProperties = (void *)p_vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceMemoryProperties" ); + + p_vkGetPhysicalDeviceMemoryProperties( physical_device, &properties ); + for (i = 0; i < properties.memoryTypeCount; i++) + { + if (!(properties.memoryTypes[i].propertyFlags & flags)) continue; + if ((1u << i) & mask) return i; + } + + return -1; +} + +static void destroy_vulkan_buffer( struct vulkan_device *dev, struct vulkan_buffer *buf ) +{ + PFN_vkFreeMemory p_vkFreeMemory; + PFN_vkDestroyBuffer p_vkDestroyBuffer; + + p_vkFreeMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkFreeMemory" ); + p_vkDestroyBuffer = (void *)p_vkGetDeviceProcAddr( dev->device, "vkDestroyBuffer" ); + + p_vkDestroyBuffer( dev->device, buf->buffer, NULL ); + p_vkFreeMemory( dev->device, buf->memory, NULL ); + free( buf ); +} + +static struct vulkan_buffer *export_vulkan_buffer( struct vulkan_device *dev, UINT width, const WCHAR *name, + UINT handle_type, HANDLE *handle ) +{ + VkExternalMemoryBufferCreateInfo external_info = {.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO}; + VkBufferCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = &external_info}; + + VkMemoryDedicatedAllocateInfoKHR dedicated_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO}; + VkExportMemoryAllocateInfoKHR export_info = {.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, .pNext = &dedicated_info}; + VkExportMemoryWin32HandleInfoKHR handle_info = {.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR, .pNext = &export_info}; + VkMemoryAllocateInfo alloc_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = &handle_info}; + + VkMemoryGetWin32HandleInfoKHR get_handle_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR}; + + PFN_vkAllocateMemory p_vkAllocateMemory; + PFN_vkBindBufferMemory p_vkBindBufferMemory; + PFN_vkCreateBuffer p_vkCreateBuffer; + PFN_vkGetBufferMemoryRequirements p_vkGetBufferMemoryRequirements; + PFN_vkGetMemoryWin32HandleKHR p_vkGetMemoryWin32HandleKHR; + + VkMemoryRequirements requirements; + struct vulkan_buffer *buf; + VkResult vr; + + buf = calloc( 1, sizeof(*buf) ); + ok_ptr( buf, !=, NULL ); + + p_vkAllocateMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkAllocateMemory" ); + p_vkBindBufferMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkBindBufferMemory" ); + p_vkCreateBuffer = (void *)p_vkGetDeviceProcAddr( dev->device, "vkCreateBuffer" ); + p_vkGetBufferMemoryRequirements = (void *)p_vkGetDeviceProcAddr( dev->device, "vkGetBufferMemoryRequirements" ); + p_vkGetMemoryWin32HandleKHR = (void *)p_vkGetDeviceProcAddr( dev->device, "vkGetMemoryWin32HandleKHR" ); + + external_info.handleTypes = handle_type; + create_info.size = width; + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vr = p_vkCreateBuffer( dev->device, &create_info, NULL, &buf->buffer ); + ok_vk( VK_SUCCESS, vr ); + p_vkGetBufferMemoryRequirements( dev->device, buf->buffer, &requirements ); + + dedicated_info.buffer = buf->buffer; + export_info.handleTypes = handle_type; + handle_info.dwAccess = GENERIC_ALL; + handle_info.name = name; + alloc_info.allocationSize = requirements.size; + alloc_info.memoryTypeIndex = find_vulkan_memory_type( dev->instance, dev->physical_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, requirements.memoryTypeBits ); + + vr = p_vkAllocateMemory( dev->device, &alloc_info, NULL, &buf->memory ); + ok_vk( VK_SUCCESS, vr ); + vr = p_vkBindBufferMemory( dev->device, buf->buffer, buf->memory, 0 ); + ok_vk( VK_SUCCESS, vr ); + + get_handle_info.memory = buf->memory; + get_handle_info.handleType = handle_type; + vr = p_vkGetMemoryWin32HandleKHR( dev->device, &get_handle_info, handle ); + ok_vk( VK_SUCCESS, vr ); + + return buf; +} + +static void destroy_vulkan_image( struct vulkan_device *dev, struct vulkan_image *img ) +{ + PFN_vkFreeMemory p_vkFreeMemory; + PFN_vkDestroyImage p_vkDestroyImage; + + p_vkFreeMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkFreeMemory" ); + p_vkDestroyImage = (void *)p_vkGetDeviceProcAddr( dev->device, "vkDestroyImage" ); + + p_vkDestroyImage( dev->device, img->image, NULL ); + p_vkFreeMemory( dev->device, img->memory, NULL ); + free( img ); +} + +static struct vulkan_image *export_vulkan_image( struct vulkan_device *dev, UINT width, UINT height, UINT depth, + const WCHAR *name, UINT handle_type, HANDLE *handle ) +{ + VkExternalMemoryImageCreateInfo external_info = {.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO}; + VkImageCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = &external_info}; + + VkMemoryDedicatedAllocateInfoKHR dedicated_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO}; + VkExportMemoryAllocateInfoKHR export_info = {.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, .pNext = &dedicated_info}; + VkExportMemoryWin32HandleInfoKHR handle_info = {.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR, .pNext = &export_info}; + VkMemoryAllocateInfo alloc_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = &handle_info}; + + VkMemoryGetWin32HandleInfoKHR get_handle_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR}; + + PFN_vkAllocateMemory p_vkAllocateMemory; + PFN_vkBindImageMemory p_vkBindImageMemory; + PFN_vkCreateImage p_vkCreateImage; + PFN_vkGetImageMemoryRequirements p_vkGetImageMemoryRequirements; + PFN_vkGetMemoryWin32HandleKHR p_vkGetMemoryWin32HandleKHR; + + VkMemoryRequirements requirements; + struct vulkan_image *img; + VkResult vr; + + img = calloc( 1, sizeof(*img) ); + ok_ptr( img, !=, NULL ); + + p_vkAllocateMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkAllocateMemory" ); + p_vkBindImageMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkBindImageMemory" ); + p_vkCreateImage = (void *)p_vkGetDeviceProcAddr( dev->device, "vkCreateImage" ); + p_vkGetImageMemoryRequirements = (void *)p_vkGetDeviceProcAddr( dev->device, "vkGetImageMemoryRequirements" ); + p_vkGetMemoryWin32HandleKHR = (void *)p_vkGetDeviceProcAddr( dev->device, "vkGetMemoryWin32HandleKHR" ); + + external_info.handleTypes = handle_type; + if (depth > 1 && height > 1) create_info.imageType = VK_IMAGE_TYPE_3D; + else if (height > 1) create_info.imageType = VK_IMAGE_TYPE_2D; + else create_info.imageType = VK_IMAGE_TYPE_1D; + create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + create_info.extent.width = width; + create_info.extent.height = height; + create_info.extent.depth = height > 1 ? depth : 1; + create_info.arrayLayers = height == 1 ? depth : 1; + create_info.mipLevels = 1; + create_info.samples = VK_SAMPLE_COUNT_1_BIT; + create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + vr = p_vkCreateImage( dev->device, &create_info, NULL, &img->image ); + ok_vk( VK_SUCCESS, vr ); + p_vkGetImageMemoryRequirements( dev->device, img->image, &requirements ); + + dedicated_info.image = img->image; + export_info.handleTypes = handle_type; + handle_info.dwAccess = GENERIC_ALL; + handle_info.name = name; + alloc_info.allocationSize = requirements.size; + alloc_info.memoryTypeIndex = find_vulkan_memory_type( dev->instance, dev->physical_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, requirements.memoryTypeBits ); + + vr = p_vkAllocateMemory( dev->device, &alloc_info, NULL, &img->memory ); + ok_vk( VK_SUCCESS, vr ); + vr = p_vkBindImageMemory( dev->device, img->image, img->memory, 0 ); + ok_vk( VK_SUCCESS, vr ); + + get_handle_info.memory = img->memory; + get_handle_info.handleType = handle_type; + vr = p_vkGetMemoryWin32HandleKHR( dev->device, &get_handle_info, handle ); + ok_vk( VK_SUCCESS, vr ); + + return img; +} + C_ASSERT( sizeof(GUID) == GL_UUID_SIZE_EXT ); C_ASSERT( sizeof(LUID) == GL_LUID_SIZE_EXT );
@@ -3355,6 +3799,7 @@ static HRESULT get_d3d12_shared_handle( ID3D12Device *d3d12, IUnknown *obj, cons
static void test_shared_resources(void) { + struct vulkan_device *vulkan_exp = NULL; struct opengl_device *opengl_imp = NULL; IDirect3DDevice9Ex *d3d9_exp = NULL, *d3d9_imp = NULL; ID3D11Device1 *d3d11_exp = NULL, *d3d11_imp = NULL; @@ -3381,6 +3826,8 @@ static void test_shared_resources(void)
trace( "adapter luid %s\n", debugstr_luid( &luid ) );
+ vulkan_exp = create_vulkan_device( &luid ); + d3d9_exp = create_d3d9ex_device( hwnd, &luid, &stencil_broken ); ok_ptr( d3d9_exp, !=, NULL ); d3d9_imp = create_d3d9ex_device( hwnd, &luid, NULL ); @@ -3431,6 +3878,8 @@ static void test_shared_resources(void)
char runtime_desc[0x1000] = {0}; IUnknown *export = NULL, *import = NULL; + struct vulkan_buffer *buf = NULL; + struct vulkan_image *img = NULL; const WCHAR *name = NULL; HANDLE handle = NULL;
@@ -4077,6 +4526,49 @@ static void test_shared_resources(void) check_d3d12_runtime_desc( (struct d3d12_runtime_desc *)runtime_desc, &desc ); break; } + + case MAKETEST(4, 0, 0): + { + if (!vulkan_exp) break; + buf = export_vulkan_buffer( vulkan_exp, resource_size, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); + get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); + break; + } + case MAKETEST(4, 0, 1): + { + if (!vulkan_exp) break; + buf = export_vulkan_buffer( vulkan_exp, resource_size, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &handle ); + get_d3dkmt_resource_desc( luid, handle, TRUE, 0, runtime_desc ); + break; + } + case MAKETEST(4, 1, 0): + { + if (!vulkan_exp) break; + img = export_vulkan_image( vulkan_exp, width_1d, 1, array_1d, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); + get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); + break; + } + case MAKETEST(4, 2, 0): + { + if (!vulkan_exp) break; + img = export_vulkan_image( vulkan_exp, width_2d, height_2d, 1, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); + get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); + break; + } + case MAKETEST(4, 2, 1): + { + if (!vulkan_exp) break; + img = export_vulkan_image( vulkan_exp, width_2d, height_2d, 1, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &handle ); + get_d3dkmt_resource_desc( luid, handle, TRUE, 0, runtime_desc ); + break; + } + case MAKETEST(4, 3, 0): + { + if (!vulkan_exp) break; + img = export_vulkan_image( vulkan_exp, width_3d, height_3d, depth_3d, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); + get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); + break; + } } if (!handle) goto skip_tests;
@@ -4087,7 +4579,7 @@ static void test_shared_resources(void) todo_wine check_object_name( handle, path ); }
- if (d3d9_imp) + if (d3d9_imp && GET_API(test) <= 3) { const struct d3d9_runtime_desc *desc = (struct d3d9_runtime_desc *)runtime_desc;
@@ -4177,7 +4669,7 @@ static void test_shared_resources(void) todo_wine ok( luid_equals( &luid, &adapter_luid ), "got %s\n", debugstr_luid( &adapter_luid ) ); }
- if (d3d10_imp) + if (d3d10_imp && GET_API(test) <= 3) { const struct d3d11_runtime_desc *desc = (struct d3d11_runtime_desc *)runtime_desc;
@@ -4188,7 +4680,7 @@ static void test_shared_resources(void) if (hr == S_OK) ok_ref( 0, IUnknown_Release( import ) ); }
- if (d3d11_imp) + if (d3d11_imp && GET_API(test) <= 3) { const struct dxgi_runtime_desc *desc = (struct dxgi_runtime_desc *)runtime_desc;
@@ -4220,7 +4712,7 @@ static void test_shared_resources(void) } }
- if (d3d12_imp) + if (d3d12_imp && GET_API(test) <= 3) { hr = ID3D12Device_OpenSharedHandle( d3d12_imp, handle, &IID_ID3D12Resource, (void **)&import ); ok_hr( S_OK, hr ); @@ -4330,6 +4822,8 @@ static void test_shared_resources(void) skip_tests: if (handle && !is_d3dkmt_handle( handle )) CloseHandle( handle ); if (export) ok_ref( 0, IUnknown_Release( export ) ); + if (buf) destroy_vulkan_buffer( vulkan_exp, buf ); + if (img) destroy_vulkan_image( vulkan_exp, img ); winetest_pop_context(); }
@@ -4346,6 +4840,7 @@ skip_tests: ok_ref( 0, IDXGIFactory3_Release( dxgi ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_imp ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_exp ) ); + if (vulkan_exp) destroy_vulkan_device( vulkan_exp ); destroy_opengl_device( opengl_imp ); DestroyWindow( hwnd ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 227 ++++++++++++++++++++++++++++++++++++- 1 file changed, 226 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 3e423702fcb..7b0a311b225 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -3503,6 +3503,64 @@ static struct vulkan_buffer *export_vulkan_buffer( struct vulkan_device *dev, UI return buf; }
+static VkResult import_vulkan_buffer( struct vulkan_device *dev, UINT width, const WCHAR *name, + HANDLE handle, UINT handle_type, struct vulkan_buffer **out ) +{ + VkExternalMemoryBufferCreateInfo external_info = {.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO}; + VkBufferCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = &external_info}; + + VkMemoryDedicatedAllocateInfoKHR dedicated_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO}; + VkImportMemoryWin32HandleInfoKHR handle_info = {.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, .pNext = &dedicated_info}; + VkMemoryAllocateInfo alloc_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = &handle_info}; + + PFN_vkAllocateMemory p_vkAllocateMemory; + PFN_vkBindBufferMemory p_vkBindBufferMemory; + PFN_vkCreateBuffer p_vkCreateBuffer; + PFN_vkGetBufferMemoryRequirements p_vkGetBufferMemoryRequirements; + + VkMemoryRequirements requirements; + struct vulkan_buffer *buf; + VkResult vr; + + buf = calloc( 1, sizeof(*buf) ); + ok_ptr( buf, !=, NULL ); + + p_vkAllocateMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkAllocateMemory" ); + p_vkBindBufferMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkBindBufferMemory" ); + p_vkCreateBuffer = (void *)p_vkGetDeviceProcAddr( dev->device, "vkCreateBuffer" ); + p_vkGetBufferMemoryRequirements = (void *)p_vkGetDeviceProcAddr( dev->device, "vkGetBufferMemoryRequirements" ); + + external_info.handleTypes = handle_type; + create_info.size = width; + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vr = p_vkCreateBuffer( dev->device, &create_info, NULL, &buf->buffer ); + ok_vk( VK_SUCCESS, vr ); + p_vkGetBufferMemoryRequirements( dev->device, buf->buffer, &requirements ); + + dedicated_info.buffer = buf->buffer; + handle_info.handle = name ? NULL : handle; + handle_info.name = name; + handle_info.handleType = handle_type; + alloc_info.allocationSize = requirements.size; + alloc_info.memoryTypeIndex = find_vulkan_memory_type( dev->instance, dev->physical_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, requirements.memoryTypeBits ); + + if ((vr = p_vkAllocateMemory( dev->device, &alloc_info, NULL, &buf->memory ))) + { + PFN_vkDestroyBuffer p_vkDestroyBuffer; + p_vkDestroyBuffer = (void *)p_vkGetDeviceProcAddr( dev->device, "vkDestroyBuffer" ); + p_vkDestroyBuffer( dev->device, buf->buffer, NULL ); + free( buf ); + *out = NULL; + return vr; + } + vr = p_vkBindBufferMemory( dev->device, buf->buffer, buf->memory, 0 ); + ok_vk( VK_SUCCESS, vr ); + + *out = buf; + return VK_SUCCESS; +} + static void destroy_vulkan_image( struct vulkan_device *dev, struct vulkan_image *img ) { PFN_vkFreeMemory p_vkFreeMemory; @@ -3587,6 +3645,75 @@ static struct vulkan_image *export_vulkan_image( struct vulkan_device *dev, UINT return img; }
+static VkResult import_vulkan_image( struct vulkan_device *dev, UINT width, UINT height, UINT depth, + const WCHAR *name, HANDLE handle, UINT handle_type, struct vulkan_image **out ) +{ + VkExternalMemoryImageCreateInfo external_info = {.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO}; + VkImageCreateInfo create_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = &external_info}; + + VkMemoryDedicatedAllocateInfoKHR dedicated_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO}; + VkImportMemoryWin32HandleInfoKHR handle_info = {.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, .pNext = &dedicated_info}; + VkMemoryAllocateInfo alloc_info = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = &handle_info}; + + PFN_vkAllocateMemory p_vkAllocateMemory; + PFN_vkBindImageMemory p_vkBindImageMemory; + PFN_vkCreateImage p_vkCreateImage; + PFN_vkGetImageMemoryRequirements p_vkGetImageMemoryRequirements; + + VkMemoryRequirements requirements; + struct vulkan_image *img; + VkResult vr; + + img = calloc( 1, sizeof(*img) ); + ok_ptr( img, !=, NULL ); + + p_vkAllocateMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkAllocateMemory" ); + p_vkBindImageMemory = (void *)p_vkGetDeviceProcAddr( dev->device, "vkBindImageMemory" ); + p_vkCreateImage = (void *)p_vkGetDeviceProcAddr( dev->device, "vkCreateImage" ); + p_vkGetImageMemoryRequirements = (void *)p_vkGetDeviceProcAddr( dev->device, "vkGetImageMemoryRequirements" ); + + external_info.handleTypes = handle_type; + if (depth > 1 && height > 1) create_info.imageType = VK_IMAGE_TYPE_3D; + else if (height > 1) create_info.imageType = VK_IMAGE_TYPE_2D; + else create_info.imageType = VK_IMAGE_TYPE_1D; + create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + create_info.extent.width = width; + create_info.extent.height = height; + create_info.extent.depth = height > 1 ? depth : 1; + create_info.arrayLayers = height == 1 ? depth : 1; + create_info.mipLevels = 1; + create_info.samples = VK_SAMPLE_COUNT_1_BIT; + create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + vr = p_vkCreateImage( dev->device, &create_info, NULL, &img->image ); + ok_vk( VK_SUCCESS, vr ); + p_vkGetImageMemoryRequirements( dev->device, img->image, &requirements ); + + dedicated_info.image = img->image; + handle_info.handle = name ? NULL : handle; + handle_info.name = name; + handle_info.handleType = handle_type; + alloc_info.allocationSize = requirements.size; + alloc_info.memoryTypeIndex = find_vulkan_memory_type( dev->instance, dev->physical_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, requirements.memoryTypeBits ); + + if ((vr = p_vkAllocateMemory( dev->device, &alloc_info, NULL, &img->memory ))) + { + PFN_vkDestroyImage p_vkDestroyImage; + p_vkDestroyImage = (void *)p_vkGetDeviceProcAddr( dev->device, "vkDestroyImage" ); + p_vkDestroyImage( dev->device, img->image, NULL ); + free( img ); + *out = NULL; + return vr; + } + vr = p_vkBindImageMemory( dev->device, img->image, img->memory, 0 ); + ok_vk( VK_SUCCESS, vr ); + + *out = img; + return VK_SUCCESS; +} + C_ASSERT( sizeof(GUID) == GL_UUID_SIZE_EXT ); C_ASSERT( sizeof(LUID) == GL_LUID_SIZE_EXT );
@@ -3799,7 +3926,7 @@ static HRESULT get_d3d12_shared_handle( ID3D12Device *d3d12, IUnknown *obj, cons
static void test_shared_resources(void) { - struct vulkan_device *vulkan_exp = NULL; + struct vulkan_device *vulkan_imp = NULL, *vulkan_exp = NULL; struct opengl_device *opengl_imp = NULL; IDirect3DDevice9Ex *d3d9_exp = NULL, *d3d9_imp = NULL; ID3D11Device1 *d3d11_exp = NULL, *d3d11_imp = NULL; @@ -3827,6 +3954,7 @@ static void test_shared_resources(void) trace( "adapter luid %s\n", debugstr_luid( &luid ) );
vulkan_exp = create_vulkan_device( &luid ); + vulkan_imp = create_vulkan_device( &luid );
d3d9_exp = create_d3d9ex_device( hwnd, &luid, &stencil_broken ); ok_ptr( d3d9_exp, !=, NULL ); @@ -4739,6 +4867,102 @@ static void test_shared_resources(void) goto skip_tests; }
+ if (vulkan_imp) + { + struct vulkan_buffer *buf_imp = NULL; + struct vulkan_image *img_imp = NULL; + VkResult vr; + + if (is_d3dkmt_handle( handle )) + { + switch (GET_DIM(test)) + { + case 0: + vr = import_vulkan_buffer( vulkan_imp, resource_size, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &buf_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_buffer( vulkan_imp, buf_imp ); + vr = import_vulkan_buffer( vulkan_imp, resource_size, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, &buf_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_buffer( vulkan_imp, buf_imp ); + break; + case 1: + vr = import_vulkan_image( vulkan_imp, width_1d, 1, array_1d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_1d, 1, array_1d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + break; + case 2: + vr = import_vulkan_image( vulkan_imp, width_2d, height_2d, 1, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_2d, height_2d, 1, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + break; + case 3: + vr = import_vulkan_image( vulkan_imp, width_3d, height_3d, depth_3d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_3d, height_3d, depth_3d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + break; + } + } + else + { + switch (GET_DIM(test)) + { + case 0: + vr = import_vulkan_buffer( vulkan_imp, resource_size, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &buf_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_buffer( vulkan_imp, buf_imp ); + vr = import_vulkan_buffer( vulkan_imp, resource_size, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, &buf_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_buffer( vulkan_imp, buf_imp ); + vr = import_vulkan_buffer( vulkan_imp, resource_size, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, &buf_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_buffer( vulkan_imp, buf_imp ); + break; + case 1: + vr = import_vulkan_image( vulkan_imp, width_1d, 1, array_1d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_1d, 1, array_1d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_1d, 1, array_1d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + break; + case 2: + vr = import_vulkan_image( vulkan_imp, width_2d, height_2d, 1, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_2d, height_2d, 1, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_2d, height_2d, 1, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + break; + case 3: + vr = import_vulkan_image( vulkan_imp, width_3d, height_3d, depth_3d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_3d, height_3d, depth_3d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + vr = import_vulkan_image( vulkan_imp, width_3d, height_3d, depth_3d, name, handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, &img_imp ); + ok_vk( VK_SUCCESS, vr ); + destroy_vulkan_image( vulkan_imp, img_imp ); + break; + } + } + } + if (opengl_imp) { if (is_d3dkmt_handle( handle )) @@ -4840,6 +5064,7 @@ skip_tests: ok_ref( 0, IDXGIFactory3_Release( dxgi ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_imp ) ); ok_ref( 0, IDirect3DDevice9Ex_Release( d3d9_exp ) ); + if (vulkan_imp) destroy_vulkan_device( vulkan_imp ); if (vulkan_exp) destroy_vulkan_device( vulkan_exp ); destroy_opengl_device( opengl_imp ); DestroyWindow( hwnd );
I'm getting some succeeding todos here:
``` d3dkmt.c:3800: Test succeeded inside todo block: got ptr 014AC236 d3dkmt.c:3205: Test succeeded inside todo block: got props.properties.deviceID 26591 d3dkmt.c:3205: Test succeeded inside todo block: got props.properties.deviceID 26591 ```