diff options
| author | 2021-05-23 04:12:08 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:29 -0400 | |
| commit | 33bebc34127305e107d54e0bdd0a6806676abf2f (patch) | |
| tree | f83852123a3ecd40822623bebc91bf74fcbfd4d1 /src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp | |
| parent | spirv: Implement int8 and int16 conversion fallbacks (diff) | |
| download | yuzu-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.cpp | 38 |
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 | ||
| 173 | Id EmitSMin32(EmitContext& ctx, Id a, Id b) { | 173 | Id 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 | ||
| 177 | Id EmitUMin32(EmitContext& ctx, Id a, Id b) { | 183 | Id EmitUMin32(EmitContext& ctx, Id a, Id b) { |
| @@ -179,7 +185,13 @@ Id EmitUMin32(EmitContext& ctx, Id a, Id b) { | |||
| 179 | } | 185 | } |
| 180 | 186 | ||
| 181 | Id EmitSMax32(EmitContext& ctx, Id a, Id b) { | 187 | Id 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 | ||
| 185 | Id EmitUMax32(EmitContext& ctx, Id a, Id b) { | 197 | Id EmitUMax32(EmitContext& ctx, Id a, Id b) { |
| @@ -187,14 +199,32 @@ Id EmitUMax32(EmitContext& ctx, Id a, Id b) { | |||
| 187 | } | 199 | } |
| 188 | 200 | ||
| 189 | Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) { | 201 | Id 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 | ||
| 196 | Id EmitUClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) { | 221 | Id 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; |