diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 33ef42570b..8606023ebe 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -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(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index c23f560268..bb360382d0 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp index 5d30ae5ab3..f043947f1f 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h index 551fa9a8cf..62075dbb4b 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h @@ -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> m_program_cache; + using shader_cache_t = std::unordered_map>; + 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, 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; }; } diff --git a/rpcs3/Emu/RSX/Program/GLSLInterpreter/VertexInterpreter.glsl b/rpcs3/Emu/RSX/Program/GLSLInterpreter/VertexInterpreter.glsl index e41fda1782..e60bc51d92 100644 --- a/rpcs3/Emu/RSX/Program/GLSLInterpreter/VertexInterpreter.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLInterpreter/VertexInterpreter.glsl @@ -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; } diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl index dfe7252ca8..b188b224ba 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl @@ -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 diff --git a/rpcs3/Emu/RSX/Program/ShaderInterpreter.h b/rpcs3/Emu/RSX/Program/ShaderInterpreter.h index a397aa2cb3..5503a2870c 100644 --- a/rpcs3/Emu/RSX/Program/ShaderInterpreter.h +++ b/rpcs3/Emu/RSX/Program/ShaderInterpreter.h @@ -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()