mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-21 00:39:53 +00:00
gl: Thread shader source compilation dispatch
- glCompileShader is in itself much slower than anticipated
This commit is contained in:
parent
3ddfa288cf
commit
7553429130
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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<bool> m_is_compiled{};
|
||||
|
||||
void precompile()
|
||||
{
|
||||
const char* str = source.c_str();
|
||||
const GLint length = ::narrow<GLint>(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<GLint>(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();
|
||||
|
@ -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<glsl::program> 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<glsl::program> 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<glsl::program>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,8 @@ namespace gl
|
||||
COMPILE_DEFERRED = 2
|
||||
};
|
||||
|
||||
using callback_t = std::function<void(std::unique_ptr<glsl::program>&)>;
|
||||
using storage_callback_t = std::function<void(std::unique_ptr<glsl::program>&)>;
|
||||
using build_callback_t = std::function<void(glsl::program*)>;
|
||||
|
||||
pipe_compiler();
|
||||
~pipe_compiler();
|
||||
@ -26,11 +27,10 @@ namespace gl
|
||||
std::function<void(draw_context_t)> context_destroy_func);
|
||||
|
||||
std::unique_ptr<glsl::program> 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<void(draw_context_t context)> m_context_destroy_func;
|
||||
|
||||
std::unique_ptr<glsl::program> 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(
|
||||
|
@ -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<gl::glsl::program>& 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<gl::glsl::shader*>(vp)->compile();
|
||||
}
|
||||
|
||||
program->attach(gl::glsl::shader_view(vp_id))
|
||||
.attach(gl::glsl::shader_view(fp_id))
|
||||
if (!fp->compiled())
|
||||
{
|
||||
const_cast<gl::glsl::shader*>(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<gl::glsl::program>& 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);
|
||||
}
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,6 @@ public:
|
||||
gl::glsl::shader shader;
|
||||
|
||||
void Decompile(const RSXVertexProgram& prog);
|
||||
void Compile();
|
||||
|
||||
private:
|
||||
void Delete();
|
||||
|
Loading…
x
Reference in New Issue
Block a user