[PATCH 4/4] winex11.drv: Fill Vulkan device LUID property.
Zhiyi Zhang
zzhang at codeweavers.com
Mon Jun 15 09:07:59 CDT 2020
On 6/13/20 3:04 AM, Brendan Shanks wrote:
>
>> 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."
I think deviceNodeMask is already set.
>
>
>> + 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