From 22bb4391ba73000ff01948a34b198caa11039abc Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 11 Jul 2018 15:31:35 +0200 Subject: [PATCH] [vr] Load OpenVR API DLL if necessary Some games initialize the DXGI factory and D3D11 device even before loading the OpenVR DLL, so we have to be even more invasive. --- src/dxvk/dxvk_openvr.cpp | 42 +++++++++++++++++++++++++++++----------- src/dxvk/dxvk_openvr.h | 4 ++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/dxvk/dxvk_openvr.cpp b/src/dxvk/dxvk_openvr.cpp index 7b77923c..706e6cac 100644 --- a/src/dxvk/dxvk_openvr.cpp +++ b/src/dxvk/dxvk_openvr.cpp @@ -67,10 +67,8 @@ namespace dxvk { instance->enumAdapters(i)->handle())); } - if (m_initializedOpenVr) - g_vrFunctions.shutdownInternal(); - m_initializedDevExt = true; + this->shutdown(); } @@ -104,18 +102,29 @@ namespace dxvk { vr::IVRCompositor* VrInstance::getCompositor() { - // Locate the OpenVR DLL if loaded by the process - HMODULE ovrApi = ::GetModuleHandle("openvr_api.dll"); + // Skip OpenVR initialization if requested + if (env::getEnvVar(L"DXVK_NO_VR") == "1") + return nullptr; - if (ovrApi == nullptr) { + // Locate the OpenVR DLL if loaded by the process. Some + // applications may not have OpenVR loaded at the time + // they create the DXGI instance, so we try our own DLL. + m_ovrApi = ::GetModuleHandle("openvr_api.dll"); + + if (m_ovrApi == nullptr) { + m_ovrApi = ::LoadLibrary("openvr_api_dxvk.dll"); + m_loadedOvrApi = m_ovrApi != nullptr; + } + + if (m_ovrApi == nullptr) { Logger::warn("OpenVR: Failed to locate module"); return nullptr; } // Load method used to retrieve the IVRCompositor interface - g_vrFunctions.initInternal = reinterpret_cast (::GetProcAddress(ovrApi, "VR_InitInternal")); - g_vrFunctions.shutdownInternal = reinterpret_cast (::GetProcAddress(ovrApi, "VR_ShutdownInternal")); - g_vrFunctions.getGenericInterface = reinterpret_cast(::GetProcAddress(ovrApi, "VR_GetGenericInterface")); + g_vrFunctions.initInternal = reinterpret_cast (::GetProcAddress(m_ovrApi, "VR_InitInternal")); + g_vrFunctions.shutdownInternal = reinterpret_cast (::GetProcAddress(m_ovrApi, "VR_ShutdownInternal")); + g_vrFunctions.getGenericInterface = reinterpret_cast(::GetProcAddress(m_ovrApi, "VR_GetGenericInterface")); if (g_vrFunctions.getGenericInterface == nullptr) { Logger::warn("OpenVR: VR_GetGenericInterface not found"); @@ -150,8 +159,7 @@ namespace dxvk { if (error != vr::VRInitError_None || compositor == nullptr) { Logger::warn("OpenVR: Failed to query compositor interface"); - g_vrFunctions.shutdownInternal(); - m_initializedOpenVr = false; + this->shutdown(); return nullptr; } } @@ -159,5 +167,17 @@ namespace dxvk { Logger::info("OpenVR: Compositor interface found"); return compositor; } + + + void VrInstance::shutdown() { + if (m_initializedOpenVr) + g_vrFunctions.shutdownInternal(); + + if (m_loadedOvrApi) + ::FreeLibrary(m_ovrApi); + + m_initializedOpenVr = false; + m_loadedOvrApi = false; + } } \ No newline at end of file diff --git a/src/dxvk/dxvk_openvr.h b/src/dxvk/dxvk_openvr.h index 2d33aa3f..7c96ff05 100644 --- a/src/dxvk/dxvk_openvr.h +++ b/src/dxvk/dxvk_openvr.h @@ -66,7 +66,9 @@ namespace dxvk { std::mutex m_mutex; vr::IVRCompositor* m_compositor = nullptr; + HMODULE m_ovrApi = nullptr; + bool m_loadedOvrApi = false; bool m_initializedOpenVr = false; bool m_initializedInsExt = false; bool m_initializedDevExt = false; @@ -83,6 +85,8 @@ namespace dxvk { const std::string& str) const; vr::IVRCompositor* getCompositor(); + + void shutdown(); };