diff options
Diffstat (limited to 'src/video_core')
-rw-r--r-- | src/video_core/gpu.cpp | 10 | ||||
-rw-r--r-- | src/video_core/gpu.h | 18 | ||||
-rw-r--r-- | src/video_core/gpu_asynch.cpp | 9 | ||||
-rw-r--r-- | src/video_core/gpu_asynch.h | 9 | ||||
-rw-r--r-- | src/video_core/gpu_synch.cpp | 17 | ||||
-rw-r--r-- | src/video_core/gpu_synch.h | 10 | ||||
-rw-r--r-- | src/video_core/gpu_thread.cpp | 15 | ||||
-rw-r--r-- | src/video_core/gpu_thread.h | 7 | ||||
-rw-r--r-- | src/video_core/renderer_base.h | 3 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 5 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 69 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 10 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 3 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.h | 2 | ||||
-rw-r--r-- | src/video_core/video_core.cpp | 28 | ||||
-rw-r--r-- | src/video_core/video_core.h | 11 |
16 files changed, 129 insertions, 97 deletions
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index e8f763ce9..8acf2eda2 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -7,6 +7,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/core_timing_util.h" +#include "core/frontend/emu_window.h" #include "core/memory.h" #include "video_core/engines/fermi_2d.h" #include "video_core/engines/kepler_compute.h" @@ -16,14 +17,15 @@ #include "video_core/gpu.h" #include "video_core/memory_manager.h" #include "video_core/renderer_base.h" +#include "video_core/video_core.h" namespace Tegra { MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); -GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async) - : system{system}, renderer{renderer}, is_async{is_async} { - auto& rasterizer{renderer.Rasterizer()}; +GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async) + : system{system}, renderer{std::move(renderer_)}, is_async{is_async} { + auto& rasterizer{renderer->Rasterizer()}; memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); dma_pusher = std::make_unique<Tegra::DmaPusher>(*this); maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); @@ -137,7 +139,7 @@ u64 GPU::GetTicks() const { } void GPU::FlushCommands() { - renderer.Rasterizer().FlushCommands(); + renderer->Rasterizer().FlushCommands(); } // Note that, traditionally, methods are treated as 4-byte addressable locations, and hence diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 64acb17df..ced9d7e28 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -25,8 +25,11 @@ inline u8* FromCacheAddr(CacheAddr cache_addr) { } namespace Core { -class System; +namespace Frontend { +class EmuWindow; } +class System; +} // namespace Core namespace VideoCore { class RendererBase; @@ -129,7 +132,8 @@ class MemoryManager; class GPU { public: - explicit GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async); + explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, + bool is_async); virtual ~GPU(); @@ -174,6 +178,14 @@ public: /// Returns a reference to the GPU DMA pusher. Tegra::DmaPusher& DmaPusher(); + VideoCore::RendererBase& Renderer() { + return *renderer; + } + + const VideoCore::RendererBase& Renderer() const { + return *renderer; + } + // Waits for the GPU to finish working virtual void WaitIdle() const = 0; @@ -287,7 +299,7 @@ private: protected: std::unique_ptr<Tegra::DmaPusher> dma_pusher; Core::System& system; - VideoCore::RendererBase& renderer; + std::unique_ptr<VideoCore::RendererBase> renderer; private: std::unique_ptr<Tegra::MemoryManager> memory_manager; diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index 04222d060..925be8d7b 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp @@ -10,13 +10,16 @@ namespace VideoCommon { -GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) - : GPU(system, renderer, true), gpu_thread{system} {} +GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, + std::unique_ptr<Core::Frontend::GraphicsContext>&& context) + : GPU(system, std::move(renderer_), true), gpu_thread{system}, gpu_context(std::move(context)), + cpu_context(renderer->GetRenderWindow().CreateSharedContext()) {} GPUAsynch::~GPUAsynch() = default; void GPUAsynch::Start() { - gpu_thread.StartThread(renderer, *dma_pusher); + cpu_context->MakeCurrent(); + gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher); } void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 1241ade1d..265c62758 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h @@ -7,6 +7,10 @@ #include "video_core/gpu.h" #include "video_core/gpu_thread.h" +namespace Core::Frontend { +class GraphicsContext; +} + namespace VideoCore { class RendererBase; } // namespace VideoCore @@ -16,7 +20,8 @@ namespace VideoCommon { /// Implementation of GPU interface that runs the GPU asynchronously class GPUAsynch final : public Tegra::GPU { public: - explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer); + explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, + std::unique_ptr<Core::Frontend::GraphicsContext>&& context); ~GPUAsynch() override; void Start() override; @@ -32,6 +37,8 @@ protected: private: GPUThread::ThreadManager gpu_thread; + std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; + std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context; }; } // namespace VideoCommon diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index d48221077..bd5278a5c 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp @@ -7,12 +7,15 @@ namespace VideoCommon { -GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) - : GPU(system, renderer, false) {} +GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, + std::unique_ptr<Core::Frontend::GraphicsContext>&& context) + : GPU(system, std::move(renderer), false), context{std::move(context)} {} GPUSynch::~GPUSynch() = default; -void GPUSynch::Start() {} +void GPUSynch::Start() { + context->MakeCurrent(); +} void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { dma_pusher->Push(std::move(entries)); @@ -20,19 +23,19 @@ void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { } void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { - renderer.SwapBuffers(framebuffer); + renderer->SwapBuffers(framebuffer); } void GPUSynch::FlushRegion(CacheAddr addr, u64 size) { - renderer.Rasterizer().FlushRegion(addr, size); + renderer->Rasterizer().FlushRegion(addr, size); } void GPUSynch::InvalidateRegion(CacheAddr addr, u64 size) { - renderer.Rasterizer().InvalidateRegion(addr, size); + renderer->Rasterizer().InvalidateRegion(addr, size); } void GPUSynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { - renderer.Rasterizer().FlushAndInvalidateRegion(addr, size); + renderer->Rasterizer().FlushAndInvalidateRegion(addr, size); } } // namespace VideoCommon diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index c71baee89..866a94c8c 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h @@ -6,6 +6,10 @@ #include "video_core/gpu.h" +namespace Core::Frontend { +class GraphicsContext; +} + namespace VideoCore { class RendererBase; } // namespace VideoCore @@ -15,7 +19,8 @@ namespace VideoCommon { /// Implementation of GPU interface that runs the GPU synchronously class GPUSynch final : public Tegra::GPU { public: - explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer); + explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, + std::unique_ptr<Core::Frontend::GraphicsContext>&& context); ~GPUSynch() override; void Start() override; @@ -29,6 +34,9 @@ public: protected: void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, [[maybe_unused]] u32 value) const override {} + +private: + std::unique_ptr<Core::Frontend::GraphicsContext> context; }; } // namespace VideoCommon diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index b1088af3d..270c7ae0d 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -5,7 +5,7 @@ #include "common/assert.h" #include "common/microprofile.h" #include "core/core.h" -#include "core/frontend/scope_acquire_context.h" +#include "core/frontend/emu_window.h" #include "video_core/dma_pusher.h" #include "video_core/gpu.h" #include "video_core/gpu_thread.h" @@ -14,8 +14,8 @@ namespace VideoCommon::GPUThread { /// Runs the GPU thread -static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher, - SynchState& state) { +static void RunThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, + Tegra::DmaPusher& dma_pusher, SynchState& state) { MicroProfileOnThreadCreate("GpuThread"); // Wait for first GPU command before acquiring the window context @@ -27,7 +27,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p return; } - Core::Frontend::ScopeAcquireContext acquire_context{renderer.GetRenderWindow()}; + auto current_context = context.Acquire(); CommandDataContainer next; while (state.is_running) { @@ -62,8 +62,11 @@ ThreadManager::~ThreadManager() { thread.join(); } -void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher) { - thread = std::thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)}; +void ThreadManager::StartThread(VideoCore::RendererBase& renderer, + Core::Frontend::GraphicsContext& context, + Tegra::DmaPusher& dma_pusher) { + thread = std::thread{RunThread, std::ref(renderer), std::ref(context), std::ref(dma_pusher), + std::ref(state)}; } void ThreadManager::SubmitList(Tegra::CommandList&& entries) { diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 882e2d9c7..be36c580e 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -10,7 +10,6 @@ #include <optional> #include <thread> #include <variant> - #include "common/threadsafe_queue.h" #include "video_core/gpu.h" @@ -20,6 +19,9 @@ class DmaPusher; } // namespace Tegra namespace Core { +namespace Frontend { +class GraphicsContext; +} class System; } // namespace Core @@ -99,7 +101,8 @@ public: ~ThreadManager(); /// Creates and starts the GPU thread. - void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher); + void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, + Tegra::DmaPusher& dma_pusher); /// Push GPU command entries to be processed void SubmitList(Tegra::CommandList&& entries); diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 5ec99a126..1d85219b6 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -46,7 +46,8 @@ public: /// Draws the latest frame to the window waiting timeout_ms for a frame to arrive (Renderer /// specific implementation) - virtual void TryPresent(int timeout_ms) = 0; + /// Returns true if a frame was drawn + virtual bool TryPresent(int timeout_ms) = 0; // Getter/setter functions: // ------------------------ diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index e3d31c3eb..8f59e0442 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -305,7 +305,6 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, } const std::vector gl_cache = disk_cache.LoadPrecompiled(); - const auto supported_formats = GetSupportedFormats(); // Track if precompiled cache was altered during loading to know if we have to // serialize the virtual precompiled cache file back to the hard drive @@ -327,8 +326,8 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin, std::size_t end) { - context->MakeCurrent(); - SCOPE_EXIT({ return context->DoneCurrent(); }); + const auto scope = context->Acquire(); + const auto supported_formats = GetSupportedFormats(); for (std::size_t i = begin; i < end; ++i) { if (stop_loading) { diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index fca5e3ec0..6f08803c1 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -7,9 +7,7 @@ #include <cstdlib> #include <cstring> #include <memory> - #include <glad/glad.h> - #include "common/assert.h" #include "common/logging/log.h" #include "common/microprofile.h" @@ -30,8 +28,6 @@ namespace OpenGL { namespace { -// If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have -// to wait on available presentation frames. constexpr std::size_t SWAP_CHAIN_SIZE = 3; struct Frame { @@ -214,7 +210,7 @@ public: std::deque<Frame*> present_queue; Frame* previous_frame{}; - FrameMailbox() : has_debug_tool{HasDebugTool()} { + FrameMailbox() { for (auto& frame : swap_chain) { free_queue.push(&frame); } @@ -285,13 +281,9 @@ public: std::unique_lock lock{swap_chain_lock}; present_queue.push_front(frame); present_cv.notify_one(); - - DebugNotifyNextFrame(); } Frame* TryGetPresentFrame(int timeout_ms) { - DebugWaitForNextFrame(); - std::unique_lock lock{swap_chain_lock}; // wait for new entries in the present_queue present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), @@ -317,38 +309,12 @@ public: previous_frame = frame; return frame; } - -private: - std::mutex debug_synch_mutex; - std::condition_variable debug_synch_condition; - std::atomic_int frame_for_debug{}; - const bool has_debug_tool; // When true, using a GPU debugger, so keep frames in lock-step - - /// Signal that a new frame is available (called from GPU thread) - void DebugNotifyNextFrame() { - if (!has_debug_tool) { - return; - } - frame_for_debug++; - std::lock_guard lock{debug_synch_mutex}; - debug_synch_condition.notify_one(); - } - - /// Wait for a new frame to be available (called from presentation thread) - void DebugWaitForNextFrame() { - if (!has_debug_tool) { - return; - } - const int last_frame = frame_for_debug; - std::unique_lock lock{debug_synch_mutex}; - debug_synch_condition.wait(lock, - [this, last_frame] { return frame_for_debug > last_frame; }); - } }; -RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) - : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, - frame_mailbox{std::make_unique<FrameMailbox>()} {} +RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, + Core::Frontend::GraphicsContext& context) + : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, frame_mailbox{}, + has_debug_tool{HasDebugTool()}, context{context} {} RendererOpenGL::~RendererOpenGL() = default; @@ -356,8 +322,6 @@ MICROPROFILE_DEFINE(OpenGL_RenderFrame, "OpenGL", "Render Frame", MP_RGB(128, 12 MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128)); void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { - render_window.PollEvents(); - if (!framebuffer) { return; } @@ -413,6 +377,13 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { m_current_frame++; rasterizer->TickFrame(); } + + render_window.PollEvents(); + if (has_debug_tool) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + Present(0); + context.SwapBuffers(); + } } void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { @@ -480,6 +451,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color } void RendererOpenGL::InitOpenGLObjects() { + frame_mailbox = std::make_unique<FrameMailbox>(); + glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, 0.0f); @@ -692,12 +665,21 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } -void RendererOpenGL::TryPresent(int timeout_ms) { +bool RendererOpenGL::TryPresent(int timeout_ms) { + if (has_debug_tool) { + LOG_DEBUG(Render_OpenGL, + "Skipping presentation because we are presenting on the main context"); + return false; + } + return Present(timeout_ms); +} + +bool RendererOpenGL::Present(int timeout_ms) { const auto& layout = render_window.GetFramebufferLayout(); auto frame = frame_mailbox->TryGetPresentFrame(timeout_ms); if (!frame) { LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present"); - return; + return false; } // Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a @@ -725,6 +707,7 @@ void RendererOpenGL::TryPresent(int timeout_ms) { glFlush(); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + return true; } void RendererOpenGL::RenderScreenshot() { diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 33073ce5b..50b647661 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -55,13 +55,14 @@ class FrameMailbox; class RendererOpenGL final : public VideoCore::RendererBase { public: - explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system); + explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, + Core::Frontend::GraphicsContext& context); ~RendererOpenGL() override; bool Init() override; void ShutDown() override; void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; - void TryPresent(int timeout_ms) override; + bool TryPresent(int timeout_ms) override; private: /// Initializes the OpenGL state and creates persistent objects. @@ -89,8 +90,11 @@ private: void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer); + bool Present(int timeout_ms); + Core::Frontend::EmuWindow& emu_window; Core::System& system; + Core::Frontend::GraphicsContext& context; StateTracker state_tracker{system}; @@ -115,6 +119,8 @@ private: /// Frame presentation mailbox std::unique_ptr<FrameMailbox> frame_mailbox; + + bool has_debug_tool = false; }; } // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 42bb01418..6953aaafe 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -141,8 +141,9 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { render_window.PollEvents(); } -void RendererVulkan::TryPresent(int /*timeout_ms*/) { +bool RendererVulkan::TryPresent(int /*timeout_ms*/) { // TODO (bunnei): ImplementMe + return true; } bool RendererVulkan::Init() { diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 3da08d2e4..d14384e79 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -42,7 +42,7 @@ public: bool Init() override; void ShutDown() override; void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; - void TryPresent(int timeout_ms) override; + bool TryPresent(int timeout_ms) override; private: std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback( diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index a5f81a8a0..fd9fec018 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -15,13 +15,13 @@ #endif #include "video_core/video_core.h" -namespace VideoCore { - -std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, - Core::System& system) { +namespace { +std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, + Core::System& system, + Core::Frontend::GraphicsContext& context) { switch (Settings::values.renderer_backend) { case Settings::RendererBackend::OpenGL: - return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); + return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); #ifdef HAS_VULKAN case Settings::RendererBackend::Vulkan: return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); @@ -30,13 +30,23 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind return nullptr; } } +} // namespace -std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) { - if (Settings::values.use_asynchronous_gpu_emulation) { - return std::make_unique<VideoCommon::GPUAsynch>(system, system.Renderer()); +namespace VideoCore { + +std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { + auto context = emu_window.CreateSharedContext(); + const auto scope = context->Acquire(); + auto renderer = CreateRenderer(emu_window, system, *context); + if (!renderer->Init()) { + return {}; } - return std::make_unique<VideoCommon::GPUSynch>(system, system.Renderer()); + if (Settings::values.use_asynchronous_gpu_emulation) { + return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), + std::move(context)); + } + return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context)); } u16 GetResolutionScaleFactor(const RendererBase& renderer) { diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index b8e0ac372..f5c27125d 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -22,17 +22,8 @@ namespace VideoCore { class RendererBase; -/** - * Creates a renderer instance. - * - * @note The returned renderer instance is simply allocated. Its Init() - * function still needs to be called to fully complete its setup. - */ -std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, - Core::System& system); - /// Creates an emulated GPU instance using the given system context. -std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system); +std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system); u16 GetResolutionScaleFactor(const RendererBase& renderer); |