diff options
Diffstat (limited to 'src/shader_recompiler/frontend')
6 files changed, 128 insertions, 10 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index ae3354c66..33819dd36 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -112,7 +112,27 @@ void IREmitter::SetPred(IR::Pred pred, const U1& value) { | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { | 114 | U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { |
| 115 | return Inst<U32>(Opcode::GetCbuf, binding, byte_offset); | 115 | return Inst<U32>(Opcode::GetCbufU32, binding, byte_offset); |
| 116 | } | ||
| 117 | |||
| 118 | UAny IREmitter::GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, | ||
| 119 | bool is_signed) { | ||
| 120 | switch (bitsize) { | ||
| 121 | case 8: | ||
| 122 | return Inst<U32>(is_signed ? Opcode::GetCbufS8 : Opcode::GetCbufU8, binding, byte_offset); | ||
| 123 | case 16: | ||
| 124 | return Inst<U32>(is_signed ? Opcode::GetCbufS16 : Opcode::GetCbufU16, binding, byte_offset); | ||
| 125 | case 32: | ||
| 126 | return Inst<U32>(Opcode::GetCbufU32, binding, byte_offset); | ||
| 127 | case 64: | ||
| 128 | return Inst<U64>(Opcode::GetCbufU64, binding, byte_offset); | ||
| 129 | default: | ||
| 130 | throw InvalidArgument("Invalid bit size {}", bitsize); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | F32 IREmitter::GetFloatCbuf(const U32& binding, const U32& byte_offset) { | ||
| 135 | return Inst<F32>(Opcode::GetCbufF32, binding, byte_offset); | ||
| 116 | } | 136 | } |
| 117 | 137 | ||
| 118 | U1 IREmitter::GetZFlag() { | 138 | U1 IREmitter::GetZFlag() { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index cb2a7710a..e4d110540 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -47,6 +47,9 @@ public: | |||
| 47 | void SetGotoVariable(u32 id, const U1& value); | 47 | void SetGotoVariable(u32 id, const U1& value); |
| 48 | 48 | ||
| 49 | [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); | 49 | [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); |
| 50 | [[nodiscard]] UAny GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, | ||
| 51 | bool is_signed); | ||
| 52 | [[nodiscard]] F32 GetFloatCbuf(const U32& binding, const U32& byte_offset); | ||
| 50 | 53 | ||
| 51 | [[nodiscard]] U1 GetZFlag(); | 54 | [[nodiscard]] U1 GetZFlag(); |
| 52 | [[nodiscard]] U1 GetSFlag(); | 55 | [[nodiscard]] U1 GetSFlag(); |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index aa011fab1..64bd495ed 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -21,7 +21,13 @@ OPCODE(GetPred, U1, Pred | |||
| 21 | OPCODE(SetPred, Void, Pred, U1, ) | 21 | OPCODE(SetPred, Void, Pred, U1, ) |
| 22 | OPCODE(GetGotoVariable, U1, U32, ) | 22 | OPCODE(GetGotoVariable, U1, U32, ) |
| 23 | OPCODE(SetGotoVariable, Void, U32, U1, ) | 23 | OPCODE(SetGotoVariable, Void, U32, U1, ) |
| 24 | OPCODE(GetCbuf, U32, U32, U32, ) | 24 | OPCODE(GetCbufU8, U32, U32, U32, ) |
| 25 | OPCODE(GetCbufS8, U32, U32, U32, ) | ||
| 26 | OPCODE(GetCbufU16, U32, U32, U32, ) | ||
| 27 | OPCODE(GetCbufS16, U32, U32, U32, ) | ||
| 28 | OPCODE(GetCbufU32, U32, U32, U32, ) | ||
| 29 | OPCODE(GetCbufF32, F32, U32, U32, ) | ||
| 30 | OPCODE(GetCbufU64, U64, U32, U32, ) | ||
| 25 | OPCODE(GetAttribute, U32, Attribute, ) | 31 | OPCODE(GetAttribute, U32, Attribute, ) |
| 26 | OPCODE(SetAttribute, Void, Attribute, U32, ) | 32 | OPCODE(SetAttribute, Void, Attribute, U32, ) |
| 27 | OPCODE(GetAttributeIndexed, U32, U32, ) | 33 | OPCODE(GetAttributeIndexed, U32, U32, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index a5a0e1a9b..7564aeeb2 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -56,25 +56,32 @@ IR::F32 TranslatorVisitor::GetFloatReg39(u64 insn) { | |||
| 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); | 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | 59 | static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { |
| 60 | union { | 60 | union { |
| 61 | u64 raw; | 61 | u64 raw; |
| 62 | BitField<20, 14, s64> offset; | 62 | BitField<20, 14, s64> offset; |
| 63 | BitField<34, 5, u64> binding; | 63 | BitField<34, 5, u64> binding; |
| 64 | } const cbuf{insn}; | 64 | } const cbuf{insn}; |
| 65 | |||
| 65 | if (cbuf.binding >= 18) { | 66 | if (cbuf.binding >= 18) { |
| 66 | throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding); | 67 | throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding); |
| 67 | } | 68 | } |
| 68 | if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) { | 69 | if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) { |
| 69 | throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset); | 70 | throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset); |
| 70 | } | 71 | } |
| 71 | const IR::U32 binding{ir.Imm32(static_cast<u32>(cbuf.binding))}; | 72 | const IR::Value binding{static_cast<u32>(cbuf.binding)}; |
| 72 | const IR::U32 byte_offset{ir.Imm32(static_cast<u32>(cbuf.offset) * 4)}; | 73 | const IR::Value byte_offset{static_cast<u32>(cbuf.offset) * 4}; |
| 74 | return {IR::U32{binding}, IR::U32{byte_offset}}; | ||
| 75 | } | ||
| 76 | |||
| 77 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | ||
| 78 | const auto[binding, byte_offset]{CbufAddr(insn)}; | ||
| 73 | return ir.GetCbuf(binding, byte_offset); | 79 | return ir.GetCbuf(binding, byte_offset); |
| 74 | } | 80 | } |
| 75 | 81 | ||
| 76 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { | 82 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { |
| 77 | return ir.BitCast<IR::F32>(GetCbuf(insn)); | 83 | const auto[binding, byte_offset]{CbufAddr(insn)}; |
| 84 | return ir.GetFloatCbuf(binding, byte_offset); | ||
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | 87 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { |
| @@ -83,6 +90,7 @@ IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | |||
| 83 | BitField<20, 19, u64> value; | 90 | BitField<20, 19, u64> value; |
| 84 | BitField<56, 1, u64> is_negative; | 91 | BitField<56, 1, u64> is_negative; |
| 85 | } const imm{insn}; | 92 | } const imm{insn}; |
| 93 | |||
| 86 | if (imm.is_negative != 0) { | 94 | if (imm.is_negative != 0) { |
| 87 | const s64 raw{static_cast<s64>(imm.value)}; | 95 | const s64 raw{static_cast<s64>(imm.value)}; |
| 88 | return ir.Imm32(static_cast<s32>(-(1LL << 19) + raw)); | 96 | return ir.Imm32(static_cast<s32>(-(1LL << 19) + raw)); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_constant.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_constant.cpp new file mode 100644 index 000000000..39becf93c --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_constant.cpp | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/bit_field.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 8 | |||
| 9 | namespace Shader::Maxwell { | ||
| 10 | namespace { | ||
| 11 | enum class Mode : u64 { | ||
| 12 | Default, | ||
| 13 | IL, | ||
| 14 | IS, | ||
| 15 | ISL, | ||
| 16 | }; | ||
| 17 | |||
| 18 | enum class Size : u64 { | ||
| 19 | U8, | ||
| 20 | S8, | ||
| 21 | U16, | ||
| 22 | S16, | ||
| 23 | B32, | ||
| 24 | B64, | ||
| 25 | }; | ||
| 26 | |||
| 27 | std::pair<IR::U32, IR::U32> Slot(IR::IREmitter& ir, Mode mode, const IR::U32& imm_index, | ||
| 28 | const IR::U32& reg, const IR::U32& imm) { | ||
| 29 | switch (mode) { | ||
| 30 | case Mode::Default: | ||
| 31 | return {imm_index, ir.IAdd(reg, imm)}; | ||
| 32 | default: | ||
| 33 | break; | ||
| 34 | } | ||
| 35 | throw NotImplementedException("Mode {}", mode); | ||
| 36 | } | ||
| 37 | } // Anonymous namespace | ||
| 38 | |||
| 39 | void TranslatorVisitor::LDC(u64 insn) { | ||
| 40 | union { | ||
| 41 | u64 raw; | ||
| 42 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 43 | BitField<8, 8, IR::Reg> src_reg; | ||
| 44 | BitField<20, 16, s64> offset; | ||
| 45 | BitField<36, 5, u64> index; | ||
| 46 | BitField<44, 2, Mode> mode; | ||
| 47 | BitField<48, 3, Size> size; | ||
| 48 | } const ldc{insn}; | ||
| 49 | |||
| 50 | const IR::U32 imm_index{ir.Imm32(static_cast<u32>(ldc.index))}; | ||
| 51 | const IR::U32 reg{X(ldc.src_reg)}; | ||
| 52 | const IR::U32 imm{ir.Imm32(static_cast<s32>(ldc.offset))}; | ||
| 53 | const auto [index, offset]{Slot(ir, ldc.mode, imm_index, reg, imm)}; | ||
| 54 | switch (ldc.size) { | ||
| 55 | case Size::U8: | ||
| 56 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 8, false)); | ||
| 57 | break; | ||
| 58 | case Size::S8: | ||
| 59 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 8, true)); | ||
| 60 | break; | ||
| 61 | case Size::U16: | ||
| 62 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 16, false)); | ||
| 63 | break; | ||
| 64 | case Size::S16: | ||
| 65 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 16, true)); | ||
| 66 | break; | ||
| 67 | case Size::B32: | ||
| 68 | X(ldc.dest_reg, ir.GetCbuf(index, offset, 32, false)); | ||
| 69 | break; | ||
| 70 | case Size::B64: { | ||
| 71 | if (!IR::IsAligned(ldc.dest_reg, 2)) { | ||
| 72 | throw NotImplementedException("Unaligned destination register"); | ||
| 73 | } | ||
| 74 | const IR::Value vector{ir.UnpackUint2x32(ir.GetCbuf(index, offset, 64, false))}; | ||
| 75 | for (int i = 0; i < 2; ++i) { | ||
| 76 | X(ldc.dest_reg + i, IR::U32{ir.CompositeExtract(vector, i)}); | ||
| 77 | } | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | default: | ||
| 81 | throw NotImplementedException("Invalid size {}", ldc.size.Value()); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index ff429c126..5b153acff 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -425,10 +425,6 @@ void TranslatorVisitor::LD(u64) { | |||
| 425 | ThrowNotImplemented(Opcode::LD); | 425 | ThrowNotImplemented(Opcode::LD); |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | void TranslatorVisitor::LDC(u64) { | ||
| 429 | ThrowNotImplemented(Opcode::LDC); | ||
| 430 | } | ||
| 431 | |||
| 432 | void TranslatorVisitor::LDL(u64) { | 428 | void TranslatorVisitor::LDL(u64) { |
| 433 | ThrowNotImplemented(Opcode::LDL); | 429 | ThrowNotImplemented(Opcode::LDL); |
| 434 | } | 430 | } |