diff options
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
4 files changed, 207 insertions, 5 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/maxwell.inc b/src/shader_recompiler/frontend/maxwell/maxwell.inc index c759bd4d4..2fee591bb 100644 --- a/src/shader_recompiler/frontend/maxwell/maxwell.inc +++ b/src/shader_recompiler/frontend/maxwell/maxwell.inc | |||
| @@ -244,7 +244,8 @@ INST(STG, "STG", "1110 1110 1101 1---") | |||
| 244 | INST(STL, "STL", "1110 1111 0101 0---") | 244 | INST(STL, "STL", "1110 1111 0101 0---") |
| 245 | INST(STP, "STP", "1110 1110 1010 0---") | 245 | INST(STP, "STP", "1110 1110 1010 0---") |
| 246 | INST(STS, "STS", "1110 1111 0101 1---") | 246 | INST(STS, "STS", "1110 1111 0101 1---") |
| 247 | INST(SUATOM_cas, "SUATOM", "1110 1010 ---- ----") | 247 | INST(SUATOM, "SUATOM", "1110 1010 0--- ----") |
| 248 | INST(SUATOM_cas, "SUATOM_cas", "1110 1010 1--- ----") | ||
| 248 | INST(SULD, "SULD", "1110 1011 000- ----") | 249 | INST(SULD, "SULD", "1110 1011 000- ----") |
| 249 | INST(SURED, "SURED", "1110 1011 010- ----") | 250 | INST(SURED, "SURED", "1110 1011 010- ----") |
| 250 | INST(SUST, "SUST", "1110 1011 001- ----") | 251 | INST(SUST, "SUST", "1110 1011 001- ----") |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index bf7d1bae8..335e4f24f 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -303,6 +303,7 @@ public: | |||
| 303 | void STL(u64 insn); | 303 | void STL(u64 insn); |
| 304 | void STP(u64 insn); | 304 | void STP(u64 insn); |
| 305 | void STS(u64 insn); | 305 | void STS(u64 insn); |
| 306 | void SUATOM(u64 insn); | ||
| 306 | void SUATOM_cas(u64 insn); | 307 | void SUATOM_cas(u64 insn); |
| 307 | void SULD(u64 insn); | 308 | void SULD(u64 insn); |
| 308 | void SURED(u64 insn); | 309 | void SURED(u64 insn); |
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 a4f99bbbe..7e26ab359 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -249,10 +249,6 @@ void TranslatorVisitor::SUATOM_cas(u64) { | |||
| 249 | ThrowNotImplemented(Opcode::SUATOM_cas); | 249 | ThrowNotImplemented(Opcode::SUATOM_cas); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | void TranslatorVisitor::SURED(u64) { | ||
| 253 | ThrowNotImplemented(Opcode::SURED); | ||
| 254 | } | ||
| 255 | |||
| 256 | void TranslatorVisitor::SYNC(u64) { | 252 | void TranslatorVisitor::SYNC(u64) { |
| 257 | ThrowNotImplemented(Opcode::SYNC); | 253 | ThrowNotImplemented(Opcode::SYNC); |
| 258 | } | 254 | } |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp new file mode 100644 index 000000000..994bdc3eb --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp | |||
| @@ -0,0 +1,204 @@ | |||
| 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 <array> | ||
| 6 | #include <bit> | ||
| 7 | |||
| 8 | #include "common/bit_field.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "shader_recompiler/frontend/ir/modifiers.h" | ||
| 11 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 12 | |||
| 13 | namespace Shader::Maxwell { | ||
| 14 | namespace { | ||
| 15 | enum class Type : u64 { | ||
| 16 | _1D, | ||
| 17 | BUFFER_1D, | ||
| 18 | ARRAY_1D, | ||
| 19 | _2D, | ||
| 20 | ARRAY_2D, | ||
| 21 | _3D, | ||
| 22 | }; | ||
| 23 | |||
| 24 | enum class Size : u64 { | ||
| 25 | U32, | ||
| 26 | S32, | ||
| 27 | U64, | ||
| 28 | S64, | ||
| 29 | F32FTZRN, | ||
| 30 | F16x2FTZRN, | ||
| 31 | SD32, | ||
| 32 | SD64, | ||
| 33 | }; | ||
| 34 | |||
| 35 | enum class AtomicOp : u64 { | ||
| 36 | ADD, | ||
| 37 | MIN, | ||
| 38 | MAX, | ||
| 39 | INC, | ||
| 40 | DEC, | ||
| 41 | AND, | ||
| 42 | OR, | ||
| 43 | XOR, | ||
| 44 | EXCH, | ||
| 45 | }; | ||
| 46 | |||
| 47 | enum class Clamp : u64 { | ||
| 48 | IGN, | ||
| 49 | Default, | ||
| 50 | TRAP, | ||
| 51 | }; | ||
| 52 | |||
| 53 | TextureType GetType(Type type) { | ||
| 54 | switch (type) { | ||
| 55 | case Type::_1D: | ||
| 56 | return TextureType::Color1D; | ||
| 57 | case Type::BUFFER_1D: | ||
| 58 | return TextureType::Buffer; | ||
| 59 | case Type::ARRAY_1D: | ||
| 60 | return TextureType::ColorArray1D; | ||
| 61 | case Type::_2D: | ||
| 62 | return TextureType::Color2D; | ||
| 63 | case Type::ARRAY_2D: | ||
| 64 | return TextureType::ColorArray2D; | ||
| 65 | case Type::_3D: | ||
| 66 | return TextureType::Color3D; | ||
| 67 | } | ||
| 68 | throw NotImplementedException("Invalid type {}", type); | ||
| 69 | } | ||
| 70 | |||
| 71 | IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, Type type) { | ||
| 72 | const auto array{[&](int index) { | ||
| 73 | return v.ir.BitFieldExtract(v.X(reg + index), v.ir.Imm32(0), v.ir.Imm32(16)); | ||
| 74 | }}; | ||
| 75 | switch (type) { | ||
| 76 | case Type::_1D: | ||
| 77 | case Type::BUFFER_1D: | ||
| 78 | return v.X(reg); | ||
| 79 | default: | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | throw NotImplementedException("Invalid type {}", type); | ||
| 83 | } | ||
| 84 | |||
| 85 | IR::Value ApplyAtomicOp(IR::IREmitter& ir, const IR::U32& handle, const IR::Value& coords, | ||
| 86 | const IR::Value& op_b, IR::TextureInstInfo info, AtomicOp op, | ||
| 87 | bool is_signed) { | ||
| 88 | switch (op) { | ||
| 89 | case AtomicOp::ADD: | ||
| 90 | return ir.ImageAtomicIAdd(handle, coords, op_b, info); | ||
| 91 | case AtomicOp::MIN: | ||
| 92 | return ir.ImageAtomicIMin(handle, coords, op_b, is_signed, info); | ||
| 93 | case AtomicOp::MAX: | ||
| 94 | return ir.ImageAtomicIMax(handle, coords, op_b, is_signed, info); | ||
| 95 | case AtomicOp::INC: | ||
| 96 | return ir.ImageAtomicInc(handle, coords, op_b, info); | ||
| 97 | case AtomicOp::DEC: | ||
| 98 | return ir.ImageAtomicDec(handle, coords, op_b, info); | ||
| 99 | case AtomicOp::AND: | ||
| 100 | return ir.ImageAtomicAnd(handle, coords, op_b, info); | ||
| 101 | case AtomicOp::OR: | ||
| 102 | return ir.ImageAtomicOr(handle, coords, op_b, info); | ||
| 103 | case AtomicOp::XOR: | ||
| 104 | return ir.ImageAtomicXor(handle, coords, op_b, info); | ||
| 105 | case AtomicOp::EXCH: | ||
| 106 | return ir.ImageAtomicExchange(handle, coords, op_b, info); | ||
| 107 | default: | ||
| 108 | throw NotImplementedException("Atomic Operation {}", op); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | ImageFormat Format(Size size) { | ||
| 113 | switch (size) { | ||
| 114 | case Size::U32: | ||
| 115 | case Size::S32: | ||
| 116 | case Size::SD32: | ||
| 117 | return ImageFormat::R32_UINT; | ||
| 118 | default: | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | throw NotImplementedException("Invalid size {}", size); | ||
| 122 | } | ||
| 123 | |||
| 124 | bool IsSizeInt32(Size size) { | ||
| 125 | switch (size) { | ||
| 126 | case Size::U32: | ||
| 127 | case Size::S32: | ||
| 128 | case Size::SD32: | ||
| 129 | return true; | ||
| 130 | default: | ||
| 131 | return false; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | void ImageAtomOp(TranslatorVisitor& v, IR::Reg dest_reg, IR::Reg operand_reg, IR::Reg coord_reg, | ||
| 136 | IR::Reg bindless_reg, AtomicOp op, Clamp clamp, Size size, Type type, | ||
| 137 | u64 bound_offset, bool is_bindless, bool write_result) { | ||
| 138 | if (clamp != Clamp::IGN) { | ||
| 139 | throw NotImplementedException("Clamp {}", clamp); | ||
| 140 | } | ||
| 141 | if (!IsSizeInt32(size)) { | ||
| 142 | throw NotImplementedException("Size {}", size); | ||
| 143 | } | ||
| 144 | const bool is_signed{size == Size::S32}; | ||
| 145 | const ImageFormat format{Format(size)}; | ||
| 146 | const TextureType tex_type{GetType(type)}; | ||
| 147 | const IR::Value coords{MakeCoords(v, coord_reg, type)}; | ||
| 148 | |||
| 149 | const IR::U32 handle{is_bindless != 0 ? v.X(bindless_reg) | ||
| 150 | : v.ir.Imm32(static_cast<u32>(bound_offset * 4))}; | ||
| 151 | IR::TextureInstInfo info{}; | ||
| 152 | info.type.Assign(tex_type); | ||
| 153 | info.image_format.Assign(format); | ||
| 154 | |||
| 155 | // TODO: float/64-bit operand | ||
| 156 | const IR::Value op_b{v.X(operand_reg)}; | ||
| 157 | const IR::Value color{ApplyAtomicOp(v.ir, handle, coords, op_b, info, op, is_signed)}; | ||
| 158 | |||
| 159 | if (write_result) { | ||
| 160 | v.X(dest_reg, IR::U32{color}); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } // Anonymous namespace | ||
| 164 | |||
| 165 | void TranslatorVisitor::SUATOM(u64 insn) { | ||
| 166 | union { | ||
| 167 | u64 raw; | ||
| 168 | BitField<54, 1, u64> is_bindless; | ||
| 169 | BitField<29, 4, AtomicOp> op; | ||
| 170 | BitField<33, 3, Type> type; | ||
| 171 | BitField<51, 3, Size> size; | ||
| 172 | BitField<49, 2, Clamp> clamp; | ||
| 173 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 174 | BitField<8, 8, IR::Reg> coord_reg; | ||
| 175 | BitField<20, 8, IR::Reg> operand_reg; | ||
| 176 | BitField<36, 13, u64> bound_offset; // !is_bindless | ||
| 177 | BitField<39, 8, IR::Reg> bindless_reg; // is_bindless | ||
| 178 | } const suatom{insn}; | ||
| 179 | |||
| 180 | ImageAtomOp(*this, suatom.dest_reg, suatom.operand_reg, suatom.coord_reg, suatom.bindless_reg, | ||
| 181 | suatom.op, suatom.clamp, suatom.size, suatom.type, suatom.bound_offset, | ||
| 182 | suatom.is_bindless != 0, true); | ||
| 183 | } | ||
| 184 | |||
| 185 | void TranslatorVisitor::SURED(u64 insn) { | ||
| 186 | // TODO: confirm offsets | ||
| 187 | union { | ||
| 188 | u64 raw; | ||
| 189 | BitField<51, 1, u64> is_bound; | ||
| 190 | BitField<21, 3, AtomicOp> op; | ||
| 191 | BitField<33, 3, Type> type; | ||
| 192 | BitField<20, 3, Size> size; | ||
| 193 | BitField<49, 2, Clamp> clamp; | ||
| 194 | BitField<0, 8, IR::Reg> operand_reg; | ||
| 195 | BitField<8, 8, IR::Reg> coord_reg; | ||
| 196 | BitField<36, 13, u64> bound_offset; // is_bound | ||
| 197 | BitField<39, 8, IR::Reg> bindless_reg; // !is_bound | ||
| 198 | } const sured{insn}; | ||
| 199 | ImageAtomOp(*this, IR::Reg::RZ, sured.operand_reg, sured.coord_reg, sured.bindless_reg, | ||
| 200 | sured.op, sured.clamp, sured.size, sured.type, sured.bound_offset, | ||
| 201 | sured.is_bound == 0, false); | ||
| 202 | } | ||
| 203 | |||
| 204 | } // namespace Shader::Maxwell | ||