diff options
4 files changed, 37 insertions, 7 deletions
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 26d066004..1a0cea9b7 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -30,7 +30,7 @@ bool ComputePipelineKey::operator==(const ComputePipelineKey& rhs) const noexcep | |||
| 30 | ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_, | 30 | ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_, |
| 31 | BufferCache& buffer_cache_, ProgramManager& program_manager_, | 31 | BufferCache& buffer_cache_, ProgramManager& program_manager_, |
| 32 | const Shader::Info& info_, std::string code, | 32 | const Shader::Info& info_, std::string code, |
| 33 | std::vector<u32> code_v) | 33 | std::vector<u32> code_v, bool force_context_flush) |
| 34 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, | 34 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 35 | program_manager{program_manager_}, info{info_} { | 35 | program_manager{program_manager_}, info{info_} { |
| 36 | switch (device.GetShaderBackend()) { | 36 | switch (device.GetShaderBackend()) { |
| @@ -63,6 +63,15 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac | |||
| 63 | writes_global_memory = !use_storage_buffers && | 63 | writes_global_memory = !use_storage_buffers && |
| 64 | std::ranges::any_of(info.storage_buffers_descriptors, | 64 | std::ranges::any_of(info.storage_buffers_descriptors, |
| 65 | [](const auto& desc) { return desc.is_written; }); | 65 | [](const auto& desc) { return desc.is_written; }); |
| 66 | if (force_context_flush) { | ||
| 67 | std::scoped_lock lock{built_mutex}; | ||
| 68 | built_fence.Create(); | ||
| 69 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. | ||
| 70 | glFlush(); | ||
| 71 | built_condvar.notify_one(); | ||
| 72 | } else { | ||
| 73 | is_built = true; | ||
| 74 | } | ||
| 66 | } | 75 | } |
| 67 | 76 | ||
| 68 | void ComputePipeline::Configure() { | 77 | void ComputePipeline::Configure() { |
| @@ -142,6 +151,9 @@ void ComputePipeline::Configure() { | |||
| 142 | } | 151 | } |
| 143 | texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); | 152 | texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); |
| 144 | 153 | ||
| 154 | if (!is_built) { | ||
| 155 | WaitForBuild(); | ||
| 156 | } | ||
| 145 | if (assembly_program.handle != 0) { | 157 | if (assembly_program.handle != 0) { |
| 146 | program_manager.BindComputeAssemblyProgram(assembly_program.handle); | 158 | program_manager.BindComputeAssemblyProgram(assembly_program.handle); |
| 147 | } else { | 159 | } else { |
| @@ -223,4 +235,13 @@ void ComputePipeline::Configure() { | |||
| 223 | } | 235 | } |
| 224 | } | 236 | } |
| 225 | 237 | ||
| 238 | void ComputePipeline::WaitForBuild() { | ||
| 239 | if (built_fence.handle == 0) { | ||
| 240 | std::unique_lock lock{built_mutex}; | ||
| 241 | built_condvar.wait(lock, [this] { return built_fence.handle != 0; }); | ||
| 242 | } | ||
| 243 | ASSERT(glClientWaitSync(built_fence.handle, 0, GL_TIMEOUT_IGNORED) != GL_WAIT_FAILED); | ||
| 244 | is_built = true; | ||
| 245 | } | ||
| 246 | |||
| 226 | } // namespace OpenGL | 247 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h index 6534dec32..9bcc72b59 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.h +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h | |||
| @@ -50,7 +50,8 @@ class ComputePipeline { | |||
| 50 | public: | 50 | public: |
| 51 | explicit ComputePipeline(const Device& device, TextureCache& texture_cache_, | 51 | explicit ComputePipeline(const Device& device, TextureCache& texture_cache_, |
| 52 | BufferCache& buffer_cache_, ProgramManager& program_manager_, | 52 | BufferCache& buffer_cache_, ProgramManager& program_manager_, |
| 53 | const Shader::Info& info_, std::string code, std::vector<u32> code_v); | 53 | const Shader::Info& info_, std::string code, std::vector<u32> code_v, |
| 54 | bool force_context_flush = false); | ||
| 54 | 55 | ||
| 55 | void Configure(); | 56 | void Configure(); |
| 56 | 57 | ||
| @@ -65,6 +66,8 @@ public: | |||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | private: | 68 | private: |
| 69 | void WaitForBuild(); | ||
| 70 | |||
| 68 | TextureCache& texture_cache; | 71 | TextureCache& texture_cache; |
| 69 | BufferCache& buffer_cache; | 72 | BufferCache& buffer_cache; |
| 70 | Tegra::MemoryManager* gpu_memory; | 73 | Tegra::MemoryManager* gpu_memory; |
| @@ -81,6 +84,11 @@ private: | |||
| 81 | 84 | ||
| 82 | bool use_storage_buffers{}; | 85 | bool use_storage_buffers{}; |
| 83 | bool writes_global_memory{}; | 86 | bool writes_global_memory{}; |
| 87 | |||
| 88 | std::mutex built_mutex; | ||
| 89 | std::condition_variable built_condvar; | ||
| 90 | OGLSync built_fence{}; | ||
| 91 | bool is_built{false}; | ||
| 84 | }; | 92 | }; |
| 85 | 93 | ||
| 86 | } // namespace OpenGL | 94 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 15812b678..626ea7dcb 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -286,7 +286,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 286 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 286 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 287 | queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { | 287 | queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { |
| 288 | ctx->pools.ReleaseContents(); | 288 | ctx->pools.ReleaseContents(); |
| 289 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; | 289 | auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)}; |
| 290 | std::scoped_lock lock{state.mutex}; | 290 | std::scoped_lock lock{state.mutex}; |
| 291 | if (pipeline) { | 291 | if (pipeline) { |
| 292 | compute_cache.emplace(key, std::move(pipeline)); | 292 | compute_cache.emplace(key, std::move(pipeline)); |
| @@ -560,8 +560,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | 562 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( |
| 563 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, | 563 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env, |
| 564 | Shader::Environment& env) try { | 564 | bool force_context_flush) try { |
| 565 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 565 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); |
| 566 | 566 | ||
| 567 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; | 567 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; |
| @@ -590,7 +590,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager, | 592 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager, |
| 593 | program.info, code, code_spirv); | 593 | program.info, code, code_spirv, force_context_flush); |
| 594 | } catch (Shader::Exception& exception) { | 594 | } catch (Shader::Exception& exception) { |
| 595 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 595 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| 596 | return nullptr; | 596 | return nullptr; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 50f610cd0..6b9732fca 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -58,7 +58,8 @@ private: | |||
| 58 | 58 | ||
| 59 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools, | 59 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools, |
| 60 | const ComputePipelineKey& key, | 60 | const ComputePipelineKey& key, |
| 61 | Shader::Environment& env); | 61 | Shader::Environment& env, |
| 62 | bool force_context_flush = false); | ||
| 62 | 63 | ||
| 63 | std::unique_ptr<ShaderWorker> CreateWorkers() const; | 64 | std::unique_ptr<ShaderWorker> CreateWorkers() const; |
| 64 | 65 | ||