Skip to content
Permalink
Browse files

Merge pull request #8258 from CookiePLMonster/dx11.1-detection-fixes

D3D11 resources refactor and DX11.1 feature detection fixes
  • Loading branch information...
stenzek committed Jul 29, 2019
2 parents b0113b6 + baa9636 commit dea2b9c509b96cb58182b883c1df9f9f7f9234bf
@@ -160,16 +160,16 @@ void GeneralWidget::SaveSettings()
const auto current_backend = m_backend_combo->currentData().toString().toStdString();
if (SConfig::GetInstance().m_strVideoBackend != current_backend)
{
if (current_backend == "Software Renderer")
auto warningMessage =
g_available_video_backends[m_backend_combo->currentIndex()]->GetWarningMessage();
if (warningMessage)
{
ModalMessageBox confirm_sw(this);

confirm_sw.setIcon(QMessageBox::Warning);
confirm_sw.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
confirm_sw.setWindowTitle(tr("Confirm backend change"));
confirm_sw.setText(tr("The software renderer is significantly slower than other "
"backends and is only recommended for debugging purposes.\n\nDo you "
"really want to enable software rendering? If unsure, select 'No'."));
confirm_sw.setText(tr(warningMessage->c_str()));

if (confirm_sw.exec() != QMessageBox::Yes)
{
@@ -64,7 +64,7 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
}

ComPtr<IDXGIAdapter> 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,16 +75,16 @@ 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<UINT>(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<UINT>(s_supported_feature_levels.size()),
D3D11_SDK_VERSION, device.GetAddressOf(), &feature_level, context.GetAddressOf());

// Debugbreak on D3D error
if (SUCCEEDED(hr) && SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&s_debug))))
if (SUCCEEDED(hr) && SUCCEEDED(device.As(&s_debug)))
{
ComPtr<ID3D11InfoQueue> info_queue;
if (SUCCEEDED(s_debug->QueryInterface(IID_PPV_ARGS(&info_queue))))
if (SUCCEEDED(s_debug.As(&info_queue)))
{
info_queue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
info_queue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
@@ -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<UINT>(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<UINT>(s_supported_feature_levels.size()), D3D11_SDK_VERSION,
device.GetAddressOf(), &feature_level, context.GetAddressOf());
}

if (FAILED(hr))
@@ -121,11 +121,10 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
return false;
}

hr = device->QueryInterface(IID_PPV_ARGS(&device1));
hr = device.As(&device1);
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<StateManager>();
@@ -171,14 +170,15 @@ std::vector<u32> GetAAModes(u32 adapter_index)
// Use temporary device if we don't have one already.
Common::DynamicLibrary temp_lib;
ComPtr<ID3D11Device> temp_device = device;
D3D_FEATURE_LEVEL temp_feature_level = feature_level;
if (!temp_device)
{
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
if (!temp_dxgi_factory)
return {};

ComPtr<IDXGIAdapter> adapter;
temp_dxgi_factory->EnumAdapters(adapter_index, &adapter);
temp_dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf());

PFN_D3D11_CREATE_DEVICE d3d11_create_device;
if (!temp_lib.Open("d3d11.dll") ||
@@ -187,21 +187,21 @@ std::vector<u32> GetAAModes(u32 adapter_index)
return {};
}

HRESULT hr = d3d11_create_device(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
s_supported_feature_levels.data(),
static_cast<UINT>(s_supported_feature_levels.size()),
D3D11_SDK_VERSION, &temp_device, nullptr, nullptr);
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(), &temp_feature_level, nullptr);
if (FAILED(hr))
return {};
}

// NOTE: D3D 10.0 doesn't support multisampled resources which are bound as depth buffers AND
// shader resources. Thus, we can't have MSAA with 10.0 level hardware.
if (temp_device->GetFeatureLevel() == D3D_FEATURE_LEVEL_10_0)
if (temp_feature_level == D3D_FEATURE_LEVEL_10_0)
return {};

std::vector<u32> aa_modes;
for (u32 samples = 1; samples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
for (u32 samples = 1; samples <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
{
UINT quality_levels = 0;
if (SUCCEEDED(temp_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, samples,
@@ -224,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<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 DX11
@@ -43,6 +43,9 @@ std::vector<u32> 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
@@ -347,10 +347,9 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
}

ComPtr<ID3D11SamplerState> res;
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, &res);
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, res.GetAddressOf());
CHECK(SUCCEEDED(hr), "Creating D3D sampler state failed");
m_sampler.emplace(state.hex, res);
return res.Get();
return m_sampler.emplace(state.hex, std::move(res)).first->second.Get();
}

ID3D11BlendState* StateCache::Get(BlendingState state)
@@ -360,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];
@@ -381,13 +380,13 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
tdesc.LogicOpEnable = TRUE;
tdesc.LogicOp = logic_ops[state.logicmode];

ID3D11BlendState1* res;
HRESULT hr = D3D::device1->CreateBlendState1(&desc, &res);
ComPtr<ID3D11BlendState1> res;
HRESULT hr = D3D::device1->CreateBlendState1(&desc, res.GetAddressOf());
if (SUCCEEDED(hr))
{
m_blend.emplace(state.hex, res);
return res;
return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
}
WARN_LOG(VIDEO, "Creating D3D blend state failed with an error: %x", hr);
}

D3D11_BLEND_DESC desc = {};
@@ -425,10 +424,9 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
tdesc.BlendOpAlpha = state.subtractAlpha ? D3D11_BLEND_OP_REV_SUBTRACT : D3D11_BLEND_OP_ADD;

ComPtr<ID3D11BlendState> res;
HRESULT hr = D3D::device->CreateBlendState(&desc, &res);
HRESULT hr = D3D::device->CreateBlendState(&desc, res.GetAddressOf());
CHECK(SUCCEEDED(hr), "Creating D3D blend state failed");
m_blend.emplace(state.hex, res);
return res.Get();
return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
}

ID3D11RasterizerState* StateCache::Get(RasterizationState state)
@@ -447,10 +445,9 @@ ID3D11RasterizerState* StateCache::Get(RasterizationState state)
desc.ScissorEnable = TRUE;

ComPtr<ID3D11RasterizerState> res;
HRESULT hr = D3D::device->CreateRasterizerState(&desc, &res);
HRESULT hr = D3D::device->CreateRasterizerState(&desc, res.GetAddressOf());
CHECK(SUCCEEDED(hr), "Creating D3D rasterizer state failed");
m_raster.emplace(state.hex, res);
return res.Get();
return m_raster.emplace(state.hex, std::move(res)).first->second.Get();
}

ID3D11DepthStencilState* StateCache::Get(DepthState state)
@@ -490,10 +487,9 @@ ID3D11DepthStencilState* StateCache::Get(DepthState state)
}

ComPtr<ID3D11DepthStencilState> res;
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, &res);
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, res.GetAddressOf());
CHECK(SUCCEEDED(hr), "Creating D3D depth stencil state failed");
m_depth.emplace(state.hex, res);
return res.Get();
return m_depth.emplace(state.hex, std::move(res)).first->second.Get();
}

D3D11_PRIMITIVE_TOPOLOGY StateCache::GetPrimitiveTopology(PrimitiveType primitive)

0 comments on commit dea2b9c

Please sign in to comment.
You can’t perform that action at this time.