gl: Support transform instancing in the shader interpreter

This commit is contained in:
kd-11 2025-03-15 23:15:29 +03:00
parent 3ed6f5a167
commit 9a7a985f12
7 changed files with 85 additions and 54 deletions

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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;
};
}

View file

@ -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;
}

View file

@ -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

View file

@ -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()