mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 05:21:25 +12:00
gl: Support transform instancing in the shader interpreter
This commit is contained in:
parent
65c0d3d425
commit
225d0b9482
7 changed files with 85 additions and 54 deletions
|
@ -814,6 +814,7 @@ void GLGSRender::end()
|
||||||
m_vertex_layout_buffer->notify();
|
m_vertex_layout_buffer->notify();
|
||||||
m_fragment_constants_buffer->notify();
|
m_fragment_constants_buffer->notify();
|
||||||
m_transform_constants_buffer->notify();
|
m_transform_constants_buffer->notify();
|
||||||
|
m_instancing_ring_buffer->notify();
|
||||||
|
|
||||||
m_frame_stats.setup_time += m_profiler.duration();
|
m_frame_stats.setup_time += m_profiler.duration();
|
||||||
|
|
||||||
|
|
|
@ -778,7 +778,10 @@ bool GLGSRender::load_program()
|
||||||
|
|
||||||
if (shadermode == shader_mode::interpreter_only)
|
if (shadermode == shader_mode::interpreter_only)
|
||||||
{
|
{
|
||||||
m_program = m_shader_interpreter.get(current_fp_metadata);
|
m_program = m_shader_interpreter.get(
|
||||||
|
current_fp_metadata,
|
||||||
|
current_vertex_program.ctrl,
|
||||||
|
current_fragment_program.ctrl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -836,7 +839,10 @@ bool GLGSRender::load_program()
|
||||||
// First load the next program if not available
|
// First load the next program if not available
|
||||||
if (!m_program)
|
if (!m_program)
|
||||||
{
|
{
|
||||||
m_program = m_shader_interpreter.get(current_fp_metadata);
|
m_program = m_shader_interpreter.get(
|
||||||
|
current_fp_metadata,
|
||||||
|
current_vertex_program.ctrl,
|
||||||
|
current_fragment_program.ctrl);
|
||||||
|
|
||||||
// Program has changed, reupload
|
// Program has changed, reupload
|
||||||
m_interpreter_state = rsx::invalidate_pipeline_bits;
|
m_interpreter_state = rsx::invalidate_pipeline_bits;
|
||||||
|
|
|
@ -46,7 +46,6 @@ namespace gl
|
||||||
|
|
||||||
void shader_interpreter::create()
|
void shader_interpreter::create()
|
||||||
{
|
{
|
||||||
build_vs();
|
|
||||||
build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES);
|
build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES);
|
||||||
build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES | ::program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT);
|
build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES | ::program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT);
|
||||||
}
|
}
|
||||||
|
@ -55,14 +54,13 @@ namespace gl
|
||||||
{
|
{
|
||||||
for (auto& prog : m_program_cache)
|
for (auto& prog : m_program_cache)
|
||||||
{
|
{
|
||||||
prog.second->fs.remove();
|
prog.second->vertex_shader.remove();
|
||||||
|
prog.second->fragment_shader.remove();
|
||||||
prog.second->prog.remove();
|
prog.second->prog.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vs.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glsl::program* shader_interpreter::get(const interpreter::program_metadata& metadata)
|
glsl::program* shader_interpreter::get(const interpreter::program_metadata& metadata, u32 vp_ctrl, u32 fp_ctrl)
|
||||||
{
|
{
|
||||||
// Build options
|
// Build options
|
||||||
u64 opt = 0;
|
u64 opt = 0;
|
||||||
|
@ -95,13 +93,14 @@ namespace gl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT;
|
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT;
|
||||||
if (rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT;
|
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT;
|
||||||
if (rsx::method_registers.shader_control() & RSX_SHADER_CONTROL_USES_KIL) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_KIL;
|
if (fp_ctrl & RSX_SHADER_CONTROL_USES_KIL) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_KIL;
|
||||||
if (metadata.referenced_textures_mask) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES;
|
if (metadata.referenced_textures_mask) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES;
|
||||||
if (metadata.has_branch_instructions) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL;
|
if (metadata.has_branch_instructions) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL;
|
||||||
if (metadata.has_pack_instructions) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_PACKING;
|
if (metadata.has_pack_instructions) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_PACKING;
|
||||||
if (rsx::method_registers.polygon_stipple_enabled()) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_STIPPLING;
|
if (rsx::method_registers.polygon_stipple_enabled()) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_STIPPLING;
|
||||||
|
if (vp_ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING;
|
||||||
|
|
||||||
if (auto it = m_program_cache.find(opt); it != m_program_cache.end()) [[likely]]
|
if (auto it = m_program_cache.find(opt); it != m_program_cache.end()) [[likely]]
|
||||||
{
|
{
|
||||||
|
@ -115,7 +114,7 @@ namespace gl
|
||||||
return &m_current_interpreter->prog;
|
return &m_current_interpreter->prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader_interpreter::build_vs()
|
void shader_interpreter::build_vs(u64 compiler_options, interpreter::cached_program& prog_data)
|
||||||
{
|
{
|
||||||
::glsl::shader_properties properties{};
|
::glsl::shader_properties properties{};
|
||||||
properties.domain = ::glsl::program_domain::glsl_vertex_program;
|
properties.domain = ::glsl::program_domain::glsl_vertex_program;
|
||||||
|
@ -126,6 +125,10 @@ namespace gl
|
||||||
RSXVertexProgram null_prog;
|
RSXVertexProgram null_prog;
|
||||||
std::string shader_str;
|
std::string shader_str;
|
||||||
ParamArray arr;
|
ParamArray arr;
|
||||||
|
|
||||||
|
null_prog.ctrl = (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING)
|
||||||
|
? RSX_SHADER_CONTROL_INSTANCED_CONSTANTS
|
||||||
|
: 0;
|
||||||
GLVertexDecompilerThread comp(null_prog, shader_str, arr);
|
GLVertexDecompilerThread comp(null_prog, shader_str, arr);
|
||||||
|
|
||||||
ParamType uniforms = { PF_PARAM_UNIFORM, "vec4" };
|
ParamType uniforms = { PF_PARAM_UNIFORM, "vec4" };
|
||||||
|
@ -141,14 +144,24 @@ namespace gl
|
||||||
|
|
||||||
// Insert vp stream input
|
// Insert vp stream input
|
||||||
builder << "\n"
|
builder << "\n"
|
||||||
"layout(std140, binding = " << GL_INTERPRETER_VERTEX_BLOCK << ") readonly restrict buffer VertexInstructionBlock\n"
|
"layout(std140, binding = " << GL_INTERPRETER_VERTEX_BLOCK << ") readonly restrict buffer VertexInstructionBlock\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" uint base_address;\n"
|
" uint base_address;\n"
|
||||||
" uint entry;\n"
|
" uint entry;\n"
|
||||||
" uint output_mask;\n"
|
" uint output_mask;\n"
|
||||||
" uint control;\n"
|
" uint control;\n"
|
||||||
" uvec4 vp_instructions[];\n"
|
" uvec4 vp_instructions[];\n"
|
||||||
"};\n\n";
|
"};\n\n";
|
||||||
|
|
||||||
|
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING)
|
||||||
|
{
|
||||||
|
builder << "#define _ENABLE_INSTANCED_CONSTANTS\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compiler_options)
|
||||||
|
{
|
||||||
|
builder << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
::glsl::insert_glsl_legacy_function(builder, properties);
|
::glsl::insert_glsl_legacy_function(builder, properties);
|
||||||
::glsl::insert_vertex_input_fetch(builder, ::glsl::glsl_rules::glsl_rules_opengl4);
|
::glsl::insert_vertex_input_fetch(builder, ::glsl::glsl_rules::glsl_rules_opengl4);
|
||||||
|
@ -156,8 +169,8 @@ namespace gl
|
||||||
builder << program_common::interpreter::get_vertex_interpreter();
|
builder << program_common::interpreter::get_vertex_interpreter();
|
||||||
const std::string s = builder.str();
|
const std::string s = builder.str();
|
||||||
|
|
||||||
m_vs.create(::glsl::program_domain::glsl_vertex_program, s);
|
prog_data.vertex_shader.create(::glsl::program_domain::glsl_vertex_program, s);
|
||||||
m_vs.compile();
|
prog_data.vertex_shader.compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader_interpreter::build_fs(u64 compiler_options, interpreter::cached_program& prog_data)
|
void shader_interpreter::build_fs(u64 compiler_options, interpreter::cached_program& prog_data)
|
||||||
|
@ -295,31 +308,32 @@ namespace gl
|
||||||
}
|
}
|
||||||
|
|
||||||
builder <<
|
builder <<
|
||||||
"layout(std430, binding =" << GL_INTERPRETER_FRAGMENT_BLOCK << ") readonly restrict buffer FragmentInstructionBlock\n"
|
"layout(std430, binding =" << GL_INTERPRETER_FRAGMENT_BLOCK << ") readonly restrict buffer FragmentInstructionBlock\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" uint shader_control;\n"
|
" uint shader_control;\n"
|
||||||
" uint texture_control;\n"
|
" uint texture_control;\n"
|
||||||
" uint reserved1;\n"
|
" uint reserved1;\n"
|
||||||
" uint reserved2;\n"
|
" uint reserved2;\n"
|
||||||
" uint texture_handles[16];\n"
|
" uint texture_handles[16];\n"
|
||||||
" uvec4 fp_instructions[];\n"
|
" uvec4 fp_instructions[];\n"
|
||||||
"};\n\n";
|
"};\n\n";
|
||||||
|
|
||||||
builder << program_common::interpreter::get_fragment_interpreter();
|
builder << program_common::interpreter::get_fragment_interpreter();
|
||||||
const std::string s = builder.str();
|
const std::string s = builder.str();
|
||||||
|
|
||||||
prog_data.fs.create(::glsl::program_domain::glsl_fragment_program, s);
|
prog_data.fragment_shader.create(::glsl::program_domain::glsl_fragment_program, s);
|
||||||
prog_data.fs.compile();
|
prog_data.fragment_shader.compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
interpreter::cached_program* shader_interpreter::build_program(u64 compiler_options)
|
interpreter::cached_program* shader_interpreter::build_program(u64 compiler_options)
|
||||||
{
|
{
|
||||||
auto data = new interpreter::cached_program();
|
auto data = new interpreter::cached_program();
|
||||||
build_fs(compiler_options, *data);
|
build_fs(compiler_options, *data);
|
||||||
|
build_vs(compiler_options, *data);
|
||||||
|
|
||||||
data->prog.create().
|
data->prog.create().
|
||||||
attach(m_vs).
|
attach(data->vertex_shader).
|
||||||
attach(data->fs).
|
attach(data->fragment_shader).
|
||||||
link();
|
link();
|
||||||
|
|
||||||
data->prog.uniforms[0] = GL_STREAM_BUFFER_START + 0;
|
data->prog.uniforms[0] = GL_STREAM_BUFFER_START + 0;
|
||||||
|
|
|
@ -59,7 +59,8 @@ namespace gl
|
||||||
|
|
||||||
struct cached_program
|
struct cached_program
|
||||||
{
|
{
|
||||||
glsl::shader fs;
|
glsl::shader vertex_shader;
|
||||||
|
glsl::shader fragment_shader;
|
||||||
glsl::program prog;
|
glsl::program prog;
|
||||||
texture_pool_allocator allocator;
|
texture_pool_allocator allocator;
|
||||||
};
|
};
|
||||||
|
@ -67,10 +68,10 @@ namespace gl
|
||||||
|
|
||||||
class shader_interpreter
|
class shader_interpreter
|
||||||
{
|
{
|
||||||
glsl::shader m_vs;
|
using shader_cache_t = std::unordered_map<u64, std::unique_ptr<interpreter::cached_program>>;
|
||||||
std::unordered_map<u64, std::unique_ptr<interpreter::cached_program>> m_program_cache;
|
shader_cache_t m_program_cache;
|
||||||
|
|
||||||
void build_vs();
|
void build_vs(u64 compiler_options, interpreter::cached_program& prog_data);
|
||||||
void build_fs(u64 compiler_options, interpreter::cached_program& prog_data);
|
void build_fs(u64 compiler_options, interpreter::cached_program& prog_data);
|
||||||
interpreter::cached_program* build_program(u64 compiler_options);
|
interpreter::cached_program* build_program(u64 compiler_options);
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ namespace gl
|
||||||
|
|
||||||
void update_fragment_textures(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, 16>& descriptors, u16 reference_mask, u32* out);
|
void update_fragment_textures(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, 16>& descriptors, u16 reference_mask, u32* out);
|
||||||
|
|
||||||
glsl::program* get(const interpreter::program_metadata& fp_metadata);
|
glsl::program* get(const interpreter::program_metadata& fp_metadata, u32 vp_ctrl, u32 fp_ctrl);
|
||||||
bool is_interpreter(const glsl::program* program) const;
|
bool is_interpreter(const glsl::program* program) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,11 +368,11 @@ vec4 read_src(const in int index)
|
||||||
case RSX_VP_REGISTER_TYPE_CONSTANT:
|
case RSX_VP_REGISTER_TYPE_CONSTANT:
|
||||||
if (d3.index_const)
|
if (d3.index_const)
|
||||||
{
|
{
|
||||||
value = vc[d1.const_src + ref(a[d0.addr_reg_sel_1], d0.addr_swz)];
|
value = _fetch_constant(d1.const_src + ref(a[d0.addr_reg_sel_1], d0.addr_swz));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = vc[d1.const_src];
|
value = _fetch_constant(d1.const_src);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,12 @@ vec4 _fetch_constant(const in int base_offset)
|
||||||
const int corrected_offset = constants_addressing_lookup[indirection_offset];
|
const int corrected_offset = constants_addressing_lookup[indirection_offset];
|
||||||
return instanced_constants_array[corrected_offset];
|
return instanced_constants_array[corrected_offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec4 _fetch_constant(const in uint base_offset)
|
||||||
|
{
|
||||||
|
// uint override
|
||||||
|
return _fetch_constant(int(base_offset));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#define _fetch_constant(x) vc[x]
|
#define _fetch_constant(x) vc[x]
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,19 +6,22 @@ namespace program_common
|
||||||
{
|
{
|
||||||
enum compiler_option
|
enum compiler_option
|
||||||
{
|
{
|
||||||
COMPILER_OPT_ENABLE_TEXTURES = 1,
|
COMPILER_OPT_ENABLE_TEXTURES = (1 << 0),
|
||||||
COMPILER_OPT_ENABLE_DEPTH_EXPORT = 2,
|
COMPILER_OPT_ENABLE_DEPTH_EXPORT = (1 << 1),
|
||||||
COMPILER_OPT_ENABLE_F32_EXPORT = 4,
|
COMPILER_OPT_ENABLE_F32_EXPORT = (1 << 2),
|
||||||
COMPILER_OPT_ENABLE_ALPHA_TEST_GE = 8,
|
COMPILER_OPT_ENABLE_ALPHA_TEST_GE = (1 << 3),
|
||||||
COMPILER_OPT_ENABLE_ALPHA_TEST_G = 16,
|
COMPILER_OPT_ENABLE_ALPHA_TEST_G = (1 << 4),
|
||||||
COMPILER_OPT_ENABLE_ALPHA_TEST_LE = 32,
|
COMPILER_OPT_ENABLE_ALPHA_TEST_LE = (1 << 5),
|
||||||
COMPILER_OPT_ENABLE_ALPHA_TEST_L = 64,
|
COMPILER_OPT_ENABLE_ALPHA_TEST_L = (1 << 6),
|
||||||
COMPILER_OPT_ENABLE_ALPHA_TEST_EQ = 128,
|
COMPILER_OPT_ENABLE_ALPHA_TEST_EQ = (1 << 7),
|
||||||
COMPILER_OPT_ENABLE_ALPHA_TEST_NE = 256,
|
COMPILER_OPT_ENABLE_ALPHA_TEST_NE = (1 << 8),
|
||||||
COMPILER_OPT_ENABLE_FLOW_CTRL = 512,
|
COMPILER_OPT_ENABLE_FLOW_CTRL = (1 << 9),
|
||||||
COMPILER_OPT_ENABLE_PACKING = 1024,
|
COMPILER_OPT_ENABLE_PACKING = (1 << 10),
|
||||||
COMPILER_OPT_ENABLE_KIL = 2048,
|
COMPILER_OPT_ENABLE_KIL = (1 << 11),
|
||||||
COMPILER_OPT_ENABLE_STIPPLING = 4096
|
COMPILER_OPT_ENABLE_STIPPLING = (1 << 12),
|
||||||
|
COMPILER_OPT_ENABLE_INSTANCING = (1 << 13),
|
||||||
|
|
||||||
|
COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_INSTANCING
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string get_vertex_interpreter()
|
static std::string get_vertex_interpreter()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue