mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-01 16:24:12 +01:00
[vr] Maintain global extension sets
Preserves the per-instance and per-adapter extension sets across multiple Vulkan instances. Works around initialization order issues with Unity-based VR apps.
This commit is contained in:
parent
eb39cf4b11
commit
0e6e985210
@ -171,7 +171,7 @@ namespace dxvk {
|
||||
|
||||
// Generate list of extensions that we're actually going to use
|
||||
vk::NameSet enabledExtensionSet = extensions->getEnabledExtensionNames();
|
||||
enabledExtensionSet.merge(m_instance->queryExtraDeviceExtensions(this));
|
||||
enabledExtensionSet.merge(g_vrInstance.getDeviceExtensions(getAdapterIndex()));
|
||||
|
||||
vk::NameList enabledExtensionList = enabledExtensionSet.getNameList();
|
||||
|
||||
@ -261,6 +261,16 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxvkAdapter::getAdapterIndex() const {
|
||||
for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++) {
|
||||
if (m_instance->enumAdapters(i).ptr() == this)
|
||||
return i;
|
||||
}
|
||||
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
|
||||
void DxvkAdapter::logNameList(const vk::NameList& names) {
|
||||
for (uint32_t i = 0; i < names.count(); i++)
|
||||
Logger::info(str::format(" ", names.name(i)));
|
||||
|
@ -168,6 +168,8 @@ namespace dxvk {
|
||||
VkPhysicalDevice m_handle;
|
||||
|
||||
std::vector<VkQueueFamilyProperties> m_queueFamilies;
|
||||
|
||||
uint32_t getAdapterIndex() const;
|
||||
|
||||
static void logNameList(const vk::NameList& names);
|
||||
|
||||
|
@ -5,10 +5,14 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkInstance::DxvkInstance()
|
||||
: m_vkl(new vk::LibraryFn()),
|
||||
m_vki(new vk::InstanceFn(this->createInstance())) {
|
||||
this->createAdapters();
|
||||
DxvkInstance::DxvkInstance() {
|
||||
g_vrInstance.initInstanceExtensions();
|
||||
|
||||
m_vkl = new vk::LibraryFn();
|
||||
m_vki = new vk::InstanceFn(this->createInstance());
|
||||
|
||||
m_adapters = this->queryAdapters();
|
||||
g_vrInstance.initDeviceExtensions(this);
|
||||
}
|
||||
|
||||
|
||||
@ -24,11 +28,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
vk::NameSet DxvkInstance::queryExtraDeviceExtensions(const DxvkAdapter* adapter) const {
|
||||
return m_vr.queryDeviceExtensions(adapter->handle());
|
||||
}
|
||||
|
||||
|
||||
VkInstance DxvkInstance::createInstance() {
|
||||
// Query available extensions and enable the ones that are needed
|
||||
vk::NameSet availableExtensions = vk::NameSet::enumerateInstanceExtensions(*m_vkl);
|
||||
@ -41,7 +40,7 @@ namespace dxvk {
|
||||
|
||||
// Generate list of extensions that we're actually going to use
|
||||
vk::NameSet enabledExtensionSet = extensionsToEnable.getEnabledExtensionNames();
|
||||
enabledExtensionSet.merge(m_vr.queryInstanceExtensions());
|
||||
enabledExtensionSet.merge(g_vrInstance.getInstanceExtensions());
|
||||
|
||||
vk::NameList enabledExtensionList = enabledExtensionSet.getNameList();
|
||||
|
||||
@ -74,7 +73,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkInstance::createAdapters() {
|
||||
std::vector<Rc<DxvkAdapter>> DxvkInstance::queryAdapters() {
|
||||
uint32_t numAdapters = 0;
|
||||
if (m_vki->vkEnumeratePhysicalDevices(m_vki->instance(), &numAdapters, nullptr) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkInstance::enumAdapters: Failed to enumerate adapters");
|
||||
@ -83,14 +82,17 @@ namespace dxvk {
|
||||
if (m_vki->vkEnumeratePhysicalDevices(m_vki->instance(), &numAdapters, adapters.data()) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkInstance::enumAdapters: Failed to enumerate adapters");
|
||||
|
||||
std::vector<Rc<DxvkAdapter>> result;
|
||||
for (uint32_t i = 0; i < numAdapters; i++)
|
||||
m_adapters.push_back(new DxvkAdapter(this, adapters[i]));
|
||||
result.push_back(new DxvkAdapter(this, adapters[i]));
|
||||
|
||||
std::sort(m_adapters.begin(), m_adapters.end(),
|
||||
std::sort(result.begin(), result.end(),
|
||||
[this] (const Rc<DxvkAdapter>& a, const Rc<DxvkAdapter>& b) -> bool {
|
||||
return a->deviceProperties().deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||
&& b->deviceProperties().deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,19 +45,8 @@ namespace dxvk {
|
||||
Rc<DxvkAdapter> enumAdapters(
|
||||
uint32_t index) const;
|
||||
|
||||
/**
|
||||
* \brief Queries extra device extensions
|
||||
*
|
||||
* \param [in] adapter The device to query
|
||||
* \returns Extra device extensions
|
||||
*/
|
||||
vk::NameSet queryExtraDeviceExtensions(
|
||||
const DxvkAdapter* adapter) const;
|
||||
|
||||
private:
|
||||
|
||||
VrInstance m_vr;
|
||||
|
||||
Rc<vk::LibraryFn> m_vkl;
|
||||
Rc<vk::InstanceFn> m_vki;
|
||||
|
||||
@ -65,9 +54,9 @@ namespace dxvk {
|
||||
|
||||
VkInstance createInstance();
|
||||
|
||||
void createAdapters();
|
||||
std::vector<Rc<DxvkAdapter>> queryAdapters();
|
||||
|
||||
void logNameList(const vk::NameList& names);
|
||||
static void logNameList(const vk::NameList& names);
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "dxvk_instance.h"
|
||||
#include "dxvk_openvr.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
@ -8,34 +9,77 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
VrInstance::VrInstance()
|
||||
: m_compositor(getCompositor()) {
|
||||
VrInstance g_vrInstance;
|
||||
|
||||
VrInstance:: VrInstance() { }
|
||||
VrInstance::~VrInstance() { }
|
||||
|
||||
|
||||
vk::NameSet VrInstance::getInstanceExtensions() {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_insExtensions;
|
||||
}
|
||||
|
||||
|
||||
vk::NameSet VrInstance::getDeviceExtensions(uint32_t adapterId) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
}
|
||||
|
||||
|
||||
VrInstance::~VrInstance() {
|
||||
if (adapterId < m_devExtensions.size())
|
||||
return m_devExtensions[adapterId];
|
||||
|
||||
return vk::NameSet();
|
||||
}
|
||||
|
||||
|
||||
void VrInstance::initInstanceExtensions() {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_initializedInsExt)
|
||||
return;
|
||||
|
||||
vr::IVRCompositor* compositor = this->getCompositor();
|
||||
|
||||
if (compositor == nullptr)
|
||||
return;
|
||||
|
||||
m_insExtensions = this->queryInstanceExtensions(compositor);
|
||||
m_initializedInsExt = true;
|
||||
}
|
||||
|
||||
|
||||
void VrInstance::initDeviceExtensions(const DxvkInstance* instance) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_initializedDevExt)
|
||||
return;
|
||||
|
||||
vr::IVRCompositor* compositor = this->getCompositor();
|
||||
|
||||
if (compositor == nullptr)
|
||||
return;
|
||||
|
||||
for (uint32_t i = 0; instance->enumAdapters(i) != nullptr; i++) {
|
||||
m_devExtensions.push_back(this->queryDeviceExtensions(
|
||||
compositor, instance->enumAdapters(i)->handle()));
|
||||
}
|
||||
|
||||
m_initializedDevExt = true;
|
||||
}
|
||||
|
||||
|
||||
vk::NameSet VrInstance::queryInstanceExtensions(vr::IVRCompositor* compositor) const {
|
||||
uint32_t len = compositor->GetVulkanInstanceExtensionsRequired(nullptr, 0);
|
||||
std::vector<char> extensionList(len);
|
||||
len = compositor->GetVulkanInstanceExtensionsRequired(extensionList.data(), len);
|
||||
return parseExtensionList(std::string(extensionList.data(), len));
|
||||
}
|
||||
|
||||
|
||||
vk::NameSet VrInstance::queryInstanceExtensions() const {
|
||||
if (m_compositor != nullptr) {
|
||||
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));
|
||||
} return vk::NameSet();
|
||||
}
|
||||
|
||||
|
||||
vk::NameSet VrInstance::queryDeviceExtensions(VkPhysicalDevice adapter) const {
|
||||
if (m_compositor != nullptr) {
|
||||
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));
|
||||
} return vk::NameSet();
|
||||
vk::NameSet VrInstance::queryDeviceExtensions(vr::IVRCompositor* compositor, VkPhysicalDevice adapter) const {
|
||||
uint32_t len = compositor->GetVulkanDeviceExtensionsRequired(adapter, nullptr, 0);
|
||||
std::vector<char> extensionList(len);
|
||||
len = compositor->GetVulkanDeviceExtensionsRequired(adapter, extensionList.data(), len);
|
||||
return parseExtensionList(std::string(extensionList.data(), len));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "dxvk_include.h"
|
||||
|
||||
namespace vr {
|
||||
@ -7,6 +10,8 @@ namespace vr {
|
||||
}
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
class DxvkInstance;
|
||||
|
||||
/**
|
||||
* \brief OpenVR instance
|
||||
@ -20,29 +25,65 @@ namespace dxvk {
|
||||
|
||||
VrInstance();
|
||||
~VrInstance();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Queries required instance extensions
|
||||
* \returns Set of required instance extensions
|
||||
* \brief Query instance extensions
|
||||
* \returns Instance extensions
|
||||
*/
|
||||
vk::NameSet queryInstanceExtensions() const;
|
||||
|
||||
vk::NameSet getInstanceExtensions();
|
||||
|
||||
/**
|
||||
* \brief Queries required device extensions
|
||||
* \brief Query device extensions
|
||||
*
|
||||
* \param [in] adapter The Vulkan device to query
|
||||
* \returns Set of required device extensions
|
||||
* Retrieves the extensions required for a specific
|
||||
* physical device. The adapter index should remain
|
||||
* the same across multiple Vulkan instances.
|
||||
* \param [in] adapterId Adapter index
|
||||
*/
|
||||
vk::NameSet queryDeviceExtensions(VkPhysicalDevice adapter) const;
|
||||
vk::NameSet getDeviceExtensions(
|
||||
uint32_t adapterId);
|
||||
|
||||
/**
|
||||
* \brief Initializes instance extension set
|
||||
*
|
||||
* Should be called before creating
|
||||
* the first Vulkan instance.
|
||||
*/
|
||||
void initInstanceExtensions();
|
||||
|
||||
/**
|
||||
* \brief Initializes device extension sets
|
||||
*
|
||||
* Should be called after setting
|
||||
* up the Vulkan physical devices.
|
||||
* \param [in] instance DXVK instance
|
||||
*/
|
||||
void initDeviceExtensions(
|
||||
const DxvkInstance* instance);
|
||||
|
||||
private:
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
bool m_initializedInsExt = false;
|
||||
bool m_initializedDevExt = false;
|
||||
|
||||
vk::NameSet m_insExtensions;
|
||||
std::vector<vk::NameSet> m_devExtensions;
|
||||
|
||||
vr::IVRCompositor* m_compositor = nullptr;
|
||||
|
||||
vk::NameSet queryInstanceExtensions(
|
||||
vr::IVRCompositor* compositor) const;
|
||||
|
||||
vk::NameSet queryDeviceExtensions(
|
||||
vr::IVRCompositor* compositor,
|
||||
VkPhysicalDevice adapter) const;
|
||||
|
||||
static vk::NameSet parseExtensionList(const std::string& str);
|
||||
|
||||
static vr::IVRCompositor* getCompositor();
|
||||
|
||||
};
|
||||
|
||||
extern VrInstance g_vrInstance;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user