diff --git a/vrclient_x64/vrclient_main.c b/vrclient_x64/vrclient_main.c index 9dec1c64..f2fc3714 100644 --- a/vrclient_x64/vrclient_main.c +++ b/vrclient_x64/vrclient_main.c @@ -31,6 +31,8 @@ CREATE_TYPE_INFO_VTABLE; struct compositor_data compositor_data = {0}; static BOOL vrclient_loaded; +char *g_instance_extensions; + BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { TRACE("(%p, %lu, %p)\n", instance, reason, reserved); @@ -64,6 +66,91 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) return TRUE; } +static BOOL get_vulkan_extensions_from_registry(void) +{ + DWORD type, value, size = sizeof(value), wait_result; + LSTATUS status; + HANDLE event; + HKEY vr_key; + DWORD len; + + if ((status = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\Wine\\VR", 0, KEY_READ, &vr_key ))) + { + ERR( "Could not create key, status %#lx.\n", status ); + return FALSE; + } + + if ((status = RegQueryValueExA( vr_key, "state", NULL, &type, (BYTE *)&value, &size ))) + { + ERR( "Could not query VR state, status %#lx\n", status ); + RegCloseKey( vr_key ); + return FALSE; + } + if (type != REG_DWORD) + { + ERR( "Invalid VR state type: %lx\n", type ); + RegCloseKey( vr_key ); + return FALSE; + } + + if (!value) + { + event = CreateEventA( NULL, FALSE, FALSE, NULL ); + while (1) + { + if (RegNotifyChangeKeyValue( vr_key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, event, TRUE )) + { + ERR( "Error registering VR key change notification" ); + break; + } + size = sizeof(value); + if ((status = RegQueryValueExA( vr_key, "state", NULL, &type, (BYTE *)&value, &size ))) + { + ERR( "Couild not query VR state, status %#lx\n", status ); + break; + } + if (value) break; + while ((wait_result = WaitForSingleObject( event, 1000 )) == WAIT_TIMEOUT) + WARN( "Waiting for VR to become ready\n" ); + + if (wait_result != WAIT_OBJECT_0) + { + ERR( "Wait for VR state change failed\n" ); + break; + } + } + CloseHandle( event ); + } + + if (value != 1) + { + RegCloseKey( vr_key ); + return FALSE; + } + if ((status = RegQueryValueExA( vr_key, "openvr_vulkan_instance_extensions", NULL, &type, NULL, &len ))) + { + ERR( "Could not query openvr vulkan instance extensions, status %#lx\n", status ); + RegCloseKey( vr_key ); + return FALSE; + } + if (!(g_instance_extensions = malloc(len))) + { + RegCloseKey( vr_key ); + return FALSE; + } + + if ((status = RegQueryValueExA( vr_key, "openvr_vulkan_instance_extensions", NULL, &type, + (BYTE *)g_instance_extensions, &len ))) + { + ERR( "Error getting openvr_vulkan_instance_extensions, status %#lx.\n", status ); + RegCloseKey( vr_key ); + return FALSE; + } + + RegCloseKey( vr_key ); + return TRUE; +} + static BOOL array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) { SIZE_T max_capacity, new_capacity; @@ -107,7 +194,7 @@ struct w_iface *create_win_interface( const char *name, struct u_iface u_iface ) return NULL; } -static int load_vrclient(void) +static int load_vrclient( BOOL initializing_registry ) { struct vrclient_init_params params = {.winevulkan = LoadLibraryW( L"winevulkan.dll" )}; WCHAR pathW[PATH_MAX]; @@ -123,6 +210,12 @@ static int load_vrclient(void) if (vrclient_loaded) return 1; + if (!(initializing_registry || get_vulkan_extensions_from_registry())) + { + TRACE( "Error getting extensions from registry.\n" ); + return 0; + } + /* PROTON_VR_RUNTIME is provided by the proton setup script */ if(!GetEnvironmentVariableW(L"PROTON_VR_RUNTIME", pathW, ARRAY_SIZE(pathW))) { @@ -184,7 +277,7 @@ void * __stdcall HmdSystemFactory(const char *name, int *return_code) { struct vrclient_HmdSystemFactory_params params = {.name = name, .return_code = return_code}; TRACE("name: %s, return_code: %p\n", name, return_code); - if (!load_vrclient()) return NULL; + if (!load_vrclient( FALSE )) return NULL; VRCLIENT_CALL( vrclient_HmdSystemFactory, ¶ms ); return create_win_interface( name, params._ret ); } @@ -193,7 +286,7 @@ void * __stdcall VRClientCoreFactory(const char *name, int *return_code) { struct vrclient_VRClientCoreFactory_params params = {.name = name, .return_code = return_code}; TRACE("name: %s, return_code: %p\n", name, return_code); - if (!load_vrclient()) return NULL; + if (!load_vrclient( FALSE )) return NULL; VRCLIENT_CALL( vrclient_VRClientCoreFactory, ¶ms ); return create_win_interface( name, params._ret ); } @@ -288,7 +381,7 @@ BOOL CDECL vrclient_init_registry(void) return FALSE; } - if (!load_vrclient()) + if (!load_vrclient( TRUE )) { TRACE( "Failed to load vrclient\n" ); set_vr_status( vr_key, -1 ); diff --git a/vrclient_x64/vrclient_private.h b/vrclient_x64/vrclient_private.h index 134f0614..9099a263 100644 --- a/vrclient_x64/vrclient_private.h +++ b/vrclient_x64/vrclient_private.h @@ -112,6 +112,8 @@ struct generic_interface void (*dtor)(struct w_iface *); }; +extern char *g_instance_extensions; + #ifdef __dxvk_interop_h__ extern w_Texture_t vrclient_translate_texture_dxvk( const w_Texture_t *texture, w_VRVulkanTextureData_t *vkdata, IDXGIVkInteropSurface *dxvk_surface, IDXGIVkInteropDevice **p_dxvk_device, diff --git a/vrclient_x64/vrsystem_manual.c b/vrclient_x64/vrsystem_manual.c index 7ff045b4..a45c31b8 100644 --- a/vrclient_x64/vrsystem_manual.c +++ b/vrclient_x64/vrsystem_manual.c @@ -3,57 +3,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(vrclient); -static BOOL wait_vr_key_ready( HKEY vr_key ) -{ - DWORD type, value, size = sizeof(value), wait_result; - LSTATUS status; - HANDLE event; - BOOL ret; - - if ((status = RegQueryValueExA(vr_key, "state", NULL, &type, (BYTE *)&value, &size))) - { - ERR("Could not query VR state, status %lx\n", status); - return FALSE; - } - if (type != REG_DWORD) - { - ERR("Invalid VR state type: %lx\n", type); - return FALSE; - } - if (value) return value == 1; - - event = CreateEventA(NULL, FALSE, FALSE, NULL); - ret = FALSE; - while (1) - { - if (RegNotifyChangeKeyValue(vr_key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, event, TRUE)) - { - ERR("Error registering VR key change notification"); - break; - } - size = sizeof(value); - if ((status = RegQueryValueExA(vr_key, "state", NULL, &type, (BYTE *)&value, &size))) - { - ERR("Couild not query VR state, status %lx\n", status); - break; - } - if (value) - { - ret = value == 1; - break; - } - while ((wait_result = WaitForSingleObject(event, 1000)) == WAIT_TIMEOUT) - WARN("Waiting for VR to because ready\n"); - if (wait_result != WAIT_OBJECT_0) - { - ERR("Wait for VR state change failed\n"); - break; - } - } - CloseHandle(event); - return ret; -} - VkResult fixup_get_output_device_pre( HMODULE winevulkan, uint32_t *texture_type, VkInstance *instance ) { /* OpenVR IVRSystem::GetOutputDevice requires a VkInstance if textureType is Vulkan, @@ -62,11 +11,9 @@ VkResult fixup_get_output_device_pre( HMODULE winevulkan, uint32_t *texture_type PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; PFN_vkCreateInstance p_vkCreateInstance; const char **instance_extension_list; - DWORD type, len, extension_count = 0; char *instance_extensions, *pos; + DWORD extension_count = 0; VkResult vk_result; - LSTATUS status; - HKEY vr_key; VkInstanceCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, @@ -75,37 +22,13 @@ VkResult fixup_get_output_device_pre( HMODULE winevulkan, uint32_t *texture_type if (*texture_type != TextureType_DirectX && *texture_type != TextureType_DirectX12 && *texture_type != TextureType_DXGISharedHandle) return VK_SUCCESS; + if (!g_instance_extensions) + return VK_ERROR_INITIALIZATION_FAILED; + p_vkGetInstanceProcAddr = (void *)GetProcAddress(winevulkan, "vkGetInstanceProcAddr"); p_vkCreateInstance = (void *)p_vkGetInstanceProcAddr(NULL, "vkCreateInstance"); - if ((status = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\VR", 0, KEY_READ, &vr_key))) - { - ERR("Failed to open OpenVR registry key, status %lx\n", status); - return VK_ERROR_INITIALIZATION_FAILED; - } - if (!wait_vr_key_ready(vr_key)) - { - RegCloseKey(vr_key); - return VK_ERROR_INITIALIZATION_FAILED; - } - - if ((status = RegQueryValueExA(vr_key, "openvr_vulkan_instance_extensions", NULL, &type, NULL, &len))) - { - ERR("Could not query openvr vulkan instance extensions, status %lx\n", status); - RegCloseKey(vr_key); - return VK_ERROR_INITIALIZATION_FAILED; - } - - instance_extensions = calloc(len + 1, 1); - status = RegQueryValueExA(vr_key, "openvr_vulkan_instance_extensions", NULL, &type, (BYTE *)instance_extensions, &len); - RegCloseKey(vr_key); - if (status) - { - ERR("Could not query openvr vulkan instance extensions, status %lx\n", status); - free(instance_extensions); - return VK_ERROR_INITIALIZATION_FAILED; - } - + instance_extensions = strdup(g_instance_extensions); TRACE("Creating VkInstance for IVRSystem::GetOutputDevice\n"); has_get_device_properties2 = strstr(instance_extensions, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) != NULL;