diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.cpp b/src/graphics/shader/recompiler/ShaderRecompiler.cpp index 05684975a..2395d7659 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.cpp +++ b/src/graphics/shader/recompiler/ShaderRecompiler.cpp @@ -130,20 +130,6 @@ uint32_t EmbeddedFetchDstSize(const Decoder::Instruction& inst) { return inst.opcode == Decoder::Opcode::V_MAD_U64_U32 ? 2u : DecodedDstSize(inst); } -bool EmbeddedFetchHasBranch(Decoder::Opcode opcode) { - switch (opcode) { - case Decoder::Opcode::S_SETPC_B64: - case Decoder::Opcode::S_BRANCH: - case Decoder::Opcode::S_CBRANCH_SCC0: - case Decoder::Opcode::S_CBRANCH_SCC1: - case Decoder::Opcode::S_CBRANCH_VCCZ: - case Decoder::Opcode::S_CBRANCH_VCCNZ: - case Decoder::Opcode::S_CBRANCH_EXECZ: - case Decoder::Opcode::S_CBRANCH_EXECNZ: return true; - default: return false; - } -} - void ClearEmbeddedFetchSgprs(std::array& sgprs, const Decoder::Operand& dst, uint32_t size) { if (!IsDecodedSgpr(dst)) { @@ -242,7 +228,10 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded EmbeddedFetchVectorLanes vector_lanes; const bool track_vector_lanes = std::none_of(decoded.instructions.begin(), decoded.instructions.end(), - [](const auto& inst) { return EmbeddedFetchHasBranch(inst.opcode); }); + [](const auto& inst) { + return Decoder::IsDirectBranch(inst.opcode) || + inst.opcode == Decoder::Opcode::S_SETPC_B64; + }); if (attrib_reg >= 0 && attrib_reg < static_cast(sgprs.size())) { sgprs[attrib_reg].type = EmbeddedFetchValueType::AttribTable; diff --git a/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp b/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp index 7c53bba5c..f1ef32a07 100644 --- a/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp +++ b/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp @@ -52,26 +52,6 @@ uint32_t ProgramEndPc(const Decoder::Program& program) { return InstructionEndPc(program.instructions.back()); } -bool IsUnconditionalBranch(Opcode opcode) { - return opcode == Opcode::S_BRANCH; -} - -bool IsConditionalBranch(Opcode opcode) { - switch (opcode) { - case Opcode::S_CBRANCH_SCC0: - case Opcode::S_CBRANCH_SCC1: - case Opcode::S_CBRANCH_VCCZ: - case Opcode::S_CBRANCH_VCCNZ: - case Opcode::S_CBRANCH_EXECZ: - case Opcode::S_CBRANCH_EXECNZ: return true; - default: return false; - } -} - -bool IsBranch(Opcode opcode) { - return IsUnconditionalBranch(opcode) || IsConditionalBranch(opcode); -} - BranchCondition ConditionForOpcode(Opcode opcode) { switch (opcode) { case Opcode::S_BRANCH: return BranchCondition::Always; @@ -1925,7 +1905,7 @@ 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 (IsBranch(inst.opcode)) { + if (Decoder::IsDirectBranch(inst.opcode)) { if (!IsValidTarget(inst.branch_target, instruction_pcs, first_pc, end_pc)) { ExitBuildFailure(graph, FailureKind::InvalidBranchTarget, UINT32_MAX, fmt::format("branch at pc 0x{:08x} targets invalid pc 0x{:08x}", @@ -2032,11 +2012,11 @@ Graph BuildGraph(const Decoder::Program& program) { block.terminator.condition = BranchCondition::Always; block.terminator.true_block = pc_to_block.at(target_info.target); } - } else if (IsUnconditionalBranch(last.opcode)) { + } else if (last.opcode == Opcode::S_BRANCH) { block.terminator.kind = TerminatorKind::Branch; block.terminator.condition = BranchCondition::Always; block.terminator.true_block = pc_to_block.at(last.branch_target); - } else if (IsConditionalBranch(last.opcode)) { + } else if (Decoder::IsConditionalBranch(last.opcode)) { block.terminator.kind = TerminatorKind::ConditionalBranch; block.terminator.condition = ConditionForOpcode(last.opcode); block.terminator.true_block = pc_to_block.at(last.branch_target); diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index 49e4aef5c..565b81ec1 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -25,19 +25,6 @@ bool HasLiteral(const Instruction& inst) { inst.src3.kind == OperandKind::LiteralConstant; } -bool IsControlFlowBranch(Opcode opcode) { - switch (opcode) { - case Opcode::S_BRANCH: - case Opcode::S_CBRANCH_SCC0: - case Opcode::S_CBRANCH_SCC1: - case Opcode::S_CBRANCH_VCCZ: - case Opcode::S_CBRANCH_VCCNZ: - case Opcode::S_CBRANCH_EXECZ: - case Opcode::S_CBRANCH_EXECNZ: return true; - default: return false; - } -} - void ApplyLiteral(Operand& operand, uint32_t literal) { if (operand.kind == OperandKind::LiteralConstant) { operand.value = literal; @@ -198,6 +185,22 @@ std::string FormatExp(const Instruction& inst) { } // namespace +bool IsConditionalBranch(Opcode opcode) { + switch (opcode) { + case Opcode::S_CBRANCH_SCC0: + case Opcode::S_CBRANCH_SCC1: + case Opcode::S_CBRANCH_VCCZ: + case Opcode::S_CBRANCH_VCCNZ: + case Opcode::S_CBRANCH_EXECZ: + case Opcode::S_CBRANCH_EXECNZ: return true; + default: return false; + } +} + +bool IsDirectBranch(Opcode opcode) { + return opcode == Opcode::S_BRANCH || IsConditionalBranch(opcode); +} + const char* ImageDimensionToString(ImageDimension dimension) { switch (dimension) { case ImageDimension::Dim1D: return "1d"; @@ -389,7 +392,7 @@ void DecodeProgram(std::span code, Program& program) { const auto& inst = program.instructions.back(); word_index += inst.word_count; - if (IsControlFlowBranch(inst.opcode)) { + if (IsDirectBranch(inst.opcode)) { const auto target_index = inst.branch_target / sizeof(uint32_t); if (branch_targets.empty()) { branch_targets.resize(code.size()); diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index 90816f81b..f94073e0e 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -717,6 +717,8 @@ Family GetInstructionFamily(uint32_t word); // The output object must be freshly initialized. void DecodeInstruction(std::span code, uint32_t word_index, Instruction& inst); void DecodeProgram(std::span code, Program& program); +bool IsConditionalBranch(Opcode opcode); +bool IsDirectBranch(Opcode opcode); void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand); void DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand);