Shaders: Implement CAL and RET, and increase program size.
This commit is contained in:
@@ -1785,6 +1785,8 @@ public:
|
|||||||
SSY,
|
SSY,
|
||||||
SYNC,
|
SYNC,
|
||||||
BRK,
|
BRK,
|
||||||
|
CAL,
|
||||||
|
RET,
|
||||||
DEPBAR,
|
DEPBAR,
|
||||||
VOTE,
|
VOTE,
|
||||||
VOTE_VTG,
|
VOTE_VTG,
|
||||||
@@ -2108,6 +2110,8 @@ private:
|
|||||||
INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"),
|
INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"),
|
||||||
INST("111000110100----", Id::BRK, Type::Flow, "BRK"),
|
INST("111000110100----", Id::BRK, Type::Flow, "BRK"),
|
||||||
INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"),
|
INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"),
|
||||||
|
INST("111000100110----", Id::CAL, Type::Flow, "CAL"),
|
||||||
|
INST("111000110010----", Id::RET, Type::Flow, "RET"),
|
||||||
INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"),
|
INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"),
|
||||||
INST("0101000011011---", Id::VOTE, Type::Warp, "VOTE"),
|
INST("0101000011011---", Id::VOTE, Type::Warp, "VOTE"),
|
||||||
INST("0101000011100---", Id::VOTE_VTG, Type::Warp, "VOTE_VTG"),
|
INST("0101000011100---", Id::VOTE_VTG, Type::Warp, "VOTE_VTG"),
|
||||||
|
|||||||
@@ -93,13 +93,15 @@ struct ProgramControl {
|
|||||||
|
|
||||||
struct CFGRebuildState {
|
struct CFGRebuildState {
|
||||||
explicit CFGRebuildState(ProgramControl& control, const ProgramCode& program_code_, u32 start_,
|
explicit CFGRebuildState(ProgramControl& control, const ProgramCode& program_code_, u32 start_,
|
||||||
Registry& registry_)
|
u32 base_start_, Registry& registry_)
|
||||||
: control{control}, program_code{program_code_}, registry{registry_}, start{start_} {}
|
: control{control}, program_code{program_code_}, registry{registry_}, start{start_},
|
||||||
|
base_start{base_start_} {}
|
||||||
|
|
||||||
ProgramControl& control;
|
ProgramControl& control;
|
||||||
const ProgramCode& program_code;
|
const ProgramCode& program_code;
|
||||||
Registry& registry;
|
Registry& registry;
|
||||||
u32 start{};
|
u32 start{};
|
||||||
|
u32 base_start{};
|
||||||
std::vector<BlockInfo> block_info;
|
std::vector<BlockInfo> block_info;
|
||||||
std::list<u32> inspect_queries;
|
std::list<u32> inspect_queries;
|
||||||
std::list<Query> queries;
|
std::list<Query> queries;
|
||||||
@@ -180,7 +182,7 @@ template <typename Result, typename TestCallable, typename PackCallable>
|
|||||||
std::optional<Result> TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test,
|
std::optional<Result> TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test,
|
||||||
PackCallable pack) {
|
PackCallable pack) {
|
||||||
for (; pos >= state.start; --pos) {
|
for (; pos >= state.start; --pos) {
|
||||||
if (IsSchedInstruction(pos, state.start)) {
|
if (IsSchedInstruction(pos, state.base_start)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const Instruction instr = state.program_code[pos];
|
const Instruction instr = state.program_code[pos];
|
||||||
@@ -287,7 +289,7 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
|
|||||||
single_branch.ignore = true;
|
single_branch.ignore = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (IsSchedInstruction(offset, state.start)) {
|
if (IsSchedInstruction(offset, state.base_start)) {
|
||||||
offset++;
|
offset++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -299,6 +301,7 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
|
case OpCode::Id::RET:
|
||||||
case OpCode::Id::EXIT: {
|
case OpCode::Id::EXIT: {
|
||||||
const auto pred_index = static_cast<u32>(instr.pred.pred_index);
|
const auto pred_index = static_cast<u32>(instr.pred.pred_index);
|
||||||
single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0);
|
single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0);
|
||||||
@@ -447,6 +450,11 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
|
|||||||
state.jump_labels.emplace(offset, it);
|
state.jump_labels.emplace(offset, it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpCode::Id::CAL: {
|
||||||
|
const u32 target = offset + instr.bra.GetBranchTarget();
|
||||||
|
state.control.RegisterFunction(target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OpCode::Id::BRX: {
|
case OpCode::Id::BRX: {
|
||||||
const auto tmp = TrackBranchIndirectInfo(state, offset);
|
const auto tmp = TrackBranchIndirectInfo(state, offset);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
@@ -681,7 +689,7 @@ void DecompileShader(CFGRebuildState& state) {
|
|||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_code,
|
ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_code,
|
||||||
u32 start_address, const CompilerSettings& settings,
|
u32 start_address, u32 base_start, const CompilerSettings& settings,
|
||||||
Registry& registry) {
|
Registry& registry) {
|
||||||
ShaderFunction result_out{};
|
ShaderFunction result_out{};
|
||||||
if (settings.depth == CompileDepth::BruteForce) {
|
if (settings.depth == CompileDepth::BruteForce) {
|
||||||
@@ -689,7 +697,7 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_
|
|||||||
return result_out;
|
return result_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGRebuildState state{control, program_code, start_address, registry};
|
CFGRebuildState state{control, program_code, start_address, base_start, registry};
|
||||||
// Inspect Code and generate blocks
|
// Inspect Code and generate blocks
|
||||||
state.labels.clear();
|
state.labels.clear();
|
||||||
state.labels.emplace(start_address);
|
state.labels.emplace(start_address);
|
||||||
@@ -784,10 +792,11 @@ std::unique_ptr<ShaderProgram> ScanFlow(const ProgramCode& program_code, u32 sta
|
|||||||
const CompilerSettings& settings, Registry& registry) {
|
const CompilerSettings& settings, Registry& registry) {
|
||||||
ProgramControl control{};
|
ProgramControl control{};
|
||||||
auto result_out = std::make_unique<ShaderProgram>();
|
auto result_out = std::make_unique<ShaderProgram>();
|
||||||
result_out->main = ScanFunction(control, program_code, start_address, settings, registry);
|
result_out->main =
|
||||||
|
ScanFunction(control, program_code, start_address, start_address, settings, registry);
|
||||||
while (!control.pending_functions.empty()) {
|
while (!control.pending_functions.empty()) {
|
||||||
u32 address = control.pending_functions.front();
|
u32 address = control.pending_functions.front();
|
||||||
auto fun = ScanFunction(control, program_code, address, settings, registry);
|
auto fun = ScanFunction(control, program_code, address, start_address, settings, registry);
|
||||||
result_out->subfunctions.emplace(address, std::move(fun));
|
result_out->subfunctions.emplace(address, std::move(fun));
|
||||||
control.pending_functions.pop_front();
|
control.pending_functions.pop_front();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace VideoCommon::Shader {
|
|||||||
|
|
||||||
struct ShaderBlock;
|
struct ShaderBlock;
|
||||||
|
|
||||||
constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
|
constexpr u32 MAX_PROGRAM_LENGTH = 0x8000;
|
||||||
|
|
||||||
struct ConstBuffer {
|
struct ConstBuffer {
|
||||||
constexpr explicit ConstBuffer(u32 max_offset_, bool is_indirect_)
|
constexpr explicit ConstBuffer(u32 max_offset_, bool is_indirect_)
|
||||||
|
|||||||
Reference in New Issue
Block a user