From 656cb2e4aaff8f34513c2bacad4768c6aeb79a08 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 23 Jul 2018 20:07:21 +0200 Subject: [PATCH] [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. --- src/dxvk/dxvk_adapter.cpp | 48 +-- src/dxvk/dxvk_adapter.h | 5 +- src/dxvk/dxvk_device.cpp | 2 +- src/dxvk/dxvk_device.h | 6 +- src/dxvk/dxvk_extensions.cpp | 158 ++++++---- src/dxvk/dxvk_extensions.h | 339 ++++++++++++++------- src/dxvk/dxvk_graphics.cpp | 2 +- src/dxvk/dxvk_include.h | 1 - src/dxvk/dxvk_instance.cpp | 36 ++- src/dxvk/dxvk_instance.h | 2 +- src/dxvk/dxvk_openvr.cpp | 16 +- src/dxvk/dxvk_openvr.h | 14 +- src/dxvk/meson.build | 1 - src/dxvk/vulkan/dxvk_vulkan_extensions.cpp | 63 ---- src/dxvk/vulkan/dxvk_vulkan_extensions.h | 110 ------- 15 files changed, 403 insertions(+), 400 deletions(-) delete mode 100644 src/dxvk/vulkan/dxvk_vulkan_extensions.cpp delete mode 100644 src/dxvk/vulkan/dxvk_vulkan_extensions.h diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index a7f78d8d..45758af3 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -160,23 +160,37 @@ namespace dxvk { Rc DxvkAdapter::createDevice(const VkPhysicalDeviceFeatures& enabledFeatures) { - // Query available extensions and enable the ones that are needed - vk::NameSet availableExtensions = vk::NameSet::enumerateDeviceExtensions(*m_vki, m_handle); - - const Rc extensions = new DxvkDeviceExtensions(); - extensions->enableExtensions(availableExtensions); - - if (!extensions->checkSupportStatus()) + DxvkDeviceExtensions devExtensions; + + std::array devExtensionList = {{ + &devExtensions.extShaderViewportIndexLayer, + &devExtensions.extVertexAttributeDivisor, + &devExtensions.khrDedicatedAllocation, + &devExtensions.khrDescriptorUpdateTemplate, + &devExtensions.khrGetMemoryRequirements2, + &devExtensions.khrImageFormatList, + &devExtensions.khrMaintenance1, + &devExtensions.khrMaintenance2, + &devExtensions.khrSamplerMirrorClampToEdge, + &devExtensions.khrShaderDrawParameters, + &devExtensions.khrSwapchain, + }}; + + DxvkNameSet extensionsEnabled; + DxvkNameSet extensionsAvailable = DxvkNameSet::enumDeviceExtensions(m_vki, m_handle); + + if (!extensionsAvailable.enableExtensions( + devExtensionList.size(), + devExtensionList.data(), + extensionsEnabled)) throw DxvkError("DxvkAdapter: Failed to create device"); - // Generate list of extensions that we're actually going to use - vk::NameSet enabledExtensionSet = extensions->getEnabledExtensionNames(); - enabledExtensionSet.merge(g_vrInstance.getDeviceExtensions(getAdapterIndex())); - - vk::NameList enabledExtensionList = enabledExtensionSet.getNameList(); + // Enable additional extensions if necessary + extensionsEnabled.merge(g_vrInstance.getDeviceExtensions(getAdapterIndex())); + DxvkNameList extensionNameList = extensionsEnabled.toNameList(); Logger::info("Enabled device extensions:"); - this->logNameList(enabledExtensionList); + this->logNameList(extensionNameList); float queuePriority = 1.0f; std::vector queueInfos; @@ -207,8 +221,8 @@ namespace dxvk { info.pQueueCreateInfos = queueInfos.data(); info.enabledLayerCount = 0; info.ppEnabledLayerNames = nullptr; - info.enabledExtensionCount = enabledExtensionList.count(); - info.ppEnabledExtensionNames = enabledExtensionList.names(); + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); info.pEnabledFeatures = &enabledFeatures; VkDevice device = VK_NULL_HANDLE; @@ -218,7 +232,7 @@ namespace dxvk { Rc result = new DxvkDevice(this, new vk::DeviceFn(m_vki->instance(), device), - extensions, enabledFeatures); + devExtensions, enabledFeatures); result->initResources(); return result; } @@ -271,7 +285,7 @@ namespace dxvk { } - void DxvkAdapter::logNameList(const vk::NameList& names) { + void DxvkAdapter::logNameList(const DxvkNameList& names) { for (uint32_t i = 0; i < names.count(); i++) Logger::info(str::format(" ", names.name(i))); } diff --git a/src/dxvk/dxvk_adapter.h b/src/dxvk/dxvk_adapter.h index 1d7cfc0a..8281e690 100644 --- a/src/dxvk/dxvk_adapter.h +++ b/src/dxvk/dxvk_adapter.h @@ -1,7 +1,6 @@ #pragma once -#include "./vulkan/dxvk_vulkan_extensions.h" - +#include "dxvk_extensions.h" #include "dxvk_include.h" namespace dxvk { @@ -171,7 +170,7 @@ namespace dxvk { uint32_t getAdapterIndex() const; - static void logNameList(const vk::NameList& names); + static void logNameList(const DxvkNameList& names); }; diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index f5eef8d2..a9cfc738 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -6,7 +6,7 @@ namespace dxvk { DxvkDevice::DxvkDevice( const Rc& adapter, const Rc& vkd, - const Rc& extensions, + const DxvkDeviceExtensions& extensions, const VkPhysicalDeviceFeatures& features) : m_adapter (adapter), m_vkd (vkd), diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index c43e92db..b07ab52b 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -64,7 +64,7 @@ namespace dxvk { DxvkDevice( const Rc& adapter, const Rc& vkd, - const Rc& extensions, + const DxvkDeviceExtensions& extensions, const VkPhysicalDeviceFeatures& features); ~DxvkDevice(); @@ -112,7 +112,7 @@ namespace dxvk { * \returns Enabled device extensions */ const DxvkDeviceExtensions& extensions() const { - return *m_extensions; + return m_extensions; } /** @@ -373,7 +373,7 @@ namespace dxvk { Rc m_adapter; Rc m_vkd; - Rc m_extensions; + DxvkDeviceExtensions m_extensions; VkPhysicalDeviceFeatures m_features; VkPhysicalDeviceProperties m_properties; diff --git a/src/dxvk/dxvk_extensions.cpp b/src/dxvk/dxvk_extensions.cpp index dce2a9b1..dc574470 100644 --- a/src/dxvk/dxvk_extensions.cpp +++ b/src/dxvk/dxvk_extensions.cpp @@ -2,74 +2,114 @@ namespace dxvk { - DxvkExtensionList:: DxvkExtensionList() { } - DxvkExtensionList::~DxvkExtensionList() { } - - - void DxvkExtensionList::enableExtensions(const vk::NameSet& extensions) { - for (auto ext : m_extensions) { - if (extensions.contains(ext->name())) - ext->setEnabled(true); - } + DxvkNameSet::DxvkNameSet() { } + DxvkNameSet::~DxvkNameSet() { } + + + void DxvkNameSet::add(const char* pName) { + m_names.insert(pName); } - - - bool DxvkExtensionList::checkSupportStatus() { - bool requiredExtensionsEnabled = true; - - for (auto ext : m_extensions) { - if (!ext->enabled()) { - switch (ext->type()) { - case DxvkExtensionType::Optional: - // An optional extension should not have any impact on - // the functionality of an application, so inform the - // user only if verbose debug messages are enabled - Logger::debug(str::format("Optional Vulkan extension ", ext->name(), " not supported")); - break; - - case DxvkExtensionType::Desired: - // If a desired extension is not supported, applications - // should keep working but may exhibit unexpected behaviour, - // so we'll inform the user anyway - Logger::warn(str::format("Vulkan extension ", ext->name(), " not supported")); - break; - - case DxvkExtensionType::Required: - // Do not exit early so we can catch all unsupported extensions. - requiredExtensionsEnabled = false; - Logger::err(str::format("Required Vulkan extension ", ext->name(), " not supported")); - break; + + + void DxvkNameSet::merge(const DxvkNameSet& names) { + for (const std::string& name : names.m_names) + m_names.insert(name); + } + + + bool DxvkNameSet::supports(const char* pName) const { + return m_names.find(pName) != m_names.end(); + } + + + bool DxvkNameSet::enableExtensions( + uint32_t numExtensions, + DxvkExt** ppExtensions, + DxvkNameSet& nameSet) const { + bool allRequiredEnabled = true; + + for (uint32_t i = 0; i < numExtensions; i++) { + DxvkExt* ext = ppExtensions[i]; + + if (ext->mode() != DxvkExtMode::Disabled) { + bool supported = supports(ext->name()); + + if (supported) { + nameSet.add(ext->name()); + ext->enable(); + } else if (ext->mode() == DxvkExtMode::Required) { + Logger::info(str::format( + "Required Vulkan extension ", ext->name(), " not supported")); + allRequiredEnabled = false; } } } + + return allRequiredEnabled; + } + + + DxvkNameList DxvkNameSet::toNameList() const { + DxvkNameList nameList; + for (const std::string& name : m_names) + nameList.add(name.c_str()); + return nameList; + } + + + DxvkNameSet DxvkNameSet::enumInstanceLayers(const Rc& vkl) { + uint32_t entryCount = 0; + if (vkl->vkEnumerateInstanceLayerProperties( + &entryCount, nullptr) != VK_SUCCESS) + return DxvkNameSet(); - return requiredExtensionsEnabled; + std::vector entries(entryCount); + if (vkl->vkEnumerateInstanceLayerProperties( + &entryCount, entries.data()) != VK_SUCCESS) + return DxvkNameSet(); + + DxvkNameSet set; + for (uint32_t i = 0; i < entryCount; i++) + set.m_names.insert(entries[i].layerName); + return set; } - - vk::NameSet DxvkExtensionList::getEnabledExtensionNames() const { - vk::NameSet names; + + DxvkNameSet DxvkNameSet::enumInstanceExtensions(const Rc& vkl) { + uint32_t entryCount = 0; + if (vkl->vkEnumerateInstanceExtensionProperties( + nullptr, &entryCount, nullptr) != VK_SUCCESS) + return DxvkNameSet(); - for (auto ext : m_extensions) { - if (ext->enabled()) - names.add(ext->name()); - } + std::vector entries(entryCount); + if (vkl->vkEnumerateInstanceExtensionProperties( + nullptr, &entryCount, entries.data()) != VK_SUCCESS) + return DxvkNameSet(); + + DxvkNameSet set; + for (uint32_t i = 0; i < entryCount; i++) + set.m_names.insert(entries[i].extensionName); + return set; + } + + + DxvkNameSet DxvkNameSet::enumDeviceExtensions( + const Rc& vki, + VkPhysicalDevice device) { + uint32_t entryCount = 0; + if (vki->vkEnumerateDeviceExtensionProperties( + device, nullptr, &entryCount, nullptr) != VK_SUCCESS) + return DxvkNameSet(); - return names; - } - - - void DxvkExtensionList::registerExtension(DxvkExtension* extension) { - m_extensions.push_back(extension); - } - - - DxvkExtension::DxvkExtension( - DxvkExtensionList* parent, - const char* name, - DxvkExtensionType type) - : m_name(name), m_type(type), m_enabled(false) { - parent->registerExtension(this); + std::vector entries(entryCount); + if (vki->vkEnumerateDeviceExtensionProperties( + device, nullptr, &entryCount, entries.data()) != VK_SUCCESS) + return DxvkNameSet(); + + DxvkNameSet set; + for (uint32_t i = 0; i < entryCount; i++) + set.m_names.insert(entries[i].extensionName); + return set; } } \ No newline at end of file diff --git a/src/dxvk/dxvk_extensions.h b/src/dxvk/dxvk_extensions.h index 6630d56f..57589eb6 100644 --- a/src/dxvk/dxvk_extensions.h +++ b/src/dxvk/dxvk_extensions.h @@ -1,91 +1,40 @@ #pragma once +#include + #include "dxvk_include.h" namespace dxvk { - // Forward declarations - class DxvkExtension; - class DxvkExtensionList; - /** - * \brief Extension type - */ - enum class DxvkExtensionType { - Optional, ///< Nothing will happen if not supported - Desired, ///< A warning will be issued if not supported - Required, ///< Device creation will fail if not supported - }; - - /** - * \brief Vulkan extension list + * \brief Vulkan extension mode * - * Convenience class to manage a set of extensions - * which can be either required or optional. + * Defines whether an extension is + * optional, required, or disabled. */ - class DxvkExtensionList : public RcObject { - friend class DxvkExtension; - public: - - DxvkExtensionList(); - ~DxvkExtensionList(); - - DxvkExtensionList (const DxvkExtensionList&) = delete; - DxvkExtensionList& operator = (const DxvkExtensionList&) = delete; - - /** - * \brief Enables Vulkan extensions - * - * Marks all extension in the list as enabled. - * \param [in] extensions Supported extensions - */ - void enableExtensions( - const vk::NameSet& extensions); - - /** - * \brief Checks extension support status - * - * Checks whether all required extensions are present - * and logs the name of any unsupported extension. - * \returns \c true if required extensions are present - */ - bool checkSupportStatus(); - - /** - * \brief Creates a list of enabled extensions - * - * The resulting list can be fed into the Vulkan - * structs for device and instance creation. - * \returns Names of enabled Vulkan extensions - */ - vk::NameSet getEnabledExtensionNames() const; - - private: - - std::vector m_extensions; - - void registerExtension(DxvkExtension* extension); - + enum class DxvkExtMode { + Disabled, + Optional, + Required, }; - + + /** - * \brief Extension class + * \brief Vulkan extension info * - * Stores the name, type and support - * status of a single Vulkan extension. + * Stores information for a single extension. + * The renderer can use this information to + * find out which extensions are enabled. */ - class DxvkExtension { - friend class DxvkExtensionList; + class DxvkExt { + public: - - DxvkExtension( - DxvkExtensionList* parent, - const char* name, - DxvkExtensionType type); - - DxvkExtension (const DxvkExtension&) = delete; - DxvkExtension& operator = (const DxvkExtension&) = delete; - + + DxvkExt( + const char* pName, + DxvkExtMode mode) + : m_name(pName), m_mode(mode) { } + /** * \brief Extension name * \returns Extension name @@ -93,53 +42,223 @@ namespace dxvk { const char* name() const { return m_name; } - + /** - * \brief Extension type - * \returns Extension type + * \brief Extension mode + * \returns Extension mode */ - DxvkExtensionType type() const { - return m_type; + DxvkExtMode mode() const { + return m_mode; } - + /** - * \brief Extension support status - * \returns \c true if supported + * \brief Checks whether the extension is enabled + * + * If an extension is enabled, the features + * provided by the extension can be used. + * \returns \c true if the extension is enabled */ - bool enabled() const { + operator bool () const { return m_enabled; } - - private: - - const char* m_name; - DxvkExtensionType m_type; - bool m_enabled; - - void setEnabled(bool enabled) { - m_enabled = enabled; + + /** + * \brief Changes extension mode + * + * In some cases, it may be useful to change the + * default mode dynamically after initialization. + */ + void setMode(DxvkExtMode mode) { + m_mode = mode; } - + + /** + * \brief Enables the extension + */ + void enable() { + m_enabled = true; + } + + private: + + const char* m_name = nullptr; + DxvkExtMode m_mode = DxvkExtMode::Disabled; + bool m_enabled = false; + }; - + + + /** + * \brief Vulkan name list + * + * A simple \c vector wrapper that can + * be used to build a list of layer and + * extension names. + */ + class DxvkNameList { + + public: + + /** + * \brief Adds a name + * \param [in] pName The name + */ + void add(const char* pName) { + m_names.push_back(pName); + } + + /** + * \brief Number of names + * \returns Name count + */ + uint32_t count() const { + return m_names.size(); + } + + /** + * \brief Name list + * \returns Name list + */ + const char* const* names() const { + return m_names.data(); + } + + /** + * \brief Retrieves a single name + * + * \param [in] index Name index + * \returns The given name + */ + const char* name(uint32_t index) const { + return m_names.at(index); + } + + private: + + std::vector m_names; + + }; + + + /** + * \brief Vulkan extension set + * + * Stores a set of extensions or layers + * supported by the Vulkan implementation. + */ + class DxvkNameSet { + + public: + + DxvkNameSet(); + ~DxvkNameSet(); + + /** + * \brief Adds a name to the set + * \param [in] pName Extension name + */ + void add( + const char* pName); + + /** + * \brief Merges two name sets + * + * Adds all names from the given name set to + * this name set, avoiding duplicate entries. + * \param [in] names Name set to merge + */ + void merge( + const DxvkNameSet& names); + + /** + * \brief Checks whether an extension is supported + * + * \param [in] pName Extension name + * \returns \c true if the extension is supported + */ + bool supports( + const char* pName) const; + + /** + * \brief Enables requested extensions + * + * Walks over a set of extensions and enables all + * extensions that are supported and not disabled. + * This also checks whether all required extensions + * could be enabled, and returns \c false otherwise. + * \param [in] numExtensions Number of extensions + * \param [in] ppExtensions List of extensions + * \param [out] nameSet Extension name set + * \returns \c true on success + */ + bool enableExtensions( + uint32_t numExtensions, + DxvkExt** ppExtensions, + DxvkNameSet& nameSet) const; + + /** + * \brief Creates name list from name set + * + * Adds all names contained in the name set + * to a name list, which can then be passed + * to Vulkan functions. + * \returns Name list + */ + DxvkNameList toNameList() const; + + /** + * \brief Enumerates instance layers + * + * \param [in] vkl Vulkan library functions + * \returns Set of available instance layers + */ + static DxvkNameSet enumInstanceLayers( + const Rc& vkl); + + /** + * \brief Enumerates instance extensions + * + * \param [in] vkl Vulkan library functions + * \returns Set of available instance extensions + */ + static DxvkNameSet enumInstanceExtensions( + const Rc& vkl); + + /** + * \brief Enumerates device extensions + * + * \param [in] vki Vulkan instance functions + * \param [in] device The device to query + * \returns Set of available device extensions + */ + static DxvkNameSet enumDeviceExtensions( + const Rc& vki, + VkPhysicalDevice device); + + private: + + std::set m_names; + + }; + /** * \brief Device extensions * * Lists all Vulkan extensions that are potentially * used by DXVK if supported by the implementation. */ - struct DxvkDeviceExtensions : public DxvkExtensionList { - DxvkExtension extShaderViewportIndexLayer = { this, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, DxvkExtensionType::Desired }; - DxvkExtension extVertexAttributeDivisor = { this, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, DxvkExtensionType::Desired }; - DxvkExtension khrDedicatedAllocation = { this, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrDescriptorUpdateTemplate = { this, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrGetMemoryRequirements2 = { this, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrImageFormatList = { this, VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrMaintenance1 = { this, VK_KHR_MAINTENANCE1_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrMaintenance2 = { this, VK_KHR_MAINTENANCE2_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrSamplerMirrorClampToEdge = { this, VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, DxvkExtensionType::Desired }; - DxvkExtension khrShaderDrawParameters = { this, VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrSwapchain = { this, VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtensionType::Required }; + struct DxvkDeviceExtensions { + DxvkExt extShaderViewportIndexLayer = { VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extVertexAttributeDivisor = { VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrDedicatedAllocation = { VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrDescriptorUpdateTemplate = { VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrGetMemoryRequirements2 = { VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrImageFormatList = { VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrMaintenance1 = { VK_KHR_MAINTENANCE1_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrMaintenance2 = { VK_KHR_MAINTENANCE2_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrSamplerMirrorClampToEdge = { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrShaderDrawParameters = { VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrSwapchain = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtMode::Required }; }; /** @@ -148,10 +267,10 @@ namespace dxvk { * Lists all Vulkan extensions that are potentially * used by DXVK if supported by the implementation. */ - struct DxvkInstanceExtensions : public DxvkExtensionList { - DxvkExtension khrGetPhysicalDeviceProperties2 = { this, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrSurface = { this, VK_KHR_SURFACE_EXTENSION_NAME, DxvkExtensionType::Required }; - DxvkExtension khrWin32Surface = { this, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, DxvkExtensionType::Required }; + struct DxvkInstanceExtensions { + DxvkExt khrGetPhysicalDeviceProperties2 = { VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrSurface = { VK_KHR_SURFACE_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrWin32Surface = { VK_KHR_WIN32_SURFACE_EXTENSION_NAME, DxvkExtMode::Required }; }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 2877c993..52440c9e 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -260,7 +260,7 @@ namespace dxvk { viInfo.pNext = viDivisorInfo.pNext; // TODO remove this once the extension is widely supported - if (!m_device->extensions().extVertexAttributeDivisor.enabled()) + if (!m_device->extensions().extVertexAttributeDivisor) viInfo.pNext = viDivisorInfo.pNext; VkPipelineInputAssemblyStateCreateInfo iaInfo; diff --git a/src/dxvk/dxvk_include.h b/src/dxvk/dxvk_include.h index c1a1ac21..2f19b3e5 100644 --- a/src/dxvk/dxvk_include.h +++ b/src/dxvk/dxvk_include.h @@ -16,6 +16,5 @@ #include "../util/sync/sync_spinlock.h" -#include "./vulkan/dxvk_vulkan_extensions.h" #include "./vulkan/dxvk_vulkan_loader.h" #include "./vulkan/dxvk_vulkan_names.h" diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index 9b10b9a2..28aecfe9 100644 --- a/src/dxvk/dxvk_instance.cpp +++ b/src/dxvk/dxvk_instance.cpp @@ -34,23 +34,29 @@ namespace dxvk { VkInstance DxvkInstance::createInstance() { - // Query available extensions and enable the ones that are needed - vk::NameSet availableExtensions = vk::NameSet::enumerateInstanceExtensions(*m_vkl); + DxvkInstanceExtensions insExtensions; + + std::array insExtensionList = {{ + &insExtensions.khrGetPhysicalDeviceProperties2, + &insExtensions.khrSurface, + &insExtensions.khrWin32Surface, + }}; + + DxvkNameSet extensionsEnabled; + DxvkNameSet extensionsAvailable = DxvkNameSet::enumInstanceExtensions(m_vkl); - DxvkInstanceExtensions extensionsToEnable; - extensionsToEnable.enableExtensions(availableExtensions); - - if (!extensionsToEnable.checkSupportStatus()) + if (!extensionsAvailable.enableExtensions( + insExtensionList.size(), + insExtensionList.data(), + extensionsEnabled)) throw DxvkError("DxvkInstance: Failed to create instance"); - // Generate list of extensions that we're actually going to use - vk::NameSet enabledExtensionSet = extensionsToEnable.getEnabledExtensionNames(); - enabledExtensionSet.merge(g_vrInstance.getInstanceExtensions()); - - vk::NameList enabledExtensionList = enabledExtensionSet.getNameList(); + // Enable additional extensions if necessary + extensionsEnabled.merge(g_vrInstance.getInstanceExtensions()); + DxvkNameList extensionNameList = extensionsEnabled.toNameList(); Logger::info("Enabled instance extensions:"); - this->logNameList(enabledExtensionList); + this->logNameList(extensionNameList); VkApplicationInfo appInfo; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -68,8 +74,8 @@ namespace dxvk { info.pApplicationInfo = &appInfo; info.enabledLayerCount = 0; info.ppEnabledLayerNames = nullptr; - info.enabledExtensionCount = enabledExtensionList.count(); - info.ppEnabledExtensionNames = enabledExtensionList.names(); + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); VkInstance result = VK_NULL_HANDLE; if (m_vkl->vkCreateInstance(&info, nullptr, &result) != VK_SUCCESS) @@ -101,7 +107,7 @@ namespace dxvk { } - void DxvkInstance::logNameList(const vk::NameList& names) { + void DxvkInstance::logNameList(const DxvkNameList& names) { for (uint32_t i = 0; i < names.count(); i++) Logger::info(str::format(" ", names.name(i))); } diff --git a/src/dxvk/dxvk_instance.h b/src/dxvk/dxvk_instance.h index c3b3878d..290266a3 100644 --- a/src/dxvk/dxvk_instance.h +++ b/src/dxvk/dxvk_instance.h @@ -56,7 +56,7 @@ namespace dxvk { std::vector> queryAdapters(); - static void logNameList(const vk::NameList& names); + static void logNameList(const DxvkNameList& names); }; diff --git a/src/dxvk/dxvk_openvr.cpp b/src/dxvk/dxvk_openvr.cpp index 706e6cac..99878732 100644 --- a/src/dxvk/dxvk_openvr.cpp +++ b/src/dxvk/dxvk_openvr.cpp @@ -26,19 +26,19 @@ namespace dxvk { VrInstance::~VrInstance() { } - vk::NameSet VrInstance::getInstanceExtensions() { + DxvkNameSet VrInstance::getInstanceExtensions() { std::lock_guard lock(m_mutex); return m_insExtensions; } - vk::NameSet VrInstance::getDeviceExtensions(uint32_t adapterId) { + DxvkNameSet VrInstance::getDeviceExtensions(uint32_t adapterId) { std::lock_guard lock(m_mutex); if (adapterId < m_devExtensions.size()) return m_devExtensions[adapterId]; - return vk::NameSet(); + return DxvkNameSet(); } @@ -72,7 +72,7 @@ namespace dxvk { } - vk::NameSet VrInstance::queryInstanceExtensions() const { + DxvkNameSet VrInstance::queryInstanceExtensions() const { uint32_t len = m_compositor->GetVulkanInstanceExtensionsRequired(nullptr, 0); std::vector extensionList(len); len = m_compositor->GetVulkanInstanceExtensionsRequired(extensionList.data(), len); @@ -80,7 +80,7 @@ namespace dxvk { } - vk::NameSet VrInstance::queryDeviceExtensions(VkPhysicalDevice adapter) const { + DxvkNameSet VrInstance::queryDeviceExtensions(VkPhysicalDevice adapter) const { uint32_t len = m_compositor->GetVulkanDeviceExtensionsRequired(adapter, nullptr, 0); std::vector extensionList(len); len = m_compositor->GetVulkanDeviceExtensionsRequired(adapter, extensionList.data(), len); @@ -88,14 +88,14 @@ namespace dxvk { } - vk::NameSet VrInstance::parseExtensionList(const std::string& str) const { - vk::NameSet result; + 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); + result.add(section.c_str()); return result; } diff --git a/src/dxvk/dxvk_openvr.h b/src/dxvk/dxvk_openvr.h index 7c96ff05..be21744e 100644 --- a/src/dxvk/dxvk_openvr.h +++ b/src/dxvk/dxvk_openvr.h @@ -31,7 +31,7 @@ namespace dxvk { * \brief Query instance extensions * \returns Instance extensions */ - vk::NameSet getInstanceExtensions(); + DxvkNameSet getInstanceExtensions(); /** * \brief Query device extensions @@ -41,7 +41,7 @@ namespace dxvk { * the same across multiple Vulkan instances. * \param [in] adapterId Adapter index */ - vk::NameSet getDeviceExtensions( + DxvkNameSet getDeviceExtensions( uint32_t adapterId); /** @@ -73,15 +73,15 @@ namespace dxvk { bool m_initializedInsExt = false; bool m_initializedDevExt = false; - vk::NameSet m_insExtensions; - std::vector m_devExtensions; + DxvkNameSet m_insExtensions; + std::vector m_devExtensions; - vk::NameSet queryInstanceExtensions() const; + DxvkNameSet queryInstanceExtensions() const; - vk::NameSet queryDeviceExtensions( + DxvkNameSet queryDeviceExtensions( VkPhysicalDevice adapter) const; - vk::NameSet parseExtensionList( + DxvkNameSet parseExtensionList( const std::string& str) const; vr::IVRCompositor* getCompositor(); diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index 1892febc..46bf0899 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -85,7 +85,6 @@ dxvk_src = files([ 'hud/dxvk_hud_renderer.cpp', 'hud/dxvk_hud_stats.cpp', - 'vulkan/dxvk_vulkan_extensions.cpp', 'vulkan/dxvk_vulkan_loader.cpp', 'vulkan/dxvk_vulkan_names.cpp', ]) diff --git a/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp b/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp deleted file mode 100644 index 380be82e..00000000 --- a/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "dxvk_vulkan_extensions.h" - -namespace dxvk::vk { - - void NameSet::add(const std::string& name) { - m_names.insert(name); - } - - - void NameSet::merge(const NameSet& other) { - for (const auto& entry : other.m_names) - this->add(entry); - } - - - bool NameSet::contains(const std::string& name) const { - return m_names.find(name) != m_names.end(); - } - - - NameSet NameSet::enumerateInstanceExtensions( - const LibraryFn& vkl) { - uint32_t extCount = 0; - if (vkl.vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr) != VK_SUCCESS) - throw DxvkError("ExtensionSet::addInstanceExtensions: Failed to query instance extensions"); - - std::vector extensions(extCount); - if (vkl.vkEnumerateInstanceExtensionProperties(nullptr, &extCount, extensions.data()) != VK_SUCCESS) - throw DxvkError("ExtensionSet::addInstanceExtensions: Failed to query instance extensions"); - - NameSet result; - for (const auto& ext : extensions) - result.add(ext.extensionName); - return result; - } - - - NameSet NameSet::enumerateDeviceExtensions( - const InstanceFn& vki, - VkPhysicalDevice device) { - uint32_t extCount = 0; - if (vki.vkEnumerateDeviceExtensionProperties(device, nullptr, &extCount, nullptr) != VK_SUCCESS) - throw DxvkError("ExtensionSet::addDeviceExtensions: Failed to query device extensions"); - - std::vector extensions(extCount); - if (vki.vkEnumerateDeviceExtensionProperties(device, nullptr, &extCount, extensions.data()) != VK_SUCCESS) - throw DxvkError("ExtensionSet::addDeviceExtensions: Failed to query device extensions"); - - NameSet result; - for (const auto& ext : extensions) - result.add(ext.extensionName); - return result; - } - - - NameList NameSet::getNameList() const { - NameList result; - for (const std::string& name : m_names) - result.add(name.c_str()); - return result; - } - -} diff --git a/src/dxvk/vulkan/dxvk_vulkan_extensions.h b/src/dxvk/vulkan/dxvk_vulkan_extensions.h deleted file mode 100644 index 824effaf..00000000 --- a/src/dxvk/vulkan/dxvk_vulkan_extensions.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "dxvk_vulkan_loader.h" - -#include "../../util/util_error.h" -#include "../../util/util_string.h" - -namespace dxvk::vk { - - /** - * \brief Name list - * - * Stores a list of extension or layer names. - * Note that only name constants may be added - * to a name list. Adding dynamically allocated - * strings will result in udefined behaviour. - */ - class NameList { - - public: - - void add(const char* name) { - m_list.push_back(name); - } - - auto name(size_t i) const { - return m_list[i]; - } - - auto names() const { return m_list.data(); } - auto count() const { return m_list.size(); } - - private: - - std::vector m_list; - - }; - - - /** - * \brief Name set - * - * Stores a set of supported layers or extensions and - * provides methods to query their support status. - */ - class NameSet { - - public: - - /** - * \brief Adds an extension to the set - * \param [in] name The extension to add - */ - void add(const std::string& name); - - /** - * \brief Merges two name sets - * \param [in] other Name set to merge - */ - void merge(const NameSet& other); - - /** - * \brief Checks whether an extension or layer is supported - * - * \param [in] name The layer or extension name - * \returns \c true if the entity is supported - */ - bool contains(const std::string& name) const; - - /** - * \brief Enumerates instance extensions - * - * \param [in] vkl Vulkan library functions - * \returns Available instance extensions - */ - static NameSet enumerateInstanceExtensions( - const LibraryFn& vkl); - - /** - * \brief Enumerates device extensions - * - * \param [in] vki Vulkan instance functions - * \param [in] device The physical device - * \returns Available device extensions - */ - static NameSet enumerateDeviceExtensions( - const InstanceFn& vki, - VkPhysicalDevice device); - - /** - * \brief Generates a name list - * - * The pointers to the names will have the same - * lifetime as the name set, and may be invalidated - * by modifications made to the name set. - * \returns Name list - */ - NameList getNameList() const; - - private: - - std::set m_names; - - }; - -}