From 282adfc70b5d7d958d564bfda0227bb3fbd8d110 Mon Sep 17 00:00:00 2001 From: James Rowe Date: Tue, 24 Mar 2020 20:58:49 -0600 Subject: Frontend/GPU: Refactor context management Changes the GraphicsContext to be managed by the GPU core. This eliminates the need for the frontends to fool around with tricky MakeCurrent/DoneCurrent calls that are dependent on the settings (such as async gpu option). This also refactors out the need to use QWidget::fromWindowContainer as that caused issues with focus and input handling. Now we use a regular QWidget and just access the native windowHandle() directly. Another change is removing the debug tool setting in FrameMailbox. Instead of trying to block the frontend until a new frame is ready, the core will now take over presentation and draw directly to the window if the renderer detects that its hooked by NSight or RenderDoc Lastly, since it was in the way, I removed ScopeAcquireWindowContext and replaced it with a simple subclass in GraphicsContext that achieves the same result --- src/video_core/renderer_opengl/gl_shader_cache.cpp | 5 +- src/video_core/renderer_opengl/renderer_opengl.cpp | 69 ++++++++-------------- src/video_core/renderer_opengl/renderer_opengl.h | 10 +++- 3 files changed, 36 insertions(+), 48 deletions(-) (limited to 'src/video_core/renderer_opengl') 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 #include #include - #include - #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 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()} {} +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(); + 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 frame_mailbox; + + bool has_debug_tool = false; }; } // namespace OpenGL -- cgit v1.2.3 From cf9c94d4017120b618194a720942ef4e5c8289bd Mon Sep 17 00:00:00 2001 From: James Rowe Date: Tue, 24 Mar 2020 22:57:36 -0600 Subject: Address review and fix broken yuzu-tester build --- src/core/core.cpp | 4 +- src/core/frontend/emu_window.h | 2 +- src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 +- src/video_core/renderer_opengl/renderer_opengl.cpp | 6 +- src/video_core/video_core.cpp | 4 +- src/yuzu/bootmanager.cpp | 97 +++++++--------------- src/yuzu/bootmanager.h | 9 +- src/yuzu_cmd/yuzu.cpp | 4 +- .../emu_window/emu_window_sdl2_hide.cpp | 42 +++++++--- src/yuzu_tester/emu_window/emu_window_sdl2_hide.h | 9 +- src/yuzu_tester/yuzu.cpp | 6 +- 11 files changed, 83 insertions(+), 102 deletions(-) (limited to 'src/video_core/renderer_opengl') diff --git a/src/core/core.cpp b/src/core/core.cpp index 6cc4a0812..26a580cb7 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -169,6 +169,9 @@ struct System::Impl { interrupt_manager = std::make_unique(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 bb283d844..72294d4d8 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 8f59e0442..046ee55a5 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 6f08803c1..f1a28cc21 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -7,7 +7,9 @@ #include #include #include + #include + #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 fd9fec018..f60bdc60a 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -30,7 +30,7 @@ std::unique_ptr CreateRenderer(Core::Frontend::EmuWindo return nullptr; } } -} // namespace +} // Anonymous namespace namespace VideoCore { @@ -39,7 +39,7 @@ std::unique_ptr 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 d120ee818..4e9ced8ba 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 GetSize() const { - return std::make_pair(width(), height()); - } - QPaintEngine* paintEngine() const override { return nullptr; } @@ -276,6 +232,7 @@ private: std::unique_ptr 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 GRenderWindow::ScaleTouch(const QPointF pos) const { +std::pair GRenderWindow::ScaleTouch(const QPointF& pos) const { const qreal pixel_ratio = windowPixelRatio(); return {static_cast(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})), static_cast(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 3739ec7ed..d69078df1 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -7,11 +7,12 @@ #include #include #include -#include + #include #include #include #include + #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 ScaleTouch(const QPointF pos) const; + std::pair 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 e5db7d819..4d2ea7e9e 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 a1bdb1a12..a837430cc 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 EmuWindow_SDL2_Hide::CreateSharedContext() const { + return std::make_unique(); +} 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 b13e15309..9f5d04fca 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 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 94ad50cb3..676e70ebd 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 emu_window{std::make_unique()}; - 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) { -- cgit v1.2.3