diff options
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp index 0d248c020..f629e7167 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp | |||
| @@ -44,6 +44,17 @@ u32 NumElements(Size size) { | |||
| 44 | } | 44 | } |
| 45 | throw InvalidArgument("Invalid size {}", size); | 45 | throw InvalidArgument("Invalid size {}", size); |
| 46 | } | 46 | } |
| 47 | |||
| 48 | template <typename F> | ||
| 49 | void HandleIndexed(TranslatorVisitor& v, IR::Reg index_reg, u32 num_elements, F&& f) { | ||
| 50 | const IR::U32 index_value{v.X(index_reg)}; | ||
| 51 | for (u32 element = 0; element < num_elements; ++element) { | ||
| 52 | const IR::U32 final_offset{ | ||
| 53 | element == 0 ? index_value : IR::U32{v.ir.IAdd(index_value, v.ir.Imm32(element * 4U))}}; | ||
| 54 | f(element, final_offset); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 47 | } // Anonymous namespace | 58 | } // Anonymous namespace |
| 48 | 59 | ||
| 49 | void TranslatorVisitor::ALD(u64 insn) { | 60 | void TranslatorVisitor::ALD(u64 insn) { |
| @@ -70,18 +81,15 @@ void TranslatorVisitor::ALD(u64 insn) { | |||
| 70 | throw NotImplementedException("Unaligned absolute offset {}", offset); | 81 | throw NotImplementedException("Unaligned absolute offset {}", offset); |
| 71 | } | 82 | } |
| 72 | const u32 num_elements{NumElements(ald.size)}; | 83 | const u32 num_elements{NumElements(ald.size)}; |
| 73 | if (ald.index_reg != IR::Reg::RZ) { | 84 | if (ald.index_reg == IR::Reg::RZ) { |
| 74 | const IR::U32 index_value = X(ald.index_reg); | ||
| 75 | for (u32 element = 0; element < num_elements; ++element) { | 85 | for (u32 element = 0; element < num_elements; ++element) { |
| 76 | const IR::U32 final_offset = | 86 | F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element})); |
| 77 | element == 0 ? index_value : IR::U32{ir.IAdd(index_value, ir.Imm32(element * 4U))}; | ||
| 78 | F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset)); | ||
| 79 | } | 87 | } |
| 80 | return; | 88 | return; |
| 81 | } | 89 | } |
| 82 | for (u32 element = 0; element < num_elements; ++element) { | 90 | HandleIndexed(*this, ald.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { |
| 83 | F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element})); | 91 | F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset)); |
| 84 | } | 92 | }); |
| 85 | } | 93 | } |
| 86 | 94 | ||
| 87 | void TranslatorVisitor::AST(u64 insn) { | 95 | void TranslatorVisitor::AST(u64 insn) { |
| @@ -110,18 +118,15 @@ void TranslatorVisitor::AST(u64 insn) { | |||
| 110 | throw NotImplementedException("Unaligned absolute offset {}", offset); | 118 | throw NotImplementedException("Unaligned absolute offset {}", offset); |
| 111 | } | 119 | } |
| 112 | const u32 num_elements{NumElements(ast.size)}; | 120 | const u32 num_elements{NumElements(ast.size)}; |
| 113 | if (ast.index_reg != IR::Reg::RZ) { | 121 | if (ast.index_reg == IR::Reg::RZ) { |
| 114 | const IR::U32 index_value = X(ast.index_reg); | ||
| 115 | for (u32 element = 0; element < num_elements; ++element) { | 122 | for (u32 element = 0; element < num_elements; ++element) { |
| 116 | const IR::U32 final_offset = | 123 | ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element)); |
| 117 | element == 0 ? index_value : IR::U32{ir.IAdd(index_value, ir.Imm32(element * 4U))}; | ||
| 118 | ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element)); | ||
| 119 | } | 124 | } |
| 120 | return; | 125 | return; |
| 121 | } | 126 | } |
| 122 | for (u32 element = 0; element < num_elements; ++element) { | 127 | HandleIndexed(*this, ast.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { |
| 123 | ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element)); | 128 | ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element)); |
| 124 | } | 129 | }); |
| 125 | } | 130 | } |
| 126 | 131 | ||
| 127 | void TranslatorVisitor::IPA(u64 insn) { | 132 | void TranslatorVisitor::IPA(u64 insn) { |