From ff00873610a3cd55e76245ef0aae892026fedd9b Mon Sep 17 00:00:00 2001 From: Silent Date: Sun, 21 Jul 2019 17:10:51 +0200 Subject: [PATCH] D3D11: Query for output merger logic op support and use logic op code only if supported Previously code assumed that if DX11.1 runtime is supported, logic ops will, but Windows 7 SP1 with a Platform Update supports DX11.1 runtime without logic ops. This created pretty jarring visual artifacts, which now should be gone OR replaced with much less jarring errors. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 66 +++++++++++++++++---- Source/Core/VideoBackends/D3D/D3DBase.h | 3 + Source/Core/VideoBackends/D3D/D3DState.cpp | 2 +- Source/Core/VideoBackends/D3D/DXTexture.cpp | 5 +- Source/Core/VideoBackends/D3D/main.cpp | 4 +- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 358841ecbc..81220dcfc3 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -64,7 +64,7 @@ bool Create(u32 adapter_index, bool enable_debug_layer) } ComPtr adapter; - HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, &adapter); + HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf()); if (FAILED(hr)) { WARN_LOG(VIDEO, "Adapter %u not found, using default", adapter_index); @@ -75,10 +75,10 @@ bool Create(u32 adapter_index, bool enable_debug_layer) // version of the DirectX SDK. If it does, simply fallback to a non-debug device. if (enable_debug_layer) { - hr = d3d11_create_device(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, - D3D11_CREATE_DEVICE_DEBUG, s_supported_feature_levels.data(), - static_cast(s_supported_feature_levels.size()), - D3D11_SDK_VERSION, &device, &feature_level, &context); + hr = d3d11_create_device( + adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_DEBUG, + s_supported_feature_levels.data(), static_cast(s_supported_feature_levels.size()), + D3D11_SDK_VERSION, device.GetAddressOf(), &feature_level, context.GetAddressOf()); // Debugbreak on D3D error if (SUCCEEDED(hr) && SUCCEEDED(device.As(&s_debug))) @@ -105,10 +105,10 @@ bool Create(u32 adapter_index, bool enable_debug_layer) if (!enable_debug_layer || FAILED(hr)) { - hr = d3d11_create_device(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, - s_supported_feature_levels.data(), - static_cast(s_supported_feature_levels.size()), - D3D11_SDK_VERSION, &device, &feature_level, &context); + hr = d3d11_create_device( + adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, s_supported_feature_levels.data(), + static_cast(s_supported_feature_levels.size()), D3D11_SDK_VERSION, + device.GetAddressOf(), &feature_level, context.GetAddressOf()); } if (FAILED(hr)) @@ -125,7 +125,6 @@ bool Create(u32 adapter_index, bool enable_debug_layer) if (FAILED(hr)) { WARN_LOG(VIDEO, "Missing Direct3D 11.1 support. Logical operations will not be supported."); - g_Config.backend_info.bSupportsLogicOp = false; } stateman = std::make_unique(); @@ -225,6 +224,53 @@ bool SupportsTextureFormat(DXGI_FORMAT format) return (support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; } +bool SupportsLogicOp(u32 adapter_index) +{ + // Use temporary device if we don't have one already. + Common::DynamicLibrary temp_lib; + ComPtr temp_device1 = device1; + if (!device) + { + ComPtr temp_device; + + ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); + if (!temp_dxgi_factory) + return false; + + ComPtr adapter; + temp_dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf()); + + PFN_D3D11_CREATE_DEVICE d3d11_create_device; + if (!temp_lib.Open("d3d11.dll") || + !temp_lib.GetSymbol("D3D11CreateDevice", &d3d11_create_device)) + { + return false; + } + + HRESULT hr = d3d11_create_device( + adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, s_supported_feature_levels.data(), + static_cast(s_supported_feature_levels.size()), D3D11_SDK_VERSION, + temp_device.GetAddressOf(), nullptr, nullptr); + if (FAILED(hr)) + return false; + + if (FAILED(temp_device.As(&temp_device1))) + return false; + } + + if (!temp_device1) + return false; + + D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; + if (FAILED(temp_device1->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, + sizeof(options)))) + { + return false; + } + + return options.OutputMergerLogicOp != FALSE; +} + } // namespace D3D } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index 090a0b4f4d..7fed1bb2c3 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -43,6 +43,9 @@ std::vector GetAAModes(u32 adapter_index); // Checks for support of the given texture format. bool SupportsTextureFormat(DXGI_FORMAT format); +// Checks for logic op support. +bool SupportsLogicOp(u32 adapter_index); + } // namespace D3D } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index a7b56145da..a9727937ac 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -359,7 +359,7 @@ ID3D11BlendState* StateCache::Get(BlendingState state) if (it != m_blend.end()) return it->second.Get(); - if (state.logicopenable && D3D::device1) + if (state.logicopenable && g_ActiveConfig.backend_info.bSupportsLogicOp) { D3D11_BLEND_DESC1 desc = {}; D3D11_RENDER_TARGET_BLEND_DESC1& tdesc = desc.RenderTarget[0]; diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index 6ab445868e..e2e818d637 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -12,6 +12,7 @@ #include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/DXTexture.h" #include "VideoBackends/D3DCommon/Common.h" +#include "VideoCommon/VideoConfig.h" namespace DX11 { @@ -360,10 +361,10 @@ std::unique_ptr DXFramebuffer::Create(DXTexture* color_attachment if (FAILED(hr)) return nullptr; - // Only create the integer RTV on Win8+. + // Only create the integer RTV when logic ops are supported (Win8+). DXGI_FORMAT integer_format = D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), true); - if (D3D::device1 && integer_format != desc.Format) + if (g_ActiveConfig.backend_info.bSupportsLogicOp && integer_format != desc.Format) { desc.Format = integer_format; hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index d87965deff..6c4bf20dd1 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -63,16 +63,13 @@ void VideoBackend::FillBackendInfo() g_Config.backend_info.bSupportsClipControl = true; g_Config.backend_info.bSupportsDepthClamp = true; g_Config.backend_info.bSupportsReversedDepthRange = false; - g_Config.backend_info.bSupportsLogicOp = true; g_Config.backend_info.bSupportsMultithreading = false; g_Config.backend_info.bSupportsGPUTextureDecoding = true; - g_Config.backend_info.bSupportsST3CTextures = false; g_Config.backend_info.bSupportsCopyToVram = true; g_Config.backend_info.bSupportsLargePoints = false; g_Config.backend_info.bSupportsPartialDepthCopies = false; g_Config.backend_info.bSupportsBitfield = false; g_Config.backend_info.bSupportsDynamicSamplerIndexing = false; - g_Config.backend_info.bSupportsBPTCTextures = false; g_Config.backend_info.bSupportsFramebufferFetch = false; g_Config.backend_info.bSupportsBackgroundCompiling = true; g_Config.backend_info.bSupportsST3CTextures = true; @@ -84,6 +81,7 @@ void VideoBackend::FillBackendInfo() g_Config.backend_info.bSupportsSSAA = true; g_Config.backend_info.bSupportsShaderBinaries = true; g_Config.backend_info.bSupportsPipelineCacheData = false; + g_Config.backend_info.bSupportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter); g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames(); g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);