diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp | 75 |
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 @@ | |||
| 7 | namespace Shader::Backend::SPIRV { | 7 | namespace Shader::Backend::SPIRV { |
| 8 | 8 | ||
| 9 | Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | 9 | Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { |
| 10 | if (inst->HasAssociatedPseudoOperation()) { | 10 | Id result{}; |
| 11 | throw NotImplementedException("Pseudo-operations on IAdd32"); | 11 | if (IR::Inst* const carry{inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) { |
| 12 | const Id carry_type{ctx.TypeStruct(ctx.U32[1], ctx.U32[1])}; | ||
| 13 | const Id carry_result{ctx.OpIAddCarry(carry_type, a, b)}; | ||
| 14 | result = ctx.OpCompositeExtract(ctx.U32[1], carry_result, 0U); | ||
| 15 | |||
| 16 | const Id carry_value{ctx.OpCompositeExtract(ctx.U32[1], carry_result, 1U)}; | ||
| 17 | carry->SetDefinition(ctx.OpINotEqual(ctx.U1, carry_value, ctx.u32_zero_value)); | ||
| 18 | carry->Invalidate(); | ||
| 19 | } else { | ||
| 20 | result = ctx.OpIAdd(ctx.U32[1], a, b); | ||
| 12 | } | 21 | } |
| 13 | return ctx.OpIAdd(ctx.U32[1], a, b); | 22 | if (IR::Inst* const zero{inst->GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)}) { |
| 23 | zero->SetDefinition(ctx.OpIEqual(ctx.U1, result, ctx.u32_zero_value)); | ||
| 24 | zero->Invalidate(); | ||
| 25 | } | ||
| 26 | if (IR::Inst* const sign{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)}) { | ||
| 27 | sign->SetDefinition(ctx.OpSLessThan(ctx.U1, result, ctx.u32_zero_value)); | ||
| 28 | sign->Invalidate(); | ||
| 29 | } | ||
| 30 | if (IR::Inst * overflow{inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) { | ||
| 31 | // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c | ||
| 32 | constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())}; | ||
| 33 | const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)}; | ||
| 34 | const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Constant(ctx.U32[1], s32_max), a)}; | ||
| 35 | |||
| 36 | const Id positive_test{ctx.OpSGreaterThan(ctx.U1, b, sub_a)}; | ||
| 37 | const Id negative_test{ctx.OpSLessThan(ctx.U1, b, sub_a)}; | ||
| 38 | const Id carry_flag{ctx.OpSelect(ctx.U1, is_positive, positive_test, negative_test)}; | ||
| 39 | overflow->SetDefinition(carry_flag); | ||
| 40 | overflow->Invalidate(); | ||
| 41 | } | ||
| 42 | return result; | ||
| 14 | } | 43 | } |
| 15 | 44 | ||
| 16 | void EmitIAdd64(EmitContext&) { | 45 | void EmitIAdd64(EmitContext&) { |
| @@ -49,16 +78,16 @@ void EmitShiftRightArithmetic32(EmitContext&) { | |||
| 49 | throw NotImplementedException("SPIR-V Instruction"); | 78 | throw NotImplementedException("SPIR-V Instruction"); |
| 50 | } | 79 | } |
| 51 | 80 | ||
| 52 | void EmitBitwiseAnd32(EmitContext&) { | 81 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) { |
| 53 | throw NotImplementedException("SPIR-V Instruction"); | 82 | return ctx.OpBitwiseAnd(ctx.U32[1], a, b); |
| 54 | } | 83 | } |
| 55 | 84 | ||
| 56 | void EmitBitwiseOr32(EmitContext&) { | 85 | Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b) { |
| 57 | throw NotImplementedException("SPIR-V Instruction"); | 86 | return ctx.OpBitwiseOr(ctx.U32[1], a, b); |
| 58 | } | 87 | } |
| 59 | 88 | ||
| 60 | void EmitBitwiseXor32(EmitContext&) { | 89 | Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b) { |
| 61 | throw NotImplementedException("SPIR-V Instruction"); | 90 | return ctx.OpBitwiseXor(ctx.U32[1], a, b); |
| 62 | } | 91 | } |
| 63 | 92 | ||
| 64 | void EmitBitFieldInsert(EmitContext&) { | 93 | void EmitBitFieldInsert(EmitContext&) { |
| @@ -77,36 +106,36 @@ Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) { | |||
| 77 | return ctx.OpSLessThan(ctx.U1, lhs, rhs); | 106 | return ctx.OpSLessThan(ctx.U1, lhs, rhs); |
| 78 | } | 107 | } |
| 79 | 108 | ||
| 80 | void EmitULessThan(EmitContext&) { | 109 | Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs) { |
| 81 | throw NotImplementedException("SPIR-V Instruction"); | 110 | return ctx.OpULessThan(ctx.U1, lhs, rhs); |
| 82 | } | 111 | } |
| 83 | 112 | ||
| 84 | void EmitIEqual(EmitContext&) { | 113 | Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs) { |
| 85 | throw NotImplementedException("SPIR-V Instruction"); | 114 | return ctx.OpIEqual(ctx.U1, lhs, rhs); |
| 86 | } | 115 | } |
| 87 | 116 | ||
| 88 | void EmitSLessThanEqual(EmitContext&) { | 117 | Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs) { |
| 89 | throw NotImplementedException("SPIR-V Instruction"); | 118 | return ctx.OpSLessThanEqual(ctx.U1, lhs, rhs); |
| 90 | } | 119 | } |
| 91 | 120 | ||
| 92 | void EmitULessThanEqual(EmitContext&) { | 121 | Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs) { |
| 93 | throw NotImplementedException("SPIR-V Instruction"); | 122 | return ctx.OpULessThanEqual(ctx.U1, lhs, rhs); |
| 94 | } | 123 | } |
| 95 | 124 | ||
| 96 | Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { | 125 | Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { |
| 97 | return ctx.OpSGreaterThan(ctx.U1, lhs, rhs); | 126 | return ctx.OpSGreaterThan(ctx.U1, lhs, rhs); |
| 98 | } | 127 | } |
| 99 | 128 | ||
| 100 | void EmitUGreaterThan(EmitContext&) { | 129 | Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { |
| 101 | throw NotImplementedException("SPIR-V Instruction"); | 130 | return ctx.OpUGreaterThan(ctx.U1, lhs, rhs); |
| 102 | } | 131 | } |
| 103 | 132 | ||
| 104 | void EmitINotEqual(EmitContext&) { | 133 | Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs) { |
| 105 | throw NotImplementedException("SPIR-V Instruction"); | 134 | return ctx.OpINotEqual(ctx.U1, lhs, rhs); |
| 106 | } | 135 | } |
| 107 | 136 | ||
| 108 | void EmitSGreaterThanEqual(EmitContext&) { | 137 | Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { |
| 109 | throw NotImplementedException("SPIR-V Instruction"); | 138 | return ctx.OpSGreaterThanEqual(ctx.U1, lhs, rhs); |
| 110 | } | 139 | } |
| 111 | 140 | ||
| 112 | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { | 141 | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { |