summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/gpu.cpp10
-rw-r--r--src/video_core/gpu.h18
-rw-r--r--src/video_core/gpu_asynch.cpp9
-rw-r--r--src/video_core/gpu_asynch.h9
-rw-r--r--src/video_core/gpu_synch.cpp17
-rw-r--r--src/video_core/gpu_synch.h10
-rw-r--r--src/video_core/gpu_thread.cpp15
-rw-r--r--src/video_core/gpu_thread.h7
-rw-r--r--src/video_core/renderer_base.h3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp5
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp69
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h10
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp3
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h2
-rw-r--r--src/video_core/video_core.cpp28
-rw-r--r--src/video_core/video_core.h11
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);