diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 934fc80d2a..ff54defdd8 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -375,11 +375,6 @@ void GLFragmentProgram::Decompile(const RSXFragmentProgram& prog) } shader.create(::glsl::program_domain::glsl_fragment_program, source); -} - -void GLFragmentProgram::Compile() -{ - shader.compile(); id = shader.id(); } diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h index a9d1373924..bff0503a68 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h @@ -68,9 +68,6 @@ public: */ void Decompile(const RSXFragmentProgram& prog); - /** Compile the decompiled fragment shader into a format we can use with OpenGL. */ - void Compile(); - private: /** Deletes the shader and any stored information */ void Delete(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 04a275f1bc..6ec28192a6 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -358,6 +358,9 @@ void GLGSRender::on_init_thread() void GLGSRender::on_exit() { + // Destroy internal RSX state, may call upon this->do_local_task + GSRender::on_exit(); + // Globals // TODO: Move these gl::destroy_compute_tasks(); @@ -491,10 +494,6 @@ void GLGSRender::on_exit() query.driver_handle = 0; } - glFlush(); - glFinish(); - - GSRender::on_exit(); zcull_ctrl.release(); gl::set_primary_context_thread(false); diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index 12946e7a77..1a7f73d726 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -25,14 +25,7 @@ namespace gl void flush_command_queue(fence& fence_obj) { - if (is_primary_context_thread()) - { - fence_obj.check_signaled(); - } - else - { - glFlush(); - } + fence_obj.check_signaled(); } GLenum draw_mode(rsx::primitive_type in) diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 4128d4b052..d5f5c644cc 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -13,6 +13,7 @@ #include "../Common/GLSLTypes.h" #include "Emu/system_config.h" +#include "Utilities/mutex.h" #include "Utilities/geometry.h" #include "util/logs.hpp" @@ -2226,6 +2227,40 @@ public: GLuint m_id = GL_NONE; fence m_compiled_fence; + fence m_init_fence; + + shared_mutex m_compile_lock; + atomic_t m_is_compiled{}; + + void precompile() + { + const char* str = source.c_str(); + const GLint length = ::narrow(source.length()); + + if (g_cfg.video.log_programs) + { + std::string base_name; + switch (type) + { + case ::glsl::program_domain::glsl_vertex_program: + base_name = "shaderlog/VertexProgram"; + break; + case ::glsl::program_domain::glsl_fragment_program: + base_name = "shaderlog/FragmentProgram"; + break; + case ::glsl::program_domain::glsl_compute_program: + base_name = "shaderlog/ComputeProgram"; + break; + } + + fs::file(fs::get_cache_dir() + base_name + std::to_string(m_id) + ".glsl", fs::rewrite).write(str); + } + + glShaderSource(m_id, 1, &str, &length); + + m_init_fence.create(); + flush_command_queue(m_init_fence); + } public: shader() = default; @@ -2268,33 +2303,21 @@ public: } m_id = glCreateShader(shader_type); + precompile(); } shader& compile() { - const char* str = source.c_str(); - const GLint length = ::narrow(source.length()); - - if (g_cfg.video.log_programs) + std::lock_guard lock(m_compile_lock); + if (m_is_compiled) { - std::string base_name; - switch (type) - { - case ::glsl::program_domain::glsl_vertex_program: - base_name = "shaderlog/VertexProgram"; - break; - case ::glsl::program_domain::glsl_fragment_program: - base_name = "shaderlog/FragmentProgram"; - break; - case ::glsl::program_domain::glsl_compute_program: - base_name = "shaderlog/ComputeProgram"; - break; - } - - fs::file(fs::get_cache_dir() + base_name + std::to_string(m_id) + ".glsl", fs::rewrite).write(str); + // Another thread compiled this already + return *this; } - glShaderSource(m_id, 1, &str, &length); + verify(HERE), !m_init_fence.is_empty(); // Do not attempt to compile a shader_view!! + m_init_fence.server_wait_sync(); + glCompileShader(m_id); GLint status = GL_FALSE; @@ -2318,6 +2341,8 @@ public: m_compiled_fence.create(); flush_command_queue(m_compiled_fence); + + m_is_compiled = true; return *this; } @@ -2355,6 +2380,11 @@ public: return m_id != GL_NONE; } + bool compiled() const + { + return m_is_compiled; + } + explicit operator bool() const { return created(); diff --git a/rpcs3/Emu/RSX/GL/GLPipelineCompiler.cpp b/rpcs3/Emu/RSX/GL/GLPipelineCompiler.cpp index 4f3a563945..72a02b7948 100644 --- a/rpcs3/Emu/RSX/GL/GLPipelineCompiler.cpp +++ b/rpcs3/Emu/RSX/GL/GLPipelineCompiler.cpp @@ -47,7 +47,6 @@ namespace gl } auto result = int_compile_graphics_pipe( - job.vp_handle, job.fp_handle, job.post_create_func, job.post_link_func); @@ -59,41 +58,33 @@ namespace gl } std::unique_ptr pipe_compiler::compile( - GLuint vp_handle, GLuint fp_handle, op_flags flags, - callback_t post_create_func, - callback_t post_link_func, - callback_t completion_callback_func) + build_callback_t post_create_func, + build_callback_t post_link_func, + storage_callback_t completion_callback_func) { if (flags == COMPILE_INLINE) { - return int_compile_graphics_pipe(vp_handle, fp_handle, post_create_func, post_link_func); + return int_compile_graphics_pipe(post_create_func, post_link_func); } - m_work_queue.push(vp_handle, fp_handle, post_create_func, post_link_func, completion_callback_func); + m_work_queue.push(post_create_func, post_link_func, completion_callback_func); return {}; } std::unique_ptr pipe_compiler::int_compile_graphics_pipe( - GLuint vp_handle, GLuint fp_handle, - callback_t post_create_func, - callback_t post_link_func) + build_callback_t post_create_func, + build_callback_t post_link_func) { auto result = std::make_unique(); result->create(); if (post_create_func) { - post_create_func(result); - } - - result->link(); - - if (post_link_func) - { - post_link_func(result); + post_create_func(result.get()); } + result->link(post_link_func); return result; } diff --git a/rpcs3/Emu/RSX/GL/GLPipelineCompiler.h b/rpcs3/Emu/RSX/GL/GLPipelineCompiler.h index c8b7d1d597..5d1802a039 100644 --- a/rpcs3/Emu/RSX/GL/GLPipelineCompiler.h +++ b/rpcs3/Emu/RSX/GL/GLPipelineCompiler.h @@ -15,7 +15,8 @@ namespace gl COMPILE_DEFERRED = 2 }; - using callback_t = std::function&)>; + using storage_callback_t = std::function&)>; + using build_callback_t = std::function; pipe_compiler(); ~pipe_compiler(); @@ -26,11 +27,10 @@ namespace gl std::function context_destroy_func); std::unique_ptr compile( - GLuint vp_handle, GLuint fp_handle, op_flags flags, - callback_t post_create_func = {}, - callback_t post_link_func = {}, - callback_t completion_callback = {}); + build_callback_t post_create_func = {}, + build_callback_t post_link_func = {}, + storage_callback_t completion_callback = {}); void operator()(); @@ -38,14 +38,12 @@ namespace gl struct pipe_compiler_job { - GLuint vp_handle; - GLuint fp_handle; - callback_t post_create_func; - callback_t post_link_func; - callback_t completion_callback; + build_callback_t post_create_func; + build_callback_t post_link_func; + storage_callback_t completion_callback; - pipe_compiler_job(GLuint vp, GLuint fp, callback_t post_create, callback_t post_link, callback_t completion) - : vp_handle(vp), fp_handle(fp), post_create_func(post_create), post_link_func(post_link), completion_callback(completion) + pipe_compiler_job(build_callback_t post_create, build_callback_t post_link, storage_callback_t completion) + : post_create_func(post_create), post_link_func(post_link), completion_callback(completion) {} }; @@ -58,7 +56,7 @@ namespace gl std::function m_context_destroy_func; std::unique_ptr int_compile_graphics_pipe( - GLuint vp_handle, GLuint fp_handle, callback_t post_create_func, callback_t post_link_func); + build_callback_t post_create_func, build_callback_t post_link_func); }; void initialize_pipe_compiler( diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h index ca3ab0ddcc..d63999ad6f 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h @@ -18,14 +18,12 @@ struct GLTraits void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t /*ID*/) { fragmentProgramData.Decompile(RSXFP); - fragmentProgramData.Compile(); } static void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t /*ID*/) { vertexProgramData.Decompile(RSXVP); - vertexProgramData.Compile(); } static @@ -44,25 +42,21 @@ struct GLTraits auto compiler = gl::get_pipe_compiler(); auto flags = (compile_async) ? gl::pipe_compiler::COMPILE_DEFERRED : gl::pipe_compiler::COMPILE_INLINE; - gl::fence vp_fence, fp_fence; - if (compile_async) + auto post_create_func = [vp = &vertexProgramData.shader, fp = &fragmentProgramData.shader] + (gl::glsl::program* program) { - vp_fence = vertexProgramData.shader.get_compile_fence_sync(); - fp_fence = fragmentProgramData.shader.get_compile_fence_sync(); - } - - auto post_create_func = [vp_id = vertexProgramData.id, fp_id = fragmentProgramData.id, vp_fence, fp_fence] - (std::unique_ptr& program) - { - if (!vp_fence.is_empty()) + if (!vp->compiled()) { - // Force server threads to wait for the compilation to finish - vp_fence.server_wait_sync(); - fp_fence.server_wait_sync(); + const_cast(vp)->compile(); } - program->attach(gl::glsl::shader_view(vp_id)) - .attach(gl::glsl::shader_view(fp_id)) + if (!fp->compiled()) + { + const_cast(fp)->compile(); + } + + program->attach(*vp) + .attach(*fp) .bind_fragment_data_location("ocol0", 0) .bind_fragment_data_location("ocol1", 1) .bind_fragment_data_location("ocol2", 2) @@ -71,12 +65,12 @@ struct GLTraits if (g_cfg.video.log_programs) { rsx_log.notice("*** prog id = %d", program->id()); - rsx_log.notice("*** vp id = %d", vp_id); - rsx_log.notice("*** fp id = %d", fp_id); + rsx_log.notice("*** vp id = %d", vp->id()); + rsx_log.notice("*** fp id = %d", fp->id()); } }; - auto post_link_func = [](std::unique_ptr& program) + auto post_link_func = [](gl::glsl::program* program) { // Program locations are guaranteed to not change after linking // Texture locations are simply bound to the TIUs so this can be done once @@ -110,9 +104,7 @@ struct GLTraits program->uniforms[1] = GL_STREAM_BUFFER_START + 1; }; - auto pipeline = compiler->compile(vertexProgramData.id, fragmentProgramData.id, - flags, post_create_func, post_link_func, callback); - + auto pipeline = compiler->compile(flags, post_create_func, post_link_func, callback); return callback(pipeline); } }; diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 69346178cc..dc00580791 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -273,11 +273,6 @@ void GLVertexProgram::Decompile(const RSXVertexProgram& prog) decompiler.Task(); shader.create(::glsl::program_domain::glsl_vertex_program, source); -} - -void GLVertexProgram::Compile() -{ - shader.compile(); id = shader.id(); } diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.h b/rpcs3/Emu/RSX/GL/GLVertexProgram.h index 3c675a4b68..bd05fcde1f 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.h +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.h @@ -59,7 +59,6 @@ public: gl::glsl::shader shader; void Decompile(const RSXVertexProgram& prog); - void Compile(); private: void Delete();