This should achieve the same thing as https://github.com/ValveSoftware/wine/commit/e8801e96fedf67b88e6f3f5d9f9e2d9...
-- v3: win32u: Enumerate offscreen vulkan devices as GPU devices. win32u: Query GPU memory from vulkan physical device. win32u: Match driver GPUs with vulkan GPUS from their ids, or index. win32u: Keep a list of vulkan GPUS in the device manager context. win32u: Load the graphics driver vulkan functions lazily. win32u: Fix default_update_display_devices return type to NTSTATUS.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e7262cd33f6..02d9a30f29f 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1711,7 +1711,7 @@ static BOOL update_display_cache_from_registry(void) return ret; }
-static BOOL default_update_display_devices( BOOL force, struct device_manager_ctx *ctx ) +static NTSTATUS default_update_display_devices( BOOL force, struct device_manager_ctx *ctx ) { /* default implementation: expose an adapter and a monitor with a few standard modes, * and read / write current display settings from / to the registry. @@ -1736,7 +1736,7 @@ static BOOL default_update_display_devices( BOOL force, struct device_manager_ct struct gdi_monitor monitor = {0}; DEVMODEW mode = {{0}};
- if (!force) return TRUE; + if (!force) return STATUS_ALREADY_COMPLETE;
add_gpu( "Default GPU", &pci_id, NULL, 0, ctx ); add_source( "Default", source_flags, ctx ); @@ -1754,7 +1754,7 @@ static BOOL default_update_display_devices( BOOL force, struct device_manager_ct add_monitor( &monitor, ctx ); add_modes( &mode, ARRAY_SIZE(modes), modes, ctx );
- return TRUE; + return STATUS_SUCCESS; }
/* parse the desktop size specification */
From: Rémi Bernon rbernon@codeweavers.com
So that VulkanInit is only called when surface related functions are needed, breaking the re-entry when we call d3dkmt vulkan functions from update_display_cache, which is called when graphics drivers are loaded. --- dlls/win32u/vulkan.c | 73 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 9 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 59b9364065e..5b128afe3cb 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -213,22 +213,14 @@ static const struct vulkan_driver_funcs nulldrv_funcs = .p_get_host_surface_extension = nulldrv_get_host_surface_extension, };
-static void vulkan_init(void) +static void vulkan_driver_init(void) { UINT status;
- if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW ))) - { - ERR( "Failed to load %s\n", SONAME_LIBVULKAN ); - return; - } - if ((status = user_driver->pVulkanInit( WINE_VULKAN_DRIVER_VERSION, vulkan_handle, &driver_funcs )) && status != STATUS_NOT_IMPLEMENTED) { ERR( "Failed to initialize the driver vulkan functions, status %#x\n", status ); - dlclose( vulkan_handle ); - vulkan_handle = NULL; return; }
@@ -239,6 +231,65 @@ static void vulkan_init(void) vulkan_funcs.p_vkGetPhysicalDeviceWin32PresentationSupportKHR = driver_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR; vulkan_funcs.p_get_host_surface_extension = driver_funcs->p_get_host_surface_extension; } +} + +static void vulkan_driver_load(void) +{ + static pthread_once_t init_once = PTHREAD_ONCE_INIT; + pthread_once( &init_once, vulkan_driver_init ); +} + +static VkResult lazydrv_vulkan_surface_create( HWND hwnd, VkInstance instance, VkSurfaceKHR *surface, void **private ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_create( hwnd, instance, surface, private ); +} + +static void lazydrv_vulkan_surface_destroy( HWND hwnd, void *private ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_destroy( hwnd, private ); +} + +static void lazydrv_vulkan_surface_detach( HWND hwnd, void *private ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_detach( hwnd, private ); +} + +static void lazydrv_vulkan_surface_presented( HWND hwnd, VkResult result ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_presented( hwnd, result ); +} + +static VkBool32 lazydrv_vkGetPhysicalDeviceWin32PresentationSupportKHR( VkPhysicalDevice device, uint32_t queue ) +{ + vulkan_driver_load(); + return driver_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR( device, queue ); +} + +static const char *lazydrv_get_host_surface_extension(void) +{ + vulkan_driver_load(); + return driver_funcs->p_get_host_surface_extension(); +} + +static const struct vulkan_driver_funcs lazydrv_funcs = +{ + .p_vulkan_surface_create = lazydrv_vulkan_surface_create, + .p_vulkan_surface_destroy = lazydrv_vulkan_surface_destroy, + .p_vulkan_surface_detach = lazydrv_vulkan_surface_detach, + .p_vulkan_surface_presented = lazydrv_vulkan_surface_presented, +}; + +static void vulkan_init(void) +{ + if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW ))) + { + ERR( "Failed to load %s\n", SONAME_LIBVULKAN ); + return; + }
#define LOAD_FUNCPTR( f ) \ if (!(p_##f = dlsym( vulkan_handle, #f ))) \ @@ -254,6 +305,10 @@ static void vulkan_init(void) LOAD_FUNCPTR( vkGetDeviceProcAddr ); LOAD_FUNCPTR( vkGetInstanceProcAddr ); #undef LOAD_FUNCPTR + + driver_funcs = &lazydrv_funcs; + vulkan_funcs.p_vkGetPhysicalDeviceWin32PresentationSupportKHR = lazydrv_vkGetPhysicalDeviceWin32PresentationSupportKHR; + vulkan_funcs.p_get_host_surface_extension = lazydrv_get_host_surface_extension; }
void vulkan_detach_surfaces( struct list *surfaces )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 59 ++++++++++++++++++++++++++++++------ dlls/win32u/sysparams.c | 12 +++++++- dlls/win32u/win32u_private.h | 11 +++++++ 3 files changed, 72 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index e75a29e0934..a016c735f13 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -189,28 +189,36 @@ NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVIC return STATUS_SUCCESS; }
-static VkPhysicalDevice get_vulkan_physical_device( const GUID *uuid ) +static UINT get_vulkan_physical_devices( VkPhysicalDevice **devices ) { - VkPhysicalDevice *devices, device; - UINT device_count, i; + UINT device_count; VkResult vr;
if ((vr = pvkEnumeratePhysicalDevices( d3dkmt_vk_instance, &device_count, NULL ))) { WARN( "vkEnumeratePhysicalDevices returned %d\n", vr ); - return VK_NULL_HANDLE; + return 0; }
- if (!device_count || !(devices = malloc( device_count * sizeof(*devices) ))) - return VK_NULL_HANDLE; + if (!device_count || !(*devices = malloc( device_count * sizeof(**devices) ))) return 0;
- if ((vr = pvkEnumeratePhysicalDevices( d3dkmt_vk_instance, &device_count, devices ))) + if ((vr = pvkEnumeratePhysicalDevices( d3dkmt_vk_instance, &device_count, *devices ))) { WARN( "vkEnumeratePhysicalDevices returned %d\n", vr ); - free( devices ); - return VK_NULL_HANDLE; + free( *devices ); + return 0; }
+ return device_count; +} + +static VkPhysicalDevice get_vulkan_physical_device( const GUID *uuid ) +{ + VkPhysicalDevice *devices, device; + UINT device_count, i; + + if (!(device_count = get_vulkan_physical_devices( &devices ))) return VK_NULL_HANDLE; + for (i = 0, device = VK_NULL_HANDLE; i < device_count; ++i) { VkPhysicalDeviceIDProperties id = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES}; @@ -549,3 +557,36 @@ NTSTATUS WINAPI NtGdiDdDDICheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNE pthread_mutex_unlock( &d3dkmt_lock ); return STATUS_SUCCESS; } + +BOOL get_vulkan_gpus( struct list *gpus ) +{ + VkPhysicalDevice *devices; + UINT i, count; + + if (!d3dkmt_use_vulkan()) return FALSE; + if (!(count = get_vulkan_physical_devices( &devices ))) return FALSE; + + for (i = 0; i < count; ++i) + { + VkPhysicalDeviceIDProperties id = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES}; + VkPhysicalDeviceProperties2 properties2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &id}; + struct vulkan_gpu *gpu; + + if (!(gpu = calloc( 1, sizeof(*gpu) ))) break; + pvkGetPhysicalDeviceProperties2KHR( devices[i], &properties2 ); + memcpy( &gpu->uuid, id.deviceUUID, sizeof(gpu->uuid) ); + gpu->name = strdup( properties2.properties.deviceName ); + gpu->pci_id.vendor = properties2.properties.vendorID; + gpu->pci_id.device = properties2.properties.deviceID; + list_add_tail( gpus, &gpu->entry ); + } + + free( devices ); + return TRUE; +} + +void free_vulkan_gpu( struct vulkan_gpu *gpu ) +{ + free( gpu->name ); + free( gpu ); +} diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 02d9a30f29f..5fd31275837 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -932,6 +932,7 @@ struct device_manager_ctx struct gpu gpu; struct source source; HKEY source_key; + struct list vulkan_gpus; /* for the virtual desktop settings */ BOOL is_primary; DEVMODEW primary; @@ -1487,6 +1488,13 @@ static void release_display_manager_ctx( struct device_manager_ctx *ctx ) last_query_display_time = 0; } if (ctx->gpu_count) cleanup_devices(); + + while (!list_empty( &ctx->vulkan_gpus )) + { + struct vulkan_gpu *gpu = LIST_ENTRY( list_head( &ctx->vulkan_gpus ), struct vulkan_gpu, entry ); + list_remove( &gpu->entry ); + free_vulkan_gpu( gpu ); + } }
static void clear_display_devices(void) @@ -1938,7 +1946,7 @@ BOOL update_display_cache( BOOL force ) static const WCHAR wine_service_station_name[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n',0}; HWINSTA winstation = NtUserGetProcessWindowStation(); - struct device_manager_ctx ctx = {0}; + struct device_manager_ctx ctx = {.vulkan_gpus = LIST_INIT(ctx.vulkan_gpus)}; UINT status; WCHAR name[MAX_PATH];
@@ -1953,6 +1961,8 @@ BOOL update_display_cache( BOOL force ) return TRUE; }
+ if (!get_vulkan_gpus( &ctx.vulkan_gpus )) WARN( "Failed to find any vulkan GPU\n" ); + status = update_display_devices( force, &ctx );
release_display_manager_ctx( &ctx ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 24e8b1b498d..849c39e65da 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -190,6 +190,17 @@ extern BOOL update_display_cache( BOOL force ); extern void user_lock(void); extern void user_unlock(void); extern void user_check_not_lock(void); + +struct vulkan_gpu +{ + struct list entry; + struct pci_id pci_id; + char *name; + GUID uuid; +}; + +extern BOOL get_vulkan_gpus( struct list *gpus ); +extern void free_vulkan_gpu( struct vulkan_gpu *gpu ); extern BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid );
/* winstation.c */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 5fd31275837..b7368961da1 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1184,12 +1184,36 @@ static BOOL write_gpu_to_registry( const struct gpu *gpu, const struct pci_id *p return TRUE; }
+static struct vulkan_gpu *find_vulkan_gpu_from_uuid( const struct device_manager_ctx *ctx, const GUID *uuid ) +{ + struct vulkan_gpu *gpu; + + if (!uuid) return NULL; + + LIST_FOR_EACH_ENTRY( gpu, &ctx->vulkan_gpus, struct vulkan_gpu, entry ) + if (!memcmp( &gpu->uuid, uuid, sizeof(*uuid) )) return gpu; + + return NULL; +} + +static struct vulkan_gpu *find_vulkan_gpu_from_pci_id( const struct device_manager_ctx *ctx, const struct pci_id *pci_id ) +{ + struct vulkan_gpu *gpu; + + LIST_FOR_EACH_ENTRY( gpu, &ctx->vulkan_gpus, struct vulkan_gpu, entry ) + if (gpu->pci_id.vendor == pci_id->vendor && gpu->pci_id.device == pci_id->device) return gpu; + + return NULL; +} + static void add_gpu( const char *name, const struct pci_id *pci_id, const GUID *vulkan_uuid, ULONGLONG memory_size, void *param ) { struct device_manager_ctx *ctx = param; char buffer[4096]; KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; + struct vulkan_gpu *vulkan_gpu = NULL; + struct list *ptr; unsigned int i; HKEY hkey, subkey; DWORD len; @@ -1209,7 +1233,24 @@ static void add_gpu( const char *name, const struct pci_id *pci_id, const GUID *
memset( &ctx->gpu, 0, sizeof(ctx->gpu) ); ctx->gpu.index = ctx->gpu_count; + + if ((vulkan_gpu = find_vulkan_gpu_from_uuid( ctx, vulkan_uuid ))) + TRACE( "Found vulkan GPU matching uuid %s, pci_id %#04x:%#04x, name %s\n", debugstr_guid(&vulkan_gpu->uuid), + pci_id->vendor, pci_id->device, debugstr_a(vulkan_gpu->name)); + else if ((vulkan_gpu = find_vulkan_gpu_from_pci_id( ctx, pci_id ))) + TRACE( "Found vulkan GPU matching pci_id %#04x:%#04x, uuid %s, name %s\n", pci_id->vendor, pci_id->device, + debugstr_guid(&vulkan_gpu->uuid), debugstr_a(vulkan_gpu->name)); + else if ((ptr = list_head( &ctx->vulkan_gpus ))) + { + vulkan_gpu = LIST_ENTRY( ptr, struct vulkan_gpu, entry ); + WARN( "Using vulkan GPU pci_id %#04x:%#04x, uuid %s, name %s\n", pci_id->vendor, pci_id->device, + debugstr_guid(&vulkan_gpu->uuid), debugstr_a(vulkan_gpu->name)); + } + if (vulkan_uuid) ctx->gpu.vulkan_uuid = *vulkan_uuid; + else if (vulkan_gpu) ctx->gpu.vulkan_uuid = vulkan_gpu->uuid; + + if (!name && vulkan_gpu) name = vulkan_gpu->name; if (name) RtlUTF8ToUnicodeN( ctx->gpu.name, sizeof(ctx->gpu.name) - sizeof(WCHAR), &len, name, strlen( name ) );
snprintf( ctx->gpu.path, sizeof(ctx->gpu.path), "PCI\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X\%08X", @@ -1257,6 +1298,12 @@ static void add_gpu( const char *name, const struct pci_id *pci_id, const GUID * WARN( "Failed to write gpu to registry\n" ); else ctx->gpu_count++; + + if (vulkan_gpu) + { + list_remove( &vulkan_gpu->entry ); + free_vulkan_gpu( vulkan_gpu ); + } }
static BOOL write_source_to_registry( const struct source *source, HKEY *source_key )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 11 +++++++++++ dlls/win32u/sysparams.c | 7 +++---- dlls/win32u/win32u_private.h | 1 + dlls/wineandroid.drv/init.c | 2 +- dlls/winemac.drv/display.c | 2 +- dlls/winewayland.drv/display.c | 2 +- dlls/winex11.drv/display.c | 3 +-- dlls/winex11.drv/x11drv.h | 1 - dlls/winex11.drv/xrandr.c | 12 +----------- include/wine/gdi_driver.h | 2 +- 10 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index a016c735f13..b644135bfa1 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -61,6 +61,7 @@ static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /
static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */ static PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR; +static PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties; static PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR; static PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices; static const struct vulkan_funcs *vulkan_funcs; @@ -107,6 +108,7 @@ static void d3dkmt_init_vulkan(void) } LOAD_VK_FUNC( vkEnumeratePhysicalDevices ) LOAD_VK_FUNC( vkGetPhysicalDeviceProperties2KHR ) + LOAD_VK_FUNC( vkGetPhysicalDeviceMemoryProperties ) LOAD_VK_FUNC( vkGetPhysicalDeviceMemoryProperties2KHR ) #undef LOAD_VK_FUNC } @@ -570,6 +572,7 @@ BOOL get_vulkan_gpus( struct list *gpus ) { VkPhysicalDeviceIDProperties id = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES}; VkPhysicalDeviceProperties2 properties2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &id}; + VkPhysicalDeviceMemoryProperties mem_properties; struct vulkan_gpu *gpu;
if (!(gpu = calloc( 1, sizeof(*gpu) ))) break; @@ -578,6 +581,14 @@ BOOL get_vulkan_gpus( struct list *gpus ) gpu->name = strdup( properties2.properties.deviceName ); gpu->pci_id.vendor = properties2.properties.vendorID; gpu->pci_id.device = properties2.properties.deviceID; + + pvkGetPhysicalDeviceMemoryProperties( devices[i], &mem_properties ); + for (i = 0; i < mem_properties.memoryHeapCount; i++) + { + if (mem_properties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) + gpu->memory += mem_properties.memoryHeaps[i].size; + } + list_add_tail( gpus, &gpu->entry ); }
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index b7368961da1..738870032f4 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1206,8 +1206,7 @@ static struct vulkan_gpu *find_vulkan_gpu_from_pci_id( const struct device_manag return NULL; }
-static void add_gpu( const char *name, const struct pci_id *pci_id, const GUID *vulkan_uuid, - ULONGLONG memory_size, void *param ) +static void add_gpu( const char *name, const struct pci_id *pci_id, const GUID *vulkan_uuid, void *param ) { struct device_manager_ctx *ctx = param; char buffer[4096]; @@ -1294,7 +1293,7 @@ static void add_gpu( const char *name, const struct pci_id *pci_id, const GUID *
NtClose( hkey );
- if (!write_gpu_to_registry( &ctx->gpu, pci_id, memory_size )) + if (!write_gpu_to_registry( &ctx->gpu, pci_id, vulkan_gpu ? vulkan_gpu->memory : 0 )) WARN( "Failed to write gpu to registry\n" ); else ctx->gpu_count++; @@ -1793,7 +1792,7 @@ static NTSTATUS default_update_display_devices( BOOL force, struct device_manage
if (!force) return STATUS_ALREADY_COMPLETE;
- add_gpu( "Default GPU", &pci_id, NULL, 0, ctx ); + add_gpu( "Default GPU", &pci_id, NULL, ctx ); add_source( "Default", source_flags, ctx );
if (!read_source_mode( ctx->source_key, ENUM_CURRENT_SETTINGS, &mode )) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 849c39e65da..d0f3e56acca 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -197,6 +197,7 @@ struct vulkan_gpu struct pci_id pci_id; char *name; GUID uuid; + ULONGLONG memory; };
extern BOOL get_vulkan_gpus( struct list *gpus ); diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index c8d997b7aa4..16c2774b689 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -288,7 +288,7 @@ UINT ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag }; DEVMODEW current = mode;
- device_manager->add_gpu( "Android GPU", &pci_id, NULL, 0, param ); + device_manager->add_gpu( "Android GPU", &pci_id, NULL, param ); device_manager->add_source( "Default", source_flags, param ); device_manager->add_monitor( &gdi_monitor, param );
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index c8e29cbf908..46723c0f9f1 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -1151,7 +1151,7 @@ UINT macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage .subsystem = gpu->subsys_id, .revision = gpu->revision_id, }; - device_manager->add_gpu(gpu->name, &pci_id, NULL, 0, param); + device_manager->add_gpu(gpu->name, &pci_id, NULL, param);
/* Initialize adapters */ if (macdrv_get_adapters(gpu->id, &adapters, &adapter_count)) break; diff --git a/dlls/winewayland.drv/display.c b/dlls/winewayland.drv/display.c index a1dc925a183..dfe2689006c 100644 --- a/dlls/winewayland.drv/display.c +++ b/dlls/winewayland.drv/display.c @@ -206,7 +206,7 @@ static void wayland_add_device_gpu(const struct gdi_device_manager *device_manag
TRACE("\n");
- device_manager->add_gpu("Wayland GPU", &pci_id, NULL, 0, param); + device_manager->add_gpu("Wayland GPU", &pci_id, NULL, param); }
static void wayland_add_device_source(const struct gdi_device_manager *device_manager, diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 861146d3e90..237aa047321 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -517,8 +517,7 @@ UINT X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
for (gpu = 0; gpu < gpu_count; gpu++) { - device_manager->add_gpu( gpus[gpu].name, &gpus[gpu].pci_id, &gpus[gpu].vulkan_uuid, - gpus[gpu].memory_size, param ); + device_manager->add_gpu( gpus[gpu].name, &gpus[gpu].pci_id, &gpus[gpu].vulkan_uuid, param );
/* Initialize adapters */ if (!host_handler.get_adapters( gpus[gpu].id, &adapters, &adapter_count )) break; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 5c9592705b8..1aaba9bf24b 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -770,7 +770,6 @@ struct x11drv_gpu char *name; struct pci_id pci_id; GUID vulkan_uuid; - ULONGLONG memory_size; };
struct x11drv_adapter diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 6cc3c277213..03b2b21a98b 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -645,11 +645,9 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro VkResult (*pvkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * ); PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR; PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices; - PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties; - uint32_t device_count, device_idx, output_idx, heap_idx, i; + uint32_t device_count, device_idx, output_idx, i; VkPhysicalDevice *vk_physical_devices = NULL; VkPhysicalDeviceProperties2 properties2; - VkPhysicalDeviceMemoryProperties mem_properties; PFN_vkCreateInstance pvkCreateInstance; VkInstanceCreateInfo create_info; VkPhysicalDeviceIDProperties id; @@ -685,7 +683,6 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro LOAD_VK_FUNC(vkEnumeratePhysicalDevices) LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR) LOAD_VK_FUNC(vkGetRandROutputDisplayEXT) - LOAD_VK_FUNC(vkGetPhysicalDeviceMemoryProperties) #undef LOAD_VK_FUNC
vr = pvkEnumeratePhysicalDevices( vk_instance, &device_count, NULL ); @@ -743,13 +740,6 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro } gpu->name = strdup( properties2.properties.deviceName );
- pvkGetPhysicalDeviceMemoryProperties( vk_physical_devices[device_idx], &mem_properties ); - for (heap_idx = 0; heap_idx < mem_properties.memoryHeapCount; heap_idx++) - { - if (mem_properties.memoryHeaps[heap_idx].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) - gpu->memory_size += mem_properties.memoryHeaps[heap_idx].size; - } - ret = TRUE; goto done; } diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index c299dc2ae42..21298587267 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -255,7 +255,7 @@ struct gdi_monitor
struct gdi_device_manager { - void (*add_gpu)( const char *name, const struct pci_id *pci_id, const GUID *vulkan_uuid, ULONGLONG memory_size, void *param ); + void (*add_gpu)( const char *name, const struct pci_id *pci_id, const GUID *vulkan_uuid, void *param ); void (*add_source)( const char *name, UINT state_flags, void *param ); void (*add_monitor)( const struct gdi_monitor *monitor, void *param ); void (*add_modes)( const DEVMODEW *current, UINT modes_count, const DEVMODEW *modes, void *param );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 738870032f4..bca2050ba4d 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1987,6 +1987,18 @@ static UINT update_display_devices( BOOL force, struct device_manager_ctx *ctx ) return status; }
+static void add_vulkan_only_gpus( struct device_manager_ctx *ctx ) +{ + struct list gpus = LIST_INIT(gpus); + struct vulkan_gpu *gpu, *next; + + LIST_FOR_EACH_ENTRY_SAFE( gpu, next, &ctx->vulkan_gpus, struct vulkan_gpu, entry ) + { + TRACE( "adding vulkan-only gpu uuid %s, name %s\n", debugstr_guid(&gpu->uuid), debugstr_a(gpu->name)); + add_gpu( gpu->name, &gpu->pci_id, &gpu->uuid, ctx ); + } +} + BOOL update_display_cache( BOOL force ) { static const WCHAR wine_service_station_name[] = @@ -2009,7 +2021,8 @@ BOOL update_display_cache( BOOL force )
if (!get_vulkan_gpus( &ctx.vulkan_gpus )) WARN( "Failed to find any vulkan GPU\n" );
- status = update_display_devices( force, &ctx ); + if (!(status = update_display_devices( force, &ctx ))) + add_vulkan_only_gpus( &ctx );
release_display_manager_ctx( &ctx ); if (status && status != STATUS_ALREADY_COMPLETE) WARN( "Failed to update display devices, status %#x\n", status );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=145615
Your paranoid android.
=== debian11b (build log) ===
009c:err:winediag:gnutls_process_attach failed to load libgnutls, no support for encryption 009c:err:winediag:process_attach failed to load libgnutls, no support for pfx import/export
On Tue May 21 12:48:24 2024 +0000, Zhiyi Zhang wrote:
The CI test failures look suspicious, could you take a look? Also, the monitor and vulkan tests timeout at https://testbot.winehq.org/JobDetails.pl?Key=145557
Thanks, there was indeed a deadlock when calling into d3dkmt vulkan, which could then call VulkanInit driver entry, which loads the graphics drivers, call into display devices again and back into d3dkmt pthread_once.
I've fixed this by lazily loading the graphics driver vulkan functions, which are now only needed when surfaces are created, which should only be happening after the display device initialization and when graphics drivers are fully loaded already anyway.
Why do you need to use the SAFE version of LIST_FOR_EACH_ENTRY?
I think that although there's no specific ordering, there's also only the winemac driver over metal that exposes multiple GPUs without having proper PCI id.
Not really. xrandr14_get_gpus() can also report multiple GPUs and one of the GPUs may not support Vulkan. Unfortunately, this isn't a good resolution to solve it without resorting to libdrm or Nvidia proprietary driver interface.
On Tue May 21 12:53:32 2024 +0000, Zhiyi Zhang wrote:
Why do you need to use the SAFE version of LIST_FOR_EACH_ENTRY?
Because add_gpu will lookup a matching GPU in the vulkan_gpus list (and here, will find the gpu itself) and remove it.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
memset( &ctx->gpu, 0, sizeof(ctx->gpu) ); ctx->gpu.index = ctx->gpu_count;
- if ((vulkan_gpu = find_vulkan_gpu_from_uuid( ctx, vulkan_uuid )))
TRACE( "Found vulkan GPU matching uuid %s, pci_id %#04x:%#04x, name %s\n", debugstr_guid(&vulkan_gpu->uuid),
pci_id->vendor, pci_id->device, debugstr_a(vulkan_gpu->name));
- else if ((vulkan_gpu = find_vulkan_gpu_from_pci_id( ctx, pci_id )))
I don't feel comfortable with matching with PCI IDs or just the random Vulkan device here. Even with PCI IDs you can have two or more GPUs of the same spec. The PCI ID must be unique to use as a fallback. So you shouldn't use the PCI IDs to match devices when there are two GPUs of the same model. But then again, I don't think there is a good solution to this. The root cause is that we don't have the infrastructure to do it properly. We need something like hardware device paths to correctly implement this. Can we not match a GPU to a Vulkan GPU if matching by UUID fails? Add then we consider the rest of Vulkan GPUs not added as offscreen and add them later. Would that work?
On Mon May 20 13:18:17 2024 +0000, Zhiyi Zhang wrote:
I don't feel comfortable with matching with PCI IDs or just the random Vulkan device here. Even with PCI IDs you can have two or more GPUs of the same spec. The PCI ID must be unique to use as a fallback. So you shouldn't use the PCI IDs to match devices when there are two GPUs of the same model. But then again, I don't think there is a good solution to this. The root cause is that we don't have the infrastructure to do it properly. We need something like hardware device paths to correctly implement this. Can we not match a GPU to a Vulkan GPU if matching by UUID fails? Add then we consider the rest of Vulkan GPUs not added as offscreen and add them later. Would that work?
I don't really see the issue with selecting one or the other GPU if they are both the same model. And I think this is more a limitation of the backends, which we cannot do much about: if Wayland abstracts the GPU information there is no way we can bind a Wayland output to a particular GPU, but that's also probably not an issue.
Instead, not matching any Vulkan GPU, we would still need to expose a fake GPU to the Windows applications, and that GPU would not have any associated Vulkan device. I think that can cause more problems than selecting an arbitrary, by PCI ID, or the first, GPU we find.
I don't really see the issue with selecting one or the other GPU if they are both the same model.
The problem is that we need to know exactly which output is connected to which GPU for things like IDXGIFactory::EnumAdapters().
On Mon May 20 14:31:31 2024 +0000, Zhiyi Zhang wrote:
I don't really see the issue with selecting one or the other GPU if
they are both the same model. The problem is that we need to know exactly which output is connected to which GPU for things like IDXGIFactory::EnumAdapters().
I still don't understand how this is an issue. Enumerating / changing display settings is done through the driver interfaces anyway, not through Vulkan?
I understand that there might be a difference if an application looks for the GPU capabilities of the GPU that is associated with some display output, but in that case using an equivalent GPU (with the same PCI ID) should also end up with pretty much the same result, doesn't it?
In many cases there's also only a single GPU exposed from the driver, we don't even have PCI ID, and all outputs can be seen as connected it regardless. So we need to pick one as the main GPU, and any could do the job just as well as a fake one which would simply not work at all from the vulkan perspective, no?
On Mon May 20 07:29:45 2024 +0000, Zhiyi Zhang wrote:
I think that although there's no specific ordering, there's also only
the winemac driver over metal that exposes multiple GPUs without having proper PCI id. Not really. xrandr14_get_gpus() can also report multiple GPUs and one of the GPUs may not support Vulkan. Unfortunately, this isn't a good resolution to solve it without resorting to libdrm or Nvidia proprietary driver interface.
Is this really something that happens? I can believe that Vulkan may not be supported at all (and if it's not supported there's no issue with GPU mismatch), but having it supported only on some GPUs, and not on the one that is used for display, seems a bit of a convoluted use case.
Anyway, IMO instead of blocking the most common use case, which is a single GPU with or without Vulkan support, because of some very unlikely broken one, we should instead make the most common use case work and block the broken one until we have a better solution for it.
Anyway, IMO instead of blocking the most common use case, which is a single GPU with or without Vulkan support, because of some very unlikely broken one, we should instead make the most common use case work and block the broken one until we have a better solution for it.
I agree. There isn't a good solution to this but let's not block on it.
This merge request was approved by Zhiyi Zhang.