summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glsl/var_alloc.cpp
diff options
context:
space:
mode:
authorGravatar ameerj2021-05-30 17:27:00 -0400
committerGravatar ameerj2021-07-22 21:51:37 -0400
commit1269a0cf8b3844c1a9bb06c843a7698b0a9643d5 (patch)
treea0716589fa3952bdeb0f1d19b4bb455d9cdd86e5 /src/shader_recompiler/backend/glsl/var_alloc.cpp
parentglsl: Fix ATOM and implement ATOMS (diff)
downloadyuzu-1269a0cf8b3844c1a9bb06c843a7698b0a9643d5.tar.gz
yuzu-1269a0cf8b3844c1a9bb06c843a7698b0a9643d5.tar.xz
yuzu-1269a0cf8b3844c1a9bb06c843a7698b0a9643d5.zip
glsl: Rework variable allocator to allow for variable reuse
Diffstat (limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')
-rw-r--r--src/shader_recompiler/backend/glsl/var_alloc.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
new file mode 100644
index 000000000..8c6944f07
--- /dev/null
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -0,0 +1,290 @@
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 <string>
6#include <string_view>
7
8#include <fmt/format.h>
9
10#include "shader_recompiler/backend/glsl/var_alloc.h"
11#include "shader_recompiler/exception.h"
12#include "shader_recompiler/frontend/ir/value.h"
13
14namespace Shader::Backend::GLSL {
15namespace {
16std::string TypePrefix(GlslVarType type) {
17 switch (type) {
18 case GlslVarType::U1:
19 return "b_";
20 case GlslVarType::F16x2:
21 return "f16x2_";
22 case GlslVarType::U32:
23 return "u_";
24 case GlslVarType::S32:
25 return "s_";
26 case GlslVarType::F32:
27 return "f_";
28 case GlslVarType::S64:
29 return "s64_";
30 case GlslVarType::U64:
31 return "u64_";
32 case GlslVarType::F64:
33 return "d_";
34 case GlslVarType::U32x2:
35 return "u2_";
36 case GlslVarType::F32x2:
37 return "f2_";
38 case GlslVarType::U32x3:
39 return "u3_";
40 case GlslVarType::F32x3:
41 return "f3_";
42 case GlslVarType::U32x4:
43 return "u4_";
44 case GlslVarType::F32x4:
45 return "f4_";
46 case GlslVarType::Void:
47 return "";
48 default:
49 throw NotImplementedException("Type {}", type);
50 }
51}
52
53std::string FormatFloat(std::string_view value, IR::Type type) {
54 // TODO: Confirm FP64 nan/inf
55 if (type == IR::Type::F32) {
56 if (value == "nan") {
57 return "uintBitsToFloat(0x7fc00000)";
58 }
59 if (value == "inf") {
60 return "uintBitsToFloat(0x7f800000)";
61 }
62 if (value == "-inf") {
63 return "uintBitsToFloat(0xff800000)";
64 }
65 }
66 if (value.find_first_of('e') != std::string_view::npos) {
67 // scientific notation
68 const auto cast{type == IR::Type::F32 ? "float" : "double"};
69 return fmt::format("{}({})", cast, value);
70 }
71 const bool needs_dot{value.find_first_of('.') == std::string_view::npos};
72 const bool needs_suffix{!value.ends_with('f')};
73 const auto suffix{type == IR::Type::F32 ? "f" : "lf"};
74 return fmt::format("{}{}{}", value, needs_dot ? "." : "", needs_suffix ? suffix : "");
75}
76
77std::string MakeImm(const IR::Value& value) {
78 switch (value.Type()) {
79 case IR::Type::U1:
80 return fmt::format("{}", value.U1() ? "true" : "false");
81 case IR::Type::U32:
82 return fmt::format("{}u", value.U32());
83 case IR::Type::F32:
84 return FormatFloat(fmt::format("{}", value.F32()), IR::Type::F32);
85 case IR::Type::U64:
86 return fmt::format("{}ul", value.U64());
87 case IR::Type::F64:
88 return FormatFloat(fmt::format("{}", value.F64()), IR::Type::F64);
89 case IR::Type::Void:
90 return "";
91 default:
92 throw NotImplementedException("Immediate type {}", value.Type());
93 }
94}
95} // Anonymous namespace
96
97std::string VarAlloc::Representation(u32 index, GlslVarType type) const {
98 const auto prefix{TypePrefix(type)};
99 return fmt::format("{}{}", prefix, index);
100}
101
102std::string VarAlloc::Representation(Id id) const {
103 return Representation(id.index, id.type);
104}
105
106std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
107 if (inst.HasUses()) {
108 inst.SetDefinition<Id>(Alloc(type));
109 return Representation(inst.Definition<Id>());
110 } else {
111 Id id{};
112 id.type.Assign(type);
113 // id.is_null.Assign(1);
114 GetUseTracker(type).uses_temp = true;
115 inst.SetDefinition<Id>(id);
116 }
117 return Representation(inst.Definition<Id>());
118}
119
120std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
121 return Define(inst, RegType(type));
122}
123
124std::string VarAlloc::Consume(const IR::Value& value) {
125 return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive());
126}
127
128std::string VarAlloc::ConsumeInst(IR::Inst& inst) {
129 inst.DestructiveRemoveUsage();
130 if (!inst.HasUses()) {
131 Free(inst.Definition<Id>());
132 }
133 return Representation(inst.Definition<Id>());
134}
135
136std::string VarAlloc::GetGlslType(IR::Type type) const {
137 return GetGlslType(RegType(type));
138}
139
140Id VarAlloc::Alloc(GlslVarType type) {
141 auto& use_tracker{GetUseTracker(type)};
142 if (use_tracker.num_used < NUM_VARS) {
143 for (size_t var = 1; var < NUM_VARS; ++var) {
144 if (use_tracker.var_use[var]) {
145 continue;
146 }
147 use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
148 use_tracker.var_use[var] = true;
149 Id ret{};
150 ret.is_valid.Assign(1);
151 ret.type.Assign(type);
152 ret.index.Assign(static_cast<u32>(var));
153 return ret;
154 }
155 }
156 throw NotImplementedException("Variable spilling");
157}
158
159void VarAlloc::Free(Id id) {
160 if (id.is_valid == 0) {
161 // throw LogicError("Freeing invalid variable");
162 return;
163 }
164 auto& use_tracker{GetUseTracker(id.type)};
165 use_tracker.var_use[id.index] = false;
166}
167
168GlslVarType VarAlloc::RegType(IR::Type type) const {
169 switch (type) {
170 case IR::Type::U1:
171 return GlslVarType::U1;
172 case IR::Type::U32:
173 return GlslVarType::U32;
174 case IR::Type::F32:
175 return GlslVarType::F32;
176 case IR::Type::U64:
177 return GlslVarType::U64;
178 case IR::Type::F64:
179 return GlslVarType::F64;
180 default:
181 throw NotImplementedException("IR type {}", type);
182 }
183}
184
185std::string VarAlloc::GetGlslType(GlslVarType type) const {
186 switch (type) {
187 case GlslVarType::U1:
188 return "bool ";
189 case GlslVarType::F16x2:
190 return "f16vec2 ";
191 case GlslVarType::U32:
192 return "uint ";
193 case GlslVarType::S32:
194 return "int ";
195 case GlslVarType::F32:
196 return "float ";
197 case GlslVarType::S64:
198 return "int64_t ";
199 case GlslVarType::U64:
200 return "uint64_t ";
201 case GlslVarType::F64:
202 return "double ";
203 case GlslVarType::U32x2:
204 return "uvec2 ";
205 case GlslVarType::F32x2:
206 return "vec2 ";
207 case GlslVarType::U32x3:
208 return "uvec3 ";
209 case GlslVarType::F32x3:
210 return "vec3 ";
211 case GlslVarType::U32x4:
212 return "uvec4 ";
213 case GlslVarType::F32x4:
214 return "vec4 ";
215 case GlslVarType::Void:
216 return "";
217 default:
218 throw NotImplementedException("Type {}", type);
219 }
220}
221
222VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
223 switch (type) {
224 case GlslVarType::U1:
225 return var_bool;
226 case GlslVarType::U32:
227 return var_u32;
228 case GlslVarType::S32:
229 return var_s32;
230 case GlslVarType::F32:
231 return var_f32;
232 case GlslVarType::S64:
233 return var_s64;
234 case GlslVarType::U64:
235 return var_u64;
236 case GlslVarType::F64:
237 return var_f64;
238 case GlslVarType::U32x2:
239 return var_u32x2;
240 case GlslVarType::F32x2:
241 return var_f32x2;
242 case GlslVarType::U32x3:
243 return var_u32x3;
244 case GlslVarType::F32x3:
245 return var_f32x3;
246 case GlslVarType::U32x4:
247 return var_u32x4;
248 case GlslVarType::F32x4:
249 return var_f32x4;
250 default:
251 throw NotImplementedException("Type {}", type);
252 }
253}
254
255const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
256 switch (type) {
257 case GlslVarType::U1:
258 return var_bool;
259 case GlslVarType::F16x2:
260 return var_f16x2;
261 case GlslVarType::U32:
262 return var_u32;
263 case GlslVarType::S32:
264 return var_s32;
265 case GlslVarType::F32:
266 return var_f32;
267 case GlslVarType::S64:
268 return var_s64;
269 case GlslVarType::U64:
270 return var_u64;
271 case GlslVarType::F64:
272 return var_f64;
273 case GlslVarType::U32x2:
274 return var_u32x2;
275 case GlslVarType::F32x2:
276 return var_f32x2;
277 case GlslVarType::U32x3:
278 return var_u32x3;
279 case GlslVarType::F32x3:
280 return var_f32x3;
281 case GlslVarType::U32x4:
282 return var_u32x4;
283 case GlslVarType::F32x4:
284 return var_f32x4;
285 default:
286 throw NotImplementedException("Type {}", type);
287 }
288}
289
290} // namespace Shader::Backend::GLSL