diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 8b45f1b623..5d659dcaff 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1785,6 +1785,8 @@ public: SSY, SYNC, BRK, + CAL, + RET, DEPBAR, VOTE, VOTE_VTG, @@ -2108,6 +2110,8 @@ private: INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), INST("111000110100----", Id::BRK, Type::Flow, "BRK"), 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("0101000011011---", Id::VOTE, Type::Warp, "VOTE"), INST("0101000011100---", Id::VOTE_VTG, Type::Warp, "VOTE_VTG"), diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index fdc1eea956..438ca9094b 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -93,13 +93,15 @@ struct ProgramControl { struct CFGRebuildState { explicit CFGRebuildState(ProgramControl& control, const ProgramCode& program_code_, u32 start_, - Registry& registry_) - : control{control}, program_code{program_code_}, registry{registry_}, start{start_} {} + u32 base_start_, Registry& registry_) + : control{control}, program_code{program_code_}, registry{registry_}, start{start_}, + base_start{base_start_} {} ProgramControl& control; const ProgramCode& program_code; Registry& registry; u32 start{}; + u32 base_start{}; std::vector block_info; std::list inspect_queries; std::list queries; @@ -180,7 +182,7 @@ template std::optional TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test, PackCallable pack) { for (; pos >= state.start; --pos) { - if (IsSchedInstruction(pos, state.start)) { + if (IsSchedInstruction(pos, state.base_start)) { continue; } const Instruction instr = state.program_code[pos]; @@ -287,7 +289,7 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) single_branch.ignore = true; break; } - if (IsSchedInstruction(offset, state.start)) { + if (IsSchedInstruction(offset, state.base_start)) { offset++; continue; } @@ -299,6 +301,7 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) } switch (opcode->get().GetId()) { + case OpCode::Id::RET: case OpCode::Id::EXIT: { const auto pred_index = static_cast(instr.pred.pred_index); single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); @@ -447,6 +450,11 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) state.jump_labels.emplace(offset, it); break; } + case OpCode::Id::CAL: { + const u32 target = offset + instr.bra.GetBranchTarget(); + state.control.RegisterFunction(target); + break; + } case OpCode::Id::BRX: { const auto tmp = TrackBranchIndirectInfo(state, offset); if (!tmp) { @@ -681,7 +689,7 @@ void DecompileShader(CFGRebuildState& state) { } // Anonymous namespace 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) { ShaderFunction result_out{}; if (settings.depth == CompileDepth::BruteForce) { @@ -689,7 +697,7 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_ 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 state.labels.clear(); state.labels.emplace(start_address); @@ -784,10 +792,11 @@ std::unique_ptr ScanFlow(const ProgramCode& program_code, u32 sta const CompilerSettings& settings, Registry& registry) { ProgramControl control{}; auto result_out = std::make_unique(); - 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()) { 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)); control.pending_functions.pop_front(); } diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 1cd7c14d76..9f1bc2eb41 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -26,7 +26,7 @@ namespace VideoCommon::Shader { struct ShaderBlock; -constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; +constexpr u32 MAX_PROGRAM_LENGTH = 0x8000; struct ConstBuffer { constexpr explicit ConstBuffer(u32 max_offset_, bool is_indirect_)