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.
This commit is contained in:
Silent 2019-07-21 17:10:51 +02:00
parent a6b8e8b9c3
commit ff00873610
No known key found for this signature in database
GPG Key ID: AE53149BB0C45AF1
5 changed files with 64 additions and 16 deletions

View File

@ -64,7 +64,7 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
} }
ComPtr<IDXGIAdapter> adapter; ComPtr<IDXGIAdapter> adapter;
HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, &adapter); HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf());
if (FAILED(hr)) if (FAILED(hr))
{ {
WARN_LOG(VIDEO, "Adapter %u not found, using default", adapter_index); 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. // version of the DirectX SDK. If it does, simply fallback to a non-debug device.
if (enable_debug_layer) if (enable_debug_layer)
{ {
hr = d3d11_create_device(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, hr = d3d11_create_device(
D3D11_CREATE_DEVICE_DEBUG, s_supported_feature_levels.data(), adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_DEBUG,
static_cast<UINT>(s_supported_feature_levels.size()), s_supported_feature_levels.data(), static_cast<UINT>(s_supported_feature_levels.size()),
D3D11_SDK_VERSION, &device, &feature_level, &context); D3D11_SDK_VERSION, device.GetAddressOf(), &feature_level, context.GetAddressOf());
// Debugbreak on D3D error // Debugbreak on D3D error
if (SUCCEEDED(hr) && SUCCEEDED(device.As(&s_debug))) 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)) if (!enable_debug_layer || FAILED(hr))
{ {
hr = d3d11_create_device(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, hr = d3d11_create_device(
s_supported_feature_levels.data(), adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, s_supported_feature_levels.data(),
static_cast<UINT>(s_supported_feature_levels.size()), static_cast<UINT>(s_supported_feature_levels.size()), D3D11_SDK_VERSION,
D3D11_SDK_VERSION, &device, &feature_level, &context); device.GetAddressOf(), &feature_level, context.GetAddressOf());
} }
if (FAILED(hr)) if (FAILED(hr))
@ -125,7 +125,6 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
if (FAILED(hr)) if (FAILED(hr))
{ {
WARN_LOG(VIDEO, "Missing Direct3D 11.1 support. Logical operations will not be supported."); WARN_LOG(VIDEO, "Missing Direct3D 11.1 support. Logical operations will not be supported.");
g_Config.backend_info.bSupportsLogicOp = false;
} }
stateman = std::make_unique<StateManager>(); stateman = std::make_unique<StateManager>();
@ -225,6 +224,53 @@ bool SupportsTextureFormat(DXGI_FORMAT format)
return (support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; 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<ID3D11Device1> temp_device1 = device1;
if (!device)
{
ComPtr<ID3D11Device> temp_device;
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
if (!temp_dxgi_factory)
return false;
ComPtr<IDXGIAdapter> 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<UINT>(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 D3D
} // namespace DX11 } // namespace DX11

View File

@ -43,6 +43,9 @@ std::vector<u32> GetAAModes(u32 adapter_index);
// Checks for support of the given texture format. // Checks for support of the given texture format.
bool SupportsTextureFormat(DXGI_FORMAT format); bool SupportsTextureFormat(DXGI_FORMAT format);
// Checks for logic op support.
bool SupportsLogicOp(u32 adapter_index);
} // namespace D3D } // namespace D3D
} // namespace DX11 } // namespace DX11

View File

@ -359,7 +359,7 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
if (it != m_blend.end()) if (it != m_blend.end())
return it->second.Get(); return it->second.Get();
if (state.logicopenable && D3D::device1) if (state.logicopenable && g_ActiveConfig.backend_info.bSupportsLogicOp)
{ {
D3D11_BLEND_DESC1 desc = {}; D3D11_BLEND_DESC1 desc = {};
D3D11_RENDER_TARGET_BLEND_DESC1& tdesc = desc.RenderTarget[0]; D3D11_RENDER_TARGET_BLEND_DESC1& tdesc = desc.RenderTarget[0];

View File

@ -12,6 +12,7 @@
#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/DXTexture.h" #include "VideoBackends/D3D/DXTexture.h"
#include "VideoBackends/D3DCommon/Common.h" #include "VideoBackends/D3DCommon/Common.h"
#include "VideoCommon/VideoConfig.h"
namespace DX11 namespace DX11
{ {
@ -360,10 +361,10 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
if (FAILED(hr)) if (FAILED(hr))
return nullptr; return nullptr;
// Only create the integer RTV on Win8+. // Only create the integer RTV when logic ops are supported (Win8+).
DXGI_FORMAT integer_format = DXGI_FORMAT integer_format =
D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), true); 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; desc.Format = integer_format;
hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,

View File

@ -63,16 +63,13 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsClipControl = true; g_Config.backend_info.bSupportsClipControl = true;
g_Config.backend_info.bSupportsDepthClamp = true; g_Config.backend_info.bSupportsDepthClamp = true;
g_Config.backend_info.bSupportsReversedDepthRange = false; g_Config.backend_info.bSupportsReversedDepthRange = false;
g_Config.backend_info.bSupportsLogicOp = true;
g_Config.backend_info.bSupportsMultithreading = false; g_Config.backend_info.bSupportsMultithreading = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = true; g_Config.backend_info.bSupportsGPUTextureDecoding = true;
g_Config.backend_info.bSupportsST3CTextures = false;
g_Config.backend_info.bSupportsCopyToVram = true; g_Config.backend_info.bSupportsCopyToVram = true;
g_Config.backend_info.bSupportsLargePoints = false; g_Config.backend_info.bSupportsLargePoints = false;
g_Config.backend_info.bSupportsPartialDepthCopies = false; g_Config.backend_info.bSupportsPartialDepthCopies = false;
g_Config.backend_info.bSupportsBitfield = false; g_Config.backend_info.bSupportsBitfield = false;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false; g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
g_Config.backend_info.bSupportsFramebufferFetch = false; g_Config.backend_info.bSupportsFramebufferFetch = false;
g_Config.backend_info.bSupportsBackgroundCompiling = true; g_Config.backend_info.bSupportsBackgroundCompiling = true;
g_Config.backend_info.bSupportsST3CTextures = true; g_Config.backend_info.bSupportsST3CTextures = true;
@ -84,6 +81,7 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsSSAA = true; g_Config.backend_info.bSupportsSSAA = true;
g_Config.backend_info.bSupportsShaderBinaries = true; g_Config.backend_info.bSupportsShaderBinaries = true;
g_Config.backend_info.bSupportsPipelineCacheData = false; 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.Adapters = D3DCommon::GetAdapterNames();
g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter); g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);