[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:
Philip Rebohle 2018-06-26 15:51:15 +02:00
parent eb39cf4b11
commit 0e6e985210
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
6 changed files with 149 additions and 61 deletions

View File

@ -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)));

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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));
}

View File

@ -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;
}