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

D3D11 resources refactor and DX11.1 feature detection fixes
This commit is contained in:
Connor McLaughlin 2019-07-30 01:24:57 +10:00 committed by GitHub
commit dea2b9c509
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 163 additions and 78 deletions

View File

@ -160,16 +160,16 @@ void GeneralWidget::SaveSettings()
const auto current_backend = m_backend_combo->currentData().toString().toStdString(); const auto current_backend = m_backend_combo->currentData().toString().toStdString();
if (SConfig::GetInstance().m_strVideoBackend != current_backend) 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); ModalMessageBox confirm_sw(this);
confirm_sw.setIcon(QMessageBox::Warning); confirm_sw.setIcon(QMessageBox::Warning);
confirm_sw.setStandardButtons(QMessageBox::Yes | QMessageBox::No); confirm_sw.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
confirm_sw.setWindowTitle(tr("Confirm backend change")); confirm_sw.setWindowTitle(tr("Confirm backend change"));
confirm_sw.setText(tr("The software renderer is significantly slower than other " confirm_sw.setText(tr(warningMessage->c_str()));
"backends and is only recommended for debugging purposes.\n\nDo you "
"really want to enable software rendering? If unsure, select 'No'."));
if (confirm_sw.exec() != QMessageBox::Yes) if (confirm_sw.exec() != QMessageBox::Yes)
{ {

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,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. // 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->QueryInterface(IID_PPV_ARGS(&s_debug)))) if (SUCCEEDED(hr) && SUCCEEDED(device.As(&s_debug)))
{ {
ComPtr<ID3D11InfoQueue> info_queue; 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_CORRUPTION, true);
info_queue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, 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)) 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))
@ -121,11 +121,10 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
return false; return false;
} }
hr = device->QueryInterface(IID_PPV_ARGS(&device1)); hr = device.As(&device1);
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>();
@ -171,6 +170,7 @@ std::vector<u32> GetAAModes(u32 adapter_index)
// Use temporary device if we don't have one already. // Use temporary device if we don't have one already.
Common::DynamicLibrary temp_lib; Common::DynamicLibrary temp_lib;
ComPtr<ID3D11Device> temp_device = device; ComPtr<ID3D11Device> temp_device = device;
D3D_FEATURE_LEVEL temp_feature_level = feature_level;
if (!temp_device) if (!temp_device)
{ {
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
@ -178,7 +178,7 @@ std::vector<u32> GetAAModes(u32 adapter_index)
return {}; return {};
ComPtr<IDXGIAdapter> adapter; 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; PFN_D3D11_CREATE_DEVICE d3d11_create_device;
if (!temp_lib.Open("d3d11.dll") || if (!temp_lib.Open("d3d11.dll") ||
@ -187,21 +187,21 @@ std::vector<u32> GetAAModes(u32 adapter_index)
return {}; return {};
} }
HRESULT hr = d3d11_create_device(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, HRESULT 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, &temp_device, nullptr, nullptr); temp_device.GetAddressOf(), &temp_feature_level, nullptr);
if (FAILED(hr)) if (FAILED(hr))
return {}; return {};
} }
// NOTE: D3D 10.0 doesn't support multisampled resources which are bound as depth buffers AND // 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. // 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 {}; return {};
std::vector<u32> aa_modes; 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; UINT quality_levels = 0;
if (SUCCEEDED(temp_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, samples, 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; 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

@ -347,10 +347,9 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
} }
ComPtr<ID3D11SamplerState> res; 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"); CHECK(SUCCEEDED(hr), "Creating D3D sampler state failed");
m_sampler.emplace(state.hex, res); return m_sampler.emplace(state.hex, std::move(res)).first->second.Get();
return res.Get();
} }
ID3D11BlendState* StateCache::Get(BlendingState state) ID3D11BlendState* StateCache::Get(BlendingState state)
@ -360,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];
@ -381,13 +380,13 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
tdesc.LogicOpEnable = TRUE; tdesc.LogicOpEnable = TRUE;
tdesc.LogicOp = logic_ops[state.logicmode]; tdesc.LogicOp = logic_ops[state.logicmode];
ID3D11BlendState1* res; ComPtr<ID3D11BlendState1> res;
HRESULT hr = D3D::device1->CreateBlendState1(&desc, &res); HRESULT hr = D3D::device1->CreateBlendState1(&desc, res.GetAddressOf());
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
m_blend.emplace(state.hex, res); return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
return res;
} }
WARN_LOG(VIDEO, "Creating D3D blend state failed with an error: %x", hr);
} }
D3D11_BLEND_DESC desc = {}; 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; tdesc.BlendOpAlpha = state.subtractAlpha ? D3D11_BLEND_OP_REV_SUBTRACT : D3D11_BLEND_OP_ADD;
ComPtr<ID3D11BlendState> res; 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"); CHECK(SUCCEEDED(hr), "Creating D3D blend state failed");
m_blend.emplace(state.hex, res); return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
return res.Get();
} }
ID3D11RasterizerState* StateCache::Get(RasterizationState state) ID3D11RasterizerState* StateCache::Get(RasterizationState state)
@ -447,10 +445,9 @@ ID3D11RasterizerState* StateCache::Get(RasterizationState state)
desc.ScissorEnable = TRUE; desc.ScissorEnable = TRUE;
ComPtr<ID3D11RasterizerState> res; 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"); CHECK(SUCCEEDED(hr), "Creating D3D rasterizer state failed");
m_raster.emplace(state.hex, res); return m_raster.emplace(state.hex, std::move(res)).first->second.Get();
return res.Get();
} }
ID3D11DepthStencilState* StateCache::Get(DepthState state) ID3D11DepthStencilState* StateCache::Get(DepthState state)
@ -490,10 +487,9 @@ ID3D11DepthStencilState* StateCache::Get(DepthState state)
} }
ComPtr<ID3D11DepthStencilState> res; 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"); CHECK(SUCCEEDED(hr), "Creating D3D depth stencil state failed");
m_depth.emplace(state.hex, res); return m_depth.emplace(state.hex, std::move(res)).first->second.Get();
return res.Get();
} }
D3D11_PRIMITIVE_TOPOLOGY StateCache::GetPrimitiveTopology(PrimitiveType primitive) D3D11_PRIMITIVE_TOPOLOGY StateCache::GetPrimitiveTopology(PrimitiveType primitive)

View File

@ -12,11 +12,12 @@
#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
{ {
DXTexture::DXTexture(const TextureConfig& config, ID3D11Texture2D* texture) DXTexture::DXTexture(const TextureConfig& config, ComPtr<ID3D11Texture2D> texture)
: AbstractTexture(config), m_texture(texture) : AbstractTexture(config), m_texture(std::move(texture))
{ {
} }
@ -41,7 +42,7 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels, CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels,
bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, 0); bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, 0);
ComPtr<ID3D11Texture2D> d3d_texture; ComPtr<ID3D11Texture2D> d3d_texture;
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &d3d_texture); HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf());
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("Failed to create %ux%ux%u D3D backing texture", config.width, config.height, PanicAlert("Failed to create %ux%ux%u D3D backing texture", config.width, config.height,
@ -49,14 +50,14 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
return nullptr; return nullptr;
} }
std::unique_ptr<DXTexture> tex(new DXTexture(config, d3d_texture.Get())); std::unique_ptr<DXTexture> tex(new DXTexture(config, std::move(d3d_texture)));
if (!tex->CreateSRV() || (config.IsComputeImage() && !tex->CreateUAV())) if (!tex->CreateSRV() || (config.IsComputeImage() && !tex->CreateUAV()))
return nullptr; return nullptr;
return tex; return tex;
} }
std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ID3D11Texture2D* texture) std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ComPtr<ID3D11Texture2D> texture)
{ {
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc); texture->GetDesc(&desc);
@ -70,7 +71,7 @@ std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ID3D11Texture2D* texture)
if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
config.flags |= AbstractTextureFlag_ComputeImage; config.flags |= AbstractTextureFlag_ComputeImage;
std::unique_ptr<DXTexture> tex(new DXTexture(config, texture)); std::unique_ptr<DXTexture> tex(new DXTexture(config, std::move(texture)));
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE && !tex->CreateSRV()) if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE && !tex->CreateSRV())
return nullptr; return nullptr;
if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS && !tex->CreateUAV()) if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS && !tex->CreateUAV())
@ -87,7 +88,8 @@ bool DXTexture::CreateSRV()
D3D11_SRV_DIMENSION_TEXTURE2DARRAY, D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, m_config.levels, 0, D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, m_config.levels, 0,
m_config.layers); m_config.layers);
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, &m_srv); DEBUG_ASSERT(!m_srv);
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, m_srv.GetAddressOf());
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("Failed to create %ux%ux%u D3D SRV", m_config.width, m_config.height, PanicAlert("Failed to create %ux%ux%u D3D SRV", m_config.width, m_config.height,
@ -103,7 +105,8 @@ bool DXTexture::CreateUAV()
const CD3D11_UNORDERED_ACCESS_VIEW_DESC desc( const CD3D11_UNORDERED_ACCESS_VIEW_DESC desc(
m_texture.Get(), D3D11_UAV_DIMENSION_TEXTURE2DARRAY, m_texture.Get(), D3D11_UAV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, 0, m_config.layers); D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, 0, m_config.layers);
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, &m_uav); DEBUG_ASSERT(!m_uav);
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, m_uav.GetAddressOf());
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("Failed to create %ux%ux%u D3D UAV", m_config.width, m_config.height, PanicAlert("Failed to create %ux%ux%u D3D UAV", m_config.width, m_config.height,
@ -161,8 +164,8 @@ void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8*
} }
DXStagingTexture::DXStagingTexture(StagingTextureType type, const TextureConfig& config, DXStagingTexture::DXStagingTexture(StagingTextureType type, const TextureConfig& config,
ID3D11Texture2D* tex) ComPtr<ID3D11Texture2D> tex)
: AbstractStagingTexture(type, config), m_tex(tex) : AbstractStagingTexture(type, config), m_tex(std::move(tex))
{ {
} }
@ -197,12 +200,12 @@ std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType ty
config.width, config.height, 1, 1, 0, usage, cpu_flags); config.width, config.height, 1, 1, 0, usage, cpu_flags);
ComPtr<ID3D11Texture2D> texture; ComPtr<ID3D11Texture2D> texture;
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &texture); HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, texture.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create staging texture"); CHECK(SUCCEEDED(hr), "Create staging texture");
if (FAILED(hr)) if (FAILED(hr))
return nullptr; return nullptr;
return std::unique_ptr<DXStagingTexture>(new DXStagingTexture(type, config, texture.Get())); return std::unique_ptr<DXStagingTexture>(new DXStagingTexture(type, config, std::move(texture)));
} }
void DXStagingTexture::CopyFromTexture(const AbstractTexture* src, void DXStagingTexture::CopyFromTexture(const AbstractTexture* src,
@ -316,11 +319,12 @@ void DXStagingTexture::Flush()
DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment, DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format, AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples, u32 width, u32 height, u32 layers, u32 samples,
ID3D11RenderTargetView* rtv, ID3D11RenderTargetView* integer_rtv, ComPtr<ID3D11RenderTargetView> rtv,
ID3D11DepthStencilView* dsv) ComPtr<ID3D11RenderTargetView> integer_rtv,
ComPtr<ID3D11DepthStencilView> dsv)
: AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width, : AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width,
height, layers, samples), height, layers, samples),
m_rtv(rtv), m_integer_rtv(integer_rtv), m_dsv(dsv) m_rtv(std::move(rtv)), m_integer_rtv(std::move(integer_rtv)), m_dsv(std::move(dsv))
{ {
} }
@ -351,20 +355,20 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
D3D11_RTV_DIMENSION_TEXTURE2DARRAY, D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), false), 0, 0, D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), false), 0, 0,
color_attachment->GetLayers()); color_attachment->GetLayers());
HRESULT hr = HRESULT hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, &rtv); rtv.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer"); CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
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,
&integer_rtv); integer_rtv.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create integer render target view for framebuffer"); CHECK(SUCCEEDED(hr), "Create integer render target view for framebuffer");
} }
} }
@ -377,16 +381,16 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
D3D11_DSV_DIMENSION_TEXTURE2DARRAY, D3D11_DSV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetDSVFormatForAbstractFormat(depth_attachment->GetFormat()), 0, 0, D3DCommon::GetDSVFormatForAbstractFormat(depth_attachment->GetFormat()), 0, 0,
depth_attachment->GetLayers(), 0); depth_attachment->GetLayers(), 0);
HRESULT hr = HRESULT hr = D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc,
D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc, &dsv); dsv.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer"); CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
if (FAILED(hr)) if (FAILED(hr))
return nullptr; return nullptr;
} }
return std::make_unique<DXFramebuffer>(color_attachment, depth_attachment, color_format, return std::make_unique<DXFramebuffer>(color_attachment, depth_attachment, color_format,
depth_format, width, height, layers, samples, rtv.Get(), depth_format, width, height, layers, samples,
integer_rtv.Get(), dsv.Get()); std::move(rtv), std::move(integer_rtv), std::move(dsv));
} }
} // namespace DX11 } // namespace DX11

View File

@ -20,7 +20,7 @@ public:
~DXTexture(); ~DXTexture();
static std::unique_ptr<DXTexture> Create(const TextureConfig& config); static std::unique_ptr<DXTexture> Create(const TextureConfig& config);
static std::unique_ptr<DXTexture> CreateAdopted(ID3D11Texture2D* texture); static std::unique_ptr<DXTexture> CreateAdopted(ComPtr<ID3D11Texture2D> texture);
void CopyRectangleFromTexture(const AbstractTexture* src, void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer, const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
@ -36,7 +36,7 @@ public:
ID3D11UnorderedAccessView* GetD3DUAV() const { return m_uav.Get(); } ID3D11UnorderedAccessView* GetD3DUAV() const { return m_uav.Get(); }
private: private:
DXTexture(const TextureConfig& config, ID3D11Texture2D* texture); DXTexture(const TextureConfig& config, ComPtr<ID3D11Texture2D> texture);
bool CreateSRV(); bool CreateSRV();
bool CreateUAV(); bool CreateUAV();
@ -67,7 +67,8 @@ public:
const TextureConfig& config); const TextureConfig& config);
private: private:
DXStagingTexture(StagingTextureType type, const TextureConfig& config, ID3D11Texture2D* tex); DXStagingTexture(StagingTextureType type, const TextureConfig& config,
ComPtr<ID3D11Texture2D> tex);
ComPtr<ID3D11Texture2D> m_tex = nullptr; ComPtr<ID3D11Texture2D> m_tex = nullptr;
}; };
@ -77,8 +78,8 @@ class DXFramebuffer final : public AbstractFramebuffer
public: public:
DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment, DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width, AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
u32 height, u32 layers, u32 samples, ID3D11RenderTargetView* rtv, u32 height, u32 layers, u32 samples, ComPtr<ID3D11RenderTargetView> rtv,
ID3D11RenderTargetView* integer_rtv, ID3D11DepthStencilView* dsv); ComPtr<ID3D11RenderTargetView> integer_rtv, ComPtr<ID3D11DepthStencilView> dsv);
~DXFramebuffer() override; ~DXFramebuffer() override;
ID3D11RenderTargetView* const* GetRTVArray() const { return m_rtv.GetAddressOf(); } ID3D11RenderTargetView* const* GetRTVArray() const { return m_rtv.GetAddressOf(); }

View File

@ -82,10 +82,10 @@ void Renderer::Create3DVisionTexture(int width, int height)
CD3D11_TEXTURE2D_DESC texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width * 2, height + 1, 1, 1, CD3D11_TEXTURE2D_DESC texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width * 2, height + 1, 1, 1,
D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0, 0); D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0, 0);
ID3D11Texture2D* texture; ComPtr<ID3D11Texture2D> texture;
HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, &texture); HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, texture.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create 3D Vision Texture"); CHECK(SUCCEEDED(hr), "Create 3D Vision Texture");
m_3d_vision_texture = DXTexture::CreateAdopted(texture); m_3d_vision_texture = DXTexture::CreateAdopted(std::move(texture));
m_3d_vision_framebuffer = DXFramebuffer::Create(m_3d_vision_texture.get(), nullptr); m_3d_vision_framebuffer = DXFramebuffer::Create(m_3d_vision_texture.get(), nullptr);
} }

View File

@ -33,7 +33,7 @@ bool SwapChain::CreateSwapChainBuffers()
if (FAILED(hr)) if (FAILED(hr))
return false; return false;
m_texture = DXTexture::CreateAdopted(texture.Get()); m_texture = DXTexture::CreateAdopted(std::move(texture));
if (!m_texture) if (!m_texture)
return false; return false;

View File

@ -17,6 +17,7 @@ public:
std::string GetName() const override; std::string GetName() const override;
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override;
void InitBackendInfo() override; void InitBackendInfo() override;

View File

@ -37,6 +37,31 @@ std::string VideoBackend::GetDisplayName() const
return _trans("Direct3D 11"); return _trans("Direct3D 11");
} }
std::optional<std::string> VideoBackend::GetWarningMessage() const
{
std::optional<std::string> result;
// If user is on Win7, show a warning about partial DX11.1 support
// This is being called BEFORE FillBackendInfo is called for this backend,
// so query for logic op support manually
bool supportsLogicOp = false;
if (D3DCommon::LoadLibraries())
{
supportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter);
D3DCommon::UnloadLibraries();
}
if (!supportsLogicOp)
{
result = _trans("Direct3D 11 renderer requires support for features not supported by your "
"system configuration. This is most likely because you are using Windows 7. "
"You may still use this backend, but you might encounter graphical artifacts."
"\n\nDo you really want to switch to Direct3D 11? If unsure, select 'No'.");
}
return result;
}
void VideoBackend::InitBackendInfo() void VideoBackend::InitBackendInfo()
{ {
if (!D3DCommon::LoadLibraries()) if (!D3DCommon::LoadLibraries())
@ -63,16 +88,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 +106,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);

View File

@ -180,7 +180,7 @@ bool DXContext::CreateDevice(u32 adapter_index, bool enable_debug_layer)
if (enable_debug_layer) if (enable_debug_layer)
{ {
ComPtr<ID3D12InfoQueue> info_queue; ComPtr<ID3D12InfoQueue> info_queue;
if (SUCCEEDED(m_device->QueryInterface(IID_PPV_ARGS(&info_queue)))) if (SUCCEEDED(m_device.As(&info_queue)))
{ {
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE); info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE); info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);

View File

@ -53,6 +53,13 @@ std::string VideoSoftware::GetDisplayName() const
return _trans("Software Renderer"); return _trans("Software Renderer");
} }
std::optional<std::string> VideoSoftware::GetWarningMessage() const
{
return _trans("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'.");
}
void VideoSoftware::InitBackendInfo() void VideoSoftware::InitBackendInfo()
{ {
g_Config.backend_info.api_type = APIType::Nothing; g_Config.backend_info.api_type = APIType::Nothing;

View File

@ -16,6 +16,7 @@ class VideoSoftware : public VideoBackendBase
std::string GetName() const override; std::string GetName() const override;
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override;
void InitBackendInfo() override; void InitBackendInfo() override;
}; };

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
@ -42,6 +43,7 @@ public:
virtual std::string GetName() const = 0; virtual std::string GetName() const = 0;
virtual std::string GetDisplayName() const { return GetName(); } virtual std::string GetDisplayName() const { return GetName(); }
virtual void InitBackendInfo() = 0; virtual void InitBackendInfo() = 0;
virtual std::optional<std::string> GetWarningMessage() const { return {}; }
// Prepares a native window for rendering. This is called on the main thread, or the // Prepares a native window for rendering. This is called on the main thread, or the
// thread which owns the window. // thread which owns the window.