diff options
Diffstat (limited to 'src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_adapter.cpp')
-rw-r--r-- | src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_adapter.cpp | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_adapter.cpp b/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_adapter.cpp new file mode 100644 index 00000000..9db50ae4 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_adapter.cpp @@ -0,0 +1,802 @@ +#include <cstring> +#include <unordered_set> + +#include "dxvk_adapter.h" +#include "dxvk_device.h" +#include "dxvk_instance.h" + +namespace dxvk { + + DxvkAdapter::DxvkAdapter( + const Rc<vk::InstanceFn>& vki, + VkPhysicalDevice handle) + : m_vki (vki), + m_handle (handle) { + this->initHeapAllocInfo(); + this->queryExtensions(); + this->queryDeviceInfo(); + this->queryDeviceFeatures(); + this->queryDeviceQueues(); + + m_hasMemoryBudget = m_deviceExtensions.supports(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); + } + + + DxvkAdapter::~DxvkAdapter() { + + } + + + DxvkAdapterMemoryInfo DxvkAdapter::getMemoryHeapInfo() const { + VkPhysicalDeviceMemoryBudgetPropertiesEXT memBudget = { }; + memBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; + memBudget.pNext = nullptr; + + VkPhysicalDeviceMemoryProperties2 memProps = { }; + memProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; + memProps.pNext = m_hasMemoryBudget ? &memBudget : nullptr; + + m_vki->vkGetPhysicalDeviceMemoryProperties2(m_handle, &memProps); + + DxvkAdapterMemoryInfo info = { }; + info.heapCount = memProps.memoryProperties.memoryHeapCount; + + for (uint32_t i = 0; i < info.heapCount; i++) { + info.heaps[i].heapFlags = memProps.memoryProperties.memoryHeaps[i].flags; + + if (m_hasMemoryBudget) { + info.heaps[i].memoryBudget = memBudget.heapBudget[i]; + info.heaps[i].memoryAllocated = memBudget.heapUsage[i]; + } else { + info.heaps[i].memoryBudget = memProps.memoryProperties.memoryHeaps[i].size; + info.heaps[i].memoryAllocated = m_heapAlloc[i].load(); + } + } + + return info; + } + + + VkPhysicalDeviceMemoryProperties DxvkAdapter::memoryProperties() const { + VkPhysicalDeviceMemoryProperties memoryProperties; + m_vki->vkGetPhysicalDeviceMemoryProperties(m_handle, &memoryProperties); + return memoryProperties; + } + + + VkFormatProperties DxvkAdapter::formatProperties(VkFormat format) const { + VkFormatProperties formatProperties; + m_vki->vkGetPhysicalDeviceFormatProperties(m_handle, format, &formatProperties); + return formatProperties; + } + + + VkResult DxvkAdapter::imageFormatProperties( + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkImageFormatProperties& properties) const { + return m_vki->vkGetPhysicalDeviceImageFormatProperties( + m_handle, format, type, tiling, usage, flags, &properties); + } + + + DxvkAdapterQueueIndices DxvkAdapter::findQueueFamilies() const { + uint32_t graphicsQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); + + uint32_t computeQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, + VK_QUEUE_COMPUTE_BIT); + + if (computeQueue == VK_QUEUE_FAMILY_IGNORED) + computeQueue = graphicsQueue; + + uint32_t transferQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, + VK_QUEUE_TRANSFER_BIT); + + if (transferQueue == VK_QUEUE_FAMILY_IGNORED) + transferQueue = computeQueue; + + DxvkAdapterQueueIndices queues; + queues.graphics = graphicsQueue; + queues.transfer = transferQueue; + return queues; + } + + + bool DxvkAdapter::checkFeatureSupport(const DxvkDeviceFeatures& required) const { + return (m_deviceFeatures.core.features.robustBufferAccess + || !required.core.features.robustBufferAccess) + && (m_deviceFeatures.core.features.fullDrawIndexUint32 + || !required.core.features.fullDrawIndexUint32) + && (m_deviceFeatures.core.features.imageCubeArray + || !required.core.features.imageCubeArray) + && (m_deviceFeatures.core.features.independentBlend + || !required.core.features.independentBlend) + && (m_deviceFeatures.core.features.geometryShader + || !required.core.features.geometryShader) + && (m_deviceFeatures.core.features.tessellationShader + || !required.core.features.tessellationShader) + && (m_deviceFeatures.core.features.sampleRateShading + || !required.core.features.sampleRateShading) + && (m_deviceFeatures.core.features.dualSrcBlend + || !required.core.features.dualSrcBlend) + && (m_deviceFeatures.core.features.logicOp + || !required.core.features.logicOp) + && (m_deviceFeatures.core.features.multiDrawIndirect + || !required.core.features.multiDrawIndirect) + && (m_deviceFeatures.core.features.drawIndirectFirstInstance + || !required.core.features.drawIndirectFirstInstance) + && (m_deviceFeatures.core.features.depthClamp + || !required.core.features.depthClamp) + && (m_deviceFeatures.core.features.depthBiasClamp + || !required.core.features.depthBiasClamp) + && (m_deviceFeatures.core.features.fillModeNonSolid + || !required.core.features.fillModeNonSolid) + && (m_deviceFeatures.core.features.depthBounds + || !required.core.features.depthBounds) + && (m_deviceFeatures.core.features.wideLines + || !required.core.features.wideLines) + && (m_deviceFeatures.core.features.largePoints + || !required.core.features.largePoints) + && (m_deviceFeatures.core.features.alphaToOne + || !required.core.features.alphaToOne) + && (m_deviceFeatures.core.features.multiViewport + || !required.core.features.multiViewport) + && (m_deviceFeatures.core.features.samplerAnisotropy + || !required.core.features.samplerAnisotropy) + && (m_deviceFeatures.core.features.textureCompressionETC2 + || !required.core.features.textureCompressionETC2) + && (m_deviceFeatures.core.features.textureCompressionASTC_LDR + || !required.core.features.textureCompressionASTC_LDR) + && (m_deviceFeatures.core.features.textureCompressionBC + || !required.core.features.textureCompressionBC) + && (m_deviceFeatures.core.features.occlusionQueryPrecise + || !required.core.features.occlusionQueryPrecise) + && (m_deviceFeatures.core.features.pipelineStatisticsQuery + || !required.core.features.pipelineStatisticsQuery) + && (m_deviceFeatures.core.features.vertexPipelineStoresAndAtomics + || !required.core.features.vertexPipelineStoresAndAtomics) + && (m_deviceFeatures.core.features.fragmentStoresAndAtomics + || !required.core.features.fragmentStoresAndAtomics) + && (m_deviceFeatures.core.features.shaderTessellationAndGeometryPointSize + || !required.core.features.shaderTessellationAndGeometryPointSize) + && (m_deviceFeatures.core.features.shaderImageGatherExtended + || !required.core.features.shaderImageGatherExtended) + && (m_deviceFeatures.core.features.shaderStorageImageExtendedFormats + || !required.core.features.shaderStorageImageExtendedFormats) + && (m_deviceFeatures.core.features.shaderStorageImageMultisample + || !required.core.features.shaderStorageImageMultisample) + && (m_deviceFeatures.core.features.shaderStorageImageReadWithoutFormat + || !required.core.features.shaderStorageImageReadWithoutFormat) + && (m_deviceFeatures.core.features.shaderStorageImageWriteWithoutFormat + || !required.core.features.shaderStorageImageWriteWithoutFormat) + && (m_deviceFeatures.core.features.shaderUniformBufferArrayDynamicIndexing + || !required.core.features.shaderUniformBufferArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderSampledImageArrayDynamicIndexing + || !required.core.features.shaderSampledImageArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderStorageBufferArrayDynamicIndexing + || !required.core.features.shaderStorageBufferArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderStorageImageArrayDynamicIndexing + || !required.core.features.shaderStorageImageArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderClipDistance + || !required.core.features.shaderClipDistance) + && (m_deviceFeatures.core.features.shaderCullDistance + || !required.core.features.shaderCullDistance) + && (m_deviceFeatures.core.features.shaderFloat64 + || !required.core.features.shaderFloat64) + && (m_deviceFeatures.core.features.shaderInt64 + || !required.core.features.shaderInt64) + && (m_deviceFeatures.core.features.shaderInt16 + || !required.core.features.shaderInt16) + && (m_deviceFeatures.core.features.shaderResourceResidency + || !required.core.features.shaderResourceResidency) + && (m_deviceFeatures.core.features.shaderResourceMinLod + || !required.core.features.shaderResourceMinLod) + && (m_deviceFeatures.core.features.sparseBinding + || !required.core.features.sparseBinding) + && (m_deviceFeatures.core.features.sparseResidencyBuffer + || !required.core.features.sparseResidencyBuffer) + && (m_deviceFeatures.core.features.sparseResidencyImage2D + || !required.core.features.sparseResidencyImage2D) + && (m_deviceFeatures.core.features.sparseResidencyImage3D + || !required.core.features.sparseResidencyImage3D) + && (m_deviceFeatures.core.features.sparseResidency2Samples + || !required.core.features.sparseResidency2Samples) + && (m_deviceFeatures.core.features.sparseResidency4Samples + || !required.core.features.sparseResidency4Samples) + && (m_deviceFeatures.core.features.sparseResidency8Samples + || !required.core.features.sparseResidency8Samples) + && (m_deviceFeatures.core.features.sparseResidency16Samples + || !required.core.features.sparseResidency16Samples) + && (m_deviceFeatures.core.features.sparseResidencyAliased + || !required.core.features.sparseResidencyAliased) + && (m_deviceFeatures.core.features.variableMultisampleRate + || !required.core.features.variableMultisampleRate) + && (m_deviceFeatures.core.features.inheritedQueries + || !required.core.features.inheritedQueries) + && (m_deviceFeatures.shaderDrawParameters.shaderDrawParameters + || !required.shaderDrawParameters.shaderDrawParameters) + && (m_deviceFeatures.ext4444Formats.formatA4R4G4B4 + || !required.ext4444Formats.formatA4R4G4B4) + && (m_deviceFeatures.ext4444Formats.formatA4B4G4R4 + || !required.ext4444Formats.formatA4B4G4R4) + && (m_deviceFeatures.extCustomBorderColor.customBorderColors + || !required.extCustomBorderColor.customBorderColors) + && (m_deviceFeatures.extCustomBorderColor.customBorderColorWithoutFormat + || !required.extCustomBorderColor.customBorderColorWithoutFormat) + && (m_deviceFeatures.extDepthClipEnable.depthClipEnable + || !required.extDepthClipEnable.depthClipEnable) + && (m_deviceFeatures.extExtendedDynamicState.extendedDynamicState + || !required.extExtendedDynamicState.extendedDynamicState) + && (m_deviceFeatures.extHostQueryReset.hostQueryReset + || !required.extHostQueryReset.hostQueryReset) + && (m_deviceFeatures.extMemoryPriority.memoryPriority + || !required.extMemoryPriority.memoryPriority) + && (m_deviceFeatures.extRobustness2.robustBufferAccess2 + || !required.extRobustness2.robustBufferAccess2) + && (m_deviceFeatures.extRobustness2.robustImageAccess2 + || !required.extRobustness2.robustImageAccess2) + && (m_deviceFeatures.extRobustness2.nullDescriptor + || !required.extRobustness2.nullDescriptor) + && (m_deviceFeatures.extTransformFeedback.transformFeedback + || !required.extTransformFeedback.transformFeedback) + && (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor + || !required.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor) + && (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor + || !required.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor); + } + + + void DxvkAdapter::enableExtensions(const DxvkNameSet& extensions) { + m_extraExtensions.merge(extensions); + } + + + Rc<DxvkDevice> DxvkAdapter::createDevice( + const Rc<DxvkInstance>& instance, + DxvkDeviceFeatures enabledFeatures) { + DxvkDeviceExtensions devExtensions; + + std::array<DxvkExt*, 28> devExtensionList = {{ + &devExtensions.amdMemoryOverallocationBehaviour, + &devExtensions.amdShaderFragmentMask, + &devExtensions.ext4444Formats, + &devExtensions.extConservativeRasterization, + &devExtensions.extCustomBorderColor, + &devExtensions.extDepthClipEnable, + &devExtensions.extExtendedDynamicState, + &devExtensions.extFullScreenExclusive, + &devExtensions.extHostQueryReset, + &devExtensions.extMemoryBudget, + &devExtensions.extMemoryPriority, + &devExtensions.extRobustness2, + &devExtensions.extShaderDemoteToHelperInvocation, + &devExtensions.extShaderStencilExport, + &devExtensions.extShaderViewportIndexLayer, + &devExtensions.extTransformFeedback, + &devExtensions.extVertexAttributeDivisor, + &devExtensions.khrBufferDeviceAddress, + &devExtensions.khrCreateRenderPass2, + &devExtensions.khrDepthStencilResolve, + &devExtensions.khrDrawIndirectCount, + &devExtensions.khrDriverProperties, + &devExtensions.khrImageFormatList, + &devExtensions.khrSamplerMirrorClampToEdge, + &devExtensions.khrShaderFloatControls, + &devExtensions.khrSwapchain, + &devExtensions.nvxBinaryImport, + &devExtensions.nvxImageViewHandle, + }}; + + // 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() && + m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) && + m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()) && + m_deviceFeatures.khrBufferDeviceAddress.bufferDeviceAddress; + + if (enableCudaInterop) { + devExtensions.nvxBinaryImport.setMode(DxvkExtMode::Optional); + devExtensions.nvxImageViewHandle.setMode(DxvkExtMode::Optional); + devExtensions.khrBufferDeviceAddress.setMode(DxvkExtMode::Optional); + + enabledFeatures.khrBufferDeviceAddress.bufferDeviceAddress = VK_TRUE; + } + + DxvkNameSet extensionsEnabled; + + if (!m_deviceExtensions.enableExtensions( + devExtensionList.size(), + devExtensionList.data(), + extensionsEnabled)) + throw DxvkError("DxvkAdapter: Failed to create device"); + + // Enable additional extensions if necessary + extensionsEnabled.merge(m_extraExtensions); + DxvkNameList extensionNameList = extensionsEnabled.toNameList(); + + // Enable additional device features if supported + enabledFeatures.extExtendedDynamicState.extendedDynamicState = m_deviceFeatures.extExtendedDynamicState.extendedDynamicState; + + enabledFeatures.ext4444Formats.formatA4B4G4R4 = m_deviceFeatures.ext4444Formats.formatA4B4G4R4; + enabledFeatures.ext4444Formats.formatA4R4G4B4 = m_deviceFeatures.ext4444Formats.formatA4R4G4B4; + + Logger::info(str::format("Device properties:" + "\n Device name: : ", m_deviceInfo.core.properties.deviceName, + "\n Driver version : ", + VK_VERSION_MAJOR(m_deviceInfo.core.properties.driverVersion), ".", + VK_VERSION_MINOR(m_deviceInfo.core.properties.driverVersion), ".", + VK_VERSION_PATCH(m_deviceInfo.core.properties.driverVersion))); + + Logger::info("Enabled device extensions:"); + this->logNameList(extensionNameList); + this->logFeatures(enabledFeatures); + + // Create pNext chain for additional device features + enabledFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + enabledFeatures.core.pNext = nullptr; + + enabledFeatures.shaderDrawParameters.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; + enabledFeatures.shaderDrawParameters.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.shaderDrawParameters); + + if (devExtensions.ext4444Formats) { + enabledFeatures.ext4444Formats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT; + enabledFeatures.ext4444Formats.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.ext4444Formats); + } + + if (devExtensions.extCustomBorderColor) { + enabledFeatures.extCustomBorderColor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; + enabledFeatures.extCustomBorderColor.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extCustomBorderColor); + } + + if (devExtensions.extDepthClipEnable) { + enabledFeatures.extDepthClipEnable.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT; + enabledFeatures.extDepthClipEnable.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extDepthClipEnable); + } + + if (devExtensions.extExtendedDynamicState) { + enabledFeatures.extExtendedDynamicState.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; + enabledFeatures.extExtendedDynamicState.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extExtendedDynamicState); + } + + if (devExtensions.extHostQueryReset) { + enabledFeatures.extHostQueryReset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; + enabledFeatures.extHostQueryReset.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extHostQueryReset); + } + + if (devExtensions.extMemoryPriority) { + enabledFeatures.extMemoryPriority.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT; + enabledFeatures.extMemoryPriority.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extMemoryPriority); + } + + if (devExtensions.extShaderDemoteToHelperInvocation) { + enabledFeatures.extShaderDemoteToHelperInvocation.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; + enabledFeatures.extShaderDemoteToHelperInvocation.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extShaderDemoteToHelperInvocation); + } + + if (devExtensions.extRobustness2) { + enabledFeatures.extRobustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + enabledFeatures.extRobustness2.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extRobustness2); + } + + if (devExtensions.extTransformFeedback) { + enabledFeatures.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + enabledFeatures.extTransformFeedback.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extTransformFeedback); + } + + if (devExtensions.extVertexAttributeDivisor.revision() >= 3) { + enabledFeatures.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; + enabledFeatures.extVertexAttributeDivisor.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extVertexAttributeDivisor); + } + + if (devExtensions.khrBufferDeviceAddress) { + enabledFeatures.khrBufferDeviceAddress.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR; + enabledFeatures.khrBufferDeviceAddress.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.khrBufferDeviceAddress); + } + + // Report the desired overallocation behaviour to the driver + VkDeviceMemoryOverallocationCreateInfoAMD overallocInfo; + overallocInfo.sType = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD; + overallocInfo.pNext = nullptr; + overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD; + + // Create the requested queues + float queuePriority = 1.0f; + std::vector<VkDeviceQueueCreateInfo> queueInfos; + + std::unordered_set<uint32_t> queueFamiliySet; + + DxvkAdapterQueueIndices queueFamilies = findQueueFamilies(); + queueFamiliySet.insert(queueFamilies.graphics); + queueFamiliySet.insert(queueFamilies.transfer); + this->logQueueFamilies(queueFamilies); + + for (uint32_t family : queueFamiliySet) { + VkDeviceQueueCreateInfo graphicsQueue; + graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + graphicsQueue.pNext = nullptr; + graphicsQueue.flags = 0; + graphicsQueue.queueFamilyIndex = family; + graphicsQueue.queueCount = 1; + graphicsQueue.pQueuePriorities = &queuePriority; + queueInfos.push_back(graphicsQueue); + } + + VkDeviceCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + info.pNext = enabledFeatures.core.pNext; + info.flags = 0; + info.queueCreateInfoCount = queueInfos.size(); + info.pQueueCreateInfos = queueInfos.data(); + info.enabledLayerCount = 0; + info.ppEnabledLayerNames = nullptr; + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); + info.pEnabledFeatures = &enabledFeatures.core.features; + + if (devExtensions.amdMemoryOverallocationBehaviour) + overallocInfo.pNext = std::exchange(info.pNext, &overallocInfo); + + VkDevice device = VK_NULL_HANDLE; + VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device); + + if (vr != VK_SUCCESS && enableCudaInterop) { + // Enabling certain Vulkan extensions can cause device creation to fail on + // Nvidia drivers if a certain kernel module isn't loaded, but we cannot know + // that in advance since the extensions are reported as supported anyway. + Logger::err("DxvkAdapter: Failed to create device, retrying without CUDA interop extensions"); + + extensionsEnabled.disableExtension(devExtensions.khrBufferDeviceAddress); + extensionsEnabled.disableExtension(devExtensions.nvxBinaryImport); + extensionsEnabled.disableExtension(devExtensions.nvxImageViewHandle); + + enabledFeatures.khrBufferDeviceAddress.bufferDeviceAddress = VK_FALSE; + + vk::removeStructFromPNextChain(&enabledFeatures.core.pNext, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR); + + extensionNameList = extensionsEnabled.toNameList(); + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); + + vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device); + } + + if (vr != VK_SUCCESS) + throw DxvkError("DxvkAdapter: Failed to create device"); + + Rc<DxvkDevice> result = new DxvkDevice(instance, this, + new vk::DeviceFn(true, m_vki->instance(), device), + devExtensions, enabledFeatures); + result->initResources(); + return result; + } + + + void DxvkAdapter::notifyHeapMemoryAlloc( + uint32_t heap, + VkDeviceSize bytes) { + if (!m_hasMemoryBudget) + m_heapAlloc[heap] += bytes; + } + + + void DxvkAdapter::notifyHeapMemoryFree( + uint32_t heap, + VkDeviceSize bytes) { + if (!m_hasMemoryBudget) + m_heapAlloc[heap] -= bytes; + } + + + bool DxvkAdapter::matchesDriver( + DxvkGpuVendor vendor, + VkDriverIdKHR driver, + uint32_t minVer, + uint32_t maxVer) const { + bool driverMatches = m_deviceInfo.khrDeviceDriverProperties.driverID + ? driver == m_deviceInfo.khrDeviceDriverProperties.driverID + : vendor == DxvkGpuVendor(m_deviceInfo.core.properties.vendorID); + + if (minVer) driverMatches &= m_deviceInfo.core.properties.driverVersion >= minVer; + if (maxVer) driverMatches &= m_deviceInfo.core.properties.driverVersion < maxVer; + + return driverMatches; + } + + + void DxvkAdapter::logAdapterInfo() const { + VkPhysicalDeviceProperties deviceInfo = this->deviceProperties(); + VkPhysicalDeviceMemoryProperties memoryInfo = this->memoryProperties(); + + Logger::info(str::format(deviceInfo.deviceName, ":")); + Logger::info(str::format(" Driver: ", + VK_VERSION_MAJOR(deviceInfo.driverVersion), ".", + VK_VERSION_MINOR(deviceInfo.driverVersion), ".", + VK_VERSION_PATCH(deviceInfo.driverVersion))); + Logger::info(str::format(" Vulkan: ", + VK_VERSION_MAJOR(deviceInfo.apiVersion), ".", + VK_VERSION_MINOR(deviceInfo.apiVersion), ".", + VK_VERSION_PATCH(deviceInfo.apiVersion))); + + for (uint32_t i = 0; i < memoryInfo.memoryHeapCount; i++) { + constexpr VkDeviceSize mib = 1024 * 1024; + + Logger::info(str::format(" Memory Heap[", i, "]: ")); + Logger::info(str::format(" Size: ", memoryInfo.memoryHeaps[i].size / mib, " MiB")); + Logger::info(str::format(" Flags: ", "0x", std::hex, memoryInfo.memoryHeaps[i].flags)); + + for (uint32_t j = 0; j < memoryInfo.memoryTypeCount; j++) { + if (memoryInfo.memoryTypes[j].heapIndex == i) { + Logger::info(str::format( + " Memory Type[", j, "]: ", + "Property Flags = ", "0x", std::hex, memoryInfo.memoryTypes[j].propertyFlags)); + } + } + } + } + + + bool DxvkAdapter::isUnifiedMemoryArchitecture() const { + auto memory = this->memoryProperties(); + bool result = true; + + for (uint32_t i = 0; i < memory.memoryHeapCount; i++) + result &= memory.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + + return result; + } + + + void DxvkAdapter::initHeapAllocInfo() { + for (uint32_t i = 0; i < m_heapAlloc.size(); i++) + m_heapAlloc[i] = 0; + } + + + void DxvkAdapter::queryExtensions() { + m_deviceExtensions = DxvkNameSet::enumDeviceExtensions(m_vki, m_handle); + } + + + void DxvkAdapter::queryDeviceInfo() { + m_deviceInfo = DxvkDeviceInfo(); + m_deviceInfo.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + m_deviceInfo.core.pNext = nullptr; + + // Query info now so that we have basic device properties available + m_vki->vkGetPhysicalDeviceProperties2(m_handle, &m_deviceInfo.core); + + m_deviceInfo.coreDeviceId.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; + m_deviceInfo.coreDeviceId.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.coreDeviceId); + + m_deviceInfo.coreSubgroup.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; + m_deviceInfo.coreSubgroup.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.coreSubgroup); + + if (m_deviceExtensions.supports(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME)) { + m_deviceInfo.extConservativeRasterization.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT; + m_deviceInfo.extConservativeRasterization.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extConservativeRasterization); + } + + if (m_deviceExtensions.supports(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME)) { + m_deviceInfo.extCustomBorderColor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT; + m_deviceInfo.extCustomBorderColor.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extCustomBorderColor); + } + + if (m_deviceExtensions.supports(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME)) { + m_deviceInfo.extRobustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT; + m_deviceInfo.extRobustness2.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extRobustness2); + } + + if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) { + m_deviceInfo.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; + m_deviceInfo.extTransformFeedback.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extTransformFeedback); + } + + if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { + m_deviceInfo.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; + m_deviceInfo.extVertexAttributeDivisor.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extVertexAttributeDivisor); + } + + if (m_deviceExtensions.supports(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME)) { + m_deviceInfo.khrDepthStencilResolve.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR; + m_deviceInfo.khrDepthStencilResolve.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrDepthStencilResolve); + } + + if (m_deviceExtensions.supports(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { + m_deviceInfo.khrDeviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; + m_deviceInfo.khrDeviceDriverProperties.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrDeviceDriverProperties); + } + + if (m_deviceExtensions.supports(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME)) { + m_deviceInfo.khrShaderFloatControls.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR; + m_deviceInfo.khrShaderFloatControls.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrShaderFloatControls); + } + + // Query full device properties for all enabled extensions + m_vki->vkGetPhysicalDeviceProperties2(m_handle, &m_deviceInfo.core); + + // Nvidia reports the driver version in a slightly different format + if (DxvkGpuVendor(m_deviceInfo.core.properties.vendorID) == DxvkGpuVendor::Nvidia) { + m_deviceInfo.core.properties.driverVersion = VK_MAKE_VERSION( + VK_VERSION_MAJOR(m_deviceInfo.core.properties.driverVersion), + VK_VERSION_MINOR(m_deviceInfo.core.properties.driverVersion >> 0) >> 2, + VK_VERSION_PATCH(m_deviceInfo.core.properties.driverVersion >> 2) >> 4); + } + } + + + void DxvkAdapter::queryDeviceFeatures() { + m_deviceFeatures = DxvkDeviceFeatures(); + m_deviceFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + m_deviceFeatures.core.pNext = nullptr; + + m_deviceFeatures.shaderDrawParameters.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; + m_deviceFeatures.shaderDrawParameters.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.shaderDrawParameters); + + if (m_deviceExtensions.supports(VK_EXT_4444_FORMATS_EXTENSION_NAME)) { + m_deviceFeatures.ext4444Formats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT; + m_deviceFeatures.ext4444Formats.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.ext4444Formats); + } + + if (m_deviceExtensions.supports(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME)) { + m_deviceFeatures.extCustomBorderColor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; + m_deviceFeatures.extCustomBorderColor.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extCustomBorderColor); + } + + if (m_deviceExtensions.supports(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME)) { + m_deviceFeatures.extDepthClipEnable.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT; + m_deviceFeatures.extDepthClipEnable.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extDepthClipEnable); + } + + if (m_deviceExtensions.supports(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)) { + m_deviceFeatures.extExtendedDynamicState.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; + m_deviceFeatures.extExtendedDynamicState.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extExtendedDynamicState); + } + + if (m_deviceExtensions.supports(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME)) { + m_deviceFeatures.extHostQueryReset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; + m_deviceFeatures.extHostQueryReset.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extHostQueryReset); + } + + if (m_deviceExtensions.supports(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME)) { + m_deviceFeatures.extMemoryPriority.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT; + m_deviceFeatures.extMemoryPriority.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extMemoryPriority); + } + + if (m_deviceExtensions.supports(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME)) { + m_deviceFeatures.extRobustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + m_deviceFeatures.extRobustness2.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extRobustness2); + } + + if (m_deviceExtensions.supports(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)) { + m_deviceFeatures.extShaderDemoteToHelperInvocation.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; + m_deviceFeatures.extShaderDemoteToHelperInvocation.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extShaderDemoteToHelperInvocation); + } + + if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) { + m_deviceFeatures.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + m_deviceFeatures.extTransformFeedback.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extTransformFeedback); + } + + if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) { + m_deviceFeatures.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; + m_deviceFeatures.extVertexAttributeDivisor.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extVertexAttributeDivisor); + } + + if (m_deviceExtensions.supports(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) { + m_deviceFeatures.khrBufferDeviceAddress.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR; + m_deviceFeatures.khrBufferDeviceAddress.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.khrBufferDeviceAddress); + } + + m_vki->vkGetPhysicalDeviceFeatures2(m_handle, &m_deviceFeatures.core); + } + + + void DxvkAdapter::queryDeviceQueues() { + uint32_t numQueueFamilies = 0; + m_vki->vkGetPhysicalDeviceQueueFamilyProperties( + m_handle, &numQueueFamilies, nullptr); + + m_queueFamilies.resize(numQueueFamilies); + m_vki->vkGetPhysicalDeviceQueueFamilyProperties( + m_handle, &numQueueFamilies, m_queueFamilies.data()); + } + + + uint32_t DxvkAdapter::findQueueFamily( + VkQueueFlags mask, + VkQueueFlags flags) const { + for (uint32_t i = 0; i < m_queueFamilies.size(); i++) { + if ((m_queueFamilies[i].queueFlags & mask) == flags) + return i; + } + + return VK_QUEUE_FAMILY_IGNORED; + } + + + void DxvkAdapter::logNameList(const DxvkNameList& names) { + for (uint32_t i = 0; i < names.count(); i++) + Logger::info(str::format(" ", names.name(i))); + } + + + void DxvkAdapter::logFeatures(const DxvkDeviceFeatures& features) { + Logger::info(str::format("Device features:", + "\n robustBufferAccess : ", features.core.features.robustBufferAccess ? "1" : "0", + "\n fullDrawIndexUint32 : ", features.core.features.fullDrawIndexUint32 ? "1" : "0", + "\n imageCubeArray : ", features.core.features.imageCubeArray ? "1" : "0", + "\n independentBlend : ", features.core.features.independentBlend ? "1" : "0", + "\n geometryShader : ", features.core.features.geometryShader ? "1" : "0", + "\n tessellationShader : ", features.core.features.tessellationShader ? "1" : "0", + "\n sampleRateShading : ", features.core.features.sampleRateShading ? "1" : "0", + "\n dualSrcBlend : ", features.core.features.dualSrcBlend ? "1" : "0", + "\n logicOp : ", features.core.features.logicOp ? "1" : "0", + "\n multiDrawIndirect : ", features.core.features.multiDrawIndirect ? "1" : "0", + "\n drawIndirectFirstInstance : ", features.core.features.drawIndirectFirstInstance ? "1" : "0", + "\n depthClamp : ", features.core.features.depthClamp ? "1" : "0", + "\n depthBiasClamp : ", features.core.features.depthBiasClamp ? "1" : "0", + "\n fillModeNonSolid : ", features.core.features.fillModeNonSolid ? "1" : "0", + "\n depthBounds : ", features.core.features.depthBounds ? "1" : "0", + "\n multiViewport : ", features.core.features.multiViewport ? "1" : "0", + "\n samplerAnisotropy : ", features.core.features.samplerAnisotropy ? "1" : "0", + "\n textureCompressionBC : ", features.core.features.textureCompressionBC ? "1" : "0", + "\n occlusionQueryPrecise : ", features.core.features.occlusionQueryPrecise ? "1" : "0", + "\n pipelineStatisticsQuery : ", features.core.features.pipelineStatisticsQuery ? "1" : "0", + "\n vertexPipelineStoresAndAtomics : ", features.core.features.vertexPipelineStoresAndAtomics ? "1" : "0", + "\n fragmentStoresAndAtomics : ", features.core.features.fragmentStoresAndAtomics ? "1" : "0", + "\n shaderImageGatherExtended : ", features.core.features.shaderImageGatherExtended ? "1" : "0", + "\n shaderStorageImageExtendedFormats : ", features.core.features.shaderStorageImageExtendedFormats ? "1" : "0", + "\n shaderStorageImageReadWithoutFormat : ", features.core.features.shaderStorageImageReadWithoutFormat ? "1" : "0", + "\n shaderStorageImageWriteWithoutFormat : ", features.core.features.shaderStorageImageWriteWithoutFormat ? "1" : "0", + "\n shaderClipDistance : ", features.core.features.shaderClipDistance ? "1" : "0", + "\n shaderCullDistance : ", features.core.features.shaderCullDistance ? "1" : "0", + "\n shaderFloat64 : ", features.core.features.shaderFloat64 ? "1" : "0", + "\n shaderInt64 : ", features.core.features.shaderInt64 ? "1" : "0", + "\n variableMultisampleRate : ", features.core.features.variableMultisampleRate ? "1" : "0", + "\n", VK_EXT_4444_FORMATS_EXTENSION_NAME, + "\n formatA4R4G4B4 : ", features.ext4444Formats.formatA4R4G4B4 ? "1" : "0", + "\n formatA4B4G4R4 : ", features.ext4444Formats.formatA4B4G4R4 ? "1" : "0", + "\n", VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, + "\n customBorderColors : ", features.extCustomBorderColor.customBorderColors ? "1" : "0", + "\n customBorderColorWithoutFormat : ", features.extCustomBorderColor.customBorderColorWithoutFormat ? "1" : "0", + "\n", VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, + "\n depthClipEnable : ", features.extDepthClipEnable.depthClipEnable ? "1" : "0", + "\n", VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, + "\n extendedDynamicState : ", features.extExtendedDynamicState.extendedDynamicState ? "1" : "0", + "\n", VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, + "\n hostQueryReset : ", features.extHostQueryReset.hostQueryReset ? "1" : "0", + "\n", VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME, + "\n memoryPriority : ", features.extMemoryPriority.memoryPriority ? "1" : "0", + "\n", VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, + "\n robustBufferAccess2 : ", features.extRobustness2.robustBufferAccess2 ? "1" : "0", + "\n robustImageAccess2 : ", features.extRobustness2.robustImageAccess2 ? "1" : "0", + "\n nullDescriptor : ", features.extRobustness2.nullDescriptor ? "1" : "0", + "\n", VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME, + "\n shaderDemoteToHelperInvocation : ", features.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation ? "1" : "0", + "\n", VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, + "\n transformFeedback : ", features.extTransformFeedback.transformFeedback ? "1" : "0", + "\n geometryStreams : ", features.extTransformFeedback.geometryStreams ? "1" : "0", + "\n", VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, + "\n vertexAttributeInstanceRateDivisor : ", features.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor ? "1" : "0", + "\n vertexAttributeInstanceRateZeroDivisor : ", features.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor ? "1" : "0", + "\n", VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, + "\n bufferDeviceAddress : ", features.khrBufferDeviceAddress.bufferDeviceAddress)); + } + + + void DxvkAdapter::logQueueFamilies(const DxvkAdapterQueueIndices& queues) { + Logger::info(str::format("Queue families:", + "\n Graphics : ", queues.graphics, + "\n Transfer : ", queues.transfer)); + } + +} |