diff --git a/Source/Core/DolphinLibretro/Video.cpp b/Source/Core/DolphinLibretro/Video.cpp index 50b8ebb57b..c4c44da821 100644 --- a/Source/Core/DolphinLibretro/Video.cpp +++ b/Source/Core/DolphinLibretro/Video.cpp @@ -11,7 +11,6 @@ #include #ifdef _WIN32 -#include "Common/DynamicLibrary.h" #include "VideoBackends/D3D/VideoBackend.h" #include "VideoBackends/D3D/D3DGfx.h" #include "VideoBackends/D3D/D3DVertexManager.h" @@ -85,8 +84,6 @@ static unsigned s_gpu_fields; static unsigned s_gpu_fields_seen; #ifdef _WIN32 -static Common::DynamicLibrary d3d11_library; -static Common::DynamicLibrary d3d12_library; /* Direct3D 11 version 2: the interface, and the levels of its context * lock this thread holds */ static retro_hw_render_interface_d3d11* s_d3d11_v2; @@ -372,19 +369,6 @@ static void ContextResetD3D11(retro_hw_render_interface_d3d11* d3d, const Window DX11::D3D::context = d3d->context; DX11::D3D::feature_level = d3d->featureLevel; - if (!d3d11_library.IsOpen() && !d3d11_library.Open("d3d11.dll")) - { - d3d11_library.Close(); - ERROR_LOG_FMT(VIDEO, "Failed to load D3D11 Libraries"); - return; - } - - if (!D3DCommon::LoadLibraries()) - { - ERROR_LOG_FMT(VIDEO, "Failed to load the dxgi library"); - return; - } - if (FAILED(DX11::D3D::device.As(&DX11::D3D::device1))) { WARN_LOG_FMT(VIDEO, "Missing Direct3D 11.1 support. Logical operations will not be supported."); @@ -402,6 +386,7 @@ static void ContextResetD3D11(retro_hw_render_interface_d3d11* d3d, const Window } d3d11->FillD3DBackendInfo(); + g_Config.VerifyValidity(); UpdateActiveConfig(); std::unique_ptr output = std::make_unique( @@ -500,19 +485,6 @@ void ContextReset(void) return; } - if (!d3d12_library.IsOpen() && !d3d12_library.Open("d3d12.dll")) - { - d3d12_library.Close(); - ERROR_LOG_FMT(VIDEO, "Failed to load D3D12 Libraries"); - return; - } - - if (!D3DCommon::LoadLibraries()) - { - ERROR_LOG_FMT(VIDEO, "Failed to load the dxgi library"); - return; - } - // Create D3D12 context with RetroArch's device and queue ID3D12Device* ra_device = static_cast(d3d12->device); ID3D12CommandQueue* ra_queue = static_cast(d3d12->queue); @@ -523,6 +495,9 @@ void ContextReset(void) return; } + static_cast(g_video_backend)->FillD3D12BackendInfo(); + g_Config.VerifyValidity(); + Microsoft::WRL::ComPtr device1; if (FAILED(DX12::g_dx_context->GetDevice()->QueryInterface(IID_PPV_ARGS(&device1)))) { @@ -674,8 +649,6 @@ void ContextDestroy(void) case RETRO_HW_CONTEXT_D3D12: #ifdef _WIN32 DX12::DXContext::Destroy(); - D3DCommon::UnloadLibraries(); - d3d12_library.Close(); #endif break; case RETRO_HW_CONTEXT_D3D11: @@ -693,8 +666,6 @@ void ContextDestroy(void) DX11::D3D::device1 = nullptr; DX11::D3D::context = nullptr; DX11::D3D::stateman.reset(); - D3DCommon::UnloadLibraries(); - d3d11_library.Close(); #endif break; case RETRO_HW_CONTEXT_VULKAN: diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 352de6d924..10ee64159c 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -7,7 +7,6 @@ #include #include "Common/CommonTypes.h" -#include "Common/DynamicLibrary.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Core/Config/GraphicsSettings.h" @@ -20,21 +19,13 @@ namespace DX11 { -static Common::DynamicLibrary s_d3d11_library; namespace D3D { -ComPtr dxgi_factory; ComPtr device; ComPtr device1; ComPtr context; D3D_FEATURE_LEVEL feature_level; -constexpr std::array s_supported_feature_levels{ - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, -}; - void Destroy() { stateman.reset(); @@ -54,44 +45,13 @@ void Destroy() else NOTICE_LOG_FMT(VIDEO, "Successfully released all device references!"); - dxgi_factory.Reset(); - D3DCommon::UnloadLibraries(); - s_d3d11_library.Close(); } -std::vector GetAAModes(u32 adapter_index) +std::vector GetAAModes() { - // 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); - if (!temp_dxgi_factory) - return {}; - - ComPtr adapter; - temp_dxgi_factory->EnumAdapters(adapter_index, &adapter); - - PFN_D3D11_CREATE_DEVICE d3d11_create_device; - if (!temp_lib.Open("d3d11.dll") || - !temp_lib.GetSymbol("D3D11CreateDevice", &d3d11_create_device)) - { - return {}; - } - - 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, &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_feature_level == D3D_FEATURE_LEVEL_10_0) + if (feature_level == D3D_FEATURE_LEVEL_10_0) return {}; const DXGI_FORMAT target_format = @@ -101,7 +61,7 @@ std::vector GetAAModes(u32 adapter_index) { UINT quality_levels = 0; if (SUCCEEDED( - temp_device->CheckMultisampleQualityLevels(target_format, samples, &quality_levels)) && + device->CheckMultisampleQualityLevels(target_format, samples, &quality_levels)) && quality_levels > 0) { aa_modes.push_back(samples); @@ -120,46 +80,14 @@ bool SupportsTextureFormat(DXGI_FORMAT format) return (support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; } -bool SupportsLogicOp(u32 adapter_index) +bool SupportsLogicOp() { - // 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); - - 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, nullptr, nullptr); - if (FAILED(hr)) - return false; - - if (FAILED(temp_device.As(&temp_device1))) - return false; - } - - if (!temp_device1) + if (!device1) return false; D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; - if (FAILED(temp_device1->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, - sizeof(options)))) + if (FAILED(device1->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, + sizeof(options)))) { return false; } diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index 42b6f31f46..8f60609d90 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -18,7 +18,6 @@ using Microsoft::WRL::ComPtr; namespace D3D { -extern ComPtr dxgi_factory; extern ComPtr device; extern ComPtr device1; extern ComPtr context; @@ -26,14 +25,14 @@ extern D3D_FEATURE_LEVEL feature_level; void Destroy(); -// Returns a list of supported AA modes for the current device. -std::vector GetAAModes(u32 adapter_index); +// The AA modes the frontend's device supports. +std::vector GetAAModes(); // Checks for support of the given texture format. bool SupportsTextureFormat(DXGI_FORMAT format); -// Checks for logic op support. -bool SupportsLogicOp(u32 adapter_index); +// Logic op support on the frontend's device. +bool SupportsLogicOp(); } // namespace D3D diff --git a/Source/Core/VideoBackends/D3D/D3DMain.cpp b/Source/Core/VideoBackends/D3D/D3DMain.cpp index cfe84e4c08..169e8c67c9 100644 --- a/Source/Core/VideoBackends/D3D/D3DMain.cpp +++ b/Source/Core/VideoBackends/D3D/D3DMain.cpp @@ -37,39 +37,9 @@ std::string VideoBackend::GetDisplayName() const return _trans("Direct3D 11"); } -std::optional VideoBackend::GetWarningMessage() const -{ - std::optional result; - - // If relevant, 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("The Direct3D 11 renderer requires support for features not supported by your " - "system configuration. You may still use this backend, but you will encounter " - "graphical artifacts in certain games.\n" - "\n" - "Do you really want to switch to Direct3D 11? If unsure, select 'No'."); - } - - return result; -} - void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { - if (!D3DCommon::LoadLibraries()) - return; - FillBackendInfo(); - D3DCommon::UnloadLibraries(); } void VideoBackend::FillBackendInfo() @@ -109,15 +79,19 @@ void VideoBackend::FillBackendInfo() g_backend_info.bSupportsCoarseDerivatives = true; g_backend_info.bSupportsTextureQueryLevels = true; g_backend_info.bSupportsLodBiasInSampler = true; - g_backend_info.bSupportsLogicOp = - !Common::is_uwp() && D3D::SupportsLogicOp(g_Config.iAdapter); + g_backend_info.bSupportsLogicOp = !Common::is_uwp() && D3D::device1 && D3D::SupportsLogicOp(); g_backend_info.bSupportsSettingObjectNames = true; g_backend_info.bSupportsPartialMultisampleResolve = true; g_backend_info.bSupportsDynamicVertexLoader = false; g_backend_info.bSupportsHDROutput = true; - g_backend_info.Adapters = D3DCommon::GetAdapterNames(); - g_backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter); + // The frontend picks the adapter and hands over its device: until then, + // the counts every D3D11 device has, narrowed to the device's own after. + g_backend_info.Adapters.clear(); + if (D3D::device) + g_backend_info.AAModes = D3D::GetAAModes(); + else + g_backend_info.AAModes = {1, 2, 4, 8}; // Override optional features if we are actually booting. if (D3D::device) diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index be5e999859..610e95ea55 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -16,7 +16,6 @@ public: std::string GetConfigName() const override; std::string GetDisplayName() const override; - std::optional GetWarningMessage() const override; void InitBackendInfo(const WindowSystemInfo& wsi) override; diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.cpp b/Source/Core/VideoBackends/D3D12/DX12Context.cpp index 9c8c5da7e6..fb6bf615ac 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Context.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Context.cpp @@ -35,35 +35,9 @@ DXContext::~DXContext() CloseHandle(m_fence_event); } -std::vector DXContext::GetAAModes(u32 adapter_index) +std::vector DXContext::GetAAModes() { - // Use a temporary device if we aren't booting. - Common::DynamicLibrary temp_lib; - ComPtr temp_device = g_dx_context ? g_dx_context->m_device : nullptr; - if (!temp_device) - { - ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); - if (!temp_dxgi_factory) - return {}; - - ComPtr adapter; - HRESULT hr = temp_dxgi_factory->EnumAdapters(adapter_index, &adapter); - - if (!SUCCEEDED(hr)) - return {}; - - PFN_D3D12_CREATE_DEVICE d3d12_create_device; - if (!temp_lib.Open("d3d12.dll") || - !temp_lib.GetSymbol("D3D12CreateDevice", &d3d12_create_device)) - { - return {}; - } - - hr = d3d12_create_device(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&temp_device)); - if (!SUCCEEDED(hr)) - return {}; - } - + ID3D12Device* const device = m_device.Get(); const DXGI_FORMAT target_format = D3DCommon::GetDXGIFormatForAbstractFormat(FramebufferManager::GetEFBColorFormat(), false); std::vector aa_modes; @@ -73,9 +47,8 @@ std::vector DXContext::GetAAModes(u32 adapter_index) multisample_quality_levels.Format = target_format; multisample_quality_levels.SampleCount = samples; - temp_device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, - &multisample_quality_levels, - sizeof(multisample_quality_levels)); + device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, + &multisample_quality_levels, sizeof(multisample_quality_levels)); if (multisample_quality_levels.NumQualityLevels > 0) aa_modes.push_back(samples); @@ -110,7 +83,6 @@ void DXContext::Destroy() s_d3d12_serialize_root_signature = nullptr; s_d3d12_library.Close(); - D3DCommon::UnloadLibraries(); } bool DXContext::CreateFence() @@ -495,12 +467,6 @@ bool DXContext::CreateWithExternalDevice(ID3D12Device* device, ID3D12CommandQueu return false; } - if (!D3DCommon::LoadLibraries()) - { - s_d3d12_library.Close(); - return false; - } - g_dx_context.reset(new DXContext()); device->AddRef(); @@ -509,14 +475,6 @@ bool DXContext::CreateWithExternalDevice(ID3D12Device* device, ID3D12CommandQueu queue->AddRef(); g_dx_context->m_command_queue.Attach(queue); - g_dx_context->m_dxgi_factory = D3DCommon::CreateDXGIFactory(false); - if (!g_dx_context->m_dxgi_factory) - { - ERROR_LOG_FMT(VIDEO, "Failed to create DXGI factory"); - Destroy(); - return false; - } - if (!g_dx_context->CreateFence()) { ERROR_LOG_FMT(VIDEO, "Failed to create fence"); diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.h b/Source/Core/VideoBackends/D3D12/DX12Context.h index c4bb75ca5f..c3d01cd891 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Context.h +++ b/Source/Core/VideoBackends/D3D12/DX12Context.h @@ -51,12 +51,12 @@ public: ~DXContext(); // Returns a list of AA modes. - static std::vector GetAAModes(u32 adapter_index); + // The AA modes the frontend's device supports. + std::vector GetAAModes(); // Destroys active context. static void Destroy(); - IDXGIFactory* GetDXGIFactory() const { return m_dxgi_factory.Get(); } ID3D12Device* GetDevice() const { return m_device.Get(); } ID3D12CommandQueue* GetCommandQueue() const { return m_command_queue.Get(); } @@ -172,7 +172,6 @@ private: void MoveToNextCommandList(); void DestroyPendingResources(CommandListResources& cmdlist); - ComPtr m_dxgi_factory; ComPtr m_device; ComPtr m_command_queue; diff --git a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp index ba4ba45c73..cac81a0ec6 100644 --- a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp +++ b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp @@ -37,11 +37,7 @@ std::string VideoBackend::GetDisplayName() const void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { - if (!D3DCommon::LoadLibraries()) - return; - FillBackendInfo(); - D3DCommon::UnloadLibraries(); } void VideoBackend::FillBackendInfo() @@ -77,8 +73,13 @@ void VideoBackend::FillBackendInfo() g_backend_info.bSupportsLargePoints = false; g_backend_info.bSupportsDepthReadback = true; g_backend_info.bSupportsPartialDepthCopies = false; - g_backend_info.Adapters = D3DCommon::GetAdapterNames(); - g_backend_info.AAModes = DXContext::GetAAModes(g_Config.iAdapter); + // The frontend picks the adapter and hands over its device: until then, + // the counts every D3D12 device has, narrowed to the device's own after. + g_backend_info.Adapters.clear(); + if (g_dx_context) + g_backend_info.AAModes = g_dx_context->GetAAModes(); + else + g_backend_info.AAModes = {1, 2, 4, 8}; g_backend_info.bSupportsShaderBinaries = true; g_backend_info.bSupportsPipelineCacheData = true; g_backend_info.bSupportsCoarseDerivatives = true; diff --git a/Source/Core/VideoBackends/D3D12/VideoBackend.h b/Source/Core/VideoBackends/D3D12/VideoBackend.h index 7be8291bcd..19303a1af3 100644 --- a/Source/Core/VideoBackends/D3D12/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D12/VideoBackend.h @@ -21,6 +21,9 @@ public: static constexpr const char* CONFIG_NAME = "D3D12"; + // Again, from the frontend's device once the context has it. + void FillD3D12BackendInfo() { FillBackendInfo(); } + private: void FillBackendInfo(); }; diff --git a/Source/Core/VideoBackends/D3DCommon/D3DCommon.cpp b/Source/Core/VideoBackends/D3DCommon/D3DCommon.cpp index 9681b8a88c..c0914675a1 100644 --- a/Source/Core/VideoBackends/D3DCommon/D3DCommon.cpp +++ b/Source/Core/VideoBackends/D3DCommon/D3DCommon.cpp @@ -9,8 +9,6 @@ #include #include "Common/Assert.h" -#include "Common/DynamicLibrary.h" -#include "Common/HRWrap.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" @@ -19,97 +17,6 @@ namespace D3DCommon { -static Common::DynamicLibrary s_dxgi_library; -static bool s_libraries_loaded = false; - -static HRESULT (*create_dxgi_factory)(REFIID riid, _COM_Outptr_ void** ppFactory); -static HRESULT (*create_dxgi_factory2)(UINT Flags, REFIID riid, void** ppFactory); - -bool LoadLibraries() -{ - if (s_libraries_loaded) - return true; - - if (!s_dxgi_library.Open("dxgi.dll")) - { - PanicAlertFmtT("Failed to load dxgi.dll"); - return false; - } - - // Required symbols. - if (!s_dxgi_library.GetSymbol("CreateDXGIFactory", &create_dxgi_factory)) - { - PanicAlertFmtT("Failed to find one or more D3D symbols"); - s_dxgi_library.Close(); - return false; - } - - // Optional symbols. - s_dxgi_library.GetSymbol("CreateDXGIFactory2", &create_dxgi_factory2); - s_libraries_loaded = true; - return true; -} - -void UnloadLibraries() -{ - create_dxgi_factory = nullptr; - create_dxgi_factory2 = nullptr; - s_dxgi_library.Close(); - s_libraries_loaded = false; -} - -Microsoft::WRL::ComPtr CreateDXGIFactory(bool debug_device) -{ - Microsoft::WRL::ComPtr factory; - - // Use Win8.1 version if available. - if (create_dxgi_factory2 && - SUCCEEDED(create_dxgi_factory2(debug_device ? DXGI_CREATE_FACTORY_DEBUG : 0, - IID_PPV_ARGS(&factory)))) - { - return factory; - } - - // Fallback to original version, without debug support. - HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(&factory)); - if (FAILED(hr)) - { - PanicAlertFmt("CreateDXGIFactory() failed: {}", Common::HRWrap(hr)); - return nullptr; - } - - return factory; -} - -std::vector GetAdapterNames() -{ - Microsoft::WRL::ComPtr factory; - HRESULT hr = E_FAIL; - - if (create_dxgi_factory2) - hr = create_dxgi_factory2(0, IID_PPV_ARGS(&factory)); - else if (create_dxgi_factory) - hr = create_dxgi_factory(IID_PPV_ARGS(&factory)); - - if (FAILED(hr)) - return {}; - - std::vector adapters; - Microsoft::WRL::ComPtr adapter; - while (factory->EnumAdapters(static_cast(adapters.size()), &adapter) != - DXGI_ERROR_NOT_FOUND) - { - std::string name; - DXGI_ADAPTER_DESC desc; - if (SUCCEEDED(adapter->GetDesc(&desc))) - name = WStringToUTF8(desc.Description); - - adapters.push_back(std::move(name)); - } - - return adapters; -} - DXGI_FORMAT GetDXGIFormatForAbstractFormat(AbstractTextureFormat format, bool typeless) { switch (format) diff --git a/Source/Core/VideoBackends/D3DCommon/D3DCommon.h b/Source/Core/VideoBackends/D3DCommon/D3DCommon.h index 3e2b0ec953..31b2c121eb 100644 --- a/Source/Core/VideoBackends/D3DCommon/D3DCommon.h +++ b/Source/Core/VideoBackends/D3DCommon/D3DCommon.h @@ -11,22 +11,10 @@ #include "Common/CommonTypes.h" -struct IDXGIFactory; - enum class AbstractTextureFormat : u32; namespace D3DCommon { -// Loading dxgi.dll -bool LoadLibraries(); -void UnloadLibraries(); - -// Returns a list of D3D device names. -std::vector GetAdapterNames(); - -// Helper function which creates a DXGI factory. -Microsoft::WRL::ComPtr CreateDXGIFactory(bool debug_device); - // Helpers for texture format conversion. DXGI_FORMAT GetDXGIFormatForAbstractFormat(AbstractTextureFormat format, bool typeless); DXGI_FORMAT GetSRVFormatForAbstractFormat(AbstractTextureFormat format);