diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | 46 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_pipeline.h | 7 |
2 files changed, 32 insertions, 21 deletions
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index f8495896c..9e6732abd 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -243,10 +243,6 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 243 | case Settings::ShaderBackend::GLASM: | 243 | case Settings::ShaderBackend::GLASM: |
| 244 | if (!sources[stage].empty()) { | 244 | if (!sources[stage].empty()) { |
| 245 | assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage)); | 245 | assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage)); |
| 246 | if (in_parallel) { | ||
| 247 | // Make sure program is built before continuing when building in parallel | ||
| 248 | glGetString(GL_PROGRAM_ERROR_STRING_NV); | ||
| 249 | } | ||
| 250 | } | 246 | } |
| 251 | break; | 247 | break; |
| 252 | case Settings::ShaderBackend::SPIRV: | 248 | case Settings::ShaderBackend::SPIRV: |
| @@ -256,20 +252,18 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 256 | break; | 252 | break; |
| 257 | } | 253 | } |
| 258 | } | 254 | } |
| 259 | if (in_parallel && backend != Settings::ShaderBackend::GLASM) { | 255 | if (in_parallel) { |
| 260 | // Make sure programs have built if we are building shaders in parallel | 256 | std::lock_guard lock{built_mutex}; |
| 261 | for (OGLProgram& program : source_programs) { | 257 | built_fence.Create(); |
| 262 | if (program.handle != 0) { | 258 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. |
| 263 | GLint status{}; | 259 | glFlush(); |
| 264 | glGetProgramiv(program.handle, GL_LINK_STATUS, &status); | 260 | built_condvar.notify_one(); |
| 265 | } | 261 | } else { |
| 266 | } | 262 | is_built = true; |
| 267 | } | 263 | } |
| 268 | if (shader_notify) { | 264 | if (shader_notify) { |
| 269 | shader_notify->MarkShaderComplete(); | 265 | shader_notify->MarkShaderComplete(); |
| 270 | } | 266 | } |
| 271 | is_built = true; | ||
| 272 | built_condvar.notify_one(); | ||
| 273 | }}; | 267 | }}; |
| 274 | if (thread_worker) { | 268 | if (thread_worker) { |
| 275 | thread_worker->QueueWork(std::move(func)); | 269 | thread_worker->QueueWork(std::move(func)); |
| @@ -440,7 +434,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 440 | buffer_cache.UpdateGraphicsBuffers(is_indexed); | 434 | buffer_cache.UpdateGraphicsBuffers(is_indexed); |
| 441 | buffer_cache.BindHostGeometryBuffers(is_indexed); | 435 | buffer_cache.BindHostGeometryBuffers(is_indexed); |
| 442 | 436 | ||
| 443 | if (!is_built.load(std::memory_order::relaxed)) { | 437 | if (!IsBuilt()) { |
| 444 | WaitForBuild(); | 438 | WaitForBuild(); |
| 445 | } | 439 | } |
| 446 | const bool use_assembly{assembly_programs[0].handle != 0}; | 440 | const bool use_assembly{assembly_programs[0].handle != 0}; |
| @@ -585,8 +579,26 @@ void GraphicsPipeline::GenerateTransformFeedbackState() { | |||
| 585 | } | 579 | } |
| 586 | 580 | ||
| 587 | void GraphicsPipeline::WaitForBuild() { | 581 | void GraphicsPipeline::WaitForBuild() { |
| 588 | std::unique_lock lock{built_mutex}; | 582 | if (built_fence.handle == 0) { |
| 589 | built_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); }); | 583 | std::unique_lock lock{built_mutex}; |
| 584 | built_condvar.wait(lock, [this] { return built_fence.handle != 0; }); | ||
| 585 | } | ||
| 586 | ASSERT(glClientWaitSync(built_fence.handle, 0, GL_TIMEOUT_IGNORED) != GL_WAIT_FAILED); | ||
| 587 | is_built = true; | ||
| 588 | } | ||
| 589 | |||
| 590 | bool GraphicsPipeline::IsBuilt() noexcept { | ||
| 591 | if (is_built) { | ||
| 592 | return true; | ||
| 593 | } | ||
| 594 | if (built_fence.handle == 0) { | ||
| 595 | return false; | ||
| 596 | } | ||
| 597 | // Timeout of zero means this is non-blocking | ||
| 598 | const auto sync_status = glClientWaitSync(built_fence.handle, 0, 0); | ||
| 599 | ASSERT(sync_status != GL_WAIT_FAILED); | ||
| 600 | is_built = sync_status != GL_TIMEOUT_EXPIRED; | ||
| 601 | return is_built; | ||
| 590 | } | 602 | } |
| 591 | 603 | ||
| 592 | } // namespace OpenGL | 604 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 4e28d9a42..311d49f3f 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h | |||
| @@ -100,9 +100,7 @@ public: | |||
| 100 | return writes_global_memory; | 100 | return writes_global_memory; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | [[nodiscard]] bool IsBuilt() const noexcept { | 103 | [[nodiscard]] bool IsBuilt() noexcept; |
| 104 | return is_built.load(std::memory_order::relaxed); | ||
| 105 | } | ||
| 106 | 104 | ||
| 107 | template <typename Spec> | 105 | template <typename Spec> |
| 108 | static auto MakeConfigureSpecFunc() { | 106 | static auto MakeConfigureSpecFunc() { |
| @@ -154,7 +152,8 @@ private: | |||
| 154 | 152 | ||
| 155 | std::mutex built_mutex; | 153 | std::mutex built_mutex; |
| 156 | std::condition_variable built_condvar; | 154 | std::condition_variable built_condvar; |
| 157 | std::atomic_bool is_built{false}; | 155 | OGLSync built_fence{}; |
| 156 | bool is_built{false}; | ||
| 158 | }; | 157 | }; |
| 159 | 158 | ||
| 160 | } // namespace OpenGL | 159 | } // namespace OpenGL |