From de5be2f1bb85e88798f1026033268b6dc51b9c9b Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 3 Dec 2024 21:52:52 -0800 Subject: [PATCH] [dxvk] Support getting device create info without creating device --- src/dxvk/dxvk_adapter.cpp | 70 +++++++++++++++++++++++++-------------- src/dxvk/dxvk_adapter.h | 42 +++++++++++++++++++++-- 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index b40115c2cca..46de66c1f08 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -272,16 +272,21 @@ namespace dxvk { } - Rc DxvkAdapter::createDevice( - const Rc& instance, - DxvkDeviceFeatures enabledFeatures) { - DxvkDeviceExtensions devExtensions; + bool DxvkAdapter::getDeviceCreateInfo( + const Rc& instance, + VkDeviceCreateInfo& info, + DxvkDeviceFeatures& enabledFeatures, + DxvkDeviceCreateExtInfo& extInfo, + DxvkDeviceCreateQueueInfo& queueInfo) const { + auto& [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo; + auto& [queueFamilies, queueInfos] = queueInfo; + auto devExtensionList = getExtensionList(devExtensions); // Only enable Cuda interop extensions in 64-bit builds in // order to avoid potential driver or address space issues. // VK_KHR_buffer_device_address is expensive on some drivers. - bool enableCudaInterop = !env::is32BitHostPlatform() && + enableCudaInterop = !env::is32BitHostPlatform() && m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) && m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()) && m_deviceFeatures.vk12.bufferDeviceAddress; @@ -298,17 +303,15 @@ namespace dxvk { if (!m_deviceExtensions.supports(devExtensions.extPageableDeviceLocalMemory.name())) devExtensions.amdMemoryOverallocationBehaviour.setMode(DxvkExtMode::Optional); - DxvkNameSet extensionsEnabled; - if (!m_deviceExtensions.enableExtensions( devExtensionList.size(), devExtensionList.data(), &extensionsEnabled)) - throw DxvkError("DxvkAdapter: Failed to create device"); + return false; // Enable additional extensions if necessary extensionsEnabled.merge(m_extraExtensions); - DxvkNameList extensionNameList = extensionsEnabled.toNameList(); + extensionNameList = extensionsEnabled.toNameList(); // Always enable robust buffer access enabledFeatures.core.features.robustBufferAccess = VK_TRUE; @@ -443,34 +446,22 @@ namespace dxvk { // Create pNext chain for additional device features initFeatureChain(enabledFeatures, devExtensions, instance->extensions()); - // Log feature support info an extension list - Logger::info(str::format("Device properties:" - "\n Device : ", m_deviceInfo.core.properties.deviceName, - "\n Driver : ", m_deviceInfo.vk12.driverName, " ", m_deviceInfo.driverVersion.toString())); - - Logger::info("Enabled device extensions:"); - this->logNameList(extensionNameList); - this->logFeatures(enabledFeatures); - // Report the desired overallocation behaviour to the driver VkDeviceMemoryOverallocationCreateInfoAMD overallocInfo = { VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD }; overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD; // Create the requested queues - float queuePriority = 1.0f; - std::vector queueInfos; + static const float queuePriority = 1.0f; std::unordered_set queueFamiliySet; - DxvkAdapterQueueIndices queueFamilies = findQueueFamilies(); + queueFamilies = findQueueFamilies(); queueFamiliySet.insert(queueFamilies.graphics); queueFamiliySet.insert(queueFamilies.transfer); if (queueFamilies.sparse != VK_QUEUE_FAMILY_IGNORED) queueFamiliySet.insert(queueFamilies.sparse); - this->logQueueFamilies(queueFamilies); - for (uint32_t family : queueFamiliySet) { VkDeviceQueueCreateInfo graphicsQueue = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; graphicsQueue.queueFamilyIndex = family; @@ -479,7 +470,8 @@ namespace dxvk { queueInfos.push_back(graphicsQueue); } - VkDeviceCreateInfo info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, enabledFeatures.core.pNext }; + info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + info.pNext = enabledFeatures.core.pNext; info.queueCreateInfoCount = queueInfos.size(); info.pQueueCreateInfos = queueInfos.data(); info.enabledExtensionCount = extensionNameList.count(); @@ -489,6 +481,34 @@ namespace dxvk { if (devExtensions.amdMemoryOverallocationBehaviour) overallocInfo.pNext = std::exchange(info.pNext, &overallocInfo); + return true; + } + + Rc DxvkAdapter::createDevice( + const Rc& instance, + DxvkDeviceFeatures enabledFeatures) { + VkDeviceCreateInfo info; + DxvkDeviceCreateExtInfo extInfo; + DxvkDeviceCreateQueueInfo queueInfo; + + // Get device creation info + if (!getDeviceCreateInfo(instance, info, enabledFeatures, extInfo, queueInfo)) + throw DxvkError("DxvkAdapter: Failed to create device"); + + auto& [devExtensions, extensionsEnabled, extensionNameList, enableCudaInterop] = extInfo; + auto& [queueFamilies, queueInfos] = queueInfo; + + // Log feature support info, extension list, and queue families + Logger::info(str::format("Device properties:" + "\n Device : ", m_deviceInfo.core.properties.deviceName, + "\n Driver : ", m_deviceInfo.vk12.driverName, " ", m_deviceInfo.driverVersion.toString())); + + Logger::info("Enabled device extensions:"); + this->logNameList(extensionNameList); + this->logFeatures(enabledFeatures); + this->logQueueFamilies(queueFamilies); + + // Create device! VkDevice device = VK_NULL_HANDLE; VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device); @@ -998,7 +1018,7 @@ namespace dxvk { std::vector DxvkAdapter::getExtensionList( - DxvkDeviceExtensions& devExtensions) { + DxvkDeviceExtensions& devExtensions) const { return {{ &devExtensions.amdMemoryOverallocationBehaviour, &devExtensions.amdShaderFragmentMask, diff --git a/src/dxvk/dxvk_adapter.h b/src/dxvk/dxvk_adapter.h index a1f77d08688..e95f1308028 100644 --- a/src/dxvk/dxvk_adapter.h +++ b/src/dxvk/dxvk_adapter.h @@ -70,6 +70,24 @@ namespace dxvk { }; + /** + * \brief Device creation extension info + */ + struct DxvkDeviceCreateExtInfo { + DxvkDeviceExtensions deviceExtensions; + DxvkNameSet extensionsEnabled; + DxvkNameList extensionNameList; + bool enableCudaInterop; + }; + + /** + * \brief Device creation queue info + */ + struct DxvkDeviceCreateQueueInfo { + DxvkAdapterQueueIndices queueFamilies; + std::vector queueInfos; + }; + /** * \brief Device import info */ @@ -218,12 +236,32 @@ namespace dxvk { void enableExtensions( const DxvkNameSet& extensions); + /** + * \brief Gets DXVK device creation info + * + * Gets device creation info required for DXVK + * to function based on enabledFeatures + * + * \param [in] instance Parent instance + * \param [out] info Device create info + * \param [in,out] enabledFeatures Device features + * \param [out] extInfo Device extension list + * \param [out] queueInfo Device queue list + * \returns true if succeeded + */ + bool getDeviceCreateInfo( + const Rc& instance, + VkDeviceCreateInfo& info, + DxvkDeviceFeatures& enabledFeatures, + DxvkDeviceCreateExtInfo& extInfo, + DxvkDeviceCreateQueueInfo& queueInfo) const; + /** * \brief Creates a DXVK device * * Creates a logical device for this adapter. * \param [in] instance Parent instance - * \param [in] enabledFeatures Device features + * \param [in] requestedFeatures Device features * \returns Device handle */ Rc createDevice( @@ -349,7 +387,7 @@ namespace dxvk { VkQueueFlags flags) const; std::vector getExtensionList( - DxvkDeviceExtensions& devExtensions); + DxvkDeviceExtensions& devExtensions) const; static void initFeatureChain( DxvkDeviceFeatures& enabledFeatures,