diff options
Diffstat (limited to 'src')
6 files changed, 49 insertions, 16 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_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index c115dabe1..29491e762 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -176,7 +176,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 176 | std::array<std::string, 5> sources, | 176 | std::array<std::string, 5> sources, |
| 177 | std::array<std::vector<u32>, 5> sources_spirv, | 177 | std::array<std::vector<u32>, 5> sources_spirv, |
| 178 | const std::array<const Shader::Info*, 5>& infos, | 178 | const std::array<const Shader::Info*, 5>& infos, |
| 179 | const GraphicsPipelineKey& key_) | 179 | const GraphicsPipelineKey& key_, bool force_context_flush) |
| 180 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, | 180 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, |
| 181 | state_tracker{state_tracker_}, key{key_} { | 181 | state_tracker{state_tracker_}, key{key_} { |
| 182 | if (shader_notify) { | 182 | if (shader_notify) { |
| @@ -231,7 +231,8 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 231 | const bool in_parallel = thread_worker != nullptr; | 231 | const bool in_parallel = thread_worker != nullptr; |
| 232 | const auto backend = device.GetShaderBackend(); | 232 | const auto backend = device.GetShaderBackend(); |
| 233 | auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv), | 233 | auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv), |
| 234 | shader_notify, backend, in_parallel](ShaderContext::Context*) mutable { | 234 | shader_notify, backend, in_parallel, |
| 235 | force_context_flush](ShaderContext::Context*) mutable { | ||
| 235 | for (size_t stage = 0; stage < 5; ++stage) { | 236 | for (size_t stage = 0; stage < 5; ++stage) { |
| 236 | switch (backend) { | 237 | switch (backend) { |
| 237 | case Settings::ShaderBackend::GLSL: | 238 | case Settings::ShaderBackend::GLSL: |
| @@ -251,7 +252,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 251 | break; | 252 | break; |
| 252 | } | 253 | } |
| 253 | } | 254 | } |
| 254 | if (in_parallel) { | 255 | if (force_context_flush || in_parallel) { |
| 255 | std::scoped_lock lock{built_mutex}; | 256 | std::scoped_lock lock{built_mutex}; |
| 256 | built_fence.Create(); | 257 | built_fence.Create(); |
| 257 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. | 258 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 1c06b3655..7bab3be0a 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h | |||
| @@ -78,7 +78,7 @@ public: | |||
| 78 | std::array<std::string, 5> sources, | 78 | std::array<std::string, 5> sources, |
| 79 | std::array<std::vector<u32>, 5> sources_spirv, | 79 | std::array<std::vector<u32>, 5> sources_spirv, |
| 80 | const std::array<const Shader::Info*, 5>& infos, | 80 | const std::array<const Shader::Info*, 5>& infos, |
| 81 | const GraphicsPipelineKey& key_); | 81 | const GraphicsPipelineKey& key_, bool force_context_flush = false); |
| 82 | 82 | ||
| 83 | void Configure(bool is_indexed) { | 83 | void Configure(bool is_indexed) { |
| 84 | configure_func(this, is_indexed); | 84 | configure_func(this, is_indexed); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7dd854e0f..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)); |
| @@ -307,7 +307,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 307 | env_ptrs.push_back(&env); | 307 | env_ptrs.push_back(&env); |
| 308 | } | 308 | } |
| 309 | ctx->pools.ReleaseContents(); | 309 | ctx->pools.ReleaseContents(); |
| 310 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)}; | 310 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false, true)}; |
| 311 | std::scoped_lock lock{state.mutex}; | 311 | std::scoped_lock lock{state.mutex}; |
| 312 | if (pipeline) { | 312 | if (pipeline) { |
| 313 | graphics_cache.emplace(key, std::move(pipeline)); | 313 | graphics_cache.emplace(key, std::move(pipeline)); |
| @@ -439,7 +439,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() { | |||
| 439 | 439 | ||
| 440 | std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | 440 | std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( |
| 441 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, | 441 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, |
| 442 | std::span<Shader::Environment* const> envs, bool build_in_parallel) try { | 442 | std::span<Shader::Environment* const> envs, bool use_shader_workers, |
| 443 | bool force_context_flush) try { | ||
| 443 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 444 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); |
| 444 | size_t env_index{}; | 445 | size_t env_index{}; |
| 445 | u32 total_storage_buffers{}; | 446 | u32 total_storage_buffers{}; |
| @@ -531,10 +532,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 531 | } | 532 | } |
| 532 | previous_program = &program; | 533 | previous_program = &program; |
| 533 | } | 534 | } |
| 534 | auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; | 535 | auto* const thread_worker{use_shader_workers ? workers.get() : nullptr}; |
| 535 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, program_manager, | 536 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, program_manager, |
| 536 | state_tracker, thread_worker, &shader_notify, sources, | 537 | state_tracker, thread_worker, &shader_notify, sources, |
| 537 | sources_spirv, infos, key); | 538 | sources_spirv, infos, key, force_context_flush); |
| 538 | 539 | ||
| 539 | } catch (Shader::Exception& exception) { | 540 | } catch (Shader::Exception& exception) { |
| 540 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 541 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| @@ -559,8 +560,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 559 | } | 560 | } |
| 560 | 561 | ||
| 561 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | 562 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( |
| 562 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, | 563 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env, |
| 563 | Shader::Environment& env) try { | 564 | bool force_context_flush) try { |
| 564 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 565 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); |
| 565 | 566 | ||
| 566 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; | 567 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; |
| @@ -589,7 +590,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 589 | } | 590 | } |
| 590 | 591 | ||
| 591 | 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, |
| 592 | program.info, code, code_spirv); | 593 | program.info, code, code_spirv, force_context_flush); |
| 593 | } catch (Shader::Exception& exception) { | 594 | } catch (Shader::Exception& exception) { |
| 594 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 595 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| 595 | 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 f82420592..6b9732fca 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -50,14 +50,16 @@ private: | |||
| 50 | 50 | ||
| 51 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( | 51 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( |
| 52 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, | 52 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, |
| 53 | std::span<Shader::Environment* const> envs, bool build_in_parallel); | 53 | std::span<Shader::Environment* const> envs, bool use_shader_workers, |
| 54 | bool force_context_flush = false); | ||
| 54 | 55 | ||
| 55 | std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key, | 56 | std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key, |
| 56 | const VideoCommon::ShaderInfo* shader); | 57 | const VideoCommon::ShaderInfo* shader); |
| 57 | 58 | ||
| 58 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools, | 59 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools, |
| 59 | const ComputePipelineKey& key, | 60 | const ComputePipelineKey& key, |
| 60 | Shader::Environment& env); | 61 | Shader::Environment& env, |
| 62 | bool force_context_flush = false); | ||
| 61 | 63 | ||
| 62 | std::unique_ptr<ShaderWorker> CreateWorkers() const; | 64 | std::unique_ptr<ShaderWorker> CreateWorkers() const; |
| 63 | 65 | ||