diff options
| author | 2019-04-09 14:02:00 -0400 | |
|---|---|---|
| committer | 2019-04-11 22:11:40 -0400 | |
| commit | 6d0551196d90af7f1233c655fd3b979811a14708 (patch) | |
| tree | 9e91a2a79d5351360efaca57cc49be7801c7faf3 /src | |
| parent | core/cpu_core_manager: Create threads separately from initialization. (diff) | |
| download | yuzu-6d0551196d90af7f1233c655fd3b979811a14708.tar.gz yuzu-6d0551196d90af7f1233c655fd3b979811a14708.tar.xz yuzu-6d0551196d90af7f1233c655fd3b979811a14708.zip | |
video_core/gpu: Create threads separately from initialization
Like with CPU emulation, we generally don't want to fire off the threads
immediately after the relevant classes are initialized, we want to do
this after all necessary data is done loading first.
This splits the thread creation into its own interface member function
to allow controlling when these threads in particular get created.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/core.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 5 | ||||
| -rw-r--r-- | src/video_core/gpu_asynch.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/gpu_asynch.h | 5 | ||||
| -rw-r--r-- | src/video_core/gpu_synch.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/gpu_synch.h | 1 | ||||
| -rw-r--r-- | src/video_core/gpu_thread.cpp | 17 | ||||
| -rw-r--r-- | src/video_core/gpu_thread.h | 6 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/video_core.h | 7 |
10 files changed, 51 insertions, 25 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 2b8ec3ca7..eb300eef7 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -3,9 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <map> | ||
| 7 | #include <memory> | 6 | #include <memory> |
| 8 | #include <thread> | ||
| 9 | #include <utility> | 7 | #include <utility> |
| 10 | 8 | ||
| 11 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| @@ -38,8 +36,6 @@ | |||
| 38 | #include "frontend/applets/software_keyboard.h" | 36 | #include "frontend/applets/software_keyboard.h" |
| 39 | #include "frontend/applets/web_browser.h" | 37 | #include "frontend/applets/web_browser.h" |
| 40 | #include "video_core/debug_utils/debug_utils.h" | 38 | #include "video_core/debug_utils/debug_utils.h" |
| 41 | #include "video_core/gpu_asynch.h" | ||
| 42 | #include "video_core/gpu_synch.h" | ||
| 43 | #include "video_core/renderer_base.h" | 39 | #include "video_core/renderer_base.h" |
| 44 | #include "video_core/video_core.h" | 40 | #include "video_core/video_core.h" |
| 45 | 41 | ||
| @@ -135,13 +131,9 @@ struct System::Impl { | |||
| 135 | return ResultStatus::ErrorVideoCore; | 131 | return ResultStatus::ErrorVideoCore; |
| 136 | } | 132 | } |
| 137 | 133 | ||
| 138 | is_powered_on = true; | 134 | gpu_core = VideoCore::CreateGPU(system); |
| 139 | 135 | ||
| 140 | if (Settings::values.use_asynchronous_gpu_emulation) { | 136 | is_powered_on = true; |
| 141 | gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer); | ||
| 142 | } else { | ||
| 143 | gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer); | ||
| 144 | } | ||
| 145 | 137 | ||
| 146 | LOG_DEBUG(Core, "Initialized OK"); | 138 | LOG_DEBUG(Core, "Initialized OK"); |
| 147 | 139 | ||
| @@ -188,7 +180,8 @@ struct System::Impl { | |||
| 188 | } | 180 | } |
| 189 | 181 | ||
| 190 | // Main process has been loaded and been made current. | 182 | // Main process has been loaded and been made current. |
| 191 | // Begin CPU execution. | 183 | // Begin GPU and CPU execution. |
| 184 | gpu_core->Start(); | ||
| 192 | cpu_core_manager.StartThreads(); | 185 | cpu_core_manager.StartThreads(); |
| 193 | 186 | ||
| 194 | status = ResultStatus::Success; | 187 | status = ResultStatus::Success; |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index de30ea354..fe6628923 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -207,6 +207,11 @@ public: | |||
| 207 | }; | 207 | }; |
| 208 | } regs{}; | 208 | } regs{}; |
| 209 | 209 | ||
| 210 | /// Performs any additional setup necessary in order to begin GPU emulation. | ||
| 211 | /// This can be used to launch any necessary threads and register any necessary | ||
| 212 | /// core timing events. | ||
| 213 | virtual void Start() = 0; | ||
| 214 | |||
| 210 | /// Push GPU command entries to be processed | 215 | /// Push GPU command entries to be processed |
| 211 | virtual void PushGPUEntries(Tegra::CommandList&& entries) = 0; | 216 | virtual void PushGPUEntries(Tegra::CommandList&& entries) = 0; |
| 212 | 217 | ||
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index db507cf04..d4e2553a9 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp | |||
| @@ -9,10 +9,14 @@ | |||
| 9 | namespace VideoCommon { | 9 | namespace VideoCommon { |
| 10 | 10 | ||
| 11 | GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) | 11 | GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) |
| 12 | : Tegra::GPU(system, renderer), gpu_thread{system, renderer, *dma_pusher} {} | 12 | : GPU(system, renderer), gpu_thread{system} {} |
| 13 | 13 | ||
| 14 | GPUAsynch::~GPUAsynch() = default; | 14 | GPUAsynch::~GPUAsynch() = default; |
| 15 | 15 | ||
| 16 | void GPUAsynch::Start() { | ||
| 17 | gpu_thread.StartThread(renderer, *dma_pusher); | ||
| 18 | } | ||
| 19 | |||
| 16 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { | 20 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { |
| 17 | gpu_thread.SubmitList(std::move(entries)); | 21 | gpu_thread.SubmitList(std::move(entries)); |
| 18 | } | 22 | } |
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 1dcc61a6c..30be74cba 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h | |||
| @@ -13,16 +13,13 @@ class RendererBase; | |||
| 13 | 13 | ||
| 14 | namespace VideoCommon { | 14 | namespace VideoCommon { |
| 15 | 15 | ||
| 16 | namespace GPUThread { | ||
| 17 | class ThreadManager; | ||
| 18 | } // namespace GPUThread | ||
| 19 | |||
| 20 | /// Implementation of GPU interface that runs the GPU asynchronously | 16 | /// Implementation of GPU interface that runs the GPU asynchronously |
| 21 | class GPUAsynch : public Tegra::GPU { | 17 | class GPUAsynch : public Tegra::GPU { |
| 22 | public: | 18 | public: |
| 23 | explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer); | 19 | explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer); |
| 24 | ~GPUAsynch() override; | 20 | ~GPUAsynch() override; |
| 25 | 21 | ||
| 22 | void Start() override; | ||
| 26 | void PushGPUEntries(Tegra::CommandList&& entries) override; | 23 | void PushGPUEntries(Tegra::CommandList&& entries) override; |
| 27 | void SwapBuffers( | 24 | void SwapBuffers( |
| 28 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; | 25 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; |
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index 2cfc900ed..45e43b1dc 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp | |||
| @@ -8,10 +8,12 @@ | |||
| 8 | namespace VideoCommon { | 8 | namespace VideoCommon { |
| 9 | 9 | ||
| 10 | GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) | 10 | GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) |
| 11 | : Tegra::GPU(system, renderer) {} | 11 | : GPU(system, renderer) {} |
| 12 | 12 | ||
| 13 | GPUSynch::~GPUSynch() = default; | 13 | GPUSynch::~GPUSynch() = default; |
| 14 | 14 | ||
| 15 | void GPUSynch::Start() {} | ||
| 16 | |||
| 15 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | 17 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { |
| 16 | dma_pusher->Push(std::move(entries)); | 18 | dma_pusher->Push(std::move(entries)); |
| 17 | dma_pusher->DispatchCalls(); | 19 | dma_pusher->DispatchCalls(); |
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 766b5631c..3031fcf72 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h | |||
| @@ -18,6 +18,7 @@ public: | |||
| 18 | explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer); | 18 | explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer); |
| 19 | ~GPUSynch() override; | 19 | ~GPUSynch() override; |
| 20 | 20 | ||
| 21 | void Start() override; | ||
| 21 | void PushGPUEntries(Tegra::CommandList&& entries) override; | 22 | void PushGPUEntries(Tegra::CommandList&& entries) override; |
| 22 | void SwapBuffers( | 23 | void SwapBuffers( |
| 23 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; | 24 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index cc56cf467..c9a2077de 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -55,19 +55,24 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p | |||
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | ThreadManager::ThreadManager(Core::System& system, VideoCore::RendererBase& renderer, | 58 | ThreadManager::ThreadManager(Core::System& system) : system{system} {} |
| 59 | Tegra::DmaPusher& dma_pusher) | ||
| 60 | : system{system}, thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)} { | ||
| 61 | synchronization_event = system.CoreTiming().RegisterEvent( | ||
| 62 | "GPUThreadSynch", [this](u64 fence, s64) { state.WaitForSynchronization(fence); }); | ||
| 63 | } | ||
| 64 | 59 | ||
| 65 | ThreadManager::~ThreadManager() { | 60 | ThreadManager::~ThreadManager() { |
| 61 | if (!thread.joinable()) { | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 66 | // Notify GPU thread that a shutdown is pending | 65 | // Notify GPU thread that a shutdown is pending |
| 67 | PushCommand(EndProcessingCommand()); | 66 | PushCommand(EndProcessingCommand()); |
| 68 | thread.join(); | 67 | thread.join(); |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 70 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher) { | ||
| 71 | thread = std::thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)}; | ||
| 72 | synchronization_event = system.CoreTiming().RegisterEvent( | ||
| 73 | "GPUThreadSynch", [this](u64 fence, s64) { state.WaitForSynchronization(fence); }); | ||
| 74 | } | ||
| 75 | |||
| 71 | void ThreadManager::SubmitList(Tegra::CommandList&& entries) { | 76 | void ThreadManager::SubmitList(Tegra::CommandList&& entries) { |
| 72 | const u64 fence{PushCommand(SubmitListCommand(std::move(entries)))}; | 77 | const u64 fence{PushCommand(SubmitListCommand(std::move(entries)))}; |
| 73 | const s64 synchronization_ticks{Core::Timing::usToCycles(9000)}; | 78 | const s64 synchronization_ticks{Core::Timing::usToCycles(9000)}; |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 62bcea5bb..cc14527c7 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -138,10 +138,12 @@ struct SynchState final { | |||
| 138 | /// Class used to manage the GPU thread | 138 | /// Class used to manage the GPU thread |
| 139 | class ThreadManager final { | 139 | class ThreadManager final { |
| 140 | public: | 140 | public: |
| 141 | explicit ThreadManager(Core::System& system, VideoCore::RendererBase& renderer, | 141 | explicit ThreadManager(Core::System& system); |
| 142 | Tegra::DmaPusher& dma_pusher); | ||
| 143 | ~ThreadManager(); | 142 | ~ThreadManager(); |
| 144 | 143 | ||
| 144 | /// Creates and starts the GPU thread. | ||
| 145 | void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher); | ||
| 146 | |||
| 145 | /// Push GPU command entries to be processed | 147 | /// Push GPU command entries to be processed |
| 146 | void SubmitList(Tegra::CommandList&& entries); | 148 | void SubmitList(Tegra::CommandList&& entries); |
| 147 | 149 | ||
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index cb82ecf3f..60cda0ca3 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/settings.h" | 7 | #include "core/settings.h" |
| 8 | #include "video_core/gpu_asynch.h" | ||
| 9 | #include "video_core/gpu_synch.h" | ||
| 8 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 9 | #include "video_core/renderer_opengl/renderer_opengl.h" | 11 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 10 | #include "video_core/video_core.h" | 12 | #include "video_core/video_core.h" |
| @@ -16,6 +18,14 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind | |||
| 16 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); | 18 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); |
| 17 | } | 19 | } |
| 18 | 20 | ||
| 21 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) { | ||
| 22 | if (Settings::values.use_asynchronous_gpu_emulation) { | ||
| 23 | return std::make_unique<VideoCommon::GPUAsynch>(system, system.Renderer()); | ||
| 24 | } | ||
| 25 | |||
| 26 | return std::make_unique<VideoCommon::GPUSynch>(system, system.Renderer()); | ||
| 27 | } | ||
| 28 | |||
| 19 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 29 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |
| 20 | return static_cast<u16>( | 30 | return static_cast<u16>( |
| 21 | Settings::values.resolution_factor | 31 | Settings::values.resolution_factor |
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 3c583f195..b8e0ac372 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h | |||
| @@ -14,6 +14,10 @@ namespace Core::Frontend { | |||
| 14 | class EmuWindow; | 14 | class EmuWindow; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace Tegra { | ||
| 18 | class GPU; | ||
| 19 | } | ||
| 20 | |||
| 17 | namespace VideoCore { | 21 | namespace VideoCore { |
| 18 | 22 | ||
| 19 | class RendererBase; | 23 | class RendererBase; |
| @@ -27,6 +31,9 @@ class RendererBase; | |||
| 27 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 31 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, |
| 28 | Core::System& system); | 32 | Core::System& system); |
| 29 | 33 | ||
| 34 | /// Creates an emulated GPU instance using the given system context. | ||
| 35 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system); | ||
| 36 | |||
| 30 | u16 GetResolutionScaleFactor(const RendererBase& renderer); | 37 | u16 GetResolutionScaleFactor(const RendererBase& renderer); |
| 31 | 38 | ||
| 32 | } // namespace VideoCore | 39 | } // namespace VideoCore |