mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
123 lines
4.2 KiB
C++
123 lines
4.2 KiB
C++
#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/frontend/decode/ShaderDecoder.h"
|
|
|
|
#include <vector>
|
|
|
|
namespace Libs::Graphics::ShaderRecompiler::CFG {
|
|
|
|
enum class BranchCondition {
|
|
Always,
|
|
SccZero,
|
|
SccNonZero,
|
|
VccZero,
|
|
VccNonZero,
|
|
ExecZero,
|
|
ExecNonZero,
|
|
ScalarInstruction,
|
|
GotoVariable,
|
|
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<uint32_t> indirect_target_pcs;
|
|
std::vector<uint32_t> indirect_targets;
|
|
std::vector<uint32_t> indirect_selector_values;
|
|
std::vector<uint32_t> indirect_selector_targets;
|
|
uint32_t goto_variable = UINT32_MAX;
|
|
int32_t goto_value = -1;
|
|
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<uint32_t> predecessors;
|
|
std::vector<uint32_t> successors;
|
|
std::vector<uint32_t> dominators;
|
|
std::vector<uint32_t> 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<uint32_t> body_blocks;
|
|
std::vector<uint32_t> exit_blocks;
|
|
};
|
|
|
|
struct StronglyConnectedComponent {
|
|
std::vector<uint32_t> blocks;
|
|
std::vector<uint32_t> entry_blocks;
|
|
bool irreducible = false;
|
|
};
|
|
|
|
struct Graph {
|
|
std::vector<BasicBlock> blocks;
|
|
std::vector<BackEdge> back_edges;
|
|
std::vector<NaturalLoop> natural_loops;
|
|
std::vector<StronglyConnectedComponent> components;
|
|
std::vector<uint32_t> 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;
|
|
};
|
|
|
|
Graph BuildGraph(const Decoder::Program& program);
|
|
// Commits structured control flow on success; preserves the original graph with
|
|
// failure diagnostics on failure. failure_block is an original block ID or UINT32_MAX.
|
|
bool Structurize(Graph& graph);
|
|
std::string BranchConditionToString(BranchCondition condition);
|
|
std::string FailureKindToString(FailureKind kind);
|
|
std::string GraphToString(const Graph& graph);
|
|
|
|
} // namespace Libs::Graphics::ShaderRecompiler::CFG
|
|
|
|
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERCFG_H_ */
|