mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-05-07 13:37:46 +00:00
gl: Fix context race condition when preparing optimized interpreter variants
- The main thread may bind the program before the compiler context has published the binding instructions - Once bound, late bindings are not updated so the program remains with uninitialized bindings and rendering breaks
This commit is contained in:
parent
c350c02592
commit
3fc41b6d66
3 changed files with 34 additions and 9 deletions
|
|
@ -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<glsl::program>& 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<interpreter::cached_program>& data, u64 compiler_options)
|
||||
void shader_interpreter::init_program(const std::shared_ptr<interpreter::cached_program>& 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<interpreter::cached_program>& data, u64 compiler_options)
|
||||
{
|
||||
data->build_compiler_options = compiler_options;
|
||||
|
||||
std::lock_guard lock(m_program_cache_lock);
|
||||
m_program_cache[compiler_options] = data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "glutils/program.h"
|
||||
#include "../Program/ProgramStateCache.h"
|
||||
#include "../Program/ShaderInterpreter.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
|
@ -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<glsl::shader> vertex_shader;
|
||||
std::shared_ptr<glsl::shader> fragment_shader;
|
||||
|
|
@ -92,7 +97,8 @@ namespace gl
|
|||
|
||||
std::shared_ptr<interpreter::cached_program> 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<interpreter::cached_program>& data, u64 compiler_options);
|
||||
void init_program(const std::shared_ptr<interpreter::cached_program>& data, u64 compiler_options);
|
||||
void store_program(const std::shared_ptr<interpreter::cached_program>& data, u64 compiler_options);
|
||||
|
||||
std::shared_ptr<interpreter::cached_program> m_current_interpreter;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue