From 3ce7947dd35278b5ec5a8ceec8d02e3a62b3923b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 11 Apr 2017 12:15:57 +0300 Subject: [PATCH] rsx: Throw if user attempts to use Vulkan/DX12 without driver support --- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 27 ++++++++++++++++++++++++++- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 1 + rpcs3/Emu/RSX/VK/VKGSRender.cpp | 23 ++++++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 59e86dd8b2..16d69631f8 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -177,7 +177,17 @@ D3D12GSRender::D3D12GSRender() } } - CHECK_HRESULT(wrapD3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device))); + if (FAILED(wrapD3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)))) + { + LOG_ERROR(RSX, "Failed to initialize D3D device on adapter '%s', falling back to first available GPU", g_cfg_d3d12_adapter.to_string().c_str()); + + //Try to create a device on the first available device + if (FAILED(wrapD3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)))) + { + LOG_FATAL(RSX, "Unable to create D3D12 device. Your GPU(s) may not have D3D12 support."); + return; + } + } // Queues D3D12_COMMAND_QUEUE_DESC graphic_queue_desc = { D3D12_COMMAND_LIST_TYPE_DIRECT }; @@ -263,6 +273,12 @@ D3D12GSRender::D3D12GSRender() D3D12GSRender::~D3D12GSRender() { + if (!m_device) + { + //Initialization must have failed + return; + } + wait_for_command_queue(m_device.Get(), m_command_queue.Get()); m_texture_cache.unprotect_all(); @@ -275,6 +291,15 @@ D3D12GSRender::~D3D12GSRender() release_d2d_structures(); } +void D3D12GSRender::on_init_thread() +{ + if (!m_device) + { + //Init must have failed + fmt::throw_exception("No D3D12 device was created"); + } +} + void D3D12GSRender::on_exit() { return GSRender::on_exit(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index f7de4266b0..94f37968fb 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -173,6 +173,7 @@ private: void copy_render_target_to_dma_location(); protected: + virtual void on_init_thread() override; virtual void on_exit() override; virtual bool do_method(u32 cmd, u32 arg) override; virtual void end() override; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 518d3883cb..d4648e8846 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -460,7 +460,17 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan) HINSTANCE hInstance = NULL; HWND hWnd = (HWND)m_frame->handle(); - std::vector& gpus = m_thread_context.enumerateDevices(); + std::vector& gpus = m_thread_context.enumerateDevices(); + + //Actually confirm that the loader found at least one compatible device + if (gpus.size() == 0) + { + //We can't throw in Emulator::Load, so we show error and return + LOG_FATAL(RSX, "Could not find a vulkan compatible GPU driver. Your GPU(s) may not support Vulkan, or you need to install the vulkan runtime and drivers"); + m_device = VK_NULL_HANDLE; + return; + } + m_swap_chain = m_thread_context.createSwapChain(hInstance, hWnd, gpus[0]); #endif @@ -543,6 +553,12 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan) VKGSRender::~VKGSRender() { + if (m_device == VK_NULL_HANDLE) + { + //Initialization failed + return; + } + //Wait for queue vkQueueWaitIdle(m_swap_chain->get_present_queue()); @@ -844,6 +860,11 @@ void VKGSRender::set_viewport() void VKGSRender::on_init_thread() { + if (m_device == VK_NULL_HANDLE) + { + fmt::throw_exception("No vulkan device was created"); + } + GSRender::on_init_thread(); m_attrib_ring_info.init(8 * RING_BUFFER_SIZE); m_attrib_ring_info.heap.reset(new vk::buffer(*m_device, 8 * RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0));