Procházet zdrojové kódy

renderer_opengl: refactor context acquire

Liam před 3 roky
rodič
revize
d5f53da79d

+ 3 - 2
src/video_core/gpu.cpp

@@ -223,8 +223,6 @@ struct GPU::Impl {
     /// core timing events.
     void Start() {
         gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler);
-        cpu_context = renderer->GetRenderWindow().CreateSharedContext();
-        cpu_context->MakeCurrent();
     }
 
     void NotifyShutdown() {
@@ -235,6 +233,9 @@ struct GPU::Impl {
 
     /// Obtain the CPU Context
     void ObtainContext() {
+        if (!cpu_context) {
+            cpu_context = renderer->GetRenderWindow().CreateSharedContext();
+        }
         cpu_context->MakeCurrent();
     }
 

+ 7 - 3
src/video_core/renderer_opengl/gl_device.cpp

@@ -126,9 +126,11 @@ Device::Device() {
     const bool is_intel = vendor_name == "Intel";
 
 #ifdef __unix__
-    const bool is_linux = true;
+    constexpr bool is_linux = true;
+    const bool is_wayland = strcasecmp(getenv("XDG_SESSION_TYPE"), "wayland") == 0;
 #else
-    const bool is_linux = false;
+    constexpr bool is_linux = false;
+    constexpr bool is_wayland = false;
 #endif
 
     bool disable_fast_buffer_sub_data = false;
@@ -194,9 +196,11 @@ Device::Device() {
     }
 
     // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation.
+    // Blocks EGL on Wayland from using asynchronous shader compilation.
     use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() &&
-                               !(is_amd || (is_intel && !is_linux));
+                               !(is_amd || (is_intel && !is_linux)) && !is_wayland;
     use_driver_cache = is_nvidia;
+    strict_context_required = is_wayland;
 
     LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
     LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);

+ 5 - 0
src/video_core/renderer_opengl/gl_device.h

@@ -173,6 +173,10 @@ public:
         return can_report_memory;
     }
 
+    bool StrictContextRequired() const {
+        return strict_context_required;
+    }
+
 private:
     static bool TestVariableAoffi();
     static bool TestPreciseBug();
@@ -216,6 +220,7 @@ private:
     bool has_cbuf_ftou_bug{};
     bool has_bool_ref_bug{};
     bool can_report_memory{};
+    bool strict_context_required{};
 
     std::string vendor_name;
 };

+ 45 - 31
src/video_core/renderer_opengl/gl_shader_cache.cpp

@@ -174,6 +174,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
       texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_},
       state_tracker{state_tracker_}, shader_notify{shader_notify_},
       use_asynchronous_shaders{device.UseAsynchronousShaders()},
+      strict_context_required{device.StrictContextRequired()},
       profile{
           .supported_spirv = 0x00010000,
 
@@ -255,9 +256,14 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
     }
     shader_cache_filename = base_dir / "opengl.bin";
 
-    if (!workers) {
+    if (!workers && !strict_context_required) {
         workers = CreateWorkers();
     }
+    std::optional<Context> strict_context;
+    if (strict_context_required) {
+        strict_context.emplace(emu_window);
+    }
+
     struct {
         std::mutex mutex;
         size_t total{};
@@ -265,44 +271,49 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
         bool has_loaded{};
     } state;
 
+    const auto queue_work{[&](Common::UniqueFunction<void, Context*>&& work) {
+        if (strict_context_required) {
+            work(&strict_context.value());
+        } else {
+            workers->QueueWork(std::move(work));
+        }
+    }};
     const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
         ComputePipelineKey key;
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
-        workers->QueueWork(
-            [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
-                ctx->pools.ReleaseContents();
-                auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
-                std::scoped_lock lock{state.mutex};
-                if (pipeline) {
-                    compute_cache.emplace(key, std::move(pipeline));
-                }
-                ++state.built;
-                if (state.has_loaded) {
-                    callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
-                }
-            });
+        queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
+            ctx->pools.ReleaseContents();
+            auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
+            std::scoped_lock lock{state.mutex};
+            if (pipeline) {
+                compute_cache.emplace(key, std::move(pipeline));
+            }
+            ++state.built;
+            if (state.has_loaded) {
+                callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
+            }
+        });
         ++state.total;
     }};
     const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
         GraphicsPipelineKey key;
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
-        workers->QueueWork(
-            [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
-                boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
-                for (auto& env : envs) {
-                    env_ptrs.push_back(&env);
-                }
-                ctx->pools.ReleaseContents();
-                auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
-                std::scoped_lock lock{state.mutex};
-                if (pipeline) {
-                    graphics_cache.emplace(key, std::move(pipeline));
-                }
-                ++state.built;
-                if (state.has_loaded) {
-                    callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
-                }
-            });
+        queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
+            boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
+            for (auto& env : envs) {
+                env_ptrs.push_back(&env);
+            }
+            ctx->pools.ReleaseContents();
+            auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
+            std::scoped_lock lock{state.mutex};
+            if (pipeline) {
+                graphics_cache.emplace(key, std::move(pipeline));
+            }
+            ++state.built;
+            if (state.has_loaded) {
+                callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
+            }
+        });
         ++state.total;
     }};
     LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics);
@@ -314,6 +325,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
     state.has_loaded = true;
     lock.unlock();
 
+    if (strict_context_required) {
+        return;
+    }
     workers->WaitForRequests(stop_loading);
     if (!use_asynchronous_shaders) {
         workers.reset();

+ 1 - 0
src/video_core/renderer_opengl/gl_shader_cache.h

@@ -69,6 +69,7 @@ private:
     StateTracker& state_tracker;
     VideoCore::ShaderNotify& shader_notify;
     const bool use_asynchronous_shaders;
+    const bool strict_context_required;
 
     GraphicsPipelineKey graphics_key{};
     GraphicsPipeline* current_pipeline{};

+ 1 - 2
src/yuzu/bootmanager.cpp

@@ -61,8 +61,6 @@ void EmuThread::run() {
 
     // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
     // execution.
-    gpu.Start();
-
     gpu.ObtainContext();
 
     emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
@@ -77,6 +75,7 @@ void EmuThread::run() {
     emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
 
     gpu.ReleaseContext();
+    gpu.Start();
 
     system.GetCpuManager().OnGpuReady();