diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index a7f78d8d3..45758af32 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 1d7cfc0a9..8281e6901 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 f5eef8d27..a9cfc738a 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 c43e92db5..b07ab52be 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 dce2a9b1b..dc5744700 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 6630d56f6..57589eb6e 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 2877c9934..52440c9ec 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 c1a1ac21a..2f19b3e50 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 9b10b9a22..28aecfe9f 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 c3b3878d4..290266a38 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 706e6cac2..998787324 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 7c96ff059..be21744e9 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 1892febc8..46bf0899f 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 380be82e1..000000000 --- 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 824effafd..000000000 --- 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; - - }; - -}