From 848e2a4088727f4261f8add5d10ee0af7f21909e Mon Sep 17 00:00:00 2001 From: gibbed Date: Sat, 3 Aug 2019 16:42:38 -0500 Subject: [PATCH] [App] Rework graphics system creation. --- src/xenia/app/xenia_main.cc | 78 +++++++++++-------- src/xenia/gpu/d3d12/d3d12_graphics_system.cc | 2 +- src/xenia/gpu/d3d12/d3d12_graphics_system.h | 2 +- src/xenia/gpu/null/null_graphics_system.h | 2 + src/xenia/gpu/vulkan/vulkan_graphics_system.h | 2 + 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 7e779b460..db78bc4bb 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -65,6 +65,43 @@ DEFINE_bool(discord, true, "Enable Discord rich presence", "General"); namespace xe { namespace app { +template +struct Factory { + std::string name; + std::function is_available; + std::function()> instantiate; + + template + static Factory Define(const std::string& name) { + return {name, DT::IsAvailable, + []() { return std::unique_ptr
(new DT); }}; + } + + static std::unique_ptr Create(const std::string& name, + const std::vector& factories) { + if (!name.empty() && name != "any") { + auto it = std::find_if( + factories.begin(), factories.end(), + [&name](const auto& f) { return name.compare(f.name) == 0; }); + if (it != factories.end() && (*it).is_available()) { + return (*it).instantiate(); + } + return nullptr; + } else { + // Create best available. + std::unique_ptr best; + for (const auto& factory : factories) { + if (!factory.is_available()) continue; + best = factory.instantiate(); + if (!best) continue; + return best; + } + // Nothing! + return nullptr; + } + } +}; + std::unique_ptr CreateAudioSystem(cpu::Processor* processor) { if (cvars::apu.compare("nop") == 0) { return apu::nop::NopAudioSystem::Create(processor); @@ -89,39 +126,18 @@ std::unique_ptr CreateAudioSystem(cpu::Processor* processor) { } std::unique_ptr CreateGraphicsSystem() { - if (cvars::gpu.compare("vulkan") == 0) { - return std::unique_ptr( - new xe::gpu::vulkan::VulkanGraphicsSystem()); + using NullGS = gpu::null::NullGraphicsSystem; + using D3D12GS = gpu::d3d12::D3D12GraphicsSystem; + using VulkanGS = gpu::vulkan::VulkanGraphicsSystem; + using Factory = Factory; + std::vector factories = { #if XE_PLATFORM_WIN32 - } else if (cvars::gpu.compare("d3d12") == 0) { - return std::unique_ptr( - new xe::gpu::d3d12::D3D12GraphicsSystem()); + Factory::Define("d3d12"), #endif // XE_PLATFORM_WIN32 - } else if (cvars::gpu.compare("null") == 0) { - return std::unique_ptr( - new xe::gpu::null::NullGraphicsSystem()); - } else { - // Create best available. - std::unique_ptr best; - -#if XE_PLATFORM_WIN32 - if (xe::gpu::d3d12::D3D12GraphicsSystem::IsD3D12APIAvailable()) { - best = std::unique_ptr( - new xe::gpu::d3d12::D3D12GraphicsSystem()); - if (best) { - return best; - } - } -#endif // XE_PLATFORM_WIN32 - best = std::unique_ptr( - new xe::gpu::vulkan::VulkanGraphicsSystem()); - if (best) { - return best; - } - - // Nothing! - return nullptr; - } + Factory::Define("vulkan"), + Factory::Define("null"), + }; + return Factory::Create(cvars::gpu, factories); } std::vector> CreateInputDrivers( diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc index 87fa23445..8e86d6490 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc @@ -27,7 +27,7 @@ D3D12GraphicsSystem::D3D12GraphicsSystem() {} D3D12GraphicsSystem::~D3D12GraphicsSystem() {} -bool D3D12GraphicsSystem::IsD3D12APIAvailable() { +bool D3D12GraphicsSystem::IsAvailable() { return xe::ui::d3d12::D3D12Provider::IsD3D12APIAvailable(); } diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.h b/src/xenia/gpu/d3d12/d3d12_graphics_system.h index 812d63126..36b3ad24f 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.h +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.h @@ -26,7 +26,7 @@ class D3D12GraphicsSystem : public GraphicsSystem { D3D12GraphicsSystem(); ~D3D12GraphicsSystem() override; - static bool IsD3D12APIAvailable(); + static bool IsAvailable(); std::wstring name() const override; diff --git a/src/xenia/gpu/null/null_graphics_system.h b/src/xenia/gpu/null/null_graphics_system.h index 52ec94992..d15527a9d 100644 --- a/src/xenia/gpu/null/null_graphics_system.h +++ b/src/xenia/gpu/null/null_graphics_system.h @@ -24,6 +24,8 @@ class NullGraphicsSystem : public GraphicsSystem { NullGraphicsSystem(); ~NullGraphicsSystem() override; + static bool IsAvailable() { return true; } + std::wstring name() const override { return L"null"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.h b/src/xenia/gpu/vulkan/vulkan_graphics_system.h index cd61fc181..c5d1b680e 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.h +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.h @@ -24,6 +24,8 @@ class VulkanGraphicsSystem : public GraphicsSystem { VulkanGraphicsSystem(); ~VulkanGraphicsSystem() override; + static bool IsAvailable() { return true; } + std::wstring name() const override { return L"Vulkan"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,