summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
-rw-r--r--src/shader_recompiler/frontend/maxwell/maxwell.inc3
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp204
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---")
244INST(STL, "STL", "1110 1111 0101 0---") 244INST(STL, "STL", "1110 1111 0101 0---")
245INST(STP, "STP", "1110 1110 1010 0---") 245INST(STP, "STP", "1110 1110 1010 0---")
246INST(STS, "STS", "1110 1111 0101 1---") 246INST(STS, "STS", "1110 1111 0101 1---")
247INST(SUATOM_cas, "SUATOM", "1110 1010 ---- ----") 247INST(SUATOM, "SUATOM", "1110 1010 0--- ----")
248INST(SUATOM_cas, "SUATOM_cas", "1110 1010 1--- ----")
248INST(SULD, "SULD", "1110 1011 000- ----") 249INST(SULD, "SULD", "1110 1011 000- ----")
249INST(SURED, "SURED", "1110 1011 010- ----") 250INST(SURED, "SURED", "1110 1011 010- ----")
250INST(SUST, "SUST", "1110 1011 001- ----") 251INST(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
252void TranslatorVisitor::SURED(u64) {
253 ThrowNotImplemented(Opcode::SURED);
254}
255
256void TranslatorVisitor::SYNC(u64) { 252void 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
13namespace Shader::Maxwell {
14namespace {
15enum class Type : u64 {
16 _1D,
17 BUFFER_1D,
18 ARRAY_1D,
19 _2D,
20 ARRAY_2D,
21 _3D,
22};
23
24enum class Size : u64 {
25 U32,
26 S32,
27 U64,
28 S64,
29 F32FTZRN,
30 F16x2FTZRN,
31 SD32,
32 SD64,
33};
34
35enum class AtomicOp : u64 {
36 ADD,
37 MIN,
38 MAX,
39 INC,
40 DEC,
41 AND,
42 OR,
43 XOR,
44 EXCH,
45};
46
47enum class Clamp : u64 {
48 IGN,
49 Default,
50 TRAP,
51};
52
53TextureType 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
71IR::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
85IR::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
112ImageFormat 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
124bool 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
135void 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
165void 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
185void 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