diff options
Diffstat (limited to '')
| -rw-r--r-- | src/common/settings.h | 3 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 8 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | 24 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 14 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.h | 3 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/opcodes.inc | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | 42 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 66 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.cpp | 8 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.ui | 26 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 8 |
16 files changed, 183 insertions, 35 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index ce1bc647d..ac0590690 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -308,6 +308,9 @@ struct Values { | |||
| 308 | // Renderer | 308 | // Renderer |
| 309 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; | 309 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; |
| 310 | BasicSetting<bool> renderer_debug{false, "debug"}; | 310 | BasicSetting<bool> renderer_debug{false, "debug"}; |
| 311 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | ||
| 312 | BasicSetting<bool> disable_shader_loop_safety_checks{false, | ||
| 313 | "disable_shader_loop_safety_checks"}; | ||
| 311 | Setting<int> vulkan_device{0, "vulkan_device"}; | 314 | Setting<int> vulkan_device{0, "vulkan_device"}; |
| 312 | 315 | ||
| 313 | Setting<u16> resolution_factor{1, "resolution_factor"}; | 316 | Setting<u16> resolution_factor{1, "resolution_factor"}; |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index c9f4826ce..fef9ff9be 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | |||
| @@ -42,6 +42,8 @@ void EmitSetGotoVariable(EmitContext& ctx); | |||
| 42 | void EmitGetGotoVariable(EmitContext& ctx); | 42 | void EmitGetGotoVariable(EmitContext& ctx); |
| 43 | void EmitSetIndirectBranchVariable(EmitContext& ctx); | 43 | void EmitSetIndirectBranchVariable(EmitContext& ctx); |
| 44 | void EmitGetIndirectBranchVariable(EmitContext& ctx); | 44 | void EmitGetIndirectBranchVariable(EmitContext& ctx); |
| 45 | void EmitSetLoopSafetyVariable(EmitContext& ctx); | ||
| 46 | void EmitGetLoopSafetyVariable(EmitContext& ctx); | ||
| 45 | void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); | 47 | void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); |
| 46 | void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); | 48 | void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); |
| 47 | void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); | 49 | void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 95bcbd750..60735fe31 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | |||
| @@ -153,6 +153,14 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) { | |||
| 153 | NotImplemented(); | 153 | NotImplemented(); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | void EmitSetLoopSafetyVariable(EmitContext& ctx) { | ||
| 157 | NotImplemented(); | ||
| 158 | } | ||
| 159 | |||
| 160 | void EmitGetLoopSafetyVariable(EmitContext& ctx) { | ||
| 161 | NotImplemented(); | ||
| 162 | } | ||
| 163 | |||
| 156 | void EmitGetZFlag(EmitContext& ctx) { | 164 | void EmitGetZFlag(EmitContext& ctx) { |
| 157 | NotImplemented(); | 165 | NotImplemented(); |
| 158 | } | 166 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 442a958a5..42fff74e3 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | |||
| @@ -163,35 +163,43 @@ Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 inde | |||
| 163 | } // Anonymous namespace | 163 | } // Anonymous namespace |
| 164 | 164 | ||
| 165 | void EmitGetRegister(EmitContext&) { | 165 | void EmitGetRegister(EmitContext&) { |
| 166 | throw NotImplementedException("SPIR-V Instruction"); | 166 | throw LogicError("Unreachable instruction"); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | void EmitSetRegister(EmitContext&) { | 169 | void EmitSetRegister(EmitContext&) { |
| 170 | throw NotImplementedException("SPIR-V Instruction"); | 170 | throw LogicError("Unreachable instruction"); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | void EmitGetPred(EmitContext&) { | 173 | void EmitGetPred(EmitContext&) { |
| 174 | throw NotImplementedException("SPIR-V Instruction"); | 174 | throw LogicError("Unreachable instruction"); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | void EmitSetPred(EmitContext&) { | 177 | void EmitSetPred(EmitContext&) { |
| 178 | throw NotImplementedException("SPIR-V Instruction"); | 178 | throw LogicError("Unreachable instruction"); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | void EmitSetGotoVariable(EmitContext&) { | 181 | void EmitSetGotoVariable(EmitContext&) { |
| 182 | throw NotImplementedException("SPIR-V Instruction"); | 182 | throw LogicError("Unreachable instruction"); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | void EmitGetGotoVariable(EmitContext&) { | 185 | void EmitGetGotoVariable(EmitContext&) { |
| 186 | throw NotImplementedException("SPIR-V Instruction"); | 186 | throw LogicError("Unreachable instruction"); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | void EmitSetIndirectBranchVariable(EmitContext&) { | 189 | void EmitSetIndirectBranchVariable(EmitContext&) { |
| 190 | throw NotImplementedException("SPIR-V Instruction"); | 190 | throw LogicError("Unreachable instruction"); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | void EmitGetIndirectBranchVariable(EmitContext&) { | 193 | void EmitGetIndirectBranchVariable(EmitContext&) { |
| 194 | throw NotImplementedException("SPIR-V Instruction"); | 194 | throw LogicError("Unreachable instruction"); |
| 195 | } | ||
| 196 | |||
| 197 | void EmitSetLoopSafetyVariable(EmitContext&) { | ||
| 198 | throw LogicError("Unreachable instruction"); | ||
| 199 | } | ||
| 200 | |||
| 201 | void EmitGetLoopSafetyVariable(EmitContext&) { | ||
| 202 | throw LogicError("Unreachable instruction"); | ||
| 195 | } | 203 | } |
| 196 | 204 | ||
| 197 | Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { | 205 | Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 1181e7b4f..e3e5b03fe 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | |||
| @@ -43,6 +43,8 @@ void EmitSetGotoVariable(EmitContext& ctx); | |||
| 43 | void EmitGetGotoVariable(EmitContext& ctx); | 43 | void EmitGetGotoVariable(EmitContext& ctx); |
| 44 | void EmitSetIndirectBranchVariable(EmitContext& ctx); | 44 | void EmitSetIndirectBranchVariable(EmitContext& ctx); |
| 45 | void EmitGetIndirectBranchVariable(EmitContext& ctx); | 45 | void EmitGetIndirectBranchVariable(EmitContext& ctx); |
| 46 | void EmitSetLoopSafetyVariable(EmitContext& ctx); | ||
| 47 | void EmitGetLoopSafetyVariable(EmitContext& ctx); | ||
| 46 | Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | 48 | Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); |
| 47 | Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | 49 | Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); |
| 48 | Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | 50 | Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); |
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 | ||
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index e54499ba5..a4ba393ef 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | |||
| @@ -48,73 +48,91 @@ struct GotoVariable : FlagTag { | |||
| 48 | u32 index; | 48 | u32 index; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | struct LoopSafetyVariable { | ||
| 52 | LoopSafetyVariable() = default; | ||
| 53 | explicit LoopSafetyVariable(u32 index_) : index{index_} {} | ||
| 54 | |||
| 55 | auto operator<=>(const LoopSafetyVariable&) const noexcept = default; | ||
| 56 | |||
| 57 | u32 index; | ||
| 58 | }; | ||
| 59 | |||
| 51 | struct IndirectBranchVariable { | 60 | struct IndirectBranchVariable { |
| 52 | auto operator<=>(const IndirectBranchVariable&) const noexcept = default; | 61 | auto operator<=>(const IndirectBranchVariable&) const noexcept = default; |
| 53 | }; | 62 | }; |
| 54 | 63 | ||
| 55 | using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, | 64 | using Variant = |
| 56 | OverflowFlagTag, GotoVariable, IndirectBranchVariable>; | 65 | std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, OverflowFlagTag, |
| 57 | using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>; | 66 | GotoVariable, LoopSafetyVariable, IndirectBranchVariable>; |
| 67 | using ValueMap = boost::container::flat_map<IR::Block*, IR::Value>; | ||
| 58 | 68 | ||
| 59 | struct DefTable { | 69 | struct DefTable { |
| 60 | const IR::Value& Def(IR::Block* block, IR::Reg variable) noexcept { | 70 | const IR::Value& Def(IR::Block* block, IR::Reg variable) { |
| 61 | return block->SsaRegValue(variable); | 71 | return block->SsaRegValue(variable); |
| 62 | } | 72 | } |
| 63 | void SetDef(IR::Block* block, IR::Reg variable, const IR::Value& value) noexcept { | 73 | void SetDef(IR::Block* block, IR::Reg variable, const IR::Value& value) { |
| 64 | block->SetSsaRegValue(variable, value); | 74 | block->SetSsaRegValue(variable, value); |
| 65 | } | 75 | } |
| 66 | 76 | ||
| 67 | const IR::Value& Def(IR::Block* block, IR::Pred variable) noexcept { | 77 | const IR::Value& Def(IR::Block* block, IR::Pred variable) { |
| 68 | return preds[IR::PredIndex(variable)][block]; | 78 | return preds[IR::PredIndex(variable)][block]; |
| 69 | } | 79 | } |
| 70 | void SetDef(IR::Block* block, IR::Pred variable, const IR::Value& value) noexcept { | 80 | void SetDef(IR::Block* block, IR::Pred variable, const IR::Value& value) { |
| 71 | preds[IR::PredIndex(variable)].insert_or_assign(block, value); | 81 | preds[IR::PredIndex(variable)].insert_or_assign(block, value); |
| 72 | } | 82 | } |
| 73 | 83 | ||
| 74 | const IR::Value& Def(IR::Block* block, GotoVariable variable) noexcept { | 84 | const IR::Value& Def(IR::Block* block, GotoVariable variable) { |
| 75 | return goto_vars[variable.index][block]; | 85 | return goto_vars[variable.index][block]; |
| 76 | } | 86 | } |
| 77 | void SetDef(IR::Block* block, GotoVariable variable, const IR::Value& value) noexcept { | 87 | void SetDef(IR::Block* block, GotoVariable variable, const IR::Value& value) { |
| 78 | goto_vars[variable.index].insert_or_assign(block, value); | 88 | goto_vars[variable.index].insert_or_assign(block, value); |
| 79 | } | 89 | } |
| 80 | 90 | ||
| 81 | const IR::Value& Def(IR::Block* block, IndirectBranchVariable) noexcept { | 91 | const IR::Value& Def(IR::Block* block, LoopSafetyVariable variable) { |
| 92 | return loop_safety_vars[variable.index][block]; | ||
| 93 | } | ||
| 94 | void SetDef(IR::Block* block, LoopSafetyVariable variable, const IR::Value& value) { | ||
| 95 | loop_safety_vars[variable.index].insert_or_assign(block, value); | ||
| 96 | } | ||
| 97 | |||
| 98 | const IR::Value& Def(IR::Block* block, IndirectBranchVariable) { | ||
| 82 | return indirect_branch_var[block]; | 99 | return indirect_branch_var[block]; |
| 83 | } | 100 | } |
| 84 | void SetDef(IR::Block* block, IndirectBranchVariable, const IR::Value& value) noexcept { | 101 | void SetDef(IR::Block* block, IndirectBranchVariable, const IR::Value& value) { |
| 85 | indirect_branch_var.insert_or_assign(block, value); | 102 | indirect_branch_var.insert_or_assign(block, value); |
| 86 | } | 103 | } |
| 87 | 104 | ||
| 88 | const IR::Value& Def(IR::Block* block, ZeroFlagTag) noexcept { | 105 | const IR::Value& Def(IR::Block* block, ZeroFlagTag) { |
| 89 | return zero_flag[block]; | 106 | return zero_flag[block]; |
| 90 | } | 107 | } |
| 91 | void SetDef(IR::Block* block, ZeroFlagTag, const IR::Value& value) noexcept { | 108 | void SetDef(IR::Block* block, ZeroFlagTag, const IR::Value& value) { |
| 92 | zero_flag.insert_or_assign(block, value); | 109 | zero_flag.insert_or_assign(block, value); |
| 93 | } | 110 | } |
| 94 | 111 | ||
| 95 | const IR::Value& Def(IR::Block* block, SignFlagTag) noexcept { | 112 | const IR::Value& Def(IR::Block* block, SignFlagTag) { |
| 96 | return sign_flag[block]; | 113 | return sign_flag[block]; |
| 97 | } | 114 | } |
| 98 | void SetDef(IR::Block* block, SignFlagTag, const IR::Value& value) noexcept { | 115 | void SetDef(IR::Block* block, SignFlagTag, const IR::Value& value) { |
| 99 | sign_flag.insert_or_assign(block, value); | 116 | sign_flag.insert_or_assign(block, value); |
| 100 | } | 117 | } |
| 101 | 118 | ||
| 102 | const IR::Value& Def(IR::Block* block, CarryFlagTag) noexcept { | 119 | const IR::Value& Def(IR::Block* block, CarryFlagTag) { |
| 103 | return carry_flag[block]; | 120 | return carry_flag[block]; |
| 104 | } | 121 | } |
| 105 | void SetDef(IR::Block* block, CarryFlagTag, const IR::Value& value) noexcept { | 122 | void SetDef(IR::Block* block, CarryFlagTag, const IR::Value& value) { |
| 106 | carry_flag.insert_or_assign(block, value); | 123 | carry_flag.insert_or_assign(block, value); |
| 107 | } | 124 | } |
| 108 | 125 | ||
| 109 | const IR::Value& Def(IR::Block* block, OverflowFlagTag) noexcept { | 126 | const IR::Value& Def(IR::Block* block, OverflowFlagTag) { |
| 110 | return overflow_flag[block]; | 127 | return overflow_flag[block]; |
| 111 | } | 128 | } |
| 112 | void SetDef(IR::Block* block, OverflowFlagTag, const IR::Value& value) noexcept { | 129 | void SetDef(IR::Block* block, OverflowFlagTag, const IR::Value& value) { |
| 113 | overflow_flag.insert_or_assign(block, value); | 130 | overflow_flag.insert_or_assign(block, value); |
| 114 | } | 131 | } |
| 115 | 132 | ||
| 116 | std::array<ValueMap, IR::NUM_USER_PREDS> preds; | 133 | std::array<ValueMap, IR::NUM_USER_PREDS> preds; |
| 117 | boost::container::flat_map<u32, ValueMap> goto_vars; | 134 | boost::container::flat_map<u32, ValueMap> goto_vars; |
| 135 | boost::container::flat_map<u32, ValueMap> loop_safety_vars; | ||
| 118 | ValueMap indirect_branch_var; | 136 | ValueMap indirect_branch_var; |
| 119 | ValueMap zero_flag; | 137 | ValueMap zero_flag; |
| 120 | ValueMap sign_flag; | 138 | ValueMap sign_flag; |
| @@ -134,6 +152,10 @@ IR::Opcode UndefOpcode(const FlagTag&) noexcept { | |||
| 134 | return IR::Opcode::UndefU1; | 152 | return IR::Opcode::UndefU1; |
| 135 | } | 153 | } |
| 136 | 154 | ||
| 155 | IR::Opcode UndefOpcode(const LoopSafetyVariable&) noexcept { | ||
| 156 | return IR::Opcode::UndefU32; | ||
| 157 | } | ||
| 158 | |||
| 137 | IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { | 159 | IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { |
| 138 | return IR::Opcode::UndefU32; | 160 | return IR::Opcode::UndefU32; |
| 139 | } | 161 | } |
| @@ -315,6 +337,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { | |||
| 315 | case IR::Opcode::SetGotoVariable: | 337 | case IR::Opcode::SetGotoVariable: |
| 316 | pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); | 338 | pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); |
| 317 | break; | 339 | break; |
| 340 | case IR::Opcode::SetLoopSafetyVariable: | ||
| 341 | pass.WriteVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block, inst.Arg(0)); | ||
| 342 | break; | ||
| 318 | case IR::Opcode::SetIndirectBranchVariable: | 343 | case IR::Opcode::SetIndirectBranchVariable: |
| 319 | pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0)); | 344 | pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0)); |
| 320 | break; | 345 | break; |
| @@ -343,6 +368,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { | |||
| 343 | case IR::Opcode::GetGotoVariable: | 368 | case IR::Opcode::GetGotoVariable: |
| 344 | inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); | 369 | inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); |
| 345 | break; | 370 | break; |
| 371 | case IR::Opcode::GetLoopSafetyVariable: | ||
| 372 | inst.ReplaceUsesWith(pass.ReadVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block)); | ||
| 373 | break; | ||
| 346 | case IR::Opcode::GetIndirectBranchVariable: | 374 | case IR::Opcode::GetIndirectBranchVariable: |
| 347 | inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block)); | 375 | inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block)); |
| 348 | break; | 376 | break; |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 8eb37a77a..bf063c047 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -467,7 +467,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv; | 469 | VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv; |
| 470 | if (nv_device_diagnostics_config) { | 470 | if (Settings::values.enable_nsight_aftermath && nv_device_diagnostics_config) { |
| 471 | nsight_aftermath_tracker = std::make_unique<NsightAftermathTracker>(); | 471 | nsight_aftermath_tracker = std::make_unique<NsightAftermathTracker>(); |
| 472 | 472 | ||
| 473 | diagnostics_nv = { | 473 | diagnostics_nv = { |
| @@ -781,7 +781,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 781 | test(has_ext_shader_atomic_int64, VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME, false); | 781 | test(has_ext_shader_atomic_int64, VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME, false); |
| 782 | test(has_khr_workgroup_memory_explicit_layout, | 782 | test(has_khr_workgroup_memory_explicit_layout, |
| 783 | VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME, false); | 783 | VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME, false); |
| 784 | if (Settings::values.renderer_debug) { | 784 | if (Settings::values.enable_nsight_aftermath) { |
| 785 | test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, | 785 | test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, |
| 786 | true); | 786 | true); |
| 787 | } | 787 | } |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index a5e032959..dc69574a9 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -824,6 +824,8 @@ void Config::ReadRendererValues() { | |||
| 824 | 824 | ||
| 825 | if (global) { | 825 | if (global) { |
| 826 | ReadBasicSetting(Settings::values.renderer_debug); | 826 | ReadBasicSetting(Settings::values.renderer_debug); |
| 827 | ReadBasicSetting(Settings::values.enable_nsight_aftermath); | ||
| 828 | ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks); | ||
| 827 | } | 829 | } |
| 828 | 830 | ||
| 829 | qt_config->endGroup(); | 831 | qt_config->endGroup(); |
| @@ -1353,6 +1355,8 @@ void Config::SaveRendererValues() { | |||
| 1353 | 1355 | ||
| 1354 | if (global) { | 1356 | if (global) { |
| 1355 | WriteBasicSetting(Settings::values.renderer_debug); | 1357 | WriteBasicSetting(Settings::values.renderer_debug); |
| 1358 | WriteBasicSetting(Settings::values.enable_nsight_aftermath); | ||
| 1359 | WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks); | ||
| 1356 | } | 1360 | } |
| 1357 | 1361 | ||
| 1358 | qt_config->endGroup(); | 1362 | qt_config->endGroup(); |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 8fceb3878..f7e29dbd7 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -45,8 +45,13 @@ void ConfigureDebug::SetConfiguration() { | |||
| 45 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); | 45 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); |
| 46 | ui->enable_cpu_debugging->setEnabled(runtime_lock); | 46 | ui->enable_cpu_debugging->setEnabled(runtime_lock); |
| 47 | ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue()); | 47 | ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue()); |
| 48 | ui->enable_nsight_aftermath->setEnabled(runtime_lock); | ||
| 49 | ui->enable_nsight_aftermath->setChecked(Settings::values.enable_nsight_aftermath.GetValue()); | ||
| 48 | ui->disable_macro_jit->setEnabled(runtime_lock); | 50 | ui->disable_macro_jit->setEnabled(runtime_lock); |
| 49 | ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue()); | 51 | ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue()); |
| 52 | ui->disable_loop_safety_checks->setEnabled(runtime_lock); | ||
| 53 | ui->disable_loop_safety_checks->setChecked( | ||
| 54 | Settings::values.disable_shader_loop_safety_checks.GetValue()); | ||
| 50 | ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); | 55 | ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); |
| 51 | } | 56 | } |
| 52 | 57 | ||
| @@ -61,6 +66,9 @@ void ConfigureDebug::ApplyConfiguration() { | |||
| 61 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); | 66 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); |
| 62 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); | 67 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); |
| 63 | Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); | 68 | Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); |
| 69 | Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked(); | ||
| 70 | Settings::values.disable_shader_loop_safety_checks = | ||
| 71 | ui->disable_loop_safety_checks->isChecked(); | ||
| 64 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); | 72 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); |
| 65 | Settings::values.extended_logging = ui->extended_logging->isChecked(); | 73 | Settings::values.extended_logging = ui->extended_logging->isChecked(); |
| 66 | Debugger::ToggleConsole(); | 74 | Debugger::ToggleConsole(); |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 1260ad6f0..c8baf2921 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -126,6 +126,16 @@ | |||
| 126 | </widget> | 126 | </widget> |
| 127 | </item> | 127 | </item> |
| 128 | <item> | 128 | <item> |
| 129 | <widget class="QCheckBox" name="enable_nsight_aftermath"> | ||
| 130 | <property name="toolTip"> | ||
| 131 | <string>When checked, it enables Nsight Aftermath crash dumps</string> | ||
| 132 | </property> | ||
| 133 | <property name="text"> | ||
| 134 | <string>Enable Nsight Aftermath</string> | ||
| 135 | </property> | ||
| 136 | </widget> | ||
| 137 | </item> | ||
| 138 | <item> | ||
| 129 | <widget class="QCheckBox" name="disable_macro_jit"> | 139 | <widget class="QCheckBox" name="disable_macro_jit"> |
| 130 | <property name="enabled"> | 140 | <property name="enabled"> |
| 131 | <bool>true</bool> | 141 | <bool>true</bool> |
| @@ -138,6 +148,16 @@ | |||
| 138 | </property> | 148 | </property> |
| 139 | </widget> | 149 | </widget> |
| 140 | </item> | 150 | </item> |
| 151 | <item> | ||
| 152 | <widget class="QCheckBox" name="disable_loop_safety_checks"> | ||
| 153 | <property name="toolTip"> | ||
| 154 | <string>When checked, it executes shaders without loop logic changes</string> | ||
| 155 | </property> | ||
| 156 | <property name="text"> | ||
| 157 | <string>Disable Loop safety checks</string> | ||
| 158 | </property> | ||
| 159 | </widget> | ||
| 160 | </item> | ||
| 141 | </layout> | 161 | </layout> |
| 142 | </widget> | 162 | </widget> |
| 143 | </item> | 163 | </item> |
| @@ -252,11 +272,17 @@ | |||
| 252 | <tabstops> | 272 | <tabstops> |
| 253 | <tabstop>log_filter_edit</tabstop> | 273 | <tabstop>log_filter_edit</tabstop> |
| 254 | <tabstop>toggle_console</tabstop> | 274 | <tabstop>toggle_console</tabstop> |
| 275 | <tabstop>extended_logging</tabstop> | ||
| 255 | <tabstop>open_log_button</tabstop> | 276 | <tabstop>open_log_button</tabstop> |
| 256 | <tabstop>homebrew_args_edit</tabstop> | 277 | <tabstop>homebrew_args_edit</tabstop> |
| 257 | <tabstop>enable_graphics_debugging</tabstop> | 278 | <tabstop>enable_graphics_debugging</tabstop> |
| 279 | <tabstop>enable_nsight_aftermath</tabstop> | ||
| 280 | <tabstop>disable_macro_jit</tabstop> | ||
| 281 | <tabstop>disable_loop_safety_checks</tabstop> | ||
| 258 | <tabstop>reporting_services</tabstop> | 282 | <tabstop>reporting_services</tabstop> |
| 259 | <tabstop>quest_flag</tabstop> | 283 | <tabstop>quest_flag</tabstop> |
| 284 | <tabstop>use_debug_asserts</tabstop> | ||
| 285 | <tabstop>use_auto_stub</tabstop> | ||
| 260 | </tabstops> | 286 | </tabstops> |
| 261 | <resources/> | 287 | <resources/> |
| 262 | <connections/> | 288 | <connections/> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 3e22fee37..763df6dd6 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -444,6 +444,8 @@ void Config::ReadValues() { | |||
| 444 | // Renderer | 444 | // Renderer |
| 445 | ReadSetting("Renderer", Settings::values.renderer_backend); | 445 | ReadSetting("Renderer", Settings::values.renderer_backend); |
| 446 | ReadSetting("Renderer", Settings::values.renderer_debug); | 446 | ReadSetting("Renderer", Settings::values.renderer_debug); |
| 447 | ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); | ||
| 448 | ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); | ||
| 447 | ReadSetting("Renderer", Settings::values.vulkan_device); | 449 | ReadSetting("Renderer", Settings::values.vulkan_device); |
| 448 | 450 | ||
| 449 | ReadSetting("Renderer", Settings::values.fullscreen_mode); | 451 | ReadSetting("Renderer", Settings::values.fullscreen_mode); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 88d33ecab..a6ca7b6cd 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -221,6 +221,14 @@ backend = | |||
| 221 | # 0 (default): Disabled, 1: Enabled | 221 | # 0 (default): Disabled, 1: Enabled |
| 222 | debug = | 222 | debug = |
| 223 | 223 | ||
| 224 | # Enable Nsight Aftermath crash dumps | ||
| 225 | # 0 (default): Disabled, 1: Enabled | ||
| 226 | nsight_aftermath = | ||
| 227 | |||
| 228 | # Disable shader loop safety checks, executing the shader without loop logic changes | ||
| 229 | # 0 (default): Disabled, 1: Enabled | ||
| 230 | disable_shader_loop_safety_checks = | ||
| 231 | |||
| 224 | # Which Vulkan physical device to use (defaults to 0) | 232 | # Which Vulkan physical device to use (defaults to 0) |
| 225 | vulkan_device = | 233 | vulkan_device = |
| 226 | 234 | ||