rsx/fp: Fix issues with FP decompiler using new CFG system

This commit is contained in:
kd-11 2025-12-06 14:01:54 +03:00 committed by kd-11
parent a7f5514913
commit e8e2d4b93d
3 changed files with 57 additions and 17 deletions

View File

@ -100,15 +100,16 @@ namespace rsx::assembler
if (found)
{
if (!bb->pred.empty())
auto front_edge = std::find_if(bb->pred.begin(), bb->pred.end(), FN(x.type != EdgeType::ENDIF && x.type != EdgeType::ENDLOOP));
if (front_edge != bb->pred.end())
{
switch (bb->pred.back().type)
auto parent = ensure(front_edge->from);
switch (front_edge->type)
{
case EdgeType::IF:
case EdgeType::ELSE:
{
// Find the merge node from the parent
auto parent = bb->pred.back().from;
auto succ = std::find_if(parent->succ.begin(), parent->succ.end(), FN(x.type == EdgeType::ENDIF));
ensure(succ != parent->succ.end(), "CFG: Broken IF linkage. Please report to developers.");
bb->insert_succ(succ->to, EdgeType::ENDIF);
@ -118,7 +119,6 @@ namespace rsx::assembler
case EdgeType::LOOP:
{
// Find the merge node from the parent
auto parent = bb->pred.back().from;
auto succ = std::find_if(parent->succ.begin(), parent->succ.end(), FN(x.type == EdgeType::ENDLOOP));
ensure(succ != parent->succ.end(), "CFG: Broken LOOP linkage. Please report to developers.");
bb->insert_succ(succ->to, EdgeType::ENDLOOP);
@ -130,7 +130,7 @@ namespace rsx::assembler
rsx_log.error("CFG: Unexpected block exit. Report to developers.");
}
}
else
else if (bb->pred.empty())
{
// Impossible situation.
rsx_log.error("CFG: Child block has no parent but has successor! Report to developers.");

View File

@ -114,5 +114,25 @@ namespace rsx::assembler
pred.push_back(e);
return &pred.back();
}
bool is_of_type(EdgeType type) const
{
return pred.size() == 1 &&
pred.front().type == type;
}
bool has_sibling_of_type(EdgeType type) const
{
if (pred.size() != 1)
{
return false;
}
auto source_node = pred.front().from;
return std::find_if(
source_node->succ.begin(),
source_node->succ.end(),
FN(x.type == type)) != source_node->succ.end();
}
};
}

View File

@ -21,6 +21,7 @@ namespace rsx
}
using namespace rsx::fragment_program;
using namespace rsx::assembler;
// SIMD vector lanes
enum VectorLane : u8
@ -1295,7 +1296,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
std::string FragmentProgramDecompiler::Decompile()
{
const auto graph = rsx::assembler::deconstruct_fragment_program(m_prog);
const auto graph = deconstruct_fragment_program(m_prog);
m_size = 0;
m_location = 0;
m_loop_count = 0;
@ -1322,22 +1323,41 @@ std::string FragmentProgramDecompiler::Decompile()
{
switch (pred.type)
{
case rsx::assembler::EdgeType::ENDLOOP:
m_loop_count--;
[[ fallthrough ]];
case rsx::assembler::EdgeType::ENDIF:
m_code_level--;
AddCode("}");
case EdgeType::ENDLOOP:
// Because of succession rules, endloop is seen twice.
// Once from the the for statement at the end of the parent
// and again at the end of the child block.
if (pred.from->is_of_type(EdgeType::LOOP))
{
m_loop_count--;
m_code_level--;
AddCode("}");
}
break;
case rsx::assembler::EdgeType::LOOP:
case EdgeType::ENDIF:
{
// Same thing happens with ENDIF
// Once for the IF statement itself
// And again for the child blocks with code for the IF and ELSE paths.
const bool is_else_end = pred.from->is_of_type(EdgeType::ELSE);
const bool is_if_end = pred.from->is_of_type(EdgeType::IF) &&
!pred.from->has_sibling_of_type(EdgeType::ELSE); // Avoid double-counting if the IF has an ELSE sibling
if (is_else_end || is_if_end)
{
m_code_level--;
AddCode("}");
}
break;
}
case EdgeType::LOOP:
m_loop_count++;
[[ fallthrough ]];
case rsx::assembler::EdgeType::IF:
case EdgeType::IF:
// Instruction will be inserted by the SIP decoder
AddCode("{");
m_code_level++;
break;
case rsx::assembler::EdgeType::ELSE:
case EdgeType::ELSE:
// This one needs more testing
m_code_level--;
AddCode("}");
@ -1440,8 +1460,8 @@ std::string FragmentProgramDecompiler::Decompile()
while (m_code_level > 1)
{
rsx_log.error("Hanging block found at end of shader. Malformed shader?");
// Happens if the last block was hanging (no merge)
// FIXME: We must always have a merge block on exit to resolve dependencies on outputs
m_code_level--;
AddCode("}");
}