diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp index 72341ea521..fc575ffc5c 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp @@ -7,7 +7,6 @@ #include "Emu/RSX/rsx_methods.h" #include "Emu/RSX/Overlays/Shaders/shader_loading_dialog.h" -#include "Emu/RSX/Program/ShaderInterpreter.h" #include "Emu/RSX/Program/GLSLCommon.h" namespace gl @@ -108,7 +107,8 @@ namespace gl } auto data = new interpreter::cached_program(); - data->flags |= CACHED_PIPE_UNOPTIMIZED; + data->flags = base_pipeline->second->flags | CACHED_PIPE_UNOPTIMIZED; + data->build_compiler_options = base_pipeline->second->build_compiler_options; data->allocator = base_pipeline->second->allocator; data->vertex_shader = base_pipeline->second->vertex_shader; data->fragment_shader = base_pipeline->second->fragment_shader; @@ -203,6 +203,13 @@ namespace gl m_current_interpreter->flags |= CACHED_PIPE_RECOMPILING; build_program_async(opt, {}); } + + if (m_current_interpreter->flags & CACHED_PIPE_UNINITIALIZED) + { + m_current_interpreter->prog->sync(); + init_program(m_current_interpreter, m_current_interpreter->build_compiler_options); + } + return m_current_interpreter->prog.get(); } } @@ -491,7 +498,8 @@ namespace gl attach(*data->fragment_shader). link(); - post_init_hook(data, compiler_options); + init_program(data, compiler_options); + store_program(data, compiler_options); return data; } @@ -510,8 +518,11 @@ namespace gl auto storage_hook = [=, this](std::unique_ptr& prog) { + // NOTE: We need to do the program bindings in the consumer's context, so we skip the post-init hook and just set a flag + // The consumer will handle initializing the bindings + // The synchronization problem doesn't matter much on Windows driver, but Mesa drivers actually care about it. data->prog = std::move(prog); - post_init_hook(data, compiler_options); + store_program(data, compiler_options); if (callback) { @@ -528,7 +539,7 @@ namespace gl ); } - void shader_interpreter::post_init_hook(const std::shared_ptr& data, u64 compiler_options) + void shader_interpreter::init_program(const std::shared_ptr& data, u64 compiler_options) { data->prog->uniforms[0] = GL_STREAM_BUFFER_START + 0; data->prog->uniforms[1] = GL_STREAM_BUFFER_START + 1; @@ -551,6 +562,13 @@ namespace gl } } + data->flags &= ~CACHED_PIPE_UNINITIALIZED; + } + + void shader_interpreter::store_program(const std::shared_ptr& data, u64 compiler_options) + { + data->build_compiler_options = compiler_options; + std::lock_guard lock(m_program_cache_lock); m_program_cache[compiler_options] = data; } diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h index 015e46cef8..ccfcde30e1 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h @@ -1,6 +1,7 @@ #pragma once #include "glutils/program.h" #include "../Program/ProgramStateCache.h" +#include "../Program/ShaderInterpreter.h" #include "../Common/TextureUtils.h" #include @@ -64,7 +65,11 @@ namespace gl struct cached_program { - u32 flags = 0; + u32 flags = program_common::interpreter::CACHED_PIPE_UNINITIALIZED; + + // Compiler options mask - May not always match the storage compiler options in case of compatible pipelines + // However the storage mask must be a subset of this options mask + u32 build_compiler_options = 0; std::shared_ptr vertex_shader; std::shared_ptr fragment_shader; @@ -92,7 +97,8 @@ namespace gl std::shared_ptr build_program(u64 compiler_options); void build_program_async(u64 compiler_options, async_build_callback_t callback); - void post_init_hook(const std::shared_ptr& data, u64 compiler_options); + void init_program(const std::shared_ptr& data, u64 compiler_options); + void store_program(const std::shared_ptr& data, u64 compiler_options); std::shared_ptr m_current_interpreter; diff --git a/rpcs3/Emu/RSX/Program/ShaderInterpreter.h b/rpcs3/Emu/RSX/Program/ShaderInterpreter.h index e6a3282448..d08b6f00ad 100644 --- a/rpcs3/Emu/RSX/Program/ShaderInterpreter.h +++ b/rpcs3/Emu/RSX/Program/ShaderInterpreter.h @@ -47,8 +47,9 @@ namespace program_common enum cached_pipeline_flags : u32 { - CACHED_PIPE_UNOPTIMIZED = (1 << 0), - CACHED_PIPE_RECOMPILING = (1 << 1), + CACHED_PIPE_UNOPTIMIZED = (1 << 0), + CACHED_PIPE_RECOMPILING = (1 << 1), + CACHED_PIPE_UNINITIALIZED = (1 << 2), }; [[maybe_unused]] static std::string get_vertex_interpreter()