forked from doitsujin/dxvk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[dxvk] Use wineopenxr to apply required OpenXR extensions
- Loading branch information
Showing
6 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
#include "dxvk_instance.h" | ||
#include "dxvk_openxr.h" | ||
|
||
#ifdef __GNUC__ | ||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" | ||
#endif | ||
|
||
using PFN___wineopenxr_GetVulkanInstanceExtensions = int (WINAPI *)(uint32_t, uint32_t *, char *); | ||
using PFN___wineopenxr_GetVulkanDeviceExtensions = int (WINAPI *)(uint32_t, uint32_t *, char *); | ||
|
||
namespace dxvk { | ||
|
||
struct WineXrFunctions { | ||
PFN___wineopenxr_GetVulkanInstanceExtensions __wineopenxr_GetVulkanInstanceExtensions = nullptr; | ||
PFN___wineopenxr_GetVulkanDeviceExtensions __wineopenxr_GetVulkanDeviceExtensions = nullptr; | ||
}; | ||
|
||
WineXrFunctions g_winexrFunctions; | ||
DxvkXrProvider DxvkXrProvider::s_instance; | ||
|
||
DxvkXrProvider:: DxvkXrProvider() { } | ||
|
||
DxvkXrProvider::~DxvkXrProvider() { } | ||
|
||
|
||
std::string_view DxvkXrProvider::getName() { | ||
return "OpenXR"; | ||
} | ||
|
||
|
||
DxvkNameSet DxvkXrProvider::getInstanceExtensions() { | ||
std::lock_guard<std::mutex> lock(m_mutex); | ||
return m_insExtensions; | ||
} | ||
|
||
|
||
DxvkNameSet DxvkXrProvider::getDeviceExtensions(uint32_t adapterId) { | ||
std::lock_guard<std::mutex> lock(m_mutex); | ||
return m_devExtensions; | ||
} | ||
|
||
|
||
void DxvkXrProvider::initInstanceExtensions() { | ||
std::lock_guard<std::mutex> lock(m_mutex); | ||
|
||
if (!m_wineOxr) | ||
m_wineOxr = this->loadLibrary(); | ||
|
||
if (!m_wineOxr || m_initializedInsExt) | ||
return; | ||
|
||
if (!this->loadFunctions()) { | ||
this->shutdown(); | ||
return; | ||
} | ||
|
||
m_insExtensions = this->queryInstanceExtensions(); | ||
m_initializedInsExt = true; | ||
} | ||
|
||
|
||
bool DxvkXrProvider::loadFunctions() { | ||
g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions = | ||
reinterpret_cast<PFN___wineopenxr_GetVulkanInstanceExtensions>(this->getSym("__wineopenxr_GetVulkanInstanceExtensions")); | ||
g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions = | ||
reinterpret_cast<PFN___wineopenxr_GetVulkanDeviceExtensions>(this->getSym("__wineopenxr_GetVulkanDeviceExtensions")); | ||
return g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions != nullptr | ||
&& g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions != nullptr; | ||
} | ||
|
||
|
||
void DxvkXrProvider::initDeviceExtensions(const DxvkInstance* instance) { | ||
std::lock_guard<std::mutex> lock(m_mutex); | ||
|
||
if (!m_wineOxr || m_initializedDevExt) | ||
return; | ||
|
||
m_devExtensions = this->queryDeviceExtensions(); | ||
m_initializedDevExt = true; | ||
|
||
this->shutdown(); | ||
} | ||
|
||
|
||
DxvkNameSet DxvkXrProvider::queryInstanceExtensions() const { | ||
int res; | ||
uint32_t len; | ||
|
||
res = g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions(0, &len, nullptr); | ||
if (res != 0) { | ||
Logger::warn("OpenXR: Unable to get required Vulkan instance extensions size"); | ||
return DxvkNameSet(); | ||
} | ||
|
||
std::vector<char> extensionList(len); | ||
res = g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions(len, &len, &extensionList[0]); | ||
if (res != 0) { | ||
Logger::warn("OpenXR: Unable to get required Vulkan instance extensions"); | ||
return DxvkNameSet(); | ||
} | ||
|
||
return parseExtensionList(std::string(extensionList.data(), len)); | ||
} | ||
|
||
|
||
DxvkNameSet DxvkXrProvider::queryDeviceExtensions() const { | ||
int res; | ||
|
||
uint32_t len; | ||
res = g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions(0, &len, nullptr); | ||
if (res != 0) { | ||
Logger::warn("OpenXR: Unable to get required Vulkan Device extensions size"); | ||
return DxvkNameSet(); | ||
} | ||
|
||
std::vector<char> extensionList(len); | ||
res = g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions(len, &len, &extensionList[0]); | ||
if (res != 0) { | ||
Logger::warn("OpenXR: Unable to get required Vulkan Device extensions"); | ||
return DxvkNameSet(); | ||
} | ||
|
||
return parseExtensionList(std::string(extensionList.data(), len)); | ||
} | ||
|
||
|
||
DxvkNameSet DxvkXrProvider::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; | ||
} | ||
|
||
|
||
void DxvkXrProvider::shutdown() { | ||
if (m_loadedOxrApi) | ||
this->freeLibrary(); | ||
|
||
m_loadedOxrApi = false; | ||
m_wineOxr = nullptr; | ||
} | ||
|
||
|
||
SoHandle DxvkXrProvider::loadLibrary() { | ||
SoHandle handle = nullptr; | ||
if (!(handle = ::GetModuleHandle("wineopenxr.dll"))) { | ||
handle = ::LoadLibrary("wineopenxr.dll"); | ||
m_loadedOxrApi = handle != nullptr; | ||
} | ||
return handle; | ||
} | ||
|
||
|
||
void DxvkXrProvider::freeLibrary() { | ||
::FreeLibrary(m_wineOxr); | ||
} | ||
|
||
|
||
void* DxvkXrProvider::getSym(const char* sym) { | ||
return reinterpret_cast<void*>( | ||
::GetProcAddress(m_wineOxr, sym)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#pragma once | ||
|
||
#include <mutex> | ||
#include <vector> | ||
|
||
#include "dxvk_extension_provider.h" | ||
|
||
#ifdef __WINE__ | ||
using SoHandle = void*; | ||
#else | ||
using SoHandle = HMODULE; | ||
#endif | ||
|
||
namespace dxvk { | ||
|
||
class DxvkInstance; | ||
|
||
/** | ||
* \brief OpenXR instance | ||
* | ||
* Loads OpenXR to provide access to Vulkan extension queries. | ||
*/ | ||
class DxvkXrProvider : public DxvkExtensionProvider { | ||
|
||
public: | ||
|
||
DxvkXrProvider(); | ||
~DxvkXrProvider(); | ||
|
||
std::string_view getName(); | ||
|
||
DxvkNameSet getInstanceExtensions(); | ||
|
||
DxvkNameSet getDeviceExtensions( | ||
uint32_t adapterId); | ||
|
||
void initInstanceExtensions(); | ||
|
||
void initDeviceExtensions( | ||
const DxvkInstance* instance); | ||
|
||
static DxvkXrProvider s_instance; | ||
|
||
private: | ||
|
||
std::mutex m_mutex; | ||
SoHandle m_wineOxr = nullptr; | ||
|
||
bool m_loadedOxrApi = false; | ||
bool m_initializedInsExt = false; | ||
bool m_initializedDevExt = false; | ||
|
||
DxvkNameSet m_insExtensions; | ||
DxvkNameSet m_devExtensions; | ||
|
||
DxvkNameSet queryInstanceExtensions() const; | ||
|
||
DxvkNameSet queryDeviceExtensions() const; | ||
|
||
DxvkNameSet parseExtensionList( | ||
const std::string& str) const; | ||
|
||
bool loadFunctions(); | ||
|
||
void shutdown(); | ||
|
||
SoHandle loadLibrary(); | ||
|
||
void freeLibrary(); | ||
|
||
void* getSym(const char* sym); | ||
|
||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters