1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00
OpenDX/src/dxvk/dxvk_openvr.cpp
Philip Rebohle 656cb2e4aa
[dxvk] Refactor Vulkan extension management
Adding an extension will now require an additional step, but
this evolved version of the extension list code is more sane
and the structures can be more easily copied around.
2018-07-23 20:07:21 +02:00

183 lines
5.7 KiB
C++

#include "dxvk_instance.h"
#include "dxvk_openvr.h"
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
#include <openvr/openvr.hpp>
using VR_InitInternalProc = vr::IVRSystem* (VR_CALLTYPE *)(vr::EVRInitError*, vr::EVRApplicationType);
using VR_ShutdownInternalProc = void (VR_CALLTYPE *)();
using VR_GetGenericInterfaceProc = void* (VR_CALLTYPE *)(const char*, vr::EVRInitError*);
namespace dxvk {
struct VrFunctions {
VR_InitInternalProc initInternal = nullptr;
VR_ShutdownInternalProc shutdownInternal = nullptr;
VR_GetGenericInterfaceProc getGenericInterface = nullptr;
};
VrFunctions g_vrFunctions;
VrInstance g_vrInstance;
VrInstance:: VrInstance() { }
VrInstance::~VrInstance() { }
DxvkNameSet VrInstance::getInstanceExtensions() {
std::lock_guard<std::mutex> lock(m_mutex);
return m_insExtensions;
}
DxvkNameSet VrInstance::getDeviceExtensions(uint32_t adapterId) {
std::lock_guard<std::mutex> lock(m_mutex);
if (adapterId < m_devExtensions.size())
return m_devExtensions[adapterId];
return DxvkNameSet();
}
void VrInstance::initInstanceExtensions() {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_compositor == nullptr)
m_compositor = this->getCompositor();
if (m_compositor == nullptr || m_initializedInsExt)
return;
m_insExtensions = this->queryInstanceExtensions();
m_initializedInsExt = true;
}
void VrInstance::initDeviceExtensions(const DxvkInstance* instance) {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_compositor == nullptr || m_initializedDevExt)
return;
for (uint32_t i = 0; instance->enumAdapters(i) != nullptr; i++) {
m_devExtensions.push_back(this->queryDeviceExtensions(
instance->enumAdapters(i)->handle()));
}
m_initializedDevExt = true;
this->shutdown();
}
DxvkNameSet VrInstance::queryInstanceExtensions() const {
uint32_t len = m_compositor->GetVulkanInstanceExtensionsRequired(nullptr, 0);
std::vector<char> extensionList(len);
len = m_compositor->GetVulkanInstanceExtensionsRequired(extensionList.data(), len);
return parseExtensionList(std::string(extensionList.data(), len));
}
DxvkNameSet VrInstance::queryDeviceExtensions(VkPhysicalDevice adapter) const {
uint32_t len = m_compositor->GetVulkanDeviceExtensionsRequired(adapter, nullptr, 0);
std::vector<char> extensionList(len);
len = m_compositor->GetVulkanDeviceExtensionsRequired(adapter, extensionList.data(), len);
return parseExtensionList(std::string(extensionList.data(), len));
}
DxvkNameSet VrInstance::parseExtensionList(const std::string& str) const {
DxvkNameSet result;
std::stringstream strstream(str);
std::string section;
while (std::getline(strstream, section, ' '))
result.add(section.c_str());
return result;
}
vr::IVRCompositor* VrInstance::getCompositor() {
// Skip OpenVR initialization if requested
if (env::getEnvVar(L"DXVK_NO_VR") == "1")
return 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<VR_InitInternalProc> (::GetProcAddress(m_ovrApi, "VR_InitInternal"));
g_vrFunctions.shutdownInternal = reinterpret_cast<VR_ShutdownInternalProc> (::GetProcAddress(m_ovrApi, "VR_ShutdownInternal"));
g_vrFunctions.getGenericInterface = reinterpret_cast<VR_GetGenericInterfaceProc>(::GetProcAddress(m_ovrApi, "VR_GetGenericInterface"));
if (g_vrFunctions.getGenericInterface == nullptr) {
Logger::warn("OpenVR: VR_GetGenericInterface not found");
return nullptr;
}
// Retrieve the compositor interface
vr::EVRInitError error = vr::VRInitError_None;
vr::IVRCompositor* compositor = reinterpret_cast<vr::IVRCompositor*>(
g_vrFunctions.getGenericInterface(vr::IVRCompositor_Version, &error));
if (error != vr::VRInitError_None || compositor == nullptr) {
if (g_vrFunctions.initInternal == nullptr
|| g_vrFunctions.shutdownInternal == nullptr) {
Logger::warn("OpenVR: VR_InitInternal or VR_ShutdownInternal not found");
return nullptr;
}
// If the app has not initialized OpenVR yet, we need
// to do it now in order to grab a compositor instance
g_vrFunctions.initInternal(&error, vr::VRApplication_Background);
m_initializedOpenVr = error == vr::VRInitError_None;
if (error != vr::VRInitError_None) {
Logger::warn("OpenVR: Failed to initialize OpenVR");
return nullptr;
}
compositor = reinterpret_cast<vr::IVRCompositor*>(
g_vrFunctions.getGenericInterface(vr::IVRCompositor_Version, &error));
if (error != vr::VRInitError_None || compositor == nullptr) {
Logger::warn("OpenVR: Failed to query compositor interface");
this->shutdown();
return nullptr;
}
}
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;
}
}