Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

steam_helper: get OpenXR extensions before initializing OpenVR #7906

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 67 additions & 47 deletions steam_helper/steam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,9 +684,66 @@ static void *get_winevulkan_unix_lib_handle(HMODULE hvulkan)
return dlopen(info.dli_fname, RTLD_NOW);
}


static int WINAPI save_openxr_extensions_to_registry(HKEY vr_key){
int (WINAPI *p__wineopenxr_get_extensions_internal)(char **instance_extensions, char **device_extensions, uint32_t *physdev_vid, uint32_t *physdev_pid);
char *xr_inst_ext, *xr_dev_ext;
HMODULE hwineopenxr;
LSTATUS status;

if ((hwineopenxr = LoadLibraryA("wineopenxr.dll")))
{
p__wineopenxr_get_extensions_internal = reinterpret_cast<decltype(p__wineopenxr_get_extensions_internal)>
(GetProcAddress(hwineopenxr, "__wineopenxr_get_extensions_internal"));
if (p__wineopenxr_get_extensions_internal)
{
uint32_t vid, pid;
if (!p__wineopenxr_get_extensions_internal(&xr_inst_ext, &xr_dev_ext, &vid, &pid))
{
WINE_TRACE("Got XR extensions.\n");
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_instance_extensions", 0, REG_SZ,
(BYTE *)xr_inst_ext, strlen(xr_inst_ext) + 1)))
{
WINE_ERR("Could not set openxr_vulkan_instance_extensions value, status %#x.\n", status);
return STATUS_UNSUCCESSFUL;
}
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_device_extensions", 0, REG_SZ,
(BYTE *)xr_dev_ext, strlen(xr_dev_ext) + 1)))
{
WINE_ERR("Could not set openxr_vulkan_device_extensions value, status %#x.\n", status);
return STATUS_UNSUCCESSFUL;
}
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_device_vid", 0, REG_DWORD,
(BYTE *)&vid, sizeof(vid))))
{
WINE_ERR("Could not set openxr_vulkan_device_vid value, status %#x.\n", status);
return STATUS_UNSUCCESSFUL;
}
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_device_pid", 0, REG_DWORD,
(BYTE *)&pid, sizeof(pid))))
{
WINE_ERR("Could not set openxr_vulkan_device_pid value, status %#x.\n", status);
return STATUS_UNSUCCESSFUL;
}
}
}
else
{
WINE_ERR("__wineopenxr_get_extensions_internal not found in wineopenxr.dll.\n");
return STATUS_UNSUCCESSFUL;
}
FreeLibrary(hwineopenxr);
}
else
{
WINE_WARN("Could not load wineopenxr.dll, err %u.\n", GetLastError());
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}

static DWORD WINAPI initialize_vr_data(void *arg)
{
int (WINAPI *p__wineopenxr_get_extensions_internal)(char **instance_extensions, char **device_extensions, uint32_t *physdev_vid, uint32_t *physdev_pid);
vr::IVRClientCore* (*vrclient_VRClientCoreFactory)(const char *name, int *return_code);
uint32_t instance_extensions_count, device_count;
VkPhysicalDevice *phys_devices = NULL;
Expand All @@ -696,7 +753,6 @@ static DWORD WINAPI initialize_vr_data(void *arg)
VkApplicationInfo app_info = {};
char *buffer = NULL, *new_buffer;
vr::IVRClientCore* client_core;
char *xr_inst_ext, *xr_dev_ext;
vr::IVRCompositor* compositor;
VkInstance vk_instance = NULL;
BOOL vr_initialized = FALSE;
Expand All @@ -707,7 +763,6 @@ static DWORD WINAPI initialize_vr_data(void *arg)
const char *env_str;
unsigned int app_id;
unsigned int length;
HMODULE hwineopenxr;
void *lib_vrclient;
void *unix_handle;
DWORD hmd_present;
Expand All @@ -717,6 +772,7 @@ static DWORD WINAPI initialize_vr_data(void *arg)
VkResult res;

WINE_TRACE("Starting VR info initialization.\n");
int openxr_extension_result = save_openxr_extensions_to_registry(vr_key);

if (!(lib_vrclient = load_vrclient()))
{
Expand Down Expand Up @@ -878,51 +934,15 @@ static DWORD WINAPI initialize_vr_data(void *arg)
}
}

if ((hwineopenxr = LoadLibraryA("wineopenxr.dll")))
{
p__wineopenxr_get_extensions_internal = reinterpret_cast<decltype(p__wineopenxr_get_extensions_internal)>
(GetProcAddress(hwineopenxr, "__wineopenxr_get_extensions_internal"));
if (p__wineopenxr_get_extensions_internal)
{
uint32_t vid, pid;
if (!p__wineopenxr_get_extensions_internal(&xr_inst_ext, &xr_dev_ext, &vid, &pid))
{
WINE_TRACE("Got XR extensions.\n");
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_instance_extensions", 0, REG_SZ,
(BYTE *)xr_inst_ext, strlen(xr_inst_ext) + 1)))
{
WINE_ERR("Could not set openxr_vulkan_instance_extensions value, status %#x.\n", status);
goto done;
}
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_device_extensions", 0, REG_SZ,
(BYTE *)xr_dev_ext, strlen(xr_dev_ext) + 1)))
{
WINE_ERR("Could not set openxr_vulkan_device_extensions value, status %#x.\n", status);
goto done;
}
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_device_vid", 0, REG_DWORD,
(BYTE *)&vid, sizeof(vid))))
{
WINE_ERR("Could not set openxr_vulkan_device_vid value, status %#x.\n", status);
goto done;
}
if ((status = RegSetValueExA(vr_key, "openxr_vulkan_device_pid", 0, REG_DWORD,
(BYTE *)&pid, sizeof(pid))))
{
WINE_ERR("Could not set openxr_vulkan_device_pid value, status %#x.\n", status);
goto done;
}
}
}
else
{
WINE_ERR("__wineopenxr_get_extensions_internal not found in wineopenxr.dll.\n");
/* When SteamVR is used as OpenXR runtime, it needs to be running for
* `save_openxr_extensions_to_registry` to succeed.
* If the previous probe was not sucessful, we can try a second time now. */
if (openxr_extension_result == STATUS_UNSUCCESSFUL) {
WINE_WARN("First attempt to get XR extensions failed. Trying again now that OpenVR is initialized.");
openxr_extension_result = save_openxr_extensions_to_registry(vr_key);
if(openxr_extension_result == STATUS_UNSUCCESSFUL) {
goto done;
}
FreeLibrary(hwineopenxr);
}
else
{
WINE_WARN("Could not load wineopenxr.dll, err %u.\n", GetLastError());
}

vr_status = 1;
Expand Down