summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-23 04:12:08 -0300
committerGravatar ameerj2021-07-22 21:51:29 -0400
commit33bebc34127305e107d54e0bdd0a6806676abf2f (patch)
treef83852123a3ecd40822623bebc91bf74fcbfd4d1 /src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
parentspirv: Implement int8 and int16 conversion fallbacks (diff)
downloadyuzu-33bebc34127305e107d54e0bdd0a6806676abf2f.tar.gz
yuzu-33bebc34127305e107d54e0bdd0a6806676abf2f.tar.xz
yuzu-33bebc34127305e107d54e0bdd0a6806676abf2f.zip
spirv: Add integer clamping workarounds
Workaround more bugs on Nvidia's OpenGL SPIR-V compiler.
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
index cd5b1f42c..86e6a4f3b 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
@@ -171,7 +171,13 @@ Id EmitFindUMsb32(EmitContext& ctx, Id value) {
171} 171}
172 172
173Id EmitSMin32(EmitContext& ctx, Id a, Id b) { 173Id EmitSMin32(EmitContext& ctx, Id a, Id b) {
174 return ctx.OpSMin(ctx.U32[1], a, b); 174 const bool is_broken{ctx.profile.has_broken_signed_operations};
175 if (is_broken) {
176 a = ctx.OpBitcast(ctx.S32[1], a);
177 b = ctx.OpBitcast(ctx.S32[1], b);
178 }
179 const Id result{ctx.OpSMin(ctx.U32[1], a, b)};
180 return is_broken ? ctx.OpBitcast(ctx.U32[1], result) : result;
175} 181}
176 182
177Id EmitUMin32(EmitContext& ctx, Id a, Id b) { 183Id EmitUMin32(EmitContext& ctx, Id a, Id b) {
@@ -179,7 +185,13 @@ Id EmitUMin32(EmitContext& ctx, Id a, Id b) {
179} 185}
180 186
181Id EmitSMax32(EmitContext& ctx, Id a, Id b) { 187Id EmitSMax32(EmitContext& ctx, Id a, Id b) {
182 return ctx.OpSMax(ctx.U32[1], a, b); 188 const bool is_broken{ctx.profile.has_broken_signed_operations};
189 if (is_broken) {
190 a = ctx.OpBitcast(ctx.S32[1], a);
191 b = ctx.OpBitcast(ctx.S32[1], b);
192 }
193 const Id result{ctx.OpSMax(ctx.U32[1], a, b)};
194 return is_broken ? ctx.OpBitcast(ctx.U32[1], result) : result;
183} 195}
184 196
185Id EmitUMax32(EmitContext& ctx, Id a, Id b) { 197Id EmitUMax32(EmitContext& ctx, Id a, Id b) {
@@ -187,14 +199,32 @@ Id EmitUMax32(EmitContext& ctx, Id a, Id b) {
187} 199}
188 200
189Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) { 201Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) {
190 const Id result{ctx.OpSClamp(ctx.U32[1], value, min, max)}; 202 Id result{};
203 if (ctx.profile.has_broken_signed_operations || ctx.profile.has_broken_spirv_clamp) {
204 value = ctx.OpBitcast(ctx.S32[1], value);
205 min = ctx.OpBitcast(ctx.S32[1], min);
206 max = ctx.OpBitcast(ctx.S32[1], max);
207 if (ctx.profile.has_broken_spirv_clamp) {
208 result = ctx.OpSMax(ctx.S32[1], ctx.OpSMin(ctx.S32[1], value, max), min);
209 } else {
210 result = ctx.OpSClamp(ctx.S32[1], value, min, max);
211 }
212 result = ctx.OpBitcast(ctx.U32[1], result);
213 } else {
214 result = ctx.OpSClamp(ctx.U32[1], value, min, max);
215 }
191 SetZeroFlag(ctx, inst, result); 216 SetZeroFlag(ctx, inst, result);
192 SetSignFlag(ctx, inst, result); 217 SetSignFlag(ctx, inst, result);
193 return result; 218 return result;
194} 219}
195 220
196Id EmitUClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) { 221Id EmitUClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) {
197 const Id result{ctx.OpUClamp(ctx.U32[1], value, min, max)}; 222 Id result{};
223 if (ctx.profile.has_broken_spirv_clamp) {
224 result = ctx.OpUMax(ctx.U32[1], ctx.OpUMin(ctx.U32[1], value, max), min);
225 } else {
226 result = ctx.OpUClamp(ctx.U32[1], value, min, max);
227 }
198 SetZeroFlag(ctx, inst, result); 228 SetZeroFlag(ctx, inst, result);
199 SetSignFlag(ctx, inst, result); 229 SetSignFlag(ctx, inst, result);
200 return result; 230 return result;