diff --git a/src/citra/emu_window/emu_window_sdl2_gl.cpp b/src/citra/emu_window/emu_window_sdl2_gl.cpp index 46098a7e7..f0256fc1e 100644 --- a/src/citra/emu_window/emu_window_sdl2_gl.cpp +++ b/src/citra/emu_window/emu_window_sdl2_gl.cpp @@ -82,6 +82,8 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary) exit(1); } + strict_context_required = std::strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0; + dummy_window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 0dc51b1b9..182a49ad1 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -407,6 +407,7 @@ GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread, bool is_se setLayout(layout); this->setMouseTracking(true); + strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland"); GMainWindow* parent = GetMainWindow(); connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 61846a8a5..a82b8559c 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -203,6 +203,10 @@ public: return active_config; } + bool StrictContextRequired() const { + return strict_context_required; + } + /** * Requests the internal configuration to be replaced by the specified argument at some point in * the future. @@ -268,6 +272,7 @@ protected: } bool is_secondary{}; + bool strict_context_required{}; WindowSystemInfo window_info; private: diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index c3ad18b57..ab1c20b1d 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "common/scope_exit.h" #include "video_core/renderer_opengl/gl_driver.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_shader_disk_cache.h" @@ -367,7 +368,9 @@ public: ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, const Driver& driver_, bool separable) - : impl(std::make_unique(separable)), emu_window{emu_window_}, driver{driver_} {} + : emu_window{emu_window_}, driver{driver_}, + strict_context_required{emu_window.StrictContextRequired()}, impl{std::make_unique( + separable)} {} ShaderProgramManager::~ShaderProgramManager() = default; @@ -622,8 +625,8 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading, compilation_failed = false; std::size_t built_shaders = 0; // It doesn't have be atomic since it's used behind a mutex - const auto LoadRawSepareble = [&](Frontend::GraphicsContext* context, std::size_t begin, - std::size_t end) { + const auto LoadRawSepareble = [&](std::size_t begin, std::size_t end, + Frontend::GraphicsContext* context = nullptr) { const auto scope = context->Acquire(); for (std::size_t i = begin; i < end; ++i) { if (stop_loading || compilation_failed) { @@ -683,27 +686,32 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading, } }; - const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())}; - const std::size_t bucket_size{load_raws_size / num_workers}; - std::vector> contexts(num_workers); - std::vector threads(num_workers); + if (!strict_context_required) { + const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())}; + const std::size_t bucket_size{load_raws_size / num_workers}; + std::vector> contexts(num_workers); + std::vector threads(num_workers); - emu_window.SaveContext(); - for (std::size_t i = 0; i < num_workers; ++i) { - const bool is_last_worker = i + 1 == num_workers; - const std::size_t start{bucket_size * i}; - const std::size_t end{is_last_worker ? load_raws_size : start + bucket_size}; + emu_window.SaveContext(); + for (std::size_t i = 0; i < num_workers; ++i) { + const bool is_last_worker = i + 1 == num_workers; + const std::size_t start{bucket_size * i}; + const std::size_t end{is_last_worker ? load_raws_size : start + bucket_size}; - // On some platforms the shared context has to be created from the GUI thread - contexts[i] = emu_window.CreateSharedContext(); - // Release the context, so it can be immediately used by the spawned thread - contexts[i]->DoneCurrent(); - threads[i] = std::thread(LoadRawSepareble, contexts[i].get(), start, end); + // On some platforms the shared context has to be created from the GUI thread + contexts[i] = emu_window.CreateSharedContext(); + // Release the context, so it can be immediately used by the spawned thread + contexts[i]->DoneCurrent(); + threads[i] = std::thread(LoadRawSepareble, start, end, contexts[i].get()); + } + for (auto& thread : threads) { + thread.join(); + } + emu_window.RestoreContext(); + } else { + const auto dummy_context{std::make_unique()}; + LoadRawSepareble(0, load_raws_size, dummy_context.get()); } - for (auto& thread : threads) { - thread.join(); - } - emu_window.RestoreContext(); if (compilation_failed) { disk_cache.InvalidateAll(); diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 561046aa7..d0b59754b 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -46,10 +46,10 @@ public: void ApplyTo(OpenGLState& state); private: - class Impl; - std::unique_ptr impl; - Frontend::EmuWindow& emu_window; const Driver& driver; + bool strict_context_required; + class Impl; + std::unique_ptr impl; }; } // namespace OpenGL