summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp14
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h3
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc2
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp42
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
128void IREmitter::SetPred(IR::Pred pred, const U1& value) {
129 if (pred != IR::Pred::PT) {
130 Inst(Opcode::SetPred, pred, value);
131 }
132}
133
128U1 IREmitter::GetGotoVariable(u32 id) { 134U1 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
144void IREmitter::SetPred(IR::Pred pred, const U1& value) { 150U32 IREmitter::GetLoopSafetyVariable(u32 id) {
145 Inst(Opcode::SetPred, pred, value); 151 return Inst<U32>(Opcode::GetLoopSafetyVariable, id);
152}
153
154void IREmitter::SetLoopSafetyVariable(u32 id, const U32& counter) {
155 Inst(Opcode::SetLoopSafetyVariable, id, counter);
146} 156}
147 157
148U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { 158U32 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,
32OPCODE(SetGotoVariable, Void, U32, U1, ) 32OPCODE(SetGotoVariable, Void, U32, U1, )
33OPCODE(GetIndirectBranchVariable, U32, ) 33OPCODE(GetIndirectBranchVariable, U32, )
34OPCODE(SetIndirectBranchVariable, Void, U32, ) 34OPCODE(SetIndirectBranchVariable, Void, U32, )
35OPCODE(GetLoopSafetyVariable, U32, U32, )
36OPCODE(SetLoopSafetyVariable, Void, U32, U32, )
35OPCODE(GetCbufU8, U32, U32, U32, ) 37OPCODE(GetCbufU8, U32, U32, U32, )
36OPCODE(GetCbufS8, U32, U32, U32, ) 38OPCODE(GetCbufS8, U32, U32, U32, )
37OPCODE(GetCbufU16, U32, U32, U32, ) 39OPCODE(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