diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 6e28366b..e1fe0398 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -160,23 +160,27 @@ 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(vk::NameSet::enumerateDeviceExtensions(*m_vki, m_handle)); + extensions->enableExtensions(availableExtensions); if (!extensions->checkSupportStatus()) throw DxvkError("DxvkAdapter: Failed to create device"); - const vk::NameList enabledExtensions = - extensions->getEnabledExtensionNames(); + // Generate list of extensions that we're actually going to use + vk::NameSet enabledExtensionSet = extensions->getEnabledExtensionNames(); + vk::NameList enabledExtensionList = enabledExtensionSet.getNameList(); Logger::info("Enabled device extensions:"); - this->logNameList(enabledExtensions); + this->logNameList(enabledExtensionList); float queuePriority = 1.0f; std::vector queueInfos; - const uint32_t gIndex = this->graphicsQueueFamily(); - const uint32_t pIndex = this->presentQueueFamily(); + uint32_t gIndex = this->graphicsQueueFamily(); + uint32_t pIndex = this->presentQueueFamily(); VkDeviceQueueCreateInfo graphicsQueue; graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; @@ -201,8 +205,8 @@ namespace dxvk { info.pQueueCreateInfos = queueInfos.data(); info.enabledLayerCount = 0; info.ppEnabledLayerNames = nullptr; - info.enabledExtensionCount = enabledExtensions.count(); - info.ppEnabledExtensionNames = enabledExtensions.names(); + info.enabledExtensionCount = enabledExtensionList.count(); + info.ppEnabledExtensionNames = enabledExtensionList.names(); info.pEnabledFeatures = &enabledFeatures; VkDevice device = VK_NULL_HANDLE; diff --git a/src/dxvk/dxvk_extensions.cpp b/src/dxvk/dxvk_extensions.cpp index 6d57c05f..dce2a9b1 100644 --- a/src/dxvk/dxvk_extensions.cpp +++ b/src/dxvk/dxvk_extensions.cpp @@ -47,8 +47,8 @@ namespace dxvk { } - vk::NameList DxvkExtensionList::getEnabledExtensionNames() const { - vk::NameList names; + vk::NameSet DxvkExtensionList::getEnabledExtensionNames() const { + vk::NameSet names; for (auto ext : m_extensions) { if (ext->enabled()) diff --git a/src/dxvk/dxvk_extensions.h b/src/dxvk/dxvk_extensions.h index 2f7da980..f0f63ad3 100644 --- a/src/dxvk/dxvk_extensions.h +++ b/src/dxvk/dxvk_extensions.h @@ -58,7 +58,7 @@ namespace dxvk { * structs for device and instance creation. * \returns Names of enabled Vulkan extensions */ - vk::NameList getEnabledExtensionNames() const; + vk::NameSet getEnabledExtensionNames() const; private: @@ -138,4 +138,15 @@ namespace dxvk { DxvkExtension khrSwapchain = { this, VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtensionType::Required }; }; + /** + * \brief Instance extensions + * + * Lists all Vulkan extensions that are potentially + * used by DXVK if supported by the implementation. + */ + struct DxvkInstanceExtensions : public DxvkExtensionList { + DxvkExtension khrSurface = { this, VK_KHR_SURFACE_EXTENSION_NAME, DxvkExtensionType::Required }; + DxvkExtension khrWin32Surface = { this, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, DxvkExtensionType::Required }; + }; + } \ No newline at end of file diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index 5a817e2e..ca6c0a40 100644 --- a/src/dxvk/dxvk_instance.cpp +++ b/src/dxvk/dxvk_instance.cpp @@ -40,13 +40,25 @@ namespace dxvk { VkInstance DxvkInstance::createInstance() { - auto enabledLayers = this->getLayers(); - auto enabledExtensions = this->getExtensions(enabledLayers); + auto enabledLayers = this->getLayers(); + + // Query available extensions and enable the ones that are needed + vk::NameSet availableExtensions = vk::NameSet::enumerateInstanceExtensions(*m_vkl, enabledLayers); + + DxvkInstanceExtensions extensionsToEnable; + extensionsToEnable.enableExtensions(availableExtensions); + + if (!extensionsToEnable.checkSupportStatus()) + throw DxvkError("DxvkInstance: Failed to create instance"); + + // Generate list of extensions that we're actually going to use + vk::NameSet enabledExtensionSet = extensionsToEnable.getEnabledExtensionNames(); + vk::NameList enabledExtensionList = enabledExtensionSet.getNameList(); Logger::info("Enabled instance layers:"); this->logNameList(enabledLayers); Logger::info("Enabled instance extensions:"); - this->logNameList(enabledExtensions); + this->logNameList(enabledExtensionList); VkApplicationInfo appInfo; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -64,8 +76,8 @@ namespace dxvk { info.pApplicationInfo = &appInfo; info.enabledLayerCount = enabledLayers.count(); info.ppEnabledLayerNames = enabledLayers.names(); - info.enabledExtensionCount = enabledExtensions.count(); - info.ppEnabledExtensionNames = enabledExtensions.names(); + info.enabledExtensionCount = enabledExtensionList.count(); + info.ppEnabledExtensionNames = enabledExtensionList.names(); VkInstance result = VK_NULL_HANDLE; if (m_vkl->vkCreateInstance(&info, nullptr, &result) != VK_SUCCESS) @@ -95,32 +107,6 @@ namespace dxvk { } - vk::NameList DxvkInstance::getExtensions(const vk::NameList& layers) { - std::vector extOptional = { }; - std::vector extRequired = { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_WIN32_SURFACE_EXTENSION_NAME, - }; - - const vk::NameSet extensionsAvailable - = vk::NameSet::enumerateInstanceExtensions(*m_vkl, layers); - vk::NameList extensionsEnabled; - - for (auto e : extOptional) { - if (extensionsAvailable.contains(e)) - extensionsEnabled.add(e); - } - - for (auto e : extRequired) { - if (!extensionsAvailable.contains(e)) - throw DxvkError(str::format("DxvkInstance::getExtensions: Extension ", e, " not supported")); - extensionsEnabled.add(e); - } - - return extensionsEnabled; - } - - void DxvkInstance::logNameList(const vk::NameList& 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 5d640390..0a0842d5 100644 --- a/src/dxvk/dxvk_instance.h +++ b/src/dxvk/dxvk_instance.h @@ -49,7 +49,6 @@ namespace dxvk { VkInstance createInstance(); vk::NameList getLayers(); - vk::NameList getExtensions(const vk::NameList& layers); void logNameList(const vk::NameList& names); diff --git a/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp b/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp index 6f7183ff..b8bdd4c3 100644 --- a/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp +++ b/src/dxvk/vulkan/dxvk_vulkan_extensions.cpp @@ -73,4 +73,12 @@ namespace dxvk::vk { this->add(ext.extensionName); } + + 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 index 6708b86d..2dd7b7ec 100644 --- a/src/dxvk/vulkan/dxvk_vulkan_extensions.h +++ b/src/dxvk/vulkan/dxvk_vulkan_extensions.h @@ -96,6 +96,16 @@ namespace dxvk::vk { 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::unordered_set m_names;