From f5cddbbf3fa6b8f6f0cdb8d636d0d4935809d9a6 Mon Sep 17 00:00:00 2001 From: gibbed Date: Sat, 3 Aug 2019 17:01:34 -0500 Subject: [PATCH] [App] Simplify and improve factory template. [App] Rework audio and input system creation. --- src/xenia/app/xenia_main.cc | 149 +++++++++++-------- src/xenia/apu/nop/nop_audio_system.h | 2 + src/xenia/apu/xaudio2/xaudio2_audio_system.h | 2 + 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index db78bc4bb..cc35b9ec3 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -65,64 +65,93 @@ 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 +class Factory { + private: + struct Creator { + std::string name; + std::function is_available; + std::function(Args...)> instantiate; + }; - template - static Factory Define(const std::string& name) { - return {name, DT::IsAvailable, - []() { return std::unique_ptr
(new DT); }}; + std::vector creators_; + + public: + void Add(const std::string& name, std::function is_available, + std::function(Args...)> instantiate) { + creators_.push_back({name, is_available, instantiate}); } - static std::unique_ptr Create(const std::string& name, - const std::vector& factories) { + void Add(const std::string& name, + std::function(Args...)> instantiate) { + Add(name, []() { return true; }, instantiate); + } + + template + void Add(const std::string& name) { + Add(name, DT::IsAvailable, [](Args... args) { + return std::unique_ptr
(new DT(std::forward(args)...)); + }); + } + + std::unique_ptr Create(const std::string& name, Args... args) { if (!name.empty() && name != "any") { auto it = std::find_if( - factories.begin(), factories.end(), + creators_.cbegin(), creators_.cend(), [&name](const auto& f) { return name.compare(f.name) == 0; }); - if (it != factories.end() && (*it).is_available()) { - return (*it).instantiate(); + if (it != creators_.cend() && (*it).is_available()) { + return (*it).instantiate(std::forward(args)...); } 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; + for (const auto& creator : creators_) { + if (!creator.is_available()) continue; + auto instance = creator.instantiate(std::forward(args)...); + if (!instance) continue; + return instance; } - // Nothing! return nullptr; } } + + std::vector> CreateAll(const std::string& name, + Args... args) { + std::vector> instances; + if (!name.empty() && name != "any") { + auto it = std::find_if( + creators_.cbegin(), creators_.cend(), + [&name](const auto& f) { return name.compare(f.name) == 0; }); + if (it != creators_.cend() && (*it).is_available()) { + auto instance = (*it).instantiate(std::forward(args)...); + if (instance) { + instances.push_back(std::move(instance)); + } + } + } else { + for (const auto& creator : creators_) { + if (!creator.is_available()) continue; + auto instance = creator.instantiate(std::forward(args)...); + if (instance) { + instances.push_back(std::move(instance)); + } + } + } + return instances; + } }; std::unique_ptr CreateAudioSystem(cpu::Processor* processor) { - if (cvars::apu.compare("nop") == 0) { - return apu::nop::NopAudioSystem::Create(processor); -#if XE_PLATFORM_WIN32 - } else if (cvars::apu.compare("xaudio2") == 0) { - return apu::xaudio2::XAudio2AudioSystem::Create(processor); -#endif // XE_PLATFORM_WIN32 - } else { - // Create best available. - std::unique_ptr best; + using NopAS = apu::nop::NopAudioSystem; + using XAudio2AS = apu::xaudio2::XAudio2AudioSystem; + using Factory = Factory; + Factory factory; #if XE_PLATFORM_WIN32 - best = apu::xaudio2::XAudio2AudioSystem::Create(processor); - if (best) { - return best; - } + factory.Add("xaudio2"); #endif // XE_PLATFORM_WIN32 + factory.Add("nop"); - // Fallback to nop. - return apu::nop::NopAudioSystem::Create(processor); - } + return factory.Create(cvars::apu, processor); } std::unique_ptr CreateGraphicsSystem() { @@ -130,39 +159,31 @@ std::unique_ptr CreateGraphicsSystem() { using D3D12GS = gpu::d3d12::D3D12GraphicsSystem; using VulkanGS = gpu::vulkan::VulkanGraphicsSystem; using Factory = Factory; - std::vector factories = { + + Factory factory; #if XE_PLATFORM_WIN32 - Factory::Define("d3d12"), + factory.Add("d3d12"); #endif // XE_PLATFORM_WIN32 - Factory::Define("vulkan"), - Factory::Define("null"), - }; - return Factory::Create(cvars::gpu, factories); + factory.Add("vulkan"); + factory.Add("null"); + + return factory.Create(cvars::gpu); } std::vector> CreateInputDrivers( ui::Window* window) { - std::vector> drivers; - if (cvars::hid.compare("nop") == 0) { - drivers.emplace_back(xe::hid::nop::Create(window)); + using Factory = Factory; + + Factory factory; #if XE_PLATFORM_WIN32 - } else if (cvars::hid.compare("winkey") == 0) { - drivers.emplace_back(xe::hid::winkey::Create(window)); - } else if (cvars::hid.compare("xinput") == 0) { - drivers.emplace_back(xe::hid::xinput::Create(window)); + factory.Add("winkey", xe::hid::winkey::Create); + factory.Add("xinput", xe::hid::xinput::Create); #endif // XE_PLATFORM_WIN32 - } else { -#if XE_PLATFORM_WIN32 - auto xinput_driver = xe::hid::xinput::Create(window); - if (xinput_driver) { - drivers.emplace_back(std::move(xinput_driver)); - } - auto winkey_driver = xe::hid::winkey::Create(window); - if (winkey_driver) { - drivers.emplace_back(std::move(winkey_driver)); - } -#endif // XE_PLATFORM_WIN32 - } + factory.Add("nop", xe::hid::nop::Create); + + auto drivers = factory.CreateAll(cvars::hid, window); + + // Remove drivers that fail to setup. for (auto it = drivers.begin(); it != drivers.end();) { if (XFAILED((*it)->Setup())) { it = drivers.erase(it); @@ -170,10 +191,12 @@ std::vector> CreateInputDrivers( ++it; } } + if (drivers.empty()) { // Fallback to nop if none created. drivers.emplace_back(xe::hid::nop::Create(window)); } + return drivers; } diff --git a/src/xenia/apu/nop/nop_audio_system.h b/src/xenia/apu/nop/nop_audio_system.h index 3beb31045..35e1286ef 100644 --- a/src/xenia/apu/nop/nop_audio_system.h +++ b/src/xenia/apu/nop/nop_audio_system.h @@ -21,6 +21,8 @@ class NopAudioSystem : public AudioSystem { explicit NopAudioSystem(cpu::Processor* processor); ~NopAudioSystem() override; + static bool IsAvailable() { return true; } + static std::unique_ptr Create(cpu::Processor* processor); X_STATUS CreateDriver(size_t index, xe::threading::Semaphore* semaphore, diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_system.h b/src/xenia/apu/xaudio2/xaudio2_audio_system.h index 74b99ee42..705f4a0a8 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_system.h +++ b/src/xenia/apu/xaudio2/xaudio2_audio_system.h @@ -21,6 +21,8 @@ class XAudio2AudioSystem : public AudioSystem { explicit XAudio2AudioSystem(cpu::Processor* processor); ~XAudio2AudioSystem() override; + static bool IsAvailable() { return true; } + static std::unique_ptr Create(cpu::Processor* processor); X_RESULT CreateDriver(size_t index, xe::threading::Semaphore* semaphore,