diff --git a/src/d3d11/d3d11_features.cpp b/src/d3d11/d3d11_features.cpp index a3fe2cce..3b764cae 100644 --- a/src/d3d11/d3d11_features.cpp +++ b/src/d3d11/d3d11_features.cpp @@ -35,6 +35,8 @@ namespace dxvk { m_d3d10Options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = TRUE; // D3D11.1 options. All of these are required for Feature Level 11_1. + auto sharedResourceTier = DetermineSharedResourceTier(Adapter, FeatureLevel); + bool hasDoublePrecisionSupport = m_features.core.features.shaderFloat64 && m_features.core.features.shaderInt64; @@ -46,7 +48,7 @@ namespace dxvk { m_d3d11Options.ConstantBufferOffsetting = TRUE; m_d3d11Options.MapNoOverwriteOnDynamicConstantBuffer = TRUE; m_d3d11Options.MapNoOverwriteOnDynamicBufferSRV = TRUE; - m_d3d11Options.ExtendedResourceSharing = TRUE; + m_d3d11Options.ExtendedResourceSharing = sharedResourceTier > D3D11_SHARED_RESOURCE_TIER_0; if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) { m_d3d11Options.OutputMergerLogicOp = m_features.core.features.logicOp; @@ -91,10 +93,10 @@ namespace dxvk { } // D3D11.4 options - m_d3d11Options4.ExtendedNV12SharedTextureSupported = TRUE; + m_d3d11Options4.ExtendedNV12SharedTextureSupported = sharedResourceTier > D3D11_SHARED_RESOURCE_TIER_0; // More D3D11.4 options - m_d3d11Options5.SharedResourceTier = DetermineSharedResourceTier(FeatureLevel); + m_d3d11Options5.SharedResourceTier = sharedResourceTier; // Double-precision support if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) @@ -205,10 +207,80 @@ namespace dxvk { D3D11_SHARED_RESOURCE_TIER D3D11DeviceFeatures::DetermineSharedResourceTier( + const Rc& Adapter, D3D_FEATURE_LEVEL FeatureLevel) { - // Shared resources are all sorts of wonky for obvious - // reasons, so don't over-promise things here for now - return D3D11_SHARED_RESOURCE_TIER_1; + static std::atomic s_errorShown = { false }; + + // Lie about supporting Tier 1 since that's the + // minimum required tier for Feature Level 11_1 + if (!Adapter->features().khrExternalMemoryWin32) { + if (!s_errorShown.exchange(true)) + Logger::warn("D3D11DeviceFeatures: External memory features not supported"); + + return D3D11_SHARED_RESOURCE_TIER_1; + } + + // Check support for extended formats. Ignore multi-plane + // formats here since driver support varies too much. + std::array requiredFormats = {{ + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT, + VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_R32G32B32A32_SINT, + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_R16G16B16A16_UINT, + VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_R16G16B16A16_SINT, + VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_A2B10G10R10_UINT_PACK32, + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SRGB, + VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB, + VK_FORMAT_R32_SFLOAT, + VK_FORMAT_R32_UINT, + VK_FORMAT_R32_SINT, + VK_FORMAT_R16_SFLOAT, + VK_FORMAT_R16_UNORM, + VK_FORMAT_R16_UINT, + VK_FORMAT_R16_SNORM, + VK_FORMAT_R16_SINT, + VK_FORMAT_R8_UNORM, + VK_FORMAT_R8_UINT, + VK_FORMAT_R8_SNORM, + VK_FORMAT_R8_SINT, + }}; + + bool allKmtHandlesSupported = true; + bool allNtHandlesSupported = true; + + for (auto f : requiredFormats) { + allKmtHandlesSupported &= CheckFormatSharingSupport(Adapter, f, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); + allNtHandlesSupported &= CheckFormatSharingSupport(Adapter, f, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT); + } + + // Again, lie about at least tier 1 support + if (!allKmtHandlesSupported) { + if (!s_errorShown.exchange(true)) + Logger::warn("D3D11DeviceFeatures: Some formats not supported for resource sharing"); + return D3D11_SHARED_RESOURCE_TIER_1; + } + + // Tier 2 requires all the above formats to be shareable + // with NT handles in order to support D3D12 interop + if (!allNtHandlesSupported) + return D3D11_SHARED_RESOURCE_TIER_1; + + // Tier 3 additionally requires R11G11B10 to be + // shareable with D3D12 + if (!CheckFormatSharingSupport(Adapter, VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)) + return D3D11_SHARED_RESOURCE_TIER_2; + + return D3D11_SHARED_RESOURCE_TIER_3; } @@ -278,6 +350,26 @@ namespace dxvk { } + BOOL D3D11DeviceFeatures::CheckFormatSharingSupport( + const Rc& Adapter, + VkFormat Format, + VkExternalMemoryHandleTypeFlagBits HandleType) { + DxvkFormatQuery query = { }; + query.format = Format; + query.type = VK_IMAGE_TYPE_2D; + query.tiling = VK_IMAGE_TILING_OPTIMAL; + query.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + query.handleType = HandleType; + + constexpr VkExternalMemoryFeatureFlags featureMask + = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT + | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + + auto limits = Adapter->getFormatLimits(query); + return limits && (limits->externalFeatures & featureMask); + } + + D3D_FEATURE_LEVEL D3D11DeviceFeatures::GetMaxFeatureLevel() const { // Check Feature Level 11_0 features if (!m_features.core.features.drawIndirectFirstInstance diff --git a/src/d3d11/d3d11_features.h b/src/d3d11/d3d11_features.h index 052eec6a..9bdd7c31 100644 --- a/src/d3d11/d3d11_features.h +++ b/src/d3d11/d3d11_features.h @@ -102,6 +102,7 @@ namespace dxvk { D3D_FEATURE_LEVEL FeatureLevel); D3D11_SHARED_RESOURCE_TIER DetermineSharedResourceTier( + const Rc& Adapter, D3D_FEATURE_LEVEL FeatureLevel); D3D11_TILED_RESOURCES_TIER DetermineTiledResourcesTier( @@ -111,6 +112,11 @@ namespace dxvk { const Rc& Adapter, D3D_FEATURE_LEVEL FeatureLevel); + BOOL CheckFormatSharingSupport( + const Rc& Adapter, + VkFormat Format, + VkExternalMemoryHandleTypeFlagBits HandleType); + D3D_FEATURE_LEVEL GetMaxFeatureLevel() const; };