[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