Ver Fonte

gl_compute_pipeline: Force context flush when loading shader cache

ameerj há 3 anos atrás
pai
commit
720ff38097

+ 22 - 1
src/video_core/renderer_opengl/gl_compute_pipeline.cpp

@@ -30,7 +30,7 @@ bool ComputePipelineKey::operator==(const ComputePipelineKey& rhs) const noexcep
 ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_,
 ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_,
                                  BufferCache& buffer_cache_, ProgramManager& program_manager_,
                                  BufferCache& buffer_cache_, ProgramManager& program_manager_,
                                  const Shader::Info& info_, std::string code,
                                  const Shader::Info& info_, std::string code,
-                                 std::vector<u32> code_v)
+                                 std::vector<u32> code_v, bool force_context_flush)
     : texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
     : texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
       program_manager{program_manager_}, info{info_} {
       program_manager{program_manager_}, info{info_} {
     switch (device.GetShaderBackend()) {
     switch (device.GetShaderBackend()) {
@@ -63,6 +63,15 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac
     writes_global_memory = !use_storage_buffers &&
     writes_global_memory = !use_storage_buffers &&
                            std::ranges::any_of(info.storage_buffers_descriptors,
                            std::ranges::any_of(info.storage_buffers_descriptors,
                                                [](const auto& desc) { return desc.is_written; });
                                                [](const auto& desc) { return desc.is_written; });
+    if (force_context_flush) {
+        std::scoped_lock lock{built_mutex};
+        built_fence.Create();
+        // Flush this context to ensure compilation commands and fence are in the GPU pipe.
+        glFlush();
+        built_condvar.notify_one();
+    } else {
+        is_built = true;
+    }
 }
 }
 
 
 void ComputePipeline::Configure() {
 void ComputePipeline::Configure() {
@@ -142,6 +151,9 @@ void ComputePipeline::Configure() {
     }
     }
     texture_cache.FillComputeImageViews(std::span(views.data(), views.size()));
     texture_cache.FillComputeImageViews(std::span(views.data(), views.size()));
 
 
+    if (!is_built) {
+        WaitForBuild();
+    }
     if (assembly_program.handle != 0) {
     if (assembly_program.handle != 0) {
         program_manager.BindComputeAssemblyProgram(assembly_program.handle);
         program_manager.BindComputeAssemblyProgram(assembly_program.handle);
     } else {
     } else {
@@ -223,4 +235,13 @@ void ComputePipeline::Configure() {
     }
     }
 }
 }
 
 
+void ComputePipeline::WaitForBuild() {
+    if (built_fence.handle == 0) {
+        std::unique_lock lock{built_mutex};
+        built_condvar.wait(lock, [this] { return built_fence.handle != 0; });
+    }
+    ASSERT(glClientWaitSync(built_fence.handle, 0, GL_TIMEOUT_IGNORED) != GL_WAIT_FAILED);
+    is_built = true;
+}
+
 } // namespace OpenGL
 } // namespace OpenGL

+ 9 - 1
src/video_core/renderer_opengl/gl_compute_pipeline.h

@@ -50,7 +50,8 @@ class ComputePipeline {
 public:
 public:
     explicit ComputePipeline(const Device& device, TextureCache& texture_cache_,
     explicit ComputePipeline(const Device& device, TextureCache& texture_cache_,
                              BufferCache& buffer_cache_, ProgramManager& program_manager_,
                              BufferCache& buffer_cache_, ProgramManager& program_manager_,
-                             const Shader::Info& info_, std::string code, std::vector<u32> code_v);
+                             const Shader::Info& info_, std::string code, std::vector<u32> code_v,
+                             bool force_context_flush = false);
 
 
     void Configure();
     void Configure();
 
 
@@ -65,6 +66,8 @@ public:
     }
     }
 
 
 private:
 private:
+    void WaitForBuild();
+
     TextureCache& texture_cache;
     TextureCache& texture_cache;
     BufferCache& buffer_cache;
     BufferCache& buffer_cache;
     Tegra::MemoryManager* gpu_memory;
     Tegra::MemoryManager* gpu_memory;
@@ -81,6 +84,11 @@ private:
 
 
     bool use_storage_buffers{};
     bool use_storage_buffers{};
     bool writes_global_memory{};
     bool writes_global_memory{};
+
+    std::mutex built_mutex;
+    std::condition_variable built_condvar;
+    OGLSync built_fence{};
+    bool is_built{false};
 };
 };
 
 
 } // namespace OpenGL
 } // namespace OpenGL

+ 4 - 4
src/video_core/renderer_opengl/gl_shader_cache.cpp

@@ -286,7 +286,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
         queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
         queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
             ctx->pools.ReleaseContents();
             ctx->pools.ReleaseContents();
-            auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
+            auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)};
             std::scoped_lock lock{state.mutex};
             std::scoped_lock lock{state.mutex};
             if (pipeline) {
             if (pipeline) {
                 compute_cache.emplace(key, std::move(pipeline));
                 compute_cache.emplace(key, std::move(pipeline));
@@ -560,8 +560,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
 }
 }
 
 
 std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
 std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
-    ShaderContext::ShaderPools& pools, const ComputePipelineKey& key,
-    Shader::Environment& env) try {
+    ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env,
+    bool force_context_flush) try {
     LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
     LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
 
 
     Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
     Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
@@ -590,7 +590,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
     }
     }
 
 
     return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager,
     return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager,
-                                             program.info, code, code_spirv);
+                                             program.info, code, code_spirv, force_context_flush);
 } catch (Shader::Exception& exception) {
 } catch (Shader::Exception& exception) {
     LOG_ERROR(Render_OpenGL, "{}", exception.what());
     LOG_ERROR(Render_OpenGL, "{}", exception.what());
     return nullptr;
     return nullptr;

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

@@ -58,7 +58,8 @@ private:
 
 
     std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools,
     std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools,
                                                            const ComputePipelineKey& key,
                                                            const ComputePipelineKey& key,
-                                                           Shader::Environment& env);
+                                                           Shader::Environment& env,
+                                                           bool force_context_flush = false);
 
 
     std::unique_ptr<ShaderWorker> CreateWorkers() const;
     std::unique_ptr<ShaderWorker> CreateWorkers() const;