[PATCH 4/4] winex11.drv: Fill Vulkan device LUID property.
Brendan Shanks
bshanks at codeweavers.com
Fri Jun 12 14:04:24 CDT 2020
> On Jun 12, 2020, at 12:21 AM, Zhiyi Zhang <zzhang at codeweavers.com> wrote:
>
> Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
> ---
> dlls/vulkan-1/tests/vulkan.c | 2 +-
> dlls/winex11.drv/vulkan.c | 11 +++
> dlls/winex11.drv/xrandr.c | 156 +++++++++++++++++++++++++++++++++++
> 3 files changed, 168 insertions(+), 1 deletion(-)
>
> diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
> index ce7efc9deb4..161c053e659 100644
> --- a/dlls/winex11.drv/xrandr.c
> +++ b/dlls/winex11.drv/xrandr.c
> @@ -35,8 +35,16 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
> #include <X11/extensions/Xrandr.h>
> #include "x11drv.h"
>
> +#define VK_NO_PROTOTYPES
> +#define WINE_VK_HOST
> +
> +#include "winreg.h"
> +#include "devguid.h"
> +#include "setupapi.h"
> #include "wine/heap.h"
> #include "wine/unicode.h"
> +#include "wine/vulkan.h"
> +#include "wine/vulkan_driver.h"
>
> static void *xrandr_handle;
>
> @@ -680,6 +688,154 @@ static BOOL is_crtc_primary( RECT primary, const XRRCrtcInfo *crtc )
> crtc->y + crtc->height == primary.bottom;
> }
>
> +#ifdef SONAME_LIBVULKAN
> +
> +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
> +DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
> +DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_GPU_RANDR_PROVIDER_ID, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5c, 2);
> +
> +static BOOL get_provider_luid( RRProvider provider_id, LUID *luid )
> +{
> + static const WCHAR pci[] = {'P','C','I',0};
> + SP_DEVINFO_DATA device_data;
> + DWORD type, device_idx = 0;
> + BOOL ret = FALSE;
> + HDEVINFO devinfo;
> + HANDLE mutex;
> + UINT64 id;
> +
> + mutex = get_display_device_init_mutex();
> + devinfo = SetupDiGetClassDevsW( &GUID_DEVCLASS_DISPLAY, pci, NULL, 0 );
> + device_data.cbSize = sizeof(device_data);
> + while (SetupDiEnumDeviceInfo( devinfo, device_idx++, &device_data) )
> + {
> + if (!SetupDiGetDevicePropertyW( devinfo, &device_data,
> + &WINE_DEVPROPKEY_GPU_RANDR_PROVIDER_ID, &type, (BYTE *)&id,
> + sizeof(id), NULL, 0) )
> + continue;
> +
> + if (id != provider_id)
> + continue;
> +
> + if (SetupDiGetDevicePropertyW( devinfo, &device_data, &DEVPROPKEY_GPU_LUID, &type,
> + (BYTE *)luid, sizeof(*luid), NULL, 0) )
> + {
> + ret = TRUE;
> + break;
> + }
> + }
> + SetupDiDestroyDeviceInfoList( devinfo );
> + release_display_device_init_mutex( mutex );
> +
> + if (!ret)
> + WARN("Failed to get LUID for RandR provider %#lx.\n", provider_id);
> + return ret;
> +}
> +
> +static void set_luid_property( VkPhysicalDeviceProperties2 *properties, const LUID *luid )
> +{
> + VkPhysicalDeviceIDProperties *id;
> + VkBaseOutStructure *header;
> +
> + for (header = (VkBaseOutStructure *)properties; header; header = header->pNext)
> + {
> + if (header->sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES)
> + continue;
> +
> + id = (VkPhysicalDeviceIDProperties *)header;
> + memcpy( &id->deviceLUID, luid, sizeof(*luid) );
> + id->deviceLUIDValid = VK_TRUE;
> + TRACE("Set LUID %08x:%08x for Vulkan physical device properties %p.\n", luid->HighPart,
> + luid->LowPart, properties);
id->deviceNodeMask also must be set, probably to 1.
“If deviceLUIDValid is VK_TRUE, deviceNodeMask must contain exactly one bit. If Vulkan is running on an operating system that supports the Direct3D 12 API and physicalDevice corresponds to an individual device in a linked device adapter, deviceNodeMask identifies the Direct3D 12 node corresponding to physicalDevice. Otherwise, deviceNodeMask must be 1."
> + return;
> + }
> +}
> +
> +void fill_vk_device_luid_property( VkPhysicalDevice physical_device,
> + VkPhysicalDeviceProperties2 *properties )
> +{
> + VkResult (*p_vkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * );
> + const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION );
> + static const char *extensions[] = { "VK_EXT_acquire_xlib_display" };
> + XRRProviderResources *provider_resources = NULL;
> + XRRScreenResources *screen_resources = NULL;
> + XRRProviderInfo *provider_info = NULL;
> + unsigned int provider_idx, output_idx;
> + VkInstanceCreateInfo create_info;
> + VkDisplayKHR vk_display;
> + VkInstance vk_instance;
> + VkResult vr;
> + LUID luid;
> +
> + memset( &create_info, 0, sizeof(create_info) );
> + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
> + create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
> + create_info.ppEnabledExtensionNames = extensions;
> +
> + vr = vulkan_funcs->p_vkCreateInstance( &create_info, NULL, &vk_instance );
> + if (vr != VK_SUCCESS)
> + {
> + ERR("Failed to create a Vulkan instance, vr %d.\n", vr);
> + return;
> + }
> +
> + p_vkGetRandROutputDisplayEXT = (void *)vulkan_funcs->p_vkGetInstanceProcAddr( vk_instance, "vkGetRandROutputDisplayEXT" );
> + if (!p_vkGetRandROutputDisplayEXT)
> + {
> + ERR("Failed to load vkGetRandROutputDisplayEXT.\n");
> + goto done;
> + }
> +
> + screen_resources = xrandr_get_screen_resources();
> + if (!screen_resources)
> + goto done;
> +
> + provider_resources = pXRRGetProviderResources( gdi_display, root_window );
> + if (!provider_resources)
> + goto done;
> +
> + if (!provider_resources->nproviders && get_provider_luid( 1, &luid ))
> + {
> + set_luid_property( properties, &luid );
> + goto done;
> + }
> +
> + for (provider_idx = 0; provider_idx < provider_resources->nproviders; ++provider_idx)
> + {
> + provider_info = pXRRGetProviderInfo( gdi_display, screen_resources,
> + provider_resources->providers[provider_idx] );
> + if (!provider_info)
> + continue;
> +
> + for (output_idx = 0; output_idx < provider_info->noutputs; ++output_idx)
> + {
> + vr = p_vkGetRandROutputDisplayEXT( physical_device, gdi_display,
> + provider_info->outputs[output_idx], &vk_display);
> + if (vr != VK_SUCCESS || vk_display == VK_NULL_HANDLE)
> + continue;
I tried these patches out but they aren’t working on my system. vkGetRandROutputDisplayEXT() is called for each output, rrOutput is unique and seems valid, but the returned vk_display is VK_NULL_HANDLE. This is on NVIDIA with driver 440.82.
I also tried calling vkGetPhysicalDeviceDisplayPropertiesKHR() here, it returns success but never fills in pPropertyCount or any valid pProperties. Adding VK_KHR_display as an extension also doesn’t help.
Something's going wrong here but I don’t know what it is, I’ll test these APIs out from a regular Linux binary.
More information about the wine-devel
mailing list