diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv.cpp | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index fd59b4d0a..278c262f8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | 10 | ||
| 11 | #include "common/settings.h" | ||
| 11 | #include "shader_recompiler/backend/spirv/emit_spirv.h" | 12 | #include "shader_recompiler/backend/spirv/emit_spirv.h" |
| 12 | #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" | 13 | #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" |
| 13 | #include "shader_recompiler/frontend/ir/basic_block.h" | 14 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| @@ -151,9 +152,25 @@ void Traverse(EmitContext& ctx, IR::Program& program) { | |||
| 151 | } | 152 | } |
| 152 | break; | 153 | break; |
| 153 | case IR::AbstractSyntaxNode::Type::Repeat: { | 154 | case IR::AbstractSyntaxNode::Type::Repeat: { |
| 155 | Id cond{ctx.Def(node.data.repeat.cond)}; | ||
| 156 | if (!Settings::values.disable_shader_loop_safety_checks) { | ||
| 157 | const Id pointer_type{ctx.TypePointer(spv::StorageClass::Private, ctx.U32[1])}; | ||
| 158 | const Id safety_counter{ctx.AddGlobalVariable( | ||
| 159 | pointer_type, spv::StorageClass::Private, ctx.Const(0x2000u))}; | ||
| 160 | if (ctx.profile.supported_spirv >= 0x00010400) { | ||
| 161 | ctx.interfaces.push_back(safety_counter); | ||
| 162 | } | ||
| 163 | const Id old_counter{ctx.OpLoad(ctx.U32[1], safety_counter)}; | ||
| 164 | const Id new_counter{ctx.OpISub(ctx.U32[1], old_counter, ctx.Const(1u))}; | ||
| 165 | ctx.OpStore(safety_counter, new_counter); | ||
| 166 | |||
| 167 | const Id safety_cond{ | ||
| 168 | ctx.OpSGreaterThanEqual(ctx.U1, new_counter, ctx.u32_zero_value)}; | ||
| 169 | cond = ctx.OpLogicalAnd(ctx.U1, cond, safety_cond); | ||
| 170 | } | ||
| 154 | const Id loop_header_label{node.data.repeat.loop_header->Definition<Id>()}; | 171 | const Id loop_header_label{node.data.repeat.loop_header->Definition<Id>()}; |
| 155 | const Id merge_label{node.data.repeat.merge->Definition<Id>()}; | 172 | const Id merge_label{node.data.repeat.merge->Definition<Id>()}; |
| 156 | ctx.OpBranchConditional(ctx.Def(node.data.repeat.cond), loop_header_label, merge_label); | 173 | ctx.OpBranchConditional(cond, loop_header_label, merge_label); |
| 157 | break; | 174 | break; |
| 158 | } | 175 | } |
| 159 | case IR::AbstractSyntaxNode::Type::Return: | 176 | case IR::AbstractSyntaxNode::Type::Return: |