summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2021-02-21 21:50:14 +0100
committerameerj <52414509+ameerj@users.noreply.github.com>2021-07-23 03:51:22 +0200
commit704c6f353f68745168902c6c66c04bb730bd30e6 (patch)
tree71ed9654de41b5828ae2613167537d39499d2f3b /src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
parentshader: Add denorm flush support (diff)
downloadyuzu-704c6f353f68745168902c6c66c04bb730bd30e6.tar
yuzu-704c6f353f68745168902c6c66c04bb730bd30e6.tar.gz
yuzu-704c6f353f68745168902c6c66c04bb730bd30e6.tar.bz2
yuzu-704c6f353f68745168902c6c66c04bb730bd30e6.tar.lz
yuzu-704c6f353f68745168902c6c66c04bb730bd30e6.tar.xz
yuzu-704c6f353f68745168902c6c66c04bb730bd30e6.tar.zst
yuzu-704c6f353f68745168902c6c66c04bb730bd30e6.zip
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp75
1 files changed, 52 insertions, 23 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
index 22117a4ee..4c0b5990d 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
@@ -7,10 +7,39 @@
namespace Shader::Backend::SPIRV {
Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
- if (inst->HasAssociatedPseudoOperation()) {
- throw NotImplementedException("Pseudo-operations on IAdd32");
+ Id result{};
+ if (IR::Inst* const carry{inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) {
+ const Id carry_type{ctx.TypeStruct(ctx.U32[1], ctx.U32[1])};
+ const Id carry_result{ctx.OpIAddCarry(carry_type, a, b)};
+ result = ctx.OpCompositeExtract(ctx.U32[1], carry_result, 0U);
+
+ const Id carry_value{ctx.OpCompositeExtract(ctx.U32[1], carry_result, 1U)};
+ carry->SetDefinition(ctx.OpINotEqual(ctx.U1, carry_value, ctx.u32_zero_value));
+ carry->Invalidate();
+ } else {
+ result = ctx.OpIAdd(ctx.U32[1], a, b);
}
- return ctx.OpIAdd(ctx.U32[1], a, b);
+ if (IR::Inst* const zero{inst->GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)}) {
+ zero->SetDefinition(ctx.OpIEqual(ctx.U1, result, ctx.u32_zero_value));
+ zero->Invalidate();
+ }
+ if (IR::Inst* const sign{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)}) {
+ sign->SetDefinition(ctx.OpSLessThan(ctx.U1, result, ctx.u32_zero_value));
+ sign->Invalidate();
+ }
+ if (IR::Inst * overflow{inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) {
+ // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c
+ constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())};
+ const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)};
+ const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Constant(ctx.U32[1], s32_max), a)};
+
+ const Id positive_test{ctx.OpSGreaterThan(ctx.U1, b, sub_a)};
+ const Id negative_test{ctx.OpSLessThan(ctx.U1, b, sub_a)};
+ const Id carry_flag{ctx.OpSelect(ctx.U1, is_positive, positive_test, negative_test)};
+ overflow->SetDefinition(carry_flag);
+ overflow->Invalidate();
+ }
+ return result;
}
void EmitIAdd64(EmitContext&) {
@@ -49,16 +78,16 @@ void EmitShiftRightArithmetic32(EmitContext&) {
throw NotImplementedException("SPIR-V Instruction");
}
-void EmitBitwiseAnd32(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) {
+ return ctx.OpBitwiseAnd(ctx.U32[1], a, b);
}
-void EmitBitwiseOr32(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b) {
+ return ctx.OpBitwiseOr(ctx.U32[1], a, b);
}
-void EmitBitwiseXor32(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b) {
+ return ctx.OpBitwiseXor(ctx.U32[1], a, b);
}
void EmitBitFieldInsert(EmitContext&) {
@@ -77,36 +106,36 @@ Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpSLessThan(ctx.U1, lhs, rhs);
}
-void EmitULessThan(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpULessThan(ctx.U1, lhs, rhs);
}
-void EmitIEqual(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpIEqual(ctx.U1, lhs, rhs);
}
-void EmitSLessThanEqual(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpSLessThanEqual(ctx.U1, lhs, rhs);
}
-void EmitULessThanEqual(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpULessThanEqual(ctx.U1, lhs, rhs);
}
Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpSGreaterThan(ctx.U1, lhs, rhs);
}
-void EmitUGreaterThan(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpUGreaterThan(ctx.U1, lhs, rhs);
}
-void EmitINotEqual(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpINotEqual(ctx.U1, lhs, rhs);
}
-void EmitSGreaterThanEqual(EmitContext&) {
- throw NotImplementedException("SPIR-V Instruction");
+Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
+ return ctx.OpSGreaterThanEqual(ctx.U1, lhs, rhs);
}
Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {