dxvk/src/dxvk/dxvk_adapter.cpp

1074 lines
56 KiB
C++

#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 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT };
VkPhysicalDeviceMemoryProperties2 memProps = { 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;
}
DxvkFormatFeatures DxvkAdapter::getFormatFeatures(VkFormat format) const {
VkFormatProperties3 properties3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 };
VkFormatProperties2 properties2 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, &properties3 };
m_vki->vkGetPhysicalDeviceFormatProperties2(m_handle, format, &properties2);
DxvkFormatFeatures result;
result.optimal = properties3.optimalTilingFeatures;
result.linear = properties3.linearTilingFeatures;
result.buffer = properties3.bufferFeatures;
return result;
}
std::optional<DxvkFormatLimits> DxvkAdapter::getFormatLimits(
const DxvkFormatQuery& query) const {
VkPhysicalDeviceExternalImageFormatInfo externalInfo = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO };
externalInfo.handleType = query.handleType;
VkPhysicalDeviceImageFormatInfo2 info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 };
info.format = query.format;
info.type = query.type;
info.tiling = query.tiling;
info.usage = query.usage;
info.flags = query.flags;
if (externalInfo.handleType)
externalInfo.pNext = std::exchange(info.pNext, &externalInfo);
VkExternalImageFormatProperties externalProperties = { VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES };
VkImageFormatProperties2 properties = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 };
if (externalInfo.handleType)
externalProperties.pNext = std::exchange(properties.pNext, &externalProperties);
VkResult vr = m_vki->vkGetPhysicalDeviceImageFormatProperties2(
m_handle, &info, &properties);
if (vr != VK_SUCCESS)
return std::nullopt;
DxvkFormatLimits result = { };
result.maxExtent = properties.imageFormatProperties.maxExtent;
result.maxMipLevels = properties.imageFormatProperties.maxMipLevels;
result.maxArrayLayers = properties.imageFormatProperties.maxArrayLayers;
result.sampleCounts = properties.imageFormatProperties.sampleCounts;
result.maxResourceSize = properties.imageFormatProperties.maxResourceSize;
result.externalFeatures = externalProperties.externalMemoryProperties.externalMemoryFeatures;
return result;
}
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;
uint32_t sparseQueue = VK_QUEUE_FAMILY_IGNORED;
if (m_queueFamilies[graphicsQueue].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
// Prefer using the graphics queue as a sparse binding queue
sparseQueue = graphicsQueue;
} else {
sparseQueue = findQueueFamily(
VK_QUEUE_SPARSE_BINDING_BIT,
VK_QUEUE_SPARSE_BINDING_BIT);
}
DxvkAdapterQueueIndices queues;
queues.graphics = graphicsQueue;
queues.transfer = transferQueue;
queues.sparse = sparseQueue;
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.vk11.shaderDrawParameters
|| !required.vk11.shaderDrawParameters)
&& (m_deviceFeatures.vk12.samplerMirrorClampToEdge
|| !required.vk12.samplerMirrorClampToEdge)
&& (m_deviceFeatures.vk12.drawIndirectCount
|| !required.vk12.drawIndirectCount)
&& (m_deviceFeatures.vk12.hostQueryReset
|| !required.vk12.hostQueryReset)
&& (m_deviceFeatures.vk12.timelineSemaphore
|| !required.vk12.timelineSemaphore)
&& (m_deviceFeatures.vk12.bufferDeviceAddress
|| !required.vk12.bufferDeviceAddress)
&& (m_deviceFeatures.vk12.shaderOutputViewportIndex
|| !required.vk12.shaderOutputViewportIndex)
&& (m_deviceFeatures.vk12.shaderOutputLayer
|| !required.vk12.shaderOutputLayer)
&& (m_deviceFeatures.vk13.pipelineCreationCacheControl
|| !required.vk13.pipelineCreationCacheControl)
&& (m_deviceFeatures.vk13.shaderDemoteToHelperInvocation
|| !required.vk13.shaderDemoteToHelperInvocation)
&& (m_deviceFeatures.vk13.shaderZeroInitializeWorkgroupMemory
|| !required.vk13.shaderZeroInitializeWorkgroupMemory)
&& (m_deviceFeatures.vk13.synchronization2
|| !required.vk13.synchronization2)
&& (m_deviceFeatures.vk13.dynamicRendering
|| !required.vk13.dynamicRendering)
&& (m_deviceFeatures.vk13.maintenance4
|| !required.vk13.maintenance4)
&& (m_deviceFeatures.extAttachmentFeedbackLoopLayout.attachmentFeedbackLoopLayout
|| !required.extAttachmentFeedbackLoopLayout.attachmentFeedbackLoopLayout)
&& (m_deviceFeatures.extConservativeRasterization
|| !required.extConservativeRasterization)
&& (m_deviceFeatures.extCustomBorderColor.customBorderColors
|| !required.extCustomBorderColor.customBorderColors)
&& (m_deviceFeatures.extCustomBorderColor.customBorderColorWithoutFormat
|| !required.extCustomBorderColor.customBorderColorWithoutFormat)
&& (m_deviceFeatures.extDepthClipEnable.depthClipEnable
|| !required.extDepthClipEnable.depthClipEnable)
&& (m_deviceFeatures.extGraphicsPipelineLibrary.graphicsPipelineLibrary
|| !required.extGraphicsPipelineLibrary.graphicsPipelineLibrary)
&& (m_deviceFeatures.extMemoryBudget
|| !required.extMemoryBudget)
&& (m_deviceFeatures.extMemoryPriority.memoryPriority
|| !required.extMemoryPriority.memoryPriority)
&& (m_deviceFeatures.extNonSeamlessCubeMap.nonSeamlessCubeMap
|| !required.extNonSeamlessCubeMap.nonSeamlessCubeMap)
&& (m_deviceFeatures.extRobustness2.robustBufferAccess2
|| !required.extRobustness2.robustBufferAccess2)
&& (m_deviceFeatures.extRobustness2.robustImageAccess2
|| !required.extRobustness2.robustImageAccess2)
&& (m_deviceFeatures.extRobustness2.nullDescriptor
|| !required.extRobustness2.nullDescriptor)
&& (m_deviceFeatures.extShaderModuleIdentifier.shaderModuleIdentifier
|| !required.extShaderModuleIdentifier.shaderModuleIdentifier)
&& (m_deviceFeatures.extShaderStencilExport
|| !required.extShaderStencilExport)
&& (m_deviceFeatures.extShaderStencilExport
|| !required.extSwapchainColorSpace)
&& (m_deviceFeatures.extHdrMetadata
|| !required.extHdrMetadata)
&& (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*, 26> devExtensionList = {{
&devExtensions.amdMemoryOverallocationBehaviour,
&devExtensions.amdShaderFragmentMask,
&devExtensions.extAttachmentFeedbackLoopLayout,
&devExtensions.extConservativeRasterization,
&devExtensions.extCustomBorderColor,
&devExtensions.extDepthClipEnable,
&devExtensions.extExtendedDynamicState3,
&devExtensions.extFragmentShaderInterlock,
&devExtensions.extFullScreenExclusive,
&devExtensions.extGraphicsPipelineLibrary,
&devExtensions.extHdrMetadata,
&devExtensions.extMemoryBudget,
&devExtensions.extMemoryPriority,
&devExtensions.extNonSeamlessCubeMap,
&devExtensions.extRobustness2,
&devExtensions.extShaderModuleIdentifier,
&devExtensions.extShaderStencilExport,
&devExtensions.extSwapchainColorSpace,
&devExtensions.extTransformFeedback,
&devExtensions.extVertexAttributeDivisor,
&devExtensions.khrExternalMemoryWin32,
&devExtensions.khrExternalSemaphoreWin32,
&devExtensions.khrPipelineLibrary,
&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.vk12.bufferDeviceAddress;
if (enableCudaInterop) {
devExtensions.nvxBinaryImport.setMode(DxvkExtMode::Optional);
devExtensions.nvxImageViewHandle.setMode(DxvkExtMode::Optional);
enabledFeatures.vk12.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();
// Always enable robust buffer access
enabledFeatures.core.features.robustBufferAccess = VK_TRUE;
// Enable variable multisample rate if supported
enabledFeatures.core.features.variableMultisampleRate =
m_deviceFeatures.core.features.variableMultisampleRate;
// Always enable memory model so client APIs can use it
enabledFeatures.vk12.vulkanMemoryModel = VK_TRUE;
// Optionally used by some client API extensions
enabledFeatures.vk12.drawIndirectCount =
m_deviceFeatures.vk12.drawIndirectCount;
// Required since we no longer have a fallback for GPU queries
enabledFeatures.vk12.hostQueryReset = VK_TRUE;
// Used by some internal shaders, and can be used by applications
enabledFeatures.vk12.shaderOutputViewportIndex =
m_deviceFeatures.vk12.shaderOutputViewportIndex;
enabledFeatures.vk12.shaderOutputLayer =
m_deviceFeatures.vk12.shaderOutputLayer;
// Required for proper GPU synchronization
enabledFeatures.vk12.timelineSemaphore = VK_TRUE;
// Only enable the base image robustness feature if robustness 2 isn't
// supported, since this is only a subset of what we actually want.
enabledFeatures.vk13.robustImageAccess =
m_deviceFeatures.vk13.robustImageAccess &&
!m_deviceFeatures.extRobustness2.robustImageAccess2;
// Only used in combination with pipeline libraries
// right now, but enabling it won't hurt anyway
enabledFeatures.vk13.pipelineCreationCacheControl =
m_deviceFeatures.vk13.pipelineCreationCacheControl;
// Core features that we're relying on in various places
enabledFeatures.vk13.synchronization2 = VK_TRUE;
enabledFeatures.vk13.dynamicRendering = VK_TRUE;
// We expose depth clip rather than depth clamp to client APIs
enabledFeatures.extDepthClipEnable.depthClipEnable =
m_deviceFeatures.extDepthClipEnable.depthClipEnable;
// Used to make pipeline library stuff less clunky
enabledFeatures.extExtendedDynamicState3.extendedDynamicState3DepthClipEnable =
m_deviceFeatures.extExtendedDynamicState3.extendedDynamicState3DepthClipEnable &&
m_deviceFeatures.extDepthClipEnable.depthClipEnable;
// Used for both pNext shader module info, and fast-linking pipelines provided
// that graphicsPipelineLibraryIndependentInterpolationDecoration is supported
enabledFeatures.extGraphicsPipelineLibrary.graphicsPipelineLibrary =
m_deviceFeatures.extGraphicsPipelineLibrary.graphicsPipelineLibrary;
// Enable memory priority if supported to improve memory management
enabledFeatures.extMemoryPriority.memoryPriority =
m_deviceFeatures.extMemoryPriority.memoryPriority;
// Require robustBufferAccess2 since we use the robustness alignment
// info in a number of places, and require null descriptor support
// since we no longer have a fallback for those in the backend
enabledFeatures.extRobustness2.robustBufferAccess2 = VK_TRUE;
enabledFeatures.extRobustness2.robustImageAccess2 = m_deviceFeatures.extRobustness2.robustImageAccess2;
enabledFeatures.extRobustness2.nullDescriptor = VK_TRUE;
// We use this to avoid decompressing SPIR-V shaders in some situations
enabledFeatures.extShaderModuleIdentifier.shaderModuleIdentifier =
m_deviceFeatures.extShaderModuleIdentifier.shaderModuleIdentifier;
// Create pNext chain for additional device features
enabledFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
enabledFeatures.core.pNext = nullptr;
enabledFeatures.vk11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
enabledFeatures.vk11.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.vk11);
enabledFeatures.vk12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
enabledFeatures.vk12.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.vk12);
enabledFeatures.vk13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
enabledFeatures.vk13.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.vk13);
if (devExtensions.amdShaderFragmentMask)
enabledFeatures.amdShaderFragmentMask = VK_TRUE;
if (devExtensions.extAttachmentFeedbackLoopLayout) {
enabledFeatures.extAttachmentFeedbackLoopLayout.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT;
enabledFeatures.extAttachmentFeedbackLoopLayout.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extAttachmentFeedbackLoopLayout);
}
if (devExtensions.extConservativeRasterization)
enabledFeatures.extConservativeRasterization = VK_TRUE;
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.extExtendedDynamicState3) {
enabledFeatures.extExtendedDynamicState3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT;
enabledFeatures.extExtendedDynamicState3.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extExtendedDynamicState3);
}
if (devExtensions.extFragmentShaderInterlock) {
enabledFeatures.extFragmentShaderInterlock.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
enabledFeatures.extFragmentShaderInterlock.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extFragmentShaderInterlock);
}
if (devExtensions.extFullScreenExclusive)
enabledFeatures.extFullScreenExclusive = VK_TRUE;
if (devExtensions.extGraphicsPipelineLibrary) {
enabledFeatures.extGraphicsPipelineLibrary.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT;
enabledFeatures.extGraphicsPipelineLibrary.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extGraphicsPipelineLibrary);
}
if (devExtensions.extMemoryBudget)
enabledFeatures.extMemoryBudget = VK_TRUE;
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.extNonSeamlessCubeMap) {
enabledFeatures.extNonSeamlessCubeMap.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT;
enabledFeatures.extNonSeamlessCubeMap.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extNonSeamlessCubeMap);
}
if (devExtensions.extShaderModuleIdentifier) {
enabledFeatures.extShaderModuleIdentifier.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT;
enabledFeatures.extShaderModuleIdentifier.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extShaderModuleIdentifier);
}
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.extShaderStencilExport)
enabledFeatures.extShaderStencilExport = VK_TRUE;
if (devExtensions.extSwapchainColorSpace)
enabledFeatures.extSwapchainColorSpace = VK_TRUE;
if (devExtensions.extHdrMetadata)
enabledFeatures.extHdrMetadata = VK_TRUE;
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.khrExternalMemoryWin32)
enabledFeatures.khrExternalMemoryWin32 = VK_TRUE;
if (devExtensions.khrExternalSemaphoreWin32)
enabledFeatures.khrExternalSemaphoreWin32 = VK_TRUE;
if (devExtensions.nvxBinaryImport)
enabledFeatures.nvxBinaryImport = VK_TRUE;
if (devExtensions.nvxImageViewHandle)
enabledFeatures.nvxImageViewHandle = VK_TRUE;
// Log feature support info an extension list
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);
// 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<VkDeviceQueueCreateInfo> queueInfos;
std::unordered_set<uint32_t> queueFamiliySet;
DxvkAdapterQueueIndices 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;
graphicsQueue.queueCount = 1;
graphicsQueue.pQueuePriorities = &queuePriority;
queueInfos.push_back(graphicsQueue);
}
VkDeviceCreateInfo info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, enabledFeatures.core.pNext };
info.queueCreateInfoCount = queueInfos.size();
info.pQueueCreateInfos = queueInfos.data();
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.nvxBinaryImport);
extensionsEnabled.disableExtension(devExtensions.nvxImageViewHandle);
enabledFeatures.vk12.bufferDeviceAddress = VK_FALSE;
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");
return new DxvkDevice(instance, this,
new vk::DeviceFn(m_vki, true, device),
enabledFeatures);
}
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(
VkDriverIdKHR driver,
uint32_t minVer,
uint32_t maxVer) const {
bool driverMatches = driver == m_deviceInfo.vk12.driverID;
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.vk11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
m_deviceInfo.vk11.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.vk11);
m_deviceInfo.vk12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
m_deviceInfo.vk12.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.vk12);
m_deviceInfo.vk13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES;
m_deviceInfo.vk13.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.vk13);
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_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME)) {
m_deviceInfo.extExtendedDynamicState3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT;
m_deviceInfo.extExtendedDynamicState3.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extExtendedDynamicState3);
}
if (m_deviceExtensions.supports(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) {
m_deviceInfo.extGraphicsPipelineLibrary.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT;
m_deviceInfo.extGraphicsPipelineLibrary.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extGraphicsPipelineLibrary);
}
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);
}
// Query full device properties for all enabled extensions
m_vki->vkGetPhysicalDeviceProperties2(m_handle, &m_deviceInfo.core);
// Some drivers reports the driver version in a slightly different format
switch (m_deviceInfo.vk12.driverID) {
case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
m_deviceInfo.core.properties.driverVersion = VK_MAKE_VERSION(
(m_deviceInfo.core.properties.driverVersion >> 22) & 0x3ff,
(m_deviceInfo.core.properties.driverVersion >> 14) & 0x0ff,
(m_deviceInfo.core.properties.driverVersion >> 6) & 0x0ff);
break;
case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
m_deviceInfo.core.properties.driverVersion = VK_MAKE_VERSION(
m_deviceInfo.core.properties.driverVersion >> 14,
m_deviceInfo.core.properties.driverVersion & 0x3fff, 0);
break;
default:;
}
}
void DxvkAdapter::queryDeviceFeatures() {
m_deviceFeatures = DxvkDeviceFeatures();
m_deviceFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
m_deviceFeatures.core.pNext = nullptr;
m_deviceFeatures.vk11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
m_deviceFeatures.vk11.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.vk11);
m_deviceFeatures.vk12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
m_deviceFeatures.vk12.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.vk12);
m_deviceFeatures.vk13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
m_deviceFeatures.vk13.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.vk13);
if (m_deviceExtensions.supports(VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME))
m_deviceFeatures.amdShaderFragmentMask = VK_TRUE;
if (m_deviceExtensions.supports(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME)) {
m_deviceFeatures.extAttachmentFeedbackLoopLayout.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT;
m_deviceFeatures.extAttachmentFeedbackLoopLayout.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extAttachmentFeedbackLoopLayout);
}
if (m_deviceExtensions.supports(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME))
m_deviceFeatures.extConservativeRasterization = VK_TRUE;
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_3_EXTENSION_NAME)) {
m_deviceFeatures.extExtendedDynamicState3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT;
m_deviceFeatures.extExtendedDynamicState3.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extExtendedDynamicState3);
}
if (m_deviceExtensions.supports(VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME)) {
m_deviceFeatures.extFragmentShaderInterlock.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
m_deviceFeatures.extFragmentShaderInterlock.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extFragmentShaderInterlock);
}
if (m_deviceExtensions.supports(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
m_deviceFeatures.extFullScreenExclusive = VK_TRUE;
if (m_deviceExtensions.supports(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) {
m_deviceFeatures.extGraphicsPipelineLibrary.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT;
m_deviceFeatures.extGraphicsPipelineLibrary.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extGraphicsPipelineLibrary);
}
if (m_deviceExtensions.supports(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME))
m_deviceFeatures.extMemoryBudget = VK_TRUE;
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_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME)) {
m_deviceFeatures.extNonSeamlessCubeMap.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT;
m_deviceFeatures.extNonSeamlessCubeMap.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extNonSeamlessCubeMap);
}
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_MODULE_IDENTIFIER_EXTENSION_NAME)) {
m_deviceFeatures.extShaderModuleIdentifier.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT;
m_deviceFeatures.extShaderModuleIdentifier.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extShaderModuleIdentifier);
}
if (m_deviceExtensions.supports(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME))
m_deviceFeatures.extShaderStencilExport = VK_TRUE;
if (m_deviceExtensions.supports(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME))
m_deviceFeatures.extSwapchainColorSpace = VK_TRUE;
if (m_deviceExtensions.supports(VK_EXT_HDR_METADATA_EXTENSION_NAME))
m_deviceFeatures.extHdrMetadata = VK_TRUE;
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_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME))
m_deviceFeatures.khrExternalMemoryWin32 = VK_TRUE;
if (m_deviceExtensions.supports(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME))
m_deviceFeatures.khrExternalSemaphoreWin32 = VK_TRUE;
if (m_deviceExtensions.supports(VK_NVX_BINARY_IMPORT_EXTENSION_NAME))
m_deviceFeatures.nvxBinaryImport = VK_TRUE;
if (m_deviceExtensions.supports(VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME))
m_deviceFeatures.nvxImageViewHandle = VK_TRUE;
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 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 shaderResourceResidency : ", features.core.features.shaderResourceResidency ? "1" : "0",
"\n shaderResourceMinLod : ", features.core.features.shaderResourceMinLod ? "1" : "0",
"\n sparseBinding : ", features.core.features.sparseBinding ? "1" : "0",
"\n sparseResidencyBuffer : ", features.core.features.sparseResidencyBuffer ? "1" : "0",
"\n sparseResidencyImage2D : ", features.core.features.sparseResidencyImage2D ? "1" : "0",
"\n sparseResidencyImage3D : ", features.core.features.sparseResidencyImage3D ? "1" : "0",
"\n sparseResidency2Samples : ", features.core.features.sparseResidency2Samples ? "1" : "0",
"\n sparseResidency4Samples : ", features.core.features.sparseResidency4Samples ? "1" : "0",
"\n sparseResidency8Samples : ", features.core.features.sparseResidency8Samples ? "1" : "0",
"\n sparseResidency16Samples : ", features.core.features.sparseResidency16Samples ? "1" : "0",
"\n sparseResidencyAliased : ", features.core.features.sparseResidencyAliased ? "1" : "0",
"\nVulkan 1.1",
"\n shaderDrawParameters : ", features.vk11.shaderDrawParameters,
"\nVulkan 1.2",
"\n samplerMirrorClampToEdge : ", features.vk12.samplerMirrorClampToEdge,
"\n drawIndirectCount : ", features.vk12.drawIndirectCount,
"\n samplerFilterMinmax : ", features.vk12.samplerFilterMinmax,
"\n hostQueryReset : ", features.vk12.hostQueryReset,
"\n timelineSemaphore : ", features.vk12.timelineSemaphore,
"\n bufferDeviceAddress : ", features.vk12.bufferDeviceAddress,
"\n shaderOutputViewportIndex : ", features.vk12.shaderOutputViewportIndex,
"\n shaderOutputLayer : ", features.vk12.shaderOutputLayer,
"\n vulkanMemoryModel : ", features.vk12.vulkanMemoryModel,
"\nVulkan 1.3",
"\n robustImageAccess : ", features.vk13.robustImageAccess,
"\n pipelineCreationCacheControl : ", features.vk13.pipelineCreationCacheControl,
"\n shaderDemoteToHelperInvocation : ", features.vk13.shaderDemoteToHelperInvocation,
"\n shaderZeroInitializeWorkgroupMemory : ", features.vk13.shaderZeroInitializeWorkgroupMemory,
"\n synchronization2 : ", features.vk13.synchronization2,
"\n dynamicRendering : ", features.vk13.dynamicRendering,
"\n", VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME,
"\n extension supported : ", features.amdShaderFragmentMask ? "1" : "0",
"\n", VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME,
"\n attachmentFeedbackLoopLayout : ", features.extAttachmentFeedbackLoopLayout.attachmentFeedbackLoopLayout ? "1" : "0",
"\n", VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME,
"\n extension supported : ", features.extConservativeRasterization ? "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_3_EXTENSION_NAME,
"\n extendedDynamicState3DepthClipEnable : ", features.extExtendedDynamicState3.extendedDynamicState3DepthClipEnable ? "1" : "0",
"\n", VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME,
"\n fragmentShaderSampleInterlock : ", features.extFragmentShaderInterlock.fragmentShaderSampleInterlock ? "1" : "0",
"\n fragmentShaderPixelInterlock : ", features.extFragmentShaderInterlock.fragmentShaderPixelInterlock ? "1" : "0",
"\n", VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME,
"\n extension supported : ", features.extFullScreenExclusive ? "1" : "0",
"\n", VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME,
"\n graphicsPipelineLibrary : ", features.extGraphicsPipelineLibrary.graphicsPipelineLibrary ? "1" : "0",
"\n", VK_EXT_MEMORY_BUDGET_EXTENSION_NAME,
"\n extension supported : ", features.extMemoryBudget ? "1" : "0",
"\n", VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME,
"\n memoryPriority : ", features.extMemoryPriority.memoryPriority ? "1" : "0",
"\n", VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME,
"\n nonSeamlessCubeMap : ", features.extNonSeamlessCubeMap.nonSeamlessCubeMap ? "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_MODULE_IDENTIFIER_EXTENSION_NAME,
"\n shaderModuleIdentifier : ", features.extShaderModuleIdentifier.shaderModuleIdentifier ? "1" : "0",
"\n", VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME,
"\n extension supported : ", features.extShaderStencilExport ? "1" : "0",
"\n", VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
"\n extension supported : ", features.extSwapchainColorSpace ? "1" : "0",
"\n", VK_EXT_HDR_METADATA_EXTENSION_NAME,
"\n extension supported : ", features.extHdrMetadata ? "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_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
"\n extension supported : ", features.khrExternalMemoryWin32 ? "1" : "0",
"\n", VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
"\n extension supported : ", features.khrExternalSemaphoreWin32 ? "1" : "0",
"\n", VK_NVX_BINARY_IMPORT_EXTENSION_NAME,
"\n extension supported : ", features.nvxBinaryImport ? "1" : "0",
"\n", VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME,
"\n extension supported : ", features.nvxImageViewHandle ? "1" : "0"));
}
void DxvkAdapter::logQueueFamilies(const DxvkAdapterQueueIndices& queues) {
Logger::info(str::format("Queue families:",
"\n Graphics : ", queues.graphics,
"\n Transfer : ", queues.transfer,
"\n Sparse : ", queues.sparse != VK_QUEUE_FAMILY_IGNORED ? str::format(queues.sparse) : "n/a"));
}
}