diff --git a/Source/Core/VideoBackends/D3D12/D3DBase.cpp b/Source/Core/VideoBackends/D3D12/D3DBase.cpp index cb166bd007..bc1d535b93 100644 --- a/Source/Core/VideoBackends/D3D12/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D12/D3DBase.cpp @@ -14,6 +14,7 @@ #include "VideoBackends/D3D12/D3DDescriptorHeapManager.h" #include "VideoBackends/D3D12/D3DState.h" #include "VideoBackends/D3D12/D3DTexture.h" +#include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/VideoConfig.h" static const unsigned int SWAP_CHAIN_BUFFER_COUNT = 4; @@ -72,18 +73,12 @@ static LARGE_INTEGER s_qpc_frequency; static ID3D12DebugDevice* s_debug_device12 = nullptr; -static D3D_FEATURE_LEVEL s_feat_level; static D3DTexture2D* s_backbuf[SWAP_CHAIN_BUFFER_COUNT]; static unsigned int s_current_back_buf = 0; static unsigned int s_xres = 0; static unsigned int s_yres = 0; static bool s_frame_in_progress = false; -static std::vector s_aa_modes; // supported AA modes of the current adapter -static const D3D_FEATURE_LEVEL s_supported_feature_levels[] = { - D3D_FEATURE_LEVEL_11_0 -}; - HRESULT LoadDXGI() { if (s_dxgi_dll_ref++ > 0) @@ -233,108 +228,29 @@ void UnloadD3DCompiler() d3d_reflect = nullptr; } -bool AlertUserIfSelectedAdapterDoesNotSupportD3D12() -{ - HRESULT hr = LoadDXGI(); - if (SUCCEEDED(hr)) - { - hr = LoadD3D(); - } - - if (FAILED(hr)) - { - // LoadDXGI / LoadD3D display a specific error message, - // no need to do that here. - return false; - } - - IDXGIFactory* factory = nullptr; - IDXGIAdapter* adapter = nullptr; - ID3D12Device* device = nullptr; - - if (SUCCEEDED(hr)) - { - hr = create_dxgi_factory(__uuidof(IDXGIFactory), (void**)&factory); - } - - if (SUCCEEDED(hr)) - { - hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter); - } - - if (SUCCEEDED(hr)) - { - hr = d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)); - - SAFE_RELEASE(device); - SAFE_RELEASE(adapter); - SAFE_RELEASE(factory); - - if (FAILED(hr)) - { - UnloadD3D(); - UnloadDXGI(); - MessageBoxA(nullptr, "Failed to create a D3D12 device on the selected adapter.\n\nPlease make sure it supports Direct3D 12, and that your graphics drivers are up-to-date.", "Critical error", MB_OK | MB_ICONERROR); - return false; - } - - // If succeeded, leave DXGI and D3D libraries loaded since we'll use them in Create(). - return true; - } - - // DXGI failed to create factory/enumerate adapter. This should be very uncommon. - MessageBoxA(nullptr, "Failed to create enumerate selected adapter. Please select a different graphics adapter.", "Critical error", MB_OK | MB_ICONERROR); - SAFE_RELEASE(adapter); - SAFE_RELEASE(factory); - - UnloadD3D(); - UnloadDXGI(); - return false; -} - -std::vector EnumAAModes(IDXGIAdapter* adapter) +std::vector EnumAAModes(ID3D12Device* device) { std::vector aa_modes; - bool d3d12_supported = AlertUserIfSelectedAdapterDoesNotSupportD3D12(); - - if (!d3d12_supported) - return aa_modes; - - ID3D12Device* device12 = nullptr; - d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device12)); - - if (device12) + for (int samples = 0; samples < D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples) { - for (int samples = 0; samples < D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples) - { - D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS multisample_quality_levels = {}; - multisample_quality_levels.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - multisample_quality_levels.SampleCount = samples; + D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS multisample_quality_levels = {}; + multisample_quality_levels.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + multisample_quality_levels.SampleCount = samples; - device12->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)); - DXGI_SAMPLE_DESC desc; - desc.Count = samples; - desc.Quality = 0; + DXGI_SAMPLE_DESC desc; + desc.Count = samples; + desc.Quality = 0; - if (multisample_quality_levels.NumQualityLevels > 0) - { - aa_modes.push_back(desc); - } - } - - device12->Release(); + if (multisample_quality_levels.NumQualityLevels > 0) + aa_modes.push_back(desc); } return aa_modes; } -D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter) -{ - return D3D_FEATURE_LEVEL_11_0; -} - HRESULT Create(HWND wnd) { hWnd = wnd; @@ -346,17 +262,21 @@ HRESULT Create(HWND wnd) s_yres = client.bottom - client.top; hr = LoadDXGI(); - if (SUCCEEDED(hr)) - hr = LoadD3D(); - - if (SUCCEEDED(hr)) - hr = LoadD3DCompiler(); + if (FAILED(hr)) + return hr; + hr = LoadD3D(); if (FAILED(hr)) { UnloadDXGI(); + return hr; + } + + hr = LoadD3DCompiler(); + if (FAILED(hr)) + { UnloadD3D(); - UnloadD3DCompiler(); + UnloadDXGI(); return hr; } @@ -364,7 +284,13 @@ HRESULT Create(HWND wnd) IDXGIAdapter* adapter; hr = create_dxgi_factory(__uuidof(IDXGIFactory), (void**)&factory); if (FAILED(hr)) + { MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR); + UnloadD3DCompiler(); + UnloadD3D(); + UnloadDXGI(); + return hr; + } hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter); if (FAILED(hr)) @@ -372,20 +298,13 @@ HRESULT Create(HWND wnd) // try using the first one hr = factory->EnumAdapters(0, &adapter); if (FAILED(hr)) + { MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR); - } - - // get supported AA modes - s_aa_modes = EnumAAModes(adapter); - - if (std::find_if( - s_aa_modes.begin(), - s_aa_modes.end(), - [](const DXGI_SAMPLE_DESC& desc) {return desc.Count == g_Config.iMultisamples; } - ) == s_aa_modes.end()) - { - g_Config.iMultisamples = 1; - UpdateActiveConfig(); + UnloadD3DCompiler(); + UnloadD3D(); + UnloadDXGI(); + return hr; + } } DXGI_SWAP_CHAIN_DESC swap_chain_desc = {}; @@ -405,74 +324,70 @@ HRESULT Create(HWND wnd) #if defined(_DEBUG) || defined(DEBUGFAST) || defined(USE_D3D12_DEBUG_LAYER) // Enabling the debug layer will fail if the Graphics Tools feature is not installed. + ID3D12Debug* debug_controller; + hr = d3d12_get_debug_interface(IID_PPV_ARGS(&debug_controller)); if (SUCCEEDED(hr)) { - ID3D12Debug* debug_controller; - hr = d3d12_get_debug_interface(IID_PPV_ARGS(&debug_controller)); - if (SUCCEEDED(hr)) - { - debug_controller->EnableDebugLayer(); - debug_controller->Release(); - } - else - { - MessageBox(wnd, _T("WARNING: Failed to enable D3D12 debug layer, please ensure the Graphics Tools feature is installed."), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR); - } + debug_controller->EnableDebugLayer(); + debug_controller->Release(); + } + else + { + MessageBox(wnd, _T("WARNING: Failed to enable D3D12 debug layer, please ensure the Graphics Tools feature is installed."), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR); } #endif - if (SUCCEEDED(hr)) - { - hr = d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device12)); - s_feat_level = D3D_FEATURE_LEVEL_11_0; - } - - if (SUCCEEDED(hr)) - { - D3D12_COMMAND_QUEUE_DESC command_queue_desc = { - D3D12_COMMAND_LIST_TYPE_DIRECT, // D3D12_COMMAND_LIST_TYPE Type; - 0, // INT Priority; - D3D12_COMMAND_QUEUE_FLAG_NONE, // D3D12_COMMAND_QUEUE_FLAG Flags; - 0 // UINT NodeMask; - }; - - CheckHR(device12->CreateCommandQueue(&command_queue_desc, IID_PPV_ARGS(&command_queue))); - - IDXGIFactory* factory = nullptr; - adapter->GetParent(IID_PPV_ARGS(&factory)); - - CheckHR(factory->CreateSwapChain(command_queue, &swap_chain_desc, &s_swap_chain)); - - s_current_back_buf = 0; - - factory->Release(); - } - - if (SUCCEEDED(hr)) - { - // Query the monitor refresh rate, to ensure proper Present throttling behavior. - DEVMODE dev_mode; - memset(&dev_mode, 0, sizeof(DEVMODE)); - dev_mode.dmSize = sizeof(DEVMODE); - dev_mode.dmDriverExtra = 0; - - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode) == 0) - { - // If EnumDisplaySettings fails, assume monitor refresh rate of 60 Hz. - s_monitor_refresh_rate = 60; - } - else - { - s_monitor_refresh_rate = dev_mode.dmDisplayFrequency; - } - } - + hr = d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device12)); if (FAILED(hr)) { MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports Direct3D 12 and your drivers are up-to-date."), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR); - SAFE_RELEASE(s_swap_chain); - return E_FAIL; + adapter->Release(); + UnloadD3DCompiler(); + UnloadD3D(); + UnloadDXGI(); + return hr; + } + + // Ensure that the chosen AA mode is supported by the device. + std::vector aa_modes = EnumAAModes(device12); + if (std::find_if( + aa_modes.begin(), + aa_modes.end(), + [](const DXGI_SAMPLE_DESC& desc) {return desc.Count == g_Config.iMultisamples; } + ) == aa_modes.end()) + { + g_Config.iMultisamples = 1; + UpdateActiveConfig(); + } + + D3D12_COMMAND_QUEUE_DESC command_queue_desc = { + D3D12_COMMAND_LIST_TYPE_DIRECT, // D3D12_COMMAND_LIST_TYPE Type; + 0, // INT Priority; + D3D12_COMMAND_QUEUE_FLAG_NONE, // D3D12_COMMAND_QUEUE_FLAG Flags; + 0 // UINT NodeMask; + }; + + CheckHR(device12->CreateCommandQueue(&command_queue_desc, IID_PPV_ARGS(&command_queue))); + + CheckHR(factory->CreateSwapChain(command_queue, &swap_chain_desc, &s_swap_chain)); + + s_current_back_buf = 0; + + // Query the monitor refresh rate, to ensure proper Present throttling behavior. + DEVMODE dev_mode; + memset(&dev_mode, 0, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); + dev_mode.dmDriverExtra = 0; + + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode) == 0) + { + // If EnumDisplaySettings fails, assume monitor refresh rate of 60 Hz. + s_monitor_refresh_rate = 60; + } + else + { + s_monitor_refresh_rate = dev_mode.dmDisplayFrequency; } ID3D12InfoQueue* info_queue = nullptr; @@ -505,9 +420,6 @@ HRESULT Create(HWND wnd) if (FAILED(hr)) MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR); - SAFE_RELEASE(factory); - SAFE_RELEASE(adapter) - CreateDescriptorHeaps(); CreateRootSignatures(); @@ -545,6 +457,14 @@ HRESULT Create(HWND wnd) QueryPerformanceFrequency(&s_qpc_frequency); + // Render the device name. + DXGI_ADAPTER_DESC adapter_desc; + CheckHR(adapter->GetDesc(&adapter_desc)); + OSD::AddMessage(StringFromFormat("Using D3D Adapter: %s.", UTF16ToUTF8(adapter_desc.Description).c_str())); + + SAFE_RELEASE(factory); + SAFE_RELEASE(adapter); + return S_OK; } @@ -757,9 +677,9 @@ void Close() current_command_list = nullptr; // unload DLLs - UnloadDXGI(); UnloadD3DCompiler(); UnloadD3D(); + UnloadDXGI(); } const std::string VertexShaderVersionString() diff --git a/Source/Core/VideoBackends/D3D12/D3DBase.h b/Source/Core/VideoBackends/D3D12/D3DBase.h index b4f58dcb21..4016a039b1 100644 --- a/Source/Core/VideoBackends/D3D12/D3DBase.h +++ b/Source/Core/VideoBackends/D3D12/D3DBase.h @@ -65,9 +65,7 @@ void UnloadDXGI(); void UnloadD3D(); void UnloadD3DCompiler(); -std::vector EnumAAModes(IDXGIAdapter* adapter); - -bool AlertUserIfSelectedAdapterDoesNotSupportD3D12(); +std::vector EnumAAModes(ID3D12Device* device); HRESULT Create(HWND wnd); @@ -148,6 +146,8 @@ using CREATEDXGIFACTORY = HRESULT(WINAPI*)(REFIID, void**); extern CREATEDXGIFACTORY create_dxgi_factory; using D3D12CREATEDEVICE = HRESULT(WINAPI*)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**); +extern D3D12CREATEDEVICE d3d12_create_device; + using D3D12SERIALIZEROOTSIGNATURE = HRESULT(WINAPI*)(const D3D12_ROOT_SIGNATURE_DESC* pRootSignature, D3D_ROOT_SIGNATURE_VERSION Version, ID3DBlob** ppBlob, ID3DBlob** ppErrorBlob); using D3D12GETDEBUGINTERFACE = HRESULT(WINAPI*)(REFIID riid, void** ppvDebug); diff --git a/Source/Core/VideoBackends/D3D12/Render.cpp b/Source/Core/VideoBackends/D3D12/Render.cpp index 75de5243a2..05cc323c0b 100644 --- a/Source/Core/VideoBackends/D3D12/Render.cpp +++ b/Source/Core/VideoBackends/D3D12/Render.cpp @@ -224,8 +224,6 @@ Renderer::Renderer(void*& window_handle) return; } - D3D::Create((HWND)window_handle); - s_backbuffer_width = D3D::GetBackBufferWidth(); s_backbuffer_height = D3D::GetBackBufferHeight(); @@ -283,7 +281,6 @@ Renderer::~Renderer() D3D::EndFrame(); D3D::WaitForOutstandingRenderingToComplete(); TeardownDeviceObjects(); - D3D::Close(); } void Renderer::RenderText(const std::string& text, int left, int top, u32 color) diff --git a/Source/Core/VideoBackends/D3D12/main.cpp b/Source/Core/VideoBackends/D3D12/main.cpp index 3cd04ba656..e67ea2777a 100644 --- a/Source/Core/VideoBackends/D3D12/main.cpp +++ b/Source/Core/VideoBackends/D3D12/main.cpp @@ -65,11 +65,14 @@ std::string VideoBackend::GetDisplayName() const void InitBackendInfo() { - HRESULT hr = DX12::D3D::LoadDXGI(); - if (SUCCEEDED(hr)) hr = DX12::D3D::LoadD3D(); + HRESULT hr = D3D::LoadDXGI(); + if (FAILED(hr)) + return; + + hr = D3D::LoadD3D(); if (FAILED(hr)) { - DX12::D3D::UnloadDXGI(); + D3D::UnloadDXGI(); return; } @@ -86,9 +89,14 @@ void InitBackendInfo() IDXGIFactory* factory; IDXGIAdapter* ad; - hr = DX12::create_dxgi_factory(__uuidof(IDXGIFactory), (void**)&factory); + hr = create_dxgi_factory(__uuidof(IDXGIFactory), (void**)&factory); if (FAILED(hr)) + { PanicAlert("Failed to create IDXGIFactory object"); + D3D::UnloadD3D(); + D3D::UnloadDXGI(); + return; + } // adapters g_Config.backend_info.Adapters.clear(); @@ -103,26 +111,34 @@ void InitBackendInfo() // TODO: These don't get updated on adapter change, yet if (adapter_index == g_Config.iAdapter) { - std::string samples; - std::vector modes = DX12::D3D::EnumAAModes(ad); - // First iteration will be 1. This equals no AA. - for (unsigned int i = 0; i < modes.size(); ++i) + ID3D12Device* temp_device; + hr = d3d12_create_device(ad, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&temp_device)); + if (SUCCEEDED(hr)) { - g_Config.backend_info.AAModes.push_back(modes[i].Count); + std::string samples; + std::vector modes = D3D::EnumAAModes(temp_device); + // First iteration will be 1. This equals no AA. + for (unsigned int i = 0; i < modes.size(); ++i) + { + g_Config.backend_info.AAModes.push_back(modes[i].Count); + } + + // Requires the earlydepthstencil attribute (only available in shader model 5) + g_Config.backend_info.bSupportsEarlyZ = true; + + // Requires full UAV functionality (only available in shader model 5) + g_Config.backend_info.bSupportsBBox = true; + + // Requires the instance attribute (only available in shader model 5) + g_Config.backend_info.bSupportsGSInstancing = true; + + // Sample shading requires shader model 5 + g_Config.backend_info.bSupportsSSAA = true; + + temp_device->Release(); } - - // Requires the earlydepthstencil attribute (only available in shader model 5) - g_Config.backend_info.bSupportsEarlyZ = true; - - // Requires full UAV functionality (only available in shader model 5) - g_Config.backend_info.bSupportsBBox = true; - - // Requires the instance attribute (only available in shader model 5) - g_Config.backend_info.bSupportsGSInstancing = true; - - // Sample shading requires shader model 5 - g_Config.backend_info.bSupportsSSAA = true; } + g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description)); ad->Release(); } @@ -132,8 +148,8 @@ void InitBackendInfo() g_Config.backend_info.PPShaders.clear(); g_Config.backend_info.AnaglyphShaders.clear(); - DX12::D3D::UnloadDXGI(); - DX12::D3D::UnloadD3D(); + D3D::UnloadD3D(); + D3D::UnloadDXGI(); } void VideoBackend::ShowConfig(void *hParent) @@ -144,11 +160,6 @@ void VideoBackend::ShowConfig(void *hParent) bool VideoBackend::Initialize(void *window_handle) { - bool d3d12_supported = D3D::AlertUserIfSelectedAdapterDoesNotSupportD3D12(); - - if (!d3d12_supported) - return false; - if (window_handle == nullptr) return false; @@ -167,6 +178,9 @@ bool VideoBackend::Initialize(void *window_handle) g_Config.VerifyValidity(); UpdateActiveConfig(); + if (FAILED(D3D::Create((HWND)window_handle))) + return false; + m_window_handle = window_handle; m_initialized = true; @@ -235,6 +249,8 @@ void VideoBackend::Shutdown() g_vertex_manager.reset(); g_texture_cache.reset(); g_renderer.reset(); + + D3D::Close(); } }