123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- // Copyright 2010 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "VideoBackends/D3D/D3DBase.h"
- #include <algorithm>
- #include <array>
- #include "Common/CommonTypes.h"
- #include "Common/DynamicLibrary.h"
- #include "Common/Logging/Log.h"
- #include "Common/MsgHandler.h"
- #include "Core/Config/GraphicsSettings.h"
- #include "Core/ConfigManager.h"
- #include "VideoBackends/D3D/D3DState.h"
- #include "VideoBackends/D3D/DXTexture.h"
- #include "VideoBackends/D3DCommon/D3DCommon.h"
- #include "VideoCommon/FramebufferManager.h"
- #include "VideoCommon/VideoConfig.h"
- namespace DX11
- {
- static Common::DynamicLibrary s_d3d11_library;
- namespace D3D
- {
- ComPtr<IDXGIFactory> dxgi_factory;
- ComPtr<ID3D11Device> device;
- ComPtr<ID3D11Device1> device1;
- ComPtr<ID3D11DeviceContext> context;
- D3D_FEATURE_LEVEL feature_level;
- static ComPtr<ID3D11Debug> s_debug;
- constexpr std::array<D3D_FEATURE_LEVEL, 3> s_supported_feature_levels{
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- };
- bool Create(u32 adapter_index, bool enable_debug_layer)
- {
- PFN_D3D11_CREATE_DEVICE d3d11_create_device;
- if (!s_d3d11_library.Open("d3d11.dll") ||
- !s_d3d11_library.GetSymbol("D3D11CreateDevice", &d3d11_create_device))
- {
- PanicAlertFmtT("Failed to load d3d11.dll");
- s_d3d11_library.Close();
- return false;
- }
- if (!D3DCommon::LoadLibraries())
- {
- s_d3d11_library.Close();
- return false;
- }
- dxgi_factory = D3DCommon::CreateDXGIFactory(enable_debug_layer);
- if (!dxgi_factory)
- {
- PanicAlertFmtT("Failed to create DXGI factory");
- D3DCommon::UnloadLibraries();
- s_d3d11_library.Close();
- return false;
- }
- ComPtr<IDXGIAdapter> adapter;
- HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf());
- if (FAILED(hr))
- {
- WARN_LOG_FMT(VIDEO, "Adapter {} not found, using default: {}", adapter_index, DX11HRWrap(hr));
- adapter = nullptr;
- }
- // Creating debug devices can sometimes fail if the user doesn't have the correct
- // 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.GetAddressOf(), &feature_level, context.GetAddressOf());
- // Debugbreak on D3D error
- if (SUCCEEDED(hr) && SUCCEEDED(hr = device.As(&s_debug)))
- {
- ComPtr<ID3D11InfoQueue> 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);
- D3D11_MESSAGE_ID hide[] = {D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS};
- D3D11_INFO_QUEUE_FILTER filter = {};
- filter.DenyList.NumIDs = sizeof(hide) / sizeof(D3D11_MESSAGE_ID);
- filter.DenyList.pIDList = hide;
- info_queue->AddStorageFilterEntries(&filter);
- }
- }
- else
- {
- WARN_LOG_FMT(VIDEO, "Debug layer requested but not available: {}", DX11HRWrap(hr));
- }
- }
- 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.GetAddressOf(), &feature_level, context.GetAddressOf());
- }
- if (FAILED(hr))
- {
- PanicAlertFmtT(
- "Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0\n{0}",
- DX11HRWrap(hr));
- dxgi_factory.Reset();
- D3DCommon::UnloadLibraries();
- s_d3d11_library.Close();
- return false;
- }
- hr = device.As(&device1);
- if (FAILED(hr))
- {
- WARN_LOG_FMT(VIDEO,
- "Missing Direct3D 11.1 support. Logical operations will not be supported.\n{}",
- DX11HRWrap(hr));
- }
- stateman = std::make_unique<StateManager>();
- return true;
- }
- void Destroy()
- {
- stateman.reset();
- context->ClearState();
- context->Flush();
- context.Reset();
- device1.Reset();
- auto remaining_references = device.Reset();
- if (s_debug)
- {
- --remaining_references; // the debug interface increases the refcount of the device, subtract
- // that.
- if (remaining_references)
- {
- // print out alive objects, but only if we actually have pending references
- // note this will also print out internal live objects to the debug console
- s_debug->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
- }
- s_debug.Reset();
- }
- if (remaining_references)
- ERROR_LOG_FMT(VIDEO, "Unreleased references: {}.", remaining_references);
- else
- NOTICE_LOG_FMT(VIDEO, "Successfully released all device references!");
- dxgi_factory.Reset();
- D3DCommon::UnloadLibraries();
- s_d3d11_library.Close();
- }
- 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.GetAddressOf());
- 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<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_feature_level == D3D_FEATURE_LEVEL_10_0)
- return {};
- const DXGI_FORMAT target_format =
- D3DCommon::GetDXGIFormatForAbstractFormat(FramebufferManager::GetEFBColorFormat(), false);
- std::vector<u32> aa_modes;
- for (u32 samples = 1; samples <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
- {
- UINT quality_levels = 0;
- if (SUCCEEDED(
- temp_device->CheckMultisampleQualityLevels(target_format, samples, &quality_levels)) &&
- quality_levels > 0)
- {
- aa_modes.push_back(samples);
- }
- }
- return aa_modes;
- }
- bool SupportsTextureFormat(DXGI_FORMAT format)
- {
- UINT support;
- if (FAILED(device->CheckFormatSupport(format, &support)))
- return false;
- 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
|