diff options
Diffstat (limited to 'src/shader_recompiler/frontend')
4 files changed, 55 insertions, 6 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index e9fd41237..6c37af5e7 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -125,6 +125,12 @@ U1 IREmitter::GetPred(IR::Pred pred, bool is_negated) { | |||
| 125 | } | 125 | } |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | void IREmitter::SetPred(IR::Pred pred, const U1& value) { | ||
| 129 | if (pred != IR::Pred::PT) { | ||
| 130 | Inst(Opcode::SetPred, pred, value); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 128 | U1 IREmitter::GetGotoVariable(u32 id) { | 134 | U1 IREmitter::GetGotoVariable(u32 id) { |
| 129 | return Inst<U1>(Opcode::GetGotoVariable, id); | 135 | return Inst<U1>(Opcode::GetGotoVariable, id); |
| 130 | } | 136 | } |
| @@ -141,8 +147,12 @@ void IREmitter::SetIndirectBranchVariable(const U32& value) { | |||
| 141 | Inst(Opcode::SetIndirectBranchVariable, value); | 147 | Inst(Opcode::SetIndirectBranchVariable, value); |
| 142 | } | 148 | } |
| 143 | 149 | ||
| 144 | void IREmitter::SetPred(IR::Pred pred, const U1& value) { | 150 | U32 IREmitter::GetLoopSafetyVariable(u32 id) { |
| 145 | Inst(Opcode::SetPred, pred, value); | 151 | return Inst<U32>(Opcode::GetLoopSafetyVariable, id); |
| 152 | } | ||
| 153 | |||
| 154 | void IREmitter::SetLoopSafetyVariable(u32 id, const U32& counter) { | ||
| 155 | Inst(Opcode::SetLoopSafetyVariable, id, counter); | ||
| 146 | } | 156 | } |
| 147 | 157 | ||
| 148 | U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { | 158 | U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index bb3500c54..7caab1f61 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -55,6 +55,9 @@ public: | |||
| 55 | [[nodiscard]] U32 GetIndirectBranchVariable(); | 55 | [[nodiscard]] U32 GetIndirectBranchVariable(); |
| 56 | void SetIndirectBranchVariable(const U32& value); | 56 | void SetIndirectBranchVariable(const U32& value); |
| 57 | 57 | ||
| 58 | [[nodiscard]] U32 GetLoopSafetyVariable(u32 id); | ||
| 59 | void SetLoopSafetyVariable(u32 id, const U32& counter); | ||
| 60 | |||
| 58 | [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); | 61 | [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); |
| 59 | [[nodiscard]] Value GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, | 62 | [[nodiscard]] Value GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, |
| 60 | bool is_signed); | 63 | bool is_signed); |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 8a8d0d759..e87aeddd5 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -32,6 +32,8 @@ OPCODE(GetGotoVariable, U1, U32, | |||
| 32 | OPCODE(SetGotoVariable, Void, U32, U1, ) | 32 | OPCODE(SetGotoVariable, Void, U32, U1, ) |
| 33 | OPCODE(GetIndirectBranchVariable, U32, ) | 33 | OPCODE(GetIndirectBranchVariable, U32, ) |
| 34 | OPCODE(SetIndirectBranchVariable, Void, U32, ) | 34 | OPCODE(SetIndirectBranchVariable, Void, U32, ) |
| 35 | OPCODE(GetLoopSafetyVariable, U32, U32, ) | ||
| 36 | OPCODE(SetLoopSafetyVariable, Void, U32, U32, ) | ||
| 35 | OPCODE(GetCbufU8, U32, U32, U32, ) | 37 | OPCODE(GetCbufU8, U32, U32, U32, ) |
| 36 | OPCODE(GetCbufS8, U32, U32, U32, ) | 38 | OPCODE(GetCbufS8, U32, U32, U32, ) |
| 37 | OPCODE(GetCbufU16, U32, U32, U32, ) | 39 | OPCODE(GetCbufU16, U32, U32, U32, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index c1e0646e6..b2b8c492a 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | |||
| @@ -9,11 +9,13 @@ | |||
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | #include <version> | ||
| 12 | 13 | ||
| 13 | #include <fmt/format.h> | 14 | #include <fmt/format.h> |
| 14 | 15 | ||
| 15 | #include <boost/intrusive/list.hpp> | 16 | #include <boost/intrusive/list.hpp> |
| 16 | 17 | ||
| 18 | #include "common/settings.h" | ||
| 17 | #include "shader_recompiler/environment.h" | 19 | #include "shader_recompiler/environment.h" |
| 18 | #include "shader_recompiler/frontend/ir/basic_block.h" | 20 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 19 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | 21 | #include "shader_recompiler/frontend/ir/ir_emitter.h" |
| @@ -739,8 +741,25 @@ private: | |||
| 739 | } | 741 | } |
| 740 | case StatementType::Loop: { | 742 | case StatementType::Loop: { |
| 741 | IR::Block* const loop_header_block{block_pool.Create(inst_pool)}; | 743 | IR::Block* const loop_header_block{block_pool.Create(inst_pool)}; |
| 742 | if (current_block) { | 744 | const u32 this_loop_id{loop_id++}; |
| 743 | current_block->AddBranch(loop_header_block); | 745 | |
| 746 | if (Settings::values.disable_shader_loop_safety_checks) { | ||
| 747 | if (current_block) { | ||
| 748 | current_block->AddBranch(loop_header_block); | ||
| 749 | } | ||
| 750 | } else { | ||
| 751 | IR::Block* const init_block{block_pool.Create(inst_pool)}; | ||
| 752 | IR::IREmitter ir{*init_block}; | ||
| 753 | ir.SetLoopSafetyVariable(this_loop_id, ir.Imm32(0x2000)); | ||
| 754 | |||
| 755 | if (current_block) { | ||
| 756 | current_block->AddBranch(init_block); | ||
| 757 | } | ||
| 758 | init_block->AddBranch(loop_header_block); | ||
| 759 | |||
| 760 | auto& init_node{syntax_list.emplace_back()}; | ||
| 761 | init_node.type = IR::AbstractSyntaxNode::Type::Block; | ||
| 762 | init_node.data.block = init_block; | ||
| 744 | } | 763 | } |
| 745 | auto& header_node{syntax_list.emplace_back()}; | 764 | auto& header_node{syntax_list.emplace_back()}; |
| 746 | header_node.type = IR::AbstractSyntaxNode::Type::Block; | 765 | header_node.type = IR::AbstractSyntaxNode::Type::Block; |
| @@ -758,7 +777,16 @@ private: | |||
| 758 | 777 | ||
| 759 | // The continue block is located at the end of the loop | 778 | // The continue block is located at the end of the loop |
| 760 | IR::IREmitter ir{*continue_block}; | 779 | IR::IREmitter ir{*continue_block}; |
| 761 | const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; | 780 | IR::U1 cond{VisitExpr(ir, *stmt.cond)}; |
| 781 | if (!Settings::values.disable_shader_loop_safety_checks) { | ||
| 782 | const IR::U32 old_counter{ir.GetLoopSafetyVariable(this_loop_id)}; | ||
| 783 | const IR::U32 new_counter{ir.ISub(old_counter, ir.Imm32(1))}; | ||
| 784 | ir.SetLoopSafetyVariable(this_loop_id, new_counter); | ||
| 785 | |||
| 786 | const IR::U1 safety_cond{ir.INotEqual(new_counter, ir.Imm32(0))}; | ||
| 787 | cond = ir.LogicalAnd(cond, safety_cond); | ||
| 788 | } | ||
| 789 | cond = ir.ConditionRef(cond); | ||
| 762 | 790 | ||
| 763 | IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; | 791 | IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; |
| 764 | loop_header_block->AddBranch(body_block); | 792 | loop_header_block->AddBranch(body_block); |
| @@ -863,8 +891,14 @@ private: | |||
| 863 | ObjectPool<IR::Block>& block_pool; | 891 | ObjectPool<IR::Block>& block_pool; |
| 864 | Environment& env; | 892 | Environment& env; |
| 865 | IR::AbstractSyntaxList& syntax_list; | 893 | IR::AbstractSyntaxList& syntax_list; |
| 866 | // TODO: Make this constexpr when std::vector is constexpr | 894 | u32 loop_id{}; |
| 895 | |||
| 896 | // TODO: C++20 Remove this when all compilers support constexpr std::vector | ||
| 897 | #if __cpp_lib_constexpr_vector >= 201907 | ||
| 898 | static constexpr Flow::Block dummy_flow_block; | ||
| 899 | #else | ||
| 867 | const Flow::Block dummy_flow_block; | 900 | const Flow::Block dummy_flow_block; |
| 901 | #endif | ||
| 868 | }; | 902 | }; |
| 869 | } // Anonymous namespace | 903 | } // Anonymous namespace |
| 870 | 904 | ||