mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
shader: link scalar leaf calls only for SWAPPC programs
Co-authored-by: Behzad <behzadkhan1736@gmail.com>
This commit is contained in:
@@ -1468,7 +1468,8 @@ Graph BuildGraph(const Decoder::Program& program) {
|
||||
for (uint32_t i = 0; i < program.instructions.size(); i++) {
|
||||
const auto& inst = program.instructions[i];
|
||||
const auto next_pc = InstructionEndPc(inst);
|
||||
if (Decoder::IsDirectBranch(inst.opcode)) {
|
||||
if (Decoder::IsDirectBranch(inst.opcode) ||
|
||||
(inst.opcode == Opcode::S_SWAPPC_B64 && inst.branch_target != UINT32_MAX)) {
|
||||
if (!IsValidTarget(inst.branch_target, program.instructions, end_pc)) {
|
||||
ExitBuildFailure(graph, FailureKind::InvalidBranchTarget, UINT32_MAX,
|
||||
fmt::format("branch at pc 0x{:08x} targets invalid pc 0x{:08x}",
|
||||
@@ -1501,7 +1502,7 @@ Graph BuildGraph(const Decoder::Program& program) {
|
||||
if (next_pc <= end_pc) {
|
||||
labels.push_back(next_pc);
|
||||
}
|
||||
} else if (inst.opcode == Opcode::S_ENDPGM) {
|
||||
} else if (inst.opcode == Opcode::S_ENDPGM || inst.opcode == Opcode::S_SWAPPC_B64) {
|
||||
labels.push_back(next_pc);
|
||||
}
|
||||
}
|
||||
@@ -1550,6 +1551,9 @@ Graph BuildGraph(const Decoder::Program& program) {
|
||||
const auto next_pc = InstructionEndPc(last);
|
||||
if (last.opcode == Opcode::S_ENDPGM) {
|
||||
block.terminator.kind = TerminatorKind::Return;
|
||||
} else if (last.opcode == Opcode::S_SWAPPC_B64 && last.branch_target != UINT32_MAX) {
|
||||
block.terminator.kind = TerminatorKind::Branch;
|
||||
block.terminator.true_block = block_at_pc(last.branch_target);
|
||||
} else if (last.opcode == Opcode::S_SETPC_B64) {
|
||||
const auto& target_info = setpc_targets.at(last.pc);
|
||||
if (target_info.indirect) {
|
||||
@@ -1676,6 +1680,36 @@ Graph Structurize(const Graph& graph) {
|
||||
return GotoStructurizer(graph).Run();
|
||||
}
|
||||
|
||||
bool MayWriteScalarRegister(const Decoder::Instruction& inst, uint32_t code) {
|
||||
uint32_t destination = UINT32_MAX;
|
||||
// Scalar ALU pair widths are not all decoded. The typed producer must confirm this word.
|
||||
return InstructionWritesScalarCode(inst, code) ||
|
||||
(ScalarOperandCode(inst.dst, destination) && code == destination + 1u);
|
||||
}
|
||||
|
||||
uint32_t FindScalarDefinition(const Decoder::Program& program, const Graph& graph,
|
||||
uint32_t before, uint32_t code) {
|
||||
EXIT_IF(before >= program.instructions.size());
|
||||
const auto found = std::ranges::find_if(graph.blocks, [before](const auto& block) {
|
||||
return block.inst_begin <= before && before < block.inst_end;
|
||||
});
|
||||
EXIT_IF(found == graph.blocks.end());
|
||||
const auto* block = &*found;
|
||||
for (size_t depth = 0; depth < graph.blocks.size(); ++depth) {
|
||||
for (uint32_t i = before; i > block->inst_begin;) {
|
||||
const auto& inst = program.instructions[--i];
|
||||
EXIT_IF(inst.opcode == Opcode::S_SWAPPC_B64);
|
||||
if (MayWriteScalarRegister(inst, code)) return i;
|
||||
}
|
||||
if (block->id == graph.entry_block) return UINT32_MAX;
|
||||
EXIT_IF(block->predecessors.size() != 1u);
|
||||
block = graph.FindBlock(block->predecessors[0]);
|
||||
EXIT_IF(block == nullptr);
|
||||
before = block->inst_end;
|
||||
}
|
||||
EXIT("scalar shader call source has cyclic reaching definitions");
|
||||
}
|
||||
|
||||
std::string BranchConditionToString(BranchCondition condition) {
|
||||
switch (condition) {
|
||||
case BranchCondition::Always: return "always";
|
||||
|
||||
@@ -113,6 +113,9 @@ struct Graph {
|
||||
};
|
||||
|
||||
Graph BuildGraph(const Decoder::Program& program);
|
||||
bool MayWriteScalarRegister(const Decoder::Instruction& inst, uint32_t code);
|
||||
uint32_t FindScalarDefinition(const Decoder::Program& program, const Graph& graph,
|
||||
uint32_t before, uint32_t code);
|
||||
// Returns structured control flow or failure diagnostics without changing the native graph.
|
||||
// On failure, failure_block is an original block ID or UINT32_MAX.
|
||||
Graph Structurize(const Graph& graph);
|
||||
|
||||
@@ -61,6 +61,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
||||
{0x1eu, Opcode::S_BITSET1_B64},
|
||||
{0x1fu, Opcode::S_GETPC_B64},
|
||||
{0x20u, Opcode::S_SETPC_B64},
|
||||
{0x21u, Opcode::S_SWAPPC_B64},
|
||||
{0x24u, Opcode::S_AND_SAVEEXEC_B64},
|
||||
{0x28u, Opcode::S_ORN2_SAVEEXEC_B64},
|
||||
{0x2du, Opcode::S_QUADMASK_B64},
|
||||
@@ -155,6 +156,10 @@ void DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
}
|
||||
|
||||
switch (inst.opcode) {
|
||||
case Opcode::S_SWAPPC_B64:
|
||||
inst.branch_target = UINT32_MAX;
|
||||
inst.data_dwords = 2;
|
||||
break;
|
||||
case Opcode::S_GETPC_B64:
|
||||
inst.src_count = 0;
|
||||
DecodeScalarDestination(sdst, pc, inst.dst);
|
||||
|
||||
@@ -60,6 +60,7 @@ enum class Opcode {
|
||||
S_QUADMASK_B64,
|
||||
S_GETPC_B64,
|
||||
S_SETPC_B64,
|
||||
S_SWAPPC_B64,
|
||||
S_SUBVECTOR_LOOP_BEGIN,
|
||||
S_SUBVECTOR_LOOP_END,
|
||||
S_AND_SAVEEXEC_B32,
|
||||
|
||||
@@ -10,7 +10,8 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
case O::S_MOV_B64: S_MOV_B64(inst); return;
|
||||
case O::S_WQM_B32: S_WQM(inst, false); return;
|
||||
case O::S_WQM_B64: S_WQM(inst, true); return;
|
||||
case O::S_GETPC_B64: S_GETPC_B64(inst); return;
|
||||
case O::S_GETPC_B64:
|
||||
case O::S_SWAPPC_B64: S_GETPC_B64(inst); return;
|
||||
case O::S_SETPC_B64: return;
|
||||
case O::S_SUBVECTOR_LOOP_BEGIN: S_SUBVECTOR_LOOP(inst, true); return;
|
||||
case O::S_SUBVECTOR_LOOP_END: S_SUBVECTOR_LOOP(inst, false); return;
|
||||
|
||||
Reference in New Issue
Block a user