From 85cefec5a3651b64db9950fdd08d0266d27a9f63 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 9 Nov 2023 01:29:37 +0300 Subject: [PATCH] rsx: Fix vertex program analyser bug --- rpcs3/Emu/RSX/Program/ProgramStateCache.cpp | 16 ++++++++++++++-- .../Emu/RSX/Program/VertexProgramDecompiler.cpp | 8 ++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp index 642415570f..588df19d44 100644 --- a/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Program/ProgramStateCache.cpp @@ -62,8 +62,9 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert { if (!has_printed_error) { - // This can be harmless if a dangling RET was encountered before - rsx_log.error("vp_analyser: Possible infinite loop detected"); + // This can be harmless if a dangling RET was encountered before. + // This can also be legal in case of BRB...BRI loops since BRIs are conditional. Might just be a loop with exit cond. + rsx_log.warning("vp_analyser: Possible infinite loop detected"); has_printed_error = true; } current_instruction++; @@ -288,6 +289,17 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert } } + // Typical ubershaders have the dispatch at the top with subroutines following. However... + // some games have the dispatch block at the end and the subroutines above them. + // We need to simulate a jump-to-entry in this situation + // Normally this condition is handled by the conditional_targets walk, but sometimes this doesn't work due to cyclic branches + if (instruction_range.first < dst_prog.entry) + { + // Is there a subroutine that jumps into the entry? If not, add to jump table + const auto target = dst_prog.entry - instruction_range.first; + dst_prog.jump_table.insert(target); + } + // Verification for (const u32 target : dst_prog.jump_table) { diff --git a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp index 9bffea5ba7..6d16a931d1 100644 --- a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp @@ -445,7 +445,7 @@ std::string VertexProgramDecompiler::Decompile() const auto& data = m_prog.data; m_instr_count = data.size() / 4; - bool is_has_BRA = false; + bool has_BRA = false; bool program_end = false; u32 i = 1; u32 last_label_addr = 0; @@ -527,7 +527,7 @@ std::string VertexProgramDecompiler::Decompile() } }; - if (is_has_BRA || !m_prog.jump_table.empty()) + if (has_BRA || !m_prog.jump_table.empty()) { m_cur_instr = &m_instructions[0]; @@ -573,7 +573,7 @@ std::string VertexProgramDecompiler::Decompile() { //TODO: Subroutines can also have arbitrary jumps! u32 jump_position = find_jump_lvl(i); - if (is_has_BRA || jump_position != umax) + if (has_BRA || jump_position != umax) { m_cur_instr->close_scopes++; AddCode("}"); @@ -782,7 +782,7 @@ std::string VertexProgramDecompiler::Decompile() } } - if (is_has_BRA || !m_prog.jump_table.empty()) + if (has_BRA || !m_prog.jump_table.empty()) { m_cur_instr = &m_instructions[m_instr_count - 1]; m_cur_instr->close_scopes++;