diff --git a/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.h b/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.h index 15e450dab7..df3fbe5e16 100644 --- a/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.h @@ -269,6 +269,7 @@ public: struct { + // Configuration properties (in) u16 in_register_mask = 0; u16 common_access_sampler_mask = 0; @@ -276,6 +277,7 @@ public: u16 redirected_sampler_mask = 0; u16 multisampled_sampler_mask = 0; + // Decoded properties (out) bool has_lit_op = false; bool has_gather_op = false; bool has_no_output = false; diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp index 5bd2278b77..3f72a3b4a7 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp @@ -262,6 +262,11 @@ namespace glsl } } + if (props.require_instanced_render) + { + enabled_options.push_back("_ENABLE_INSTANCED_CONSTANTS"); + } + // Import vertex header program_common::define_glsl_switches(OS, enabled_options); diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl index fd8c9f596d..db2a91ff99 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXVertexPrologue.glsl @@ -55,4 +55,16 @@ vec4 apply_zclip_xform( } #endif +#if defined(_ENABLE_INSTANCED_CONSTANTS) +vec4 _fetch_constant(const in int base_offset) +{ + // Get virtual draw/instance id. Normally will be 1:1 based on instance index + const int indirection_offset = (gl_InstanceID * CONSTANTS_ARRAY_LENGTH) + base_offset; + const int corrected_offset = constants_addressing_lookup[indirection_offset]; + return instanced_constants_array[corrected_offset]; +} +#else +#define _fetch_constant(x) vc[x] +#endif + )" diff --git a/rpcs3/Emu/RSX/Program/GLSLTypes.h b/rpcs3/Emu/RSX/Program/GLSLTypes.h index 11f657ddf5..8967dd7598 100644 --- a/rpcs3/Emu/RSX/Program/GLSLTypes.h +++ b/rpcs3/Emu/RSX/Program/GLSLTypes.h @@ -22,6 +22,7 @@ namespace glsl // Applicable in vertex stage bool require_lit_emulation : 1; bool require_explicit_invariance : 1; + bool require_instanced_render : 1; bool emulate_zclip_transform : 1; bool emulate_depth_clip_only : 1; diff --git a/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp index 8c1318ad28..2f7330f8fa 100644 --- a/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp @@ -341,6 +341,7 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert usz vertex_program_storage_hash::operator()(const RSXVertexProgram &program) const { usz hash = vertex_program_utils::get_vertex_program_ucode_hash(program); + hash ^= program.ctrl; hash ^= program.output_mask; hash ^= program.texture_state.texture_dimensions; hash ^= program.texture_state.multisampled_textures; @@ -351,6 +352,8 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R { if (binary1.output_mask != binary2.output_mask) return false; + if (binary1.ctrl != binary2.ctrl) + return false; if (binary1.texture_state != binary2.texture_state) return false; if (binary1.data.size() != binary2.data.size()) diff --git a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp index 7cb7d578a4..53cece6ad5 100644 --- a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp @@ -131,7 +131,7 @@ std::string VertexProgramDecompiler::GetSRC(const u32 n) m_parr.AddParam(PF_PARAM_UNIFORM, float4, std::string("vc[468]")); properties.has_indexed_constants |= !!d3.index_const; m_constant_ids.insert(static_cast(d1.const_src)); - ret += std::string("vc[") + std::to_string(d1.const_src) + (d3.index_const ? " + " + AddAddrReg() : "") + "]"; + fmt::append(ret, "_fetch_constant(%u%s)", d1.const_src, (d3.index_const ? " + " + AddAddrReg() : "")); break; default: diff --git a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h index b1147c7016..94b25f8076 100644 --- a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h @@ -132,6 +132,10 @@ protected: public: struct { + // Configuration properties (in) + // None + + // Decoded properties (out) bool has_lit_op = false; bool has_indexed_constants = false; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 5e10e67e59..5d44a95a87 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2202,6 +2202,13 @@ namespace rsx void thread::prefetch_vertex_program() { + // Test if instanced command is coming up + current_vertex_program.ctrl = 0; + if (rsx::method_registers.current_draw_clause.is_trivial_instanced_draw) + { + current_vertex_program.ctrl |= RSX_SHADER_CONTROL_INSTANCED_CONSTANTS; + } + if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty)) { return; @@ -2256,7 +2263,6 @@ namespace rsx ensure(!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty)); current_vertex_program.output_mask = rsx::method_registers.vertex_attrib_output_mask(); - current_vertex_program.ctrl = 0; // Reserved for (u32 textures_ref = current_vp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i) { diff --git a/rpcs3/Emu/RSX/gcm_enums.h b/rpcs3/Emu/RSX/gcm_enums.h index 816aec77c0..dcf8b51b28 100644 --- a/rpcs3/Emu/RSX/gcm_enums.h +++ b/rpcs3/Emu/RSX/gcm_enums.h @@ -455,7 +455,8 @@ namespace gcm RSX_SHADER_CONTROL_UNKNOWN1 = 0x8000, // seemingly set when srgb packer is used?? // Custom - RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION = 0x10000 // Rasterizing triangles and not lines or points + RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION = 0x10000, // Rasterizing triangles and not lines or points + RSX_SHADER_CONTROL_INSTANCED_CONSTANTS = 0x20000, // Support instance ID offsets when loading constants }; // GCM Reports