mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-19 19:15:26 +00: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_fragment_constants_buffer->notify();
|
||||
m_transform_constants_buffer->notify();
|
||||
m_instancing_ring_buffer->notify();
|
||||
|
||||
m_frame_stats.setup_time += m_profiler.duration();
|
||||
|
||||
|
|
|
@ -778,7 +778,10 @@ bool GLGSRender::load_program()
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -836,7 +839,10 @@ bool GLGSRender::load_program()
|
|||
// First load the next program if not available
|
||||
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
|
||||
m_interpreter_state = rsx::invalidate_pipeline_bits;
|
||||
|
|
|
@ -46,7 +46,6 @@ namespace gl
|
|||
|
||||
void shader_interpreter::create()
|
||||
{
|
||||
build_vs();
|
||||
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);
|
||||
}
|
||||
|
@ -55,14 +54,13 @@ namespace gl
|
|||
{
|
||||
for (auto& prog : m_program_cache)
|
||||
{
|
||||
prog.second->fs.remove();
|
||||
prog.second->vertex_shader.remove();
|
||||
prog.second->fragment_shader.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
|
||||
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 (rsx::method_registers.shader_control() & 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 & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT;
|
||||
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT;
|
||||
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.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 (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]]
|
||||
{
|
||||
|
@ -115,7 +114,7 @@ namespace gl
|
|||
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{};
|
||||
properties.domain = ::glsl::program_domain::glsl_vertex_program;
|
||||
|
@ -126,6 +125,10 @@ namespace gl
|
|||
RSXVertexProgram null_prog;
|
||||
std::string shader_str;
|
||||
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);
|
||||
|
||||
ParamType uniforms = { PF_PARAM_UNIFORM, "vec4" };
|
||||
|
@ -141,14 +144,24 @@ namespace gl
|
|||
|
||||
// Insert vp stream input
|
||||
builder << "\n"
|
||||
"layout(std140, binding = " << GL_INTERPRETER_VERTEX_BLOCK << ") readonly restrict buffer VertexInstructionBlock\n"
|
||||
"{\n"
|
||||
" uint base_address;\n"
|
||||
" uint entry;\n"
|
||||
" uint output_mask;\n"
|
||||
" uint control;\n"
|
||||
" uvec4 vp_instructions[];\n"
|
||||
"};\n\n";
|
||||
"layout(std140, binding = " << GL_INTERPRETER_VERTEX_BLOCK << ") readonly restrict buffer VertexInstructionBlock\n"
|
||||
"{\n"
|
||||
" uint base_address;\n"
|
||||
" uint entry;\n"
|
||||
" uint output_mask;\n"
|
||||
" uint control;\n"
|
||||
" uvec4 vp_instructions[];\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_vertex_input_fetch(builder, ::glsl::glsl_rules::glsl_rules_opengl4);
|
||||
|
@ -156,8 +169,8 @@ namespace gl
|
|||
builder << program_common::interpreter::get_vertex_interpreter();
|
||||
const std::string s = builder.str();
|
||||
|
||||
m_vs.create(::glsl::program_domain::glsl_vertex_program, s);
|
||||
m_vs.compile();
|
||||
prog_data.vertex_shader.create(::glsl::program_domain::glsl_vertex_program, s);
|
||||
prog_data.vertex_shader.compile();
|
||||
}
|
||||
|
||||
void shader_interpreter::build_fs(u64 compiler_options, interpreter::cached_program& prog_data)
|
||||
|
@ -295,31 +308,32 @@ namespace gl
|
|||
}
|
||||
|
||||
builder <<
|
||||
"layout(std430, binding =" << GL_INTERPRETER_FRAGMENT_BLOCK << ") readonly restrict buffer FragmentInstructionBlock\n"
|
||||
"{\n"
|
||||
" uint shader_control;\n"
|
||||
" uint texture_control;\n"
|
||||
" uint reserved1;\n"
|
||||
" uint reserved2;\n"
|
||||
" uint texture_handles[16];\n"
|
||||
" uvec4 fp_instructions[];\n"
|
||||
"};\n\n";
|
||||
"layout(std430, binding =" << GL_INTERPRETER_FRAGMENT_BLOCK << ") readonly restrict buffer FragmentInstructionBlock\n"
|
||||
"{\n"
|
||||
" uint shader_control;\n"
|
||||
" uint texture_control;\n"
|
||||
" uint reserved1;\n"
|
||||
" uint reserved2;\n"
|
||||
" uint texture_handles[16];\n"
|
||||
" uvec4 fp_instructions[];\n"
|
||||
"};\n\n";
|
||||
|
||||
builder << program_common::interpreter::get_fragment_interpreter();
|
||||
const std::string s = builder.str();
|
||||
|
||||
prog_data.fs.create(::glsl::program_domain::glsl_fragment_program, s);
|
||||
prog_data.fs.compile();
|
||||
prog_data.fragment_shader.create(::glsl::program_domain::glsl_fragment_program, s);
|
||||
prog_data.fragment_shader.compile();
|
||||
}
|
||||
|
||||
interpreter::cached_program* shader_interpreter::build_program(u64 compiler_options)
|
||||
{
|
||||
auto data = new interpreter::cached_program();
|
||||
build_fs(compiler_options, *data);
|
||||
build_vs(compiler_options, *data);
|
||||
|
||||
data->prog.create().
|
||||
attach(m_vs).
|
||||
attach(data->fs).
|
||||
attach(data->vertex_shader).
|
||||
attach(data->fragment_shader).
|
||||
link();
|
||||
|
||||
data->prog.uniforms[0] = GL_STREAM_BUFFER_START + 0;
|
||||
|
|
|
@ -59,7 +59,8 @@ namespace gl
|
|||
|
||||
struct cached_program
|
||||
{
|
||||
glsl::shader fs;
|
||||
glsl::shader vertex_shader;
|
||||
glsl::shader fragment_shader;
|
||||
glsl::program prog;
|
||||
texture_pool_allocator allocator;
|
||||
};
|
||||
|
@ -67,10 +68,10 @@ namespace gl
|
|||
|
||||
class shader_interpreter
|
||||
{
|
||||
glsl::shader m_vs;
|
||||
std::unordered_map<u64, std::unique_ptr<interpreter::cached_program>> m_program_cache;
|
||||
using shader_cache_t = std::unordered_map<u64, std::unique_ptr<interpreter::cached_program>>;
|
||||
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);
|
||||
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);
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -368,11 +368,11 @@ vec4 read_src(const in int index)
|
|||
case RSX_VP_REGISTER_TYPE_CONSTANT:
|
||||
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
|
||||
{
|
||||
value = vc[d1.const_src];
|
||||
value = _fetch_constant(d1.const_src);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,12 @@ vec4 _fetch_constant(const in int base_offset)
|
|||
const int corrected_offset = constants_addressing_lookup[indirection_offset];
|
||||
return instanced_constants_array[corrected_offset];
|
||||
}
|
||||
|
||||
vec4 _fetch_constant(const in uint base_offset)
|
||||
{
|
||||
// uint override
|
||||
return _fetch_constant(int(base_offset));
|
||||
}
|
||||
#else
|
||||
#define _fetch_constant(x) vc[x]
|
||||
#endif
|
||||
|
|
|
@ -6,19 +6,22 @@ namespace program_common
|
|||
{
|
||||
enum compiler_option
|
||||
{
|
||||
COMPILER_OPT_ENABLE_TEXTURES = 1,
|
||||
COMPILER_OPT_ENABLE_DEPTH_EXPORT = 2,
|
||||
COMPILER_OPT_ENABLE_F32_EXPORT = 4,
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_GE = 8,
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_G = 16,
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_LE = 32,
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_L = 64,
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_EQ = 128,
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_NE = 256,
|
||||
COMPILER_OPT_ENABLE_FLOW_CTRL = 512,
|
||||
COMPILER_OPT_ENABLE_PACKING = 1024,
|
||||
COMPILER_OPT_ENABLE_KIL = 2048,
|
||||
COMPILER_OPT_ENABLE_STIPPLING = 4096
|
||||
COMPILER_OPT_ENABLE_TEXTURES = (1 << 0),
|
||||
COMPILER_OPT_ENABLE_DEPTH_EXPORT = (1 << 1),
|
||||
COMPILER_OPT_ENABLE_F32_EXPORT = (1 << 2),
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_GE = (1 << 3),
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_G = (1 << 4),
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_LE = (1 << 5),
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_L = (1 << 6),
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_EQ = (1 << 7),
|
||||
COMPILER_OPT_ENABLE_ALPHA_TEST_NE = (1 << 8),
|
||||
COMPILER_OPT_ENABLE_FLOW_CTRL = (1 << 9),
|
||||
COMPILER_OPT_ENABLE_PACKING = (1 << 10),
|
||||
COMPILER_OPT_ENABLE_KIL = (1 << 11),
|
||||
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()
|
||||
|
|
Loading…
Add table
Reference in a new issue