#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERCFG_H_ #define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERCFG_H_ #include "common/common.h" #include "common/stringUtils.h" #include "graphics/shader/recompiler/ShaderDecoder.h" #include namespace Libs::Graphics::ShaderRecompiler::CFG { enum class BranchCondition { Always, SccZero, SccNonZero, VccZero, VccNonZero, ExecZero, ExecNonZero, Unknown }; enum class TerminatorKind { Branch, ConditionalBranch, IndirectBranch, Return, Unsupported }; enum class FailureKind { None, InvalidInput, UnsupportedInstruction, InvalidBranchTarget, MissingFallthrough, InvalidLabel, IrreducibleControlFlow, StructuredControlFlow }; struct Terminator { TerminatorKind kind = TerminatorKind::Return; BranchCondition condition = BranchCondition::Always; uint32_t true_block = UINT32_MAX; uint32_t false_block = UINT32_MAX; uint32_t merge_block = UINT32_MAX; uint32_t continue_block = UINT32_MAX; uint32_t indirect_pc_sgpr = UINT32_MAX; uint32_t indirect_selector_code = UINT32_MAX; std::vector indirect_target_pcs; std::vector indirect_targets; std::vector indirect_selector_values; std::vector indirect_selector_targets; bool loop_header = false; }; struct BasicBlock { uint32_t id = 0; uint32_t start_pc = 0; uint32_t end_pc = 0; uint32_t inst_begin = 0; uint32_t inst_end = 0; std::vector predecessors; std::vector successors; std::vector dominators; std::vector post_dominators; Terminator terminator; }; struct BackEdge { uint32_t from = UINT32_MAX; uint32_t to = UINT32_MAX; bool natural = false; }; struct NaturalLoop { uint32_t header = UINT32_MAX; uint32_t latch = UINT32_MAX; uint32_t merge = UINT32_MAX; uint32_t continue_block = UINT32_MAX; std::vector body_blocks; std::vector exit_blocks; }; struct StronglyConnectedComponent { std::vector blocks; std::vector entry_blocks; bool irreducible = false; }; struct Graph { std::vector blocks; std::vector back_edges; std::vector natural_loops; std::vector components; std::vector code_table_load_pcs; uint32_t entry_block = UINT32_MAX; bool irreducible = false; bool unsupported = false; FailureKind failure_kind = FailureKind::None; uint32_t failure_block = UINT32_MAX; std::string unsupported_reason; const BasicBlock* FindBlock(uint32_t id) const; BasicBlock* FindBlock(uint32_t id); const BasicBlock* FindBlockByPc(uint32_t pc) const; BasicBlock* FindBlockByPc(uint32_t pc); bool Dominates(uint32_t dominator, uint32_t block) const; bool PostDominates(uint32_t post_dominator, uint32_t block) const; uint32_t FindNearestCommonPostDominator(uint32_t block_a, uint32_t block_b) const; }; bool BuildGraph(const Decoder::Program& program, Graph* graph, std::string* error); bool Structurize(Graph* graph, std::string* error); std::string BranchConditionToString(BranchCondition condition); std::string FailureKindToString(FailureKind kind); std::string FormatBlockDiagnostic(const Graph& graph, uint32_t block_id, const char* stage, const std::string& reason); std::string GraphToString(const Graph& graph); } // namespace Libs::Graphics::ShaderRecompiler::CFG #endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERCFG_H_ */