mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-02-18 11:55:38 +00:00
Settings: Add GPU adapter option and hook up to D3D11/Vulkan
This commit is contained in:
parent
1b5f8db2fc
commit
77291096db
|
@ -31,6 +31,7 @@ void Settings::Load(SettingsInterface& si)
|
||||||
|
|
||||||
gpu_renderer = ParseRendererName(si.GetStringValue("GPU", "Renderer", GetRendererName(DEFAULT_GPU_RENDERER)).c_str())
|
gpu_renderer = ParseRendererName(si.GetStringValue("GPU", "Renderer", GetRendererName(DEFAULT_GPU_RENDERER)).c_str())
|
||||||
.value_or(DEFAULT_GPU_RENDERER);
|
.value_or(DEFAULT_GPU_RENDERER);
|
||||||
|
gpu_adapter = si.GetStringValue("GPU", "Adapter", "");
|
||||||
gpu_resolution_scale = static_cast<u32>(si.GetIntValue("GPU", "ResolutionScale", 1));
|
gpu_resolution_scale = static_cast<u32>(si.GetIntValue("GPU", "ResolutionScale", 1));
|
||||||
gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false);
|
gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false);
|
||||||
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", true);
|
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", true);
|
||||||
|
@ -128,6 +129,7 @@ void Settings::Save(SettingsInterface& si) const
|
||||||
si.SetStringValue("CPU", "ExecutionMode", GetCPUExecutionModeName(cpu_execution_mode));
|
si.SetStringValue("CPU", "ExecutionMode", GetCPUExecutionModeName(cpu_execution_mode));
|
||||||
|
|
||||||
si.SetStringValue("GPU", "Renderer", GetRendererName(gpu_renderer));
|
si.SetStringValue("GPU", "Renderer", GetRendererName(gpu_renderer));
|
||||||
|
si.SetStringValue("GPU", "Adapter", gpu_adapter.c_str());
|
||||||
si.SetIntValue("GPU", "ResolutionScale", static_cast<long>(gpu_resolution_scale));
|
si.SetIntValue("GPU", "ResolutionScale", static_cast<long>(gpu_resolution_scale));
|
||||||
si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device);
|
si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device);
|
||||||
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
|
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct Settings
|
||||||
bool load_memory_cards_from_save_states = false;
|
bool load_memory_cards_from_save_states = false;
|
||||||
|
|
||||||
GPURenderer gpu_renderer = GPURenderer::Software;
|
GPURenderer gpu_renderer = GPURenderer::Software;
|
||||||
|
std::string gpu_adapter;
|
||||||
u32 gpu_resolution_scale = 1;
|
u32 gpu_resolution_scale = 1;
|
||||||
bool gpu_use_debug_device = false;
|
bool gpu_use_debug_device = false;
|
||||||
bool gpu_true_color = true;
|
bool gpu_true_color = true;
|
||||||
|
|
|
@ -59,11 +59,14 @@ bool D3D11HostDisplay::hasDeviceContext() const
|
||||||
return m_interface.HasContext();
|
return m_interface.HasContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11HostDisplay::createDeviceContext(bool debug_device)
|
bool D3D11HostDisplay::createDeviceContext(const QString& adapter_name, bool debug_device)
|
||||||
{
|
{
|
||||||
std::optional<WindowInfo> wi = getWindowInfo();
|
std::optional<WindowInfo> wi = getWindowInfo();
|
||||||
if (!wi || !m_interface.CreateContextAndSwapChain(wi.value(), shouldUseFlipModelSwapChain(), debug_device))
|
if (!wi || !m_interface.CreateContextAndSwapChain(wi.value(), adapter_name.toStdString(),
|
||||||
|
shouldUseFlipModelSwapChain(), debug_device))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_window_width = static_cast<s32>(m_interface.GetSwapChainWidth());
|
m_window_width = static_cast<s32>(m_interface.GetSwapChainWidth());
|
||||||
m_window_height = static_cast<s32>(m_interface.GetSwapChainHeight());
|
m_window_height = static_cast<s32>(m_interface.GetSwapChainHeight());
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
~D3D11HostDisplay();
|
~D3D11HostDisplay();
|
||||||
|
|
||||||
bool hasDeviceContext() const override;
|
bool hasDeviceContext() const override;
|
||||||
bool createDeviceContext(bool debug_device) override;
|
bool createDeviceContext(const QString& adapter_name, bool debug_device) override;
|
||||||
bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device) override;
|
bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device) override;
|
||||||
bool activateDeviceContext() override;
|
bool activateDeviceContext() override;
|
||||||
void deactivateDeviceContext() override;
|
void deactivateDeviceContext() override;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "aboutdialog.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/game_list.h"
|
#include "core/game_list.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
#include "aboutdialog.h"
|
|
||||||
#include "gamelistsettingswidget.h"
|
#include "gamelistsettingswidget.h"
|
||||||
#include "gamelistwidget.h"
|
#include "gamelistwidget.h"
|
||||||
#include "gamepropertiesdialog.h"
|
#include "gamepropertiesdialog.h"
|
||||||
|
@ -69,7 +69,8 @@ bool MainWindow::confirmMessage(const QString& message)
|
||||||
return (result == QMessageBox::Yes);
|
return (result == QMessageBox::Yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::createDisplay(QThread* worker_thread, bool use_debug_device, bool fullscreen, bool render_to_main)
|
void MainWindow::createDisplay(QThread* worker_thread, const QString& adapter_name, bool use_debug_device,
|
||||||
|
bool fullscreen, bool render_to_main)
|
||||||
{
|
{
|
||||||
Assert(!m_host_display && !m_display_widget);
|
Assert(!m_host_display && !m_display_widget);
|
||||||
Assert(!fullscreen || !render_to_main);
|
Assert(!fullscreen || !render_to_main);
|
||||||
|
@ -97,7 +98,7 @@ void MainWindow::createDisplay(QThread* worker_thread, bool use_debug_device, bo
|
||||||
// we need the surface visible.. this might be able to be replaced with something else
|
// we need the surface visible.. this might be able to be replaced with something else
|
||||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
|
||||||
if (!m_host_display->createDeviceContext(use_debug_device))
|
if (!m_host_display->createDeviceContext(adapter_name, use_debug_device))
|
||||||
{
|
{
|
||||||
reportError(tr("Failed to create host display device context."));
|
reportError(tr("Failed to create host display device context."));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -29,7 +29,8 @@ private Q_SLOTS:
|
||||||
void reportError(const QString& message);
|
void reportError(const QString& message);
|
||||||
void reportMessage(const QString& message);
|
void reportMessage(const QString& message);
|
||||||
bool confirmMessage(const QString& message);
|
bool confirmMessage(const QString& message);
|
||||||
void createDisplay(QThread* worker_thread, bool use_debug_device, bool fullscreen, bool render_to_main);
|
void createDisplay(QThread* worker_thread, const QString& adapter_name, bool use_debug_device, bool fullscreen,
|
||||||
|
bool render_to_main);
|
||||||
void updateDisplay(QThread* worker_thread, bool fullscreen, bool render_to_main);
|
void updateDisplay(QThread* worker_thread, bool fullscreen, bool render_to_main);
|
||||||
void destroyDisplay();
|
void destroyDisplay();
|
||||||
void focusDisplayWidget();
|
void focusDisplayWidget();
|
||||||
|
|
|
@ -188,7 +188,7 @@ bool OpenGLHostDisplay::hasDeviceContext() const
|
||||||
return static_cast<bool>(m_gl_context);
|
return static_cast<bool>(m_gl_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLHostDisplay::createDeviceContext(bool debug_device)
|
bool OpenGLHostDisplay::createDeviceContext(const QString& adapter_name, bool debug_device)
|
||||||
{
|
{
|
||||||
m_window_width = m_widget->scaledWindowWidth();
|
m_window_width = m_widget->scaledWindowWidth();
|
||||||
m_window_height = m_widget->scaledWindowHeight();
|
m_window_height = m_widget->scaledWindowHeight();
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
~OpenGLHostDisplay();
|
~OpenGLHostDisplay();
|
||||||
|
|
||||||
bool hasDeviceContext() const override;
|
bool hasDeviceContext() const override;
|
||||||
bool createDeviceContext(bool debug_device) override;
|
bool createDeviceContext(const QString& adapter_name, bool debug_device) override;
|
||||||
bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device) override;
|
bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device) override;
|
||||||
bool activateDeviceContext() override;
|
bool activateDeviceContext() override;
|
||||||
void deactivateDeviceContext() override;
|
void deactivateDeviceContext() override;
|
||||||
|
|
|
@ -42,7 +42,7 @@ bool QtHostDisplay::hasDeviceContext() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtHostDisplay::createDeviceContext(bool debug_device)
|
bool QtHostDisplay::createDeviceContext(const QString& adapter_name, bool debug_device)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
class QString;
|
||||||
class QThread;
|
class QThread;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ public:
|
||||||
virtual void destroyWidget();
|
virtual void destroyWidget();
|
||||||
|
|
||||||
virtual bool hasDeviceContext() const;
|
virtual bool hasDeviceContext() const;
|
||||||
virtual bool createDeviceContext(bool debug_device);
|
virtual bool createDeviceContext(const QString& adapter_name, bool debug_device);
|
||||||
virtual bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device);
|
virtual bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device);
|
||||||
virtual bool activateDeviceContext();
|
virtual bool activateDeviceContext();
|
||||||
virtual void deactivateDeviceContext();
|
virtual void deactivateDeviceContext();
|
||||||
|
|
|
@ -316,8 +316,8 @@ bool QtHostInterface::AcquireHostDisplay()
|
||||||
Assert(!m_display);
|
Assert(!m_display);
|
||||||
|
|
||||||
m_is_rendering_to_main = getSettingValue("Main/RenderToMainWindow", true).toBool();
|
m_is_rendering_to_main = getSettingValue("Main/RenderToMainWindow", true).toBool();
|
||||||
emit createDisplayRequested(m_worker_thread, m_settings.gpu_use_debug_device, m_is_fullscreen,
|
emit createDisplayRequested(m_worker_thread, QString::fromStdString(m_settings.gpu_adapter),
|
||||||
m_is_rendering_to_main);
|
m_settings.gpu_use_debug_device, m_is_fullscreen, m_is_rendering_to_main);
|
||||||
Assert(m_display);
|
Assert(m_display);
|
||||||
|
|
||||||
if (!getHostDisplay()->hasDeviceContext())
|
if (!getHostDisplay()->hasDeviceContext())
|
||||||
|
|
|
@ -96,7 +96,8 @@ Q_SIGNALS:
|
||||||
void emulationPaused(bool paused);
|
void emulationPaused(bool paused);
|
||||||
void stateSaved(const QString& game_code, bool global, qint32 slot);
|
void stateSaved(const QString& game_code, bool global, qint32 slot);
|
||||||
void gameListRefreshed();
|
void gameListRefreshed();
|
||||||
void createDisplayRequested(QThread* worker_thread, bool use_debug_device, bool fullscreen, bool render_to_main);
|
void createDisplayRequested(QThread* worker_thread, const QString& adapter_name, bool use_debug_device,
|
||||||
|
bool fullscreen, bool render_to_main);
|
||||||
void updateDisplayRequested(QThread* worker_thread, bool fullscreen, bool render_to_main);
|
void updateDisplayRequested(QThread* worker_thread, bool fullscreen, bool render_to_main);
|
||||||
void focusDisplayWidgetRequested();
|
void focusDisplayWidgetRequested();
|
||||||
void destroyDisplayRequested();
|
void destroyDisplayRequested();
|
||||||
|
|
|
@ -52,10 +52,10 @@ bool VulkanHostDisplay::hasDeviceContext() const
|
||||||
return m_vulkan_display.HasContext();
|
return m_vulkan_display.HasContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanHostDisplay::createDeviceContext(bool debug_device)
|
bool VulkanHostDisplay::createDeviceContext(const QString& adapter_name, bool debug_device)
|
||||||
{
|
{
|
||||||
std::optional<WindowInfo> wi = getWindowInfo();
|
std::optional<WindowInfo> wi = getWindowInfo();
|
||||||
if (!wi || !m_vulkan_display.CreateContextAndSwapChain(wi.value(), debug_device))
|
if (!wi || !m_vulkan_display.CreateContextAndSwapChain(wi.value(), adapter_name.toStdString(), debug_device))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_window_width = static_cast<s32>(m_vulkan_display.GetSwapChainWidth());
|
m_window_width = static_cast<s32>(m_vulkan_display.GetSwapChainWidth());
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
~VulkanHostDisplay();
|
~VulkanHostDisplay();
|
||||||
|
|
||||||
bool hasDeviceContext() const override;
|
bool hasDeviceContext() const override;
|
||||||
bool createDeviceContext(bool debug_device) override;
|
bool createDeviceContext(const QString& adapter_name, bool debug_device) override;
|
||||||
bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device) override;
|
bool initializeDeviceContext(std::string_view shader_cache_directory, bool debug_device) override;
|
||||||
bool activateDeviceContext() override;
|
bool activateDeviceContext() override;
|
||||||
void deactivateDeviceContext() override;
|
void deactivateDeviceContext() override;
|
||||||
|
|
|
@ -18,10 +18,10 @@ SDLD3D11HostDisplay::~SDLD3D11HostDisplay()
|
||||||
SDL_DestroyWindow(m_window);
|
SDL_DestroyWindow(m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<HostDisplay> SDLD3D11HostDisplay::Create(SDL_Window* window, bool debug_device)
|
std::unique_ptr<HostDisplay> SDLD3D11HostDisplay::Create(SDL_Window* window, std::string_view adapter_name, bool debug_device)
|
||||||
{
|
{
|
||||||
std::unique_ptr<SDLD3D11HostDisplay> display = std::make_unique<SDLD3D11HostDisplay>(window);
|
std::unique_ptr<SDLD3D11HostDisplay> display = std::make_unique<SDLD3D11HostDisplay>(window);
|
||||||
if (!display->Initialize(debug_device))
|
if (!display->Initialize(adapter_name, debug_device))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return display;
|
return display;
|
||||||
|
@ -74,13 +74,13 @@ void SDLD3D11HostDisplay::SetVSync(bool enabled)
|
||||||
m_interface.SetVSync(enabled);
|
m_interface.SetVSync(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDLD3D11HostDisplay::Initialize(bool debug_device)
|
bool SDLD3D11HostDisplay::Initialize(std::string_view adapter_name, bool debug_device)
|
||||||
{
|
{
|
||||||
std::optional<WindowInfo> wi = SDLUtil::GetWindowInfoForSDLWindow(m_window);
|
std::optional<WindowInfo> wi = SDLUtil::GetWindowInfoForSDLWindow(m_window);
|
||||||
if (!wi.has_value())
|
if (!wi.has_value())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_interface.CreateContextAndSwapChain(wi.value(), true, debug_device))
|
if (!m_interface.CreateContextAndSwapChain(wi.value(), adapter_name, true, debug_device))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_interface.CreateResources())
|
if (!m_interface.CreateResources())
|
||||||
|
|
|
@ -12,7 +12,7 @@ public:
|
||||||
SDLD3D11HostDisplay(SDL_Window* window);
|
SDLD3D11HostDisplay(SDL_Window* window);
|
||||||
~SDLD3D11HostDisplay();
|
~SDLD3D11HostDisplay();
|
||||||
|
|
||||||
static std::unique_ptr<HostDisplay> Create(SDL_Window* window, bool debug_device);
|
static std::unique_ptr<HostDisplay> Create(SDL_Window* window, std::string_view adapter_name, bool debug_device);
|
||||||
|
|
||||||
RenderAPI GetRenderAPI() const override;
|
RenderAPI GetRenderAPI() const override;
|
||||||
void* GetRenderDevice() const override;
|
void* GetRenderDevice() const override;
|
||||||
|
@ -35,5 +35,5 @@ private:
|
||||||
|
|
||||||
FrontendCommon::D3D11HostDisplay m_interface;
|
FrontendCommon::D3D11HostDisplay m_interface;
|
||||||
|
|
||||||
bool Initialize(bool debug_device);
|
bool Initialize(std::string_view adapter_name, bool debug_device);
|
||||||
};
|
};
|
||||||
|
|
|
@ -129,27 +129,27 @@ void SDLHostInterface::DestroySDLWindow()
|
||||||
|
|
||||||
bool SDLHostInterface::CreateDisplay()
|
bool SDLHostInterface::CreateDisplay()
|
||||||
{
|
{
|
||||||
const bool debug_device = m_settings.gpu_use_debug_device;
|
|
||||||
const std::string shader_cache_directory(GetShaderCacheDirectory());
|
const std::string shader_cache_directory(GetShaderCacheDirectory());
|
||||||
std::unique_ptr<HostDisplay> display;
|
std::unique_ptr<HostDisplay> display;
|
||||||
|
|
||||||
switch (m_settings.gpu_renderer)
|
switch (m_settings.gpu_renderer)
|
||||||
{
|
{
|
||||||
case GPURenderer::HardwareVulkan:
|
case GPURenderer::HardwareVulkan:
|
||||||
display = SDLVulkanHostDisplay::Create(m_window, shader_cache_directory, debug_device);
|
display = SDLVulkanHostDisplay::Create(m_window, m_settings.gpu_adapter, shader_cache_directory,
|
||||||
|
m_settings.gpu_use_debug_device);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GPURenderer::HardwareOpenGL:
|
case GPURenderer::HardwareOpenGL:
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
default:
|
default:
|
||||||
#endif
|
#endif
|
||||||
display = OpenGLHostDisplay::Create(m_window, debug_device);
|
display = OpenGLHostDisplay::Create(m_window, m_settings.gpu_use_debug_device);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
case GPURenderer::HardwareD3D11:
|
case GPURenderer::HardwareD3D11:
|
||||||
default:
|
default:
|
||||||
display = SDLD3D11HostDisplay::Create(m_window, debug_device);
|
display = SDLD3D11HostDisplay::Create(m_window, m_settings.gpu_adapter, m_settings.gpu_use_debug_device);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,11 @@ SDLVulkanHostDisplay::~SDLVulkanHostDisplay()
|
||||||
SDL_DestroyWindow(m_window);
|
SDL_DestroyWindow(m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<HostDisplay> SDLVulkanHostDisplay::Create(SDL_Window* window, std::string_view shader_cache_directory,
|
std::unique_ptr<HostDisplay> SDLVulkanHostDisplay::Create(SDL_Window* window, std::string_view adapter_name,
|
||||||
bool debug_device)
|
std::string_view shader_cache_directory, bool debug_device)
|
||||||
{
|
{
|
||||||
std::unique_ptr<SDLVulkanHostDisplay> display = std::make_unique<SDLVulkanHostDisplay>(window);
|
std::unique_ptr<SDLVulkanHostDisplay> display = std::make_unique<SDLVulkanHostDisplay>(window);
|
||||||
if (!display->Initialize(shader_cache_directory, debug_device))
|
if (!display->Initialize(adapter_name, shader_cache_directory, debug_device))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return display;
|
return display;
|
||||||
|
@ -84,7 +84,8 @@ void SDLVulkanHostDisplay::SetVSync(bool enabled)
|
||||||
m_display.SetVSync(enabled);
|
m_display.SetVSync(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDLVulkanHostDisplay::Initialize(std::string_view shader_cache_directory, bool debug_device)
|
bool SDLVulkanHostDisplay::Initialize(std::string_view adapter_name, std::string_view shader_cache_directory,
|
||||||
|
bool debug_device)
|
||||||
{
|
{
|
||||||
std::optional<WindowInfo> wi = SDLUtil::GetWindowInfoForSDLWindow(m_window);
|
std::optional<WindowInfo> wi = SDLUtil::GetWindowInfoForSDLWindow(m_window);
|
||||||
if (!wi.has_value())
|
if (!wi.has_value())
|
||||||
|
@ -93,7 +94,7 @@ bool SDLVulkanHostDisplay::Initialize(std::string_view shader_cache_directory, b
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_display.CreateContextAndSwapChain(wi.value(), debug_device))
|
if (!m_display.CreateContextAndSwapChain(wi.value(), adapter_name, debug_device))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_display.CreateShaderCache(shader_cache_directory, debug_device);
|
m_display.CreateShaderCache(shader_cache_directory, debug_device);
|
||||||
|
|
|
@ -10,8 +10,8 @@ public:
|
||||||
SDLVulkanHostDisplay(SDL_Window* window);
|
SDLVulkanHostDisplay(SDL_Window* window);
|
||||||
~SDLVulkanHostDisplay();
|
~SDLVulkanHostDisplay();
|
||||||
|
|
||||||
static std::unique_ptr<HostDisplay> Create(SDL_Window* window, std::string_view shader_cache_directory,
|
static std::unique_ptr<HostDisplay> Create(SDL_Window* window, std::string_view adapter_name,
|
||||||
bool debug_device);
|
std::string_view shader_cache_directory, bool debug_device);
|
||||||
|
|
||||||
RenderAPI GetRenderAPI() const override;
|
RenderAPI GetRenderAPI() const override;
|
||||||
void* GetRenderDevice() const override;
|
void* GetRenderDevice() const override;
|
||||||
|
@ -33,7 +33,7 @@ public:
|
||||||
void Render() override;
|
void Render() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Initialize(std::string_view shader_cache_directory, bool debug_device);
|
bool Initialize(std::string_view adapter_name, std::string_view shader_cache_directory, bool debug_device);
|
||||||
|
|
||||||
SDL_Window* m_window = nullptr;
|
SDL_Window* m_window = nullptr;
|
||||||
FrontendCommon::VulkanHostDisplay m_display;
|
FrontendCommon::VulkanHostDisplay m_display;
|
||||||
|
|
|
@ -140,14 +140,55 @@ bool D3D11HostDisplay::HasContext() const
|
||||||
return static_cast<bool>(m_device);
|
return static_cast<bool>(m_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11HostDisplay::CreateContextAndSwapChain(const WindowInfo& wi, bool use_flip_model, bool debug_device)
|
bool D3D11HostDisplay::CreateContextAndSwapChain(const WindowInfo& wi, std::string_view adapter_name,
|
||||||
|
bool use_flip_model, bool debug_device)
|
||||||
{
|
{
|
||||||
UINT create_flags = 0;
|
UINT create_flags = 0;
|
||||||
if (debug_device)
|
if (debug_device)
|
||||||
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
|
||||||
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0,
|
ComPtr<IDXGIFactory> temp_dxgi_factory;
|
||||||
D3D11_SDK_VERSION, m_device.GetAddressOf(), nullptr, m_context.GetAddressOf());
|
HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(temp_dxgi_factory.GetAddressOf()));
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Failed to create DXGI factory: 0x%08X", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 adapter_index;
|
||||||
|
if (!adapter_name.empty())
|
||||||
|
{
|
||||||
|
std::vector<std::string> adapter_names = EnumerateAdapterNames(temp_dxgi_factory.Get());
|
||||||
|
for (adapter_index = 0; adapter_index < static_cast<u32>(adapter_names.size()); adapter_index++)
|
||||||
|
{
|
||||||
|
if (adapter_name == adapter_names[adapter_index])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (adapter_index == static_cast<u32>(adapter_names.size()))
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Could not find adapter '%s', using first (%s)", std::string(adapter_name).c_str(),
|
||||||
|
adapter_names[0].c_str());
|
||||||
|
adapter_index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log_InfoPrintf("No adapter selected, using first.");
|
||||||
|
adapter_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<IDXGIAdapter> dxgi_adapter;
|
||||||
|
hr = temp_dxgi_factory->EnumAdapters(adapter_index, dxgi_adapter.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_WarningPrintf("Failed to enumerate adapter %u, using default", adapter_index);
|
||||||
|
|
||||||
|
hr = D3D11CreateDevice(dxgi_adapter.Get(), dxgi_adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, nullptr,
|
||||||
|
create_flags, nullptr, 0, D3D11_SDK_VERSION, m_device.GetAddressOf(), nullptr,
|
||||||
|
m_context.GetAddressOf());
|
||||||
|
|
||||||
|
// we re-grab these later, see below
|
||||||
|
dxgi_adapter.Reset();
|
||||||
|
temp_dxgi_factory.Reset();
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
@ -168,7 +209,6 @@ bool D3D11HostDisplay::CreateContextAndSwapChain(const WindowInfo& wi, bool use_
|
||||||
|
|
||||||
// we need the specific factory for the device, otherwise MakeWindowAssociation() is flaky.
|
// we need the specific factory for the device, otherwise MakeWindowAssociation() is flaky.
|
||||||
ComPtr<IDXGIDevice> dxgi_device;
|
ComPtr<IDXGIDevice> dxgi_device;
|
||||||
ComPtr<IDXGIAdapter> dxgi_adapter;
|
|
||||||
if (FAILED(m_device.As(&dxgi_device)) || FAILED(dxgi_device->GetParent(IID_PPV_ARGS(dxgi_adapter.GetAddressOf()))) ||
|
if (FAILED(m_device.As(&dxgi_device)) || FAILED(dxgi_device->GetParent(IID_PPV_ARGS(dxgi_adapter.GetAddressOf()))) ||
|
||||||
FAILED(dxgi_adapter->GetParent(IID_PPV_ARGS(m_dxgi_factory.GetAddressOf()))))
|
FAILED(dxgi_adapter->GetParent(IID_PPV_ARGS(m_dxgi_factory.GetAddressOf()))))
|
||||||
{
|
{
|
||||||
|
@ -482,54 +522,56 @@ std::vector<std::string> D3D11HostDisplay::EnumerateAdapterNames()
|
||||||
{
|
{
|
||||||
ComPtr<IDXGIFactory> dxgi_factory;
|
ComPtr<IDXGIFactory> dxgi_factory;
|
||||||
HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf()));
|
HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf()));
|
||||||
if (SUCCEEDED(hr))
|
if (FAILED(hr))
|
||||||
{
|
return {};
|
||||||
std::vector<std::string> adapter_names;
|
|
||||||
ComPtr<IDXGIAdapter> current_adapter;
|
|
||||||
while (SUCCEEDED(
|
|
||||||
dxgi_factory->EnumAdapters(static_cast<UINT>(adapter_names.size()), current_adapter.ReleaseAndGetAddressOf())))
|
|
||||||
{
|
|
||||||
DXGI_ADAPTER_DESC adapter_desc;
|
|
||||||
std::string adapter_name;
|
|
||||||
if (SUCCEEDED(current_adapter->GetDesc(&adapter_desc)))
|
|
||||||
{
|
|
||||||
char adapter_name_buffer[128];
|
|
||||||
const int name_length = WideCharToMultiByte(CP_UTF8, 0, adapter_desc.Description,
|
|
||||||
static_cast<int>(std::wcslen(adapter_desc.Description)),
|
|
||||||
adapter_name_buffer, countof(adapter_name_buffer), 0, nullptr);
|
|
||||||
if (name_length >= 0)
|
|
||||||
adapter_name.assign(adapter_name_buffer, static_cast<size_t>(name_length));
|
|
||||||
else
|
|
||||||
adapter_name.assign("(Unknown)");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
adapter_name.assign("(Unknown)");
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle duplicate adapter names
|
return EnumerateAdapterNames(dxgi_factory.Get());
|
||||||
if (std::any_of(adapter_names.begin(), adapter_names.end(),
|
|
||||||
[&adapter_name](const std::string& other) { return (adapter_name == other); }))
|
|
||||||
{
|
|
||||||
std::string original_adapter_name = std::move(adapter_name);
|
|
||||||
|
|
||||||
u32 current_extra = 2;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
adapter_name = StringUtil::StdStringFromFormat("%s (%u)", original_adapter_name.c_str(), current_extra);
|
|
||||||
current_extra++;
|
|
||||||
} while (std::any_of(adapter_names.begin(), adapter_names.end(),
|
|
||||||
[&adapter_name](const std::string& other) { return (adapter_name == other); }));
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter_names.push_back(std::move(adapter_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!adapter_names.empty())
|
|
||||||
return adapter_names;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {"(Default)"};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace FrontendCommon
|
std::vector<std::string> D3D11HostDisplay::EnumerateAdapterNames(IDXGIFactory* dxgi_factory)
|
||||||
|
{
|
||||||
|
std::vector<std::string> adapter_names;
|
||||||
|
ComPtr<IDXGIAdapter> current_adapter;
|
||||||
|
while (SUCCEEDED(
|
||||||
|
dxgi_factory->EnumAdapters(static_cast<UINT>(adapter_names.size()), current_adapter.ReleaseAndGetAddressOf())))
|
||||||
|
{
|
||||||
|
DXGI_ADAPTER_DESC adapter_desc;
|
||||||
|
std::string adapter_name;
|
||||||
|
if (SUCCEEDED(current_adapter->GetDesc(&adapter_desc)))
|
||||||
|
{
|
||||||
|
char adapter_name_buffer[128];
|
||||||
|
const int name_length = WideCharToMultiByte(CP_UTF8, 0, adapter_desc.Description,
|
||||||
|
static_cast<int>(std::wcslen(adapter_desc.Description)),
|
||||||
|
adapter_name_buffer, countof(adapter_name_buffer), 0, nullptr);
|
||||||
|
if (name_length >= 0)
|
||||||
|
adapter_name.assign(adapter_name_buffer, static_cast<size_t>(name_length));
|
||||||
|
else
|
||||||
|
adapter_name.assign("(Unknown)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
adapter_name.assign("(Unknown)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle duplicate adapter names
|
||||||
|
if (std::any_of(adapter_names.begin(), adapter_names.end(),
|
||||||
|
[&adapter_name](const std::string& other) { return (adapter_name == other); }))
|
||||||
|
{
|
||||||
|
std::string original_adapter_name = std::move(adapter_name);
|
||||||
|
|
||||||
|
u32 current_extra = 2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
adapter_name = StringUtil::StdStringFromFormat("%s (%u)", original_adapter_name.c_str(), current_extra);
|
||||||
|
current_extra++;
|
||||||
|
} while (std::any_of(adapter_names.begin(), adapter_names.end(),
|
||||||
|
[&adapter_name](const std::string& other) { return (adapter_name == other); }));
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter_names.push_back(std::move(adapter_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapter_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace FrontendCommon
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <wrl/client.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace FrontendCommon {
|
||||||
|
|
||||||
|
@ -27,7 +28,8 @@ public:
|
||||||
ALWAYS_INLINE void* GetRenderDevice() const { return m_device.Get(); }
|
ALWAYS_INLINE void* GetRenderDevice() const { return m_device.Get(); }
|
||||||
ALWAYS_INLINE void* GetRenderContext() const { return m_context.Get(); }
|
ALWAYS_INLINE void* GetRenderContext() const { return m_context.Get(); }
|
||||||
|
|
||||||
bool CreateContextAndSwapChain(const WindowInfo& wi, bool use_flip_model, bool debug_device);
|
bool CreateContextAndSwapChain(const WindowInfo& wi, std::string_view adapter_name, bool use_flip_model,
|
||||||
|
bool debug_device);
|
||||||
bool HasContext() const;
|
bool HasContext() const;
|
||||||
void DestroyContext();
|
void DestroyContext();
|
||||||
|
|
||||||
|
@ -67,6 +69,8 @@ public:
|
||||||
private:
|
private:
|
||||||
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 16;
|
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 16;
|
||||||
|
|
||||||
|
static std::vector<std::string> EnumerateAdapterNames(IDXGIFactory* dxgi_factory);
|
||||||
|
|
||||||
bool CreateSwapChain(const WindowInfo& new_wi, bool use_flip_model);
|
bool CreateSwapChain(const WindowInfo& new_wi, bool use_flip_model);
|
||||||
bool CreateSwapChainRTV();
|
bool CreateSwapChainRTV();
|
||||||
|
|
||||||
|
|
|
@ -192,9 +192,9 @@ void VulkanHostDisplay::SetVSync(bool enabled)
|
||||||
m_swap_chain->SetVSync(enabled);
|
m_swap_chain->SetVSync(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanHostDisplay::CreateContextAndSwapChain(const WindowInfo& wi, bool debug_device)
|
bool VulkanHostDisplay::CreateContextAndSwapChain(const WindowInfo& wi, std::string_view gpu_name, bool debug_device)
|
||||||
{
|
{
|
||||||
if (!Vulkan::Context::Create({}, &wi, &m_swap_chain, debug_device, false))
|
if (!Vulkan::Context::Create(gpu_name, &wi, &m_swap_chain, debug_device, false))
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Failed to create Vulkan context");
|
Log_ErrorPrintf("Failed to create Vulkan context");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
void RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 height, HostDisplayTexture* texture_handle);
|
void RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 height, HostDisplayTexture* texture_handle);
|
||||||
void EndRenderAndPresent();
|
void EndRenderAndPresent();
|
||||||
|
|
||||||
bool CreateContextAndSwapChain(const WindowInfo& wi, bool debug_device);
|
bool CreateContextAndSwapChain(const WindowInfo& wi, std::string_view gpu_name, bool debug_device);
|
||||||
bool HasContext() const;
|
bool HasContext() const;
|
||||||
void DestroyContext();
|
void DestroyContext();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue