mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-16 04:09:07 +00:00
rsx/fp: Fix issues with FP decompiler using new CFG system
This commit is contained in:
parent
a7f5514913
commit
e8e2d4b93d
@ -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.");
|
||||
|
||||
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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:
|
||||
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--;
|
||||
[[ fallthrough ]];
|
||||
case rsx::assembler::EdgeType::ENDIF:
|
||||
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("}");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user