diff --git a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp index 978da839bc..28a2fd5182 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp @@ -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) { diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index ab3ea9321c..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,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(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->QueryInterface(IID_PPV_ARGS(&s_debug)))) + if (SUCCEEDED(hr) && SUCCEEDED(device.As(&s_debug))) { ComPtr 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(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)) @@ -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(); @@ -171,6 +170,7 @@ std::vector GetAAModes(u32 adapter_index) // Use temporary device if we don't have one already. Common::DynamicLibrary temp_lib; ComPtr temp_device = device; + D3D_FEATURE_LEVEL temp_feature_level = feature_level; if (!temp_device) { ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); @@ -178,7 +178,7 @@ std::vector GetAAModes(u32 adapter_index) return {}; ComPtr 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 GetAAModes(u32 adapter_index) return {}; } - HRESULT hr = d3d11_create_device(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, - s_supported_feature_levels.data(), - static_cast(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(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 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 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 15e84f2018..8923a9e676 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -347,10 +347,9 @@ ID3D11SamplerState* StateCache::Get(SamplerState state) } ComPtr 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 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 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 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 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) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index 30737ff318..e2e818d637 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -12,11 +12,12 @@ #include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/DXTexture.h" #include "VideoBackends/D3DCommon/Common.h" +#include "VideoCommon/VideoConfig.h" namespace DX11 { -DXTexture::DXTexture(const TextureConfig& config, ID3D11Texture2D* texture) - : AbstractTexture(config), m_texture(texture) +DXTexture::DXTexture(const TextureConfig& config, ComPtr texture) + : AbstractTexture(config), m_texture(std::move(texture)) { } @@ -41,7 +42,7 @@ std::unique_ptr DXTexture::Create(const TextureConfig& config) CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels, bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, 0); ComPtr d3d_texture; - HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &d3d_texture); + HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf()); if (FAILED(hr)) { PanicAlert("Failed to create %ux%ux%u D3D backing texture", config.width, config.height, @@ -49,14 +50,14 @@ std::unique_ptr DXTexture::Create(const TextureConfig& config) return nullptr; } - std::unique_ptr tex(new DXTexture(config, d3d_texture.Get())); + std::unique_ptr tex(new DXTexture(config, std::move(d3d_texture))); if (!tex->CreateSRV() || (config.IsComputeImage() && !tex->CreateUAV())) return nullptr; return tex; } -std::unique_ptr DXTexture::CreateAdopted(ID3D11Texture2D* texture) +std::unique_ptr DXTexture::CreateAdopted(ComPtr texture) { D3D11_TEXTURE2D_DESC desc; texture->GetDesc(&desc); @@ -70,7 +71,7 @@ std::unique_ptr DXTexture::CreateAdopted(ID3D11Texture2D* texture) if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) config.flags |= AbstractTextureFlag_ComputeImage; - std::unique_ptr tex(new DXTexture(config, texture)); + std::unique_ptr tex(new DXTexture(config, std::move(texture))); if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE && !tex->CreateSRV()) return nullptr; if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS && !tex->CreateUAV()) @@ -87,7 +88,8 @@ bool DXTexture::CreateSRV() D3D11_SRV_DIMENSION_TEXTURE2DARRAY, D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, m_config.levels, 0, 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)) { 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( m_texture.Get(), D3D11_UAV_DIMENSION_TEXTURE2DARRAY, 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)) { 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, - ID3D11Texture2D* tex) - : AbstractStagingTexture(type, config), m_tex(tex) + ComPtr tex) + : AbstractStagingTexture(type, config), m_tex(std::move(tex)) { } @@ -197,12 +200,12 @@ std::unique_ptr DXStagingTexture::Create(StagingTextureType ty config.width, config.height, 1, 1, 0, usage, cpu_flags); ComPtr texture; - HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &texture); + HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, texture.GetAddressOf()); CHECK(SUCCEEDED(hr), "Create staging texture"); if (FAILED(hr)) return nullptr; - return std::unique_ptr(new DXStagingTexture(type, config, texture.Get())); + return std::unique_ptr(new DXStagingTexture(type, config, std::move(texture))); } void DXStagingTexture::CopyFromTexture(const AbstractTexture* src, @@ -316,11 +319,12 @@ void DXStagingTexture::Flush() DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment, AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width, u32 height, u32 layers, u32 samples, - ID3D11RenderTargetView* rtv, ID3D11RenderTargetView* integer_rtv, - ID3D11DepthStencilView* dsv) + ComPtr rtv, + ComPtr integer_rtv, + ComPtr dsv) : AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width, 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::Create(DXTexture* color_attachment D3D11_RTV_DIMENSION_TEXTURE2DARRAY, D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), false), 0, 0, color_attachment->GetLayers()); - HRESULT hr = - D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, &rtv); + HRESULT hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, + rtv.GetAddressOf()); CHECK(SUCCEEDED(hr), "Create render target view for framebuffer"); 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, - &integer_rtv); + integer_rtv.GetAddressOf()); CHECK(SUCCEEDED(hr), "Create integer render target view for framebuffer"); } } @@ -377,16 +381,16 @@ std::unique_ptr DXFramebuffer::Create(DXTexture* color_attachment D3D11_DSV_DIMENSION_TEXTURE2DARRAY, D3DCommon::GetDSVFormatForAbstractFormat(depth_attachment->GetFormat()), 0, 0, depth_attachment->GetLayers(), 0); - HRESULT hr = - D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc, &dsv); + HRESULT hr = D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc, + dsv.GetAddressOf()); CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer"); if (FAILED(hr)) return nullptr; } return std::make_unique(color_attachment, depth_attachment, color_format, - depth_format, width, height, layers, samples, rtv.Get(), - integer_rtv.Get(), dsv.Get()); + depth_format, width, height, layers, samples, + std::move(rtv), std::move(integer_rtv), std::move(dsv)); } } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/DXTexture.h b/Source/Core/VideoBackends/D3D/DXTexture.h index 21e38c35bb..1f33e3b217 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.h +++ b/Source/Core/VideoBackends/D3D/DXTexture.h @@ -20,7 +20,7 @@ public: ~DXTexture(); static std::unique_ptr Create(const TextureConfig& config); - static std::unique_ptr CreateAdopted(ID3D11Texture2D* texture); + static std::unique_ptr CreateAdopted(ComPtr texture); void CopyRectangleFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& src_rect, u32 src_layer, @@ -36,7 +36,7 @@ public: ID3D11UnorderedAccessView* GetD3DUAV() const { return m_uav.Get(); } private: - DXTexture(const TextureConfig& config, ID3D11Texture2D* texture); + DXTexture(const TextureConfig& config, ComPtr texture); bool CreateSRV(); bool CreateUAV(); @@ -67,7 +67,8 @@ public: const TextureConfig& config); private: - DXStagingTexture(StagingTextureType type, const TextureConfig& config, ID3D11Texture2D* tex); + DXStagingTexture(StagingTextureType type, const TextureConfig& config, + ComPtr tex); ComPtr m_tex = nullptr; }; @@ -77,8 +78,8 @@ class DXFramebuffer final : public AbstractFramebuffer public: DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment, AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width, - u32 height, u32 layers, u32 samples, ID3D11RenderTargetView* rtv, - ID3D11RenderTargetView* integer_rtv, ID3D11DepthStencilView* dsv); + u32 height, u32 layers, u32 samples, ComPtr rtv, + ComPtr integer_rtv, ComPtr dsv); ~DXFramebuffer() override; ID3D11RenderTargetView* const* GetRTVArray() const { return m_rtv.GetAddressOf(); } diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index e058bd1c66..d16a530c81 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -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, D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0, 0); - ID3D11Texture2D* texture; - HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, &texture); + ComPtr texture; + HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, texture.GetAddressOf()); 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); } diff --git a/Source/Core/VideoBackends/D3D/SwapChain.cpp b/Source/Core/VideoBackends/D3D/SwapChain.cpp index 7c60554859..7a2e889194 100644 --- a/Source/Core/VideoBackends/D3D/SwapChain.cpp +++ b/Source/Core/VideoBackends/D3D/SwapChain.cpp @@ -33,7 +33,7 @@ bool SwapChain::CreateSwapChainBuffers() if (FAILED(hr)) return false; - m_texture = DXTexture::CreateAdopted(texture.Get()); + m_texture = DXTexture::CreateAdopted(std::move(texture)); if (!m_texture) return false; diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index 0b4c61fc66..e5b996c7e1 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -17,6 +17,7 @@ public: std::string GetName() const override; std::string GetDisplayName() const override; + std::optional GetWarningMessage() const override; void InitBackendInfo() override; diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index d87965deff..33c9117f25 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -37,6 +37,31 @@ std::string VideoBackend::GetDisplayName() const return _trans("Direct3D 11"); } +std::optional VideoBackend::GetWarningMessage() const +{ + std::optional 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() { if (!D3DCommon::LoadLibraries()) @@ -63,16 +88,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 +106,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); diff --git a/Source/Core/VideoBackends/D3D12/DXContext.cpp b/Source/Core/VideoBackends/D3D12/DXContext.cpp index 63eb4dca51..6793c915e0 100644 --- a/Source/Core/VideoBackends/D3D12/DXContext.cpp +++ b/Source/Core/VideoBackends/D3D12/DXContext.cpp @@ -180,7 +180,7 @@ bool DXContext::CreateDevice(u32 adapter_index, bool enable_debug_layer) if (enable_debug_layer) { ComPtr 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_WARNING, TRUE); diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 1d02660cf7..4309e39021 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -53,6 +53,13 @@ std::string VideoSoftware::GetDisplayName() const return _trans("Software Renderer"); } +std::optional 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() { g_Config.backend_info.api_type = APIType::Nothing; diff --git a/Source/Core/VideoBackends/Software/VideoBackend.h b/Source/Core/VideoBackends/Software/VideoBackend.h index bad120d6a1..10d70722cd 100644 --- a/Source/Core/VideoBackends/Software/VideoBackend.h +++ b/Source/Core/VideoBackends/Software/VideoBackend.h @@ -16,6 +16,7 @@ class VideoSoftware : public VideoBackendBase std::string GetName() const override; std::string GetDisplayName() const override; + std::optional GetWarningMessage() const override; void InitBackendInfo() override; }; diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 0a248dbd70..c7587dea9e 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include @@ -42,6 +43,7 @@ public: virtual std::string GetName() const = 0; virtual std::string GetDisplayName() const { return GetName(); } virtual void InitBackendInfo() = 0; + virtual std::optional GetWarningMessage() const { return {}; } // Prepares a native window for rendering. This is called on the main thread, or the // thread which owns the window.