diff --git a/src/core/core.cpp b/src/core/core.cpp
index 6cc4a0812110bc61db0640274d3f048ef0415bce..26a580cb73e656ac8468f25db5d3d68bdb78526e 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -169,6 +169,9 @@ struct System::Impl {
 
         interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
         gpu_core = VideoCore::CreateGPU(emu_window, system);
+        if (!gpu_core) {
+            return ResultStatus::ErrorVideoCore;
+        }
         gpu_core->Renderer().Rasterizer().SetupDirtyFlags();
 
         is_powered_on = true;
@@ -181,7 +184,6 @@ struct System::Impl {
 
     ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
                       const std::string& filepath) {
-
         app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
         if (!app_loader) {
             LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index bb283d84443567d4c608f02e0597e45ab328f788..72294d4d8555e14f4ff04ddbd53cfe3c53e5bf4a 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -30,7 +30,7 @@ public:
 
     class Scoped {
     public:
-        Scoped(GraphicsContext& context_) : context(context_) {
+        explicit Scoped(GraphicsContext& context_) : context(context_) {
             context.MakeCurrent();
         }
         ~Scoped() {
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 8f59e04425a23f24a1a1d3d29a2c765e0497831a..046ee55a59f1418a6e70b71c9ca98877b9ef0682 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -305,6 +305,7 @@ 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,7 +328,6 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
     const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin,
                             std::size_t end) {
         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 6f08803c128a4d8c4f41c3ba23cd311c7b53cba4..f1a28cc210df4cf5945ca311027437f224c27f10 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -7,7 +7,9 @@
 #include <cstdlib>
 #include <cstring>
 #include <memory>
+
 #include <glad/glad.h>
+
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "common/microprofile.h"
@@ -313,8 +315,8 @@ public:
 
 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} {}
+    : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system},
+      frame_mailbox{}, context{context}, has_debug_tool{HasDebugTool()} {}
 
 RendererOpenGL::~RendererOpenGL() = default;
 
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index fd9fec0186f18e769dc5644c433351f071ca1fa6..f60bdc60a5646a2e5097012fefc84c39ebab1284 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -30,7 +30,7 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindo
         return nullptr;
     }
 }
-} // namespace
+} // Anonymous namespace
 
 namespace VideoCore {
 
@@ -39,7 +39,7 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor
     const auto scope = context->Acquire();
     auto renderer = CreateRenderer(emu_window, system, *context);
     if (!renderer->Init()) {
-        return {};
+        return nullptr;
     }
 
     if (Settings::values.use_asynchronous_gpu_emulation) {
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index d120ee81871874658d799a54db78dad4107ccc95..4e9ced8bafaca703478ff05ad3c0a0137f7ee2fd 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -42,6 +42,10 @@ EmuThread::~EmuThread() = default;
 void EmuThread::run() {
     MicroProfileOnThreadCreate("EmuThread");
 
+    // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
+    // execution.
+    Core::System::GetInstance().GPU().Start();
+
     emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
 
     Core::System::GetInstance().Renderer().Rasterizer().LoadDiskResources(
@@ -51,10 +55,6 @@ void EmuThread::run() {
 
     emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
 
-    // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
-    // execution.
-    Core::System::GetInstance().GPU().Start();
-
     // Holds whether the cpu was running during the last iteration,
     // so that the DebugModeLeft signal can be emitted before the
     // next execution step
@@ -152,7 +152,7 @@ public:
         if (is_current) {
             return;
         }
-        context->makeCurrent(surface);
+        is_current = context->makeCurrent(surface);
     }
 
     void DoneCurrent() override {
@@ -160,7 +160,11 @@ public:
         is_current = false;
     }
 
-    QOpenGLContext* GetShareContext() const {
+    QOpenGLContext* GetShareContext() {
+        return context.get();
+    }
+
+    const QOpenGLContext* GetShareContext() const {
         return context.get();
     }
 
@@ -177,13 +181,15 @@ class DummyContext : public Core::Frontend::GraphicsContext {};
 
 class RenderWidget : public QWidget {
 public:
-    RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {
+    explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {
         setAttribute(Qt::WA_NativeWindow);
         setAttribute(Qt::WA_PaintOnScreen);
     }
 
     virtual ~RenderWidget() = default;
 
+    /// Called on the UI thread when this Widget is ready to draw
+    /// Dervied classes can override this to draw the latest frame.
     virtual void Present() {}
 
     void paintEvent(QPaintEvent* event) override {
@@ -191,56 +197,6 @@ public:
         update();
     }
 
-    void resizeEvent(QResizeEvent* ev) override {
-        render_window->resize(ev->size());
-        render_window->OnFramebufferSizeChanged();
-    }
-
-    void keyPressEvent(QKeyEvent* event) override {
-        InputCommon::GetKeyboard()->PressKey(event->key());
-    }
-
-    void keyReleaseEvent(QKeyEvent* event) override {
-        InputCommon::GetKeyboard()->ReleaseKey(event->key());
-    }
-
-    void mousePressEvent(QMouseEvent* event) override {
-        if (event->source() == Qt::MouseEventSynthesizedBySystem)
-            return; // touch input is handled in TouchBeginEvent
-
-        const auto pos{event->pos()};
-        if (event->button() == Qt::LeftButton) {
-            const auto [x, y] = render_window->ScaleTouch(pos);
-            render_window->TouchPressed(x, y);
-        } else if (event->button() == Qt::RightButton) {
-            InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
-        }
-    }
-
-    void mouseMoveEvent(QMouseEvent* event) override {
-        if (event->source() == Qt::MouseEventSynthesizedBySystem)
-            return; // touch input is handled in TouchUpdateEvent
-
-        const auto pos{event->pos()};
-        const auto [x, y] = render_window->ScaleTouch(pos);
-        render_window->TouchMoved(x, y);
-        InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
-    }
-
-    void mouseReleaseEvent(QMouseEvent* event) override {
-        if (event->source() == Qt::MouseEventSynthesizedBySystem)
-            return; // touch input is handled in TouchEndEvent
-
-        if (event->button() == Qt::LeftButton)
-            render_window->TouchReleased();
-        else if (event->button() == Qt::RightButton)
-            InputCommon::GetMotionEmu()->EndTilt();
-    }
-
-    std::pair<unsigned, unsigned> GetSize() const {
-        return std::make_pair(width(), height());
-    }
-
     QPaintEngine* paintEngine() const override {
         return nullptr;
     }
@@ -276,6 +232,7 @@ private:
     std::unique_ptr<Core::Frontend::GraphicsContext> context{};
 };
 
+#ifdef HAS_VULKAN
 class VulkanRenderWidget : public RenderWidget {
 public:
     explicit VulkanRenderWidget(GRenderWindow* parent, QVulkanInstance* instance)
@@ -284,6 +241,7 @@ public:
         windowHandle()->setVulkanInstance(instance);
     }
 };
+#endif
 
 GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread)
     : QWidget(parent_), emu_thread(emu_thread) {
@@ -358,7 +316,7 @@ qreal GRenderWindow::windowPixelRatio() const {
     return devicePixelRatio();
 }
 
-std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF pos) const {
+std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF& pos) const {
     const qreal pixel_ratio = windowPixelRatio();
     return {static_cast<u32>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})),
             static_cast<u32>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))};
@@ -378,8 +336,10 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
 }
 
 void GRenderWindow::mousePressEvent(QMouseEvent* event) {
-    if (event->source() == Qt::MouseEventSynthesizedBySystem)
-        return; // touch input is handled in TouchBeginEvent
+    // touch input is handled in TouchBeginEvent
+    if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+        return;
+    }
 
     auto pos = event->pos();
     if (event->button() == Qt::LeftButton) {
@@ -391,8 +351,10 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
 }
 
 void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
-    if (event->source() == Qt::MouseEventSynthesizedBySystem)
-        return; // touch input is handled in TouchUpdateEvent
+    // touch input is handled in TouchUpdateEvent
+    if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+        return;
+    }
 
     auto pos = event->pos();
     const auto [x, y] = ScaleTouch(pos);
@@ -401,13 +363,16 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
 }
 
 void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
-    if (event->source() == Qt::MouseEventSynthesizedBySystem)
-        return; // touch input is handled in TouchEndEvent
+    // touch input is handled in TouchEndEvent
+    if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+        return;
+    }
 
-    if (event->button() == Qt::LeftButton)
+    if (event->button() == Qt::LeftButton) {
         this->TouchReleased();
-    else if (event->button() == Qt::RightButton)
+    } else if (event->button() == Qt::RightButton) {
         InputCommon::GetMotionEmu()->EndTilt();
+    }
 }
 
 void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 3739ec7ed02f890274f80c3744dc4e9e6a6448e7..d69078df12e1602550436b24a3badbbefb2b0bee 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -7,11 +7,12 @@
 #include <atomic>
 #include <condition_variable>
 #include <mutex>
-#include <thread>
+
 #include <QImage>
 #include <QThread>
 #include <QWidget>
 #include <QWindow>
+
 #include "common/thread.h"
 #include "core/core.h"
 #include "core/frontend/emu_window.h"
@@ -84,8 +85,8 @@ private:
     bool exec_step = false;
     bool running = false;
     std::atomic_bool stop_run{false};
-    std::mutex running_mutex = {};
-    std::condition_variable running_cv = {};
+    std::mutex running_mutex;
+    std::condition_variable running_cv;
 
 signals:
     /**
@@ -154,7 +155,7 @@ public:
 
     void CaptureScreenshot(u32 res_scale, const QString& screenshot_path);
 
-    std::pair<u32, u32> ScaleTouch(const QPointF pos) const;
+    std::pair<u32, u32> ScaleTouch(const QPointF& pos) const;
 
 public slots:
     void OnEmulationStarting(EmuThread* emu_thread);
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index e5db7d819aab0cc6508d327abd3f4024a4c9083f..4d2ea7e9e943e12db42b78bf5aa02817cd7cc5ea 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -230,11 +230,11 @@ int main(int argc, char** argv) {
 
     system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDL");
 
-    system.Renderer().Rasterizer().LoadDiskResources();
-
     // Core is loaded, start the GPU (makes the GPU contexts current to this thread)
     system.GPU().Start();
 
+    system.Renderer().Rasterizer().LoadDiskResources();
+
     std::thread render_thread([&emu_window] { emu_window->Present(); });
     while (emu_window->IsOpen()) {
         system.RunLoop();
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
index a1bdb1a12b6dcfea71ff2863097a448513337486..a837430cc3e6915d738cc9841d1f790dfe5811e3 100644
--- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
+++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
@@ -102,8 +102,6 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() {
     LOG_INFO(Frontend, "yuzu-tester Version: {} | {}-{}", Common::g_build_fullname,
              Common::g_scm_branch, Common::g_scm_desc);
     Settings::LogSettings();
-
-    DoneCurrent();
 }
 
 EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
@@ -114,14 +112,6 @@ EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
 
 void EmuWindow_SDL2_Hide::PollEvents() {}
 
-void EmuWindow_SDL2_Hide::MakeCurrent() {
-    SDL_GL_MakeCurrent(render_window, gl_context);
-}
-
-void EmuWindow_SDL2_Hide::DoneCurrent() {
-    SDL_GL_MakeCurrent(render_window, nullptr);
-}
-
 bool EmuWindow_SDL2_Hide::IsShown() const {
     return false;
 }
@@ -129,3 +119,35 @@ bool EmuWindow_SDL2_Hide::IsShown() const {
 void EmuWindow_SDL2_Hide::RetrieveVulkanHandlers(void*, void*, void*) const {
     UNREACHABLE();
 }
+
+class SDLGLContext : public Core::Frontend::GraphicsContext {
+public:
+    explicit SDLGLContext() {
+        // create a hidden window to make the shared context against
+        window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
+                                  SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
+        context = SDL_GL_CreateContext(window);
+    }
+
+    ~SDLGLContext() {
+        DoneCurrent();
+        SDL_GL_DeleteContext(context);
+        SDL_DestroyWindow(window);
+    }
+
+    void MakeCurrent() override {
+        SDL_GL_MakeCurrent(window, context);
+    }
+
+    void DoneCurrent() override {
+        SDL_GL_MakeCurrent(window, nullptr);
+    }
+
+private:
+    SDL_Window* window;
+    SDL_GLContext context;
+};
+
+std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_Hide::CreateSharedContext() const {
+    return std::make_unique<SDLGLContext>();
+}
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
index b13e15309975a6ee0b32ad6b2c26cbe9656cfbc3..9f5d04fca796356b851b56cc75c1220b64e3dde1 100644
--- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
+++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
@@ -16,12 +16,6 @@ public:
     /// Polls window events
     void PollEvents() override;
 
-    /// Makes the graphics context current for the caller thread
-    void MakeCurrent() override;
-
-    /// Releases the GL context from the caller thread
-    void DoneCurrent() override;
-
     /// Whether the screen is being shown or not.
     bool IsShown() const override;
 
@@ -29,8 +23,7 @@ public:
     void RetrieveVulkanHandlers(void* get_instance_proc_addr, void* instance,
                                 void* surface) const override;
 
-    /// Whether the window is still open, and a close request hasn't yet been sent
-    bool IsOpen() const;
+    std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
 
 private:
     /// Whether the GPU and driver supports the OpenGL extension required
diff --git a/src/yuzu_tester/yuzu.cpp b/src/yuzu_tester/yuzu.cpp
index 94ad50cb334449a15e1223cd5a7eea1565a62881..676e70ebd710f24bc3d01430654b67db9c7e8303 100644
--- a/src/yuzu_tester/yuzu.cpp
+++ b/src/yuzu_tester/yuzu.cpp
@@ -164,11 +164,6 @@ int main(int argc, char** argv) {
 
     std::unique_ptr<EmuWindow_SDL2_Hide> emu_window{std::make_unique<EmuWindow_SDL2_Hide>()};
 
-    if (!Settings::values.use_multi_core) {
-        // Single core mode must acquire OpenGL context for entire emulation session
-        emu_window->MakeCurrent();
-    }
-
     bool finished = false;
     int return_value = 0;
     const auto callback = [&finished,
@@ -257,6 +252,7 @@ int main(int argc, char** argv) {
 
     system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDLHideTester");
 
+    system.GPU().Start();
     system.Renderer().Rasterizer().LoadDiskResources();
 
     while (!finished) {