diff options
18 files changed, 213 insertions, 127 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index fbd4ec6dc..802527255 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -74,9 +74,10 @@ add_library(shader_recompiler STATIC | |||
| 74 | frontend/maxwell/translate/impl/integer_short_multiply_add.cpp | 74 | frontend/maxwell/translate/impl/integer_short_multiply_add.cpp |
| 75 | frontend/maxwell/translate/impl/load_store_attribute.cpp | 75 | frontend/maxwell/translate/impl/load_store_attribute.cpp |
| 76 | frontend/maxwell/translate/impl/load_store_memory.cpp | 76 | frontend/maxwell/translate/impl/load_store_memory.cpp |
| 77 | frontend/maxwell/translate/impl/not_implemented.cpp | 77 | frontend/maxwell/translate/impl/move_predicate_to_register.cpp |
| 78 | frontend/maxwell/translate/impl/move_register.cpp | 78 | frontend/maxwell/translate/impl/move_register.cpp |
| 79 | frontend/maxwell/translate/impl/move_special_register.cpp | 79 | frontend/maxwell/translate/impl/move_special_register.cpp |
| 80 | frontend/maxwell/translate/impl/not_implemented.cpp | ||
| 80 | frontend/maxwell/translate/translate.cpp | 81 | frontend/maxwell/translate/translate.cpp |
| 81 | frontend/maxwell/translate/translate.h | 82 | frontend/maxwell/translate/translate.h |
| 82 | ir_opt/collect_shader_info_pass.cpp | 83 | ir_opt/collect_shader_info_pass.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index de624a151..922e294a7 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -110,7 +110,7 @@ void EmitCompositeExtractF64x3(EmitContext& ctx); | |||
| 110 | void EmitCompositeExtractF64x4(EmitContext& ctx); | 110 | void EmitCompositeExtractF64x4(EmitContext& ctx); |
| 111 | void EmitSelect8(EmitContext& ctx); | 111 | void EmitSelect8(EmitContext& ctx); |
| 112 | void EmitSelect16(EmitContext& ctx); | 112 | void EmitSelect16(EmitContext& ctx); |
| 113 | void EmitSelect32(EmitContext& ctx); | 113 | Id EmitSelect32(EmitContext& ctx, Id cond, Id true_value, Id false_value); |
| 114 | void EmitSelect64(EmitContext& ctx); | 114 | void EmitSelect64(EmitContext& ctx); |
| 115 | void EmitBitCastU16F16(EmitContext& ctx); | 115 | void EmitBitCastU16F16(EmitContext& ctx); |
| 116 | Id EmitBitCastU32F32(EmitContext& ctx, Id value); | 116 | Id EmitBitCastU32F32(EmitContext& ctx, Id value); |
| @@ -130,9 +130,9 @@ void EmitGetZeroFromOp(EmitContext& ctx); | |||
| 130 | void EmitGetSignFromOp(EmitContext& ctx); | 130 | void EmitGetSignFromOp(EmitContext& ctx); |
| 131 | void EmitGetCarryFromOp(EmitContext& ctx); | 131 | void EmitGetCarryFromOp(EmitContext& ctx); |
| 132 | void EmitGetOverflowFromOp(EmitContext& ctx); | 132 | void EmitGetOverflowFromOp(EmitContext& ctx); |
| 133 | void EmitFPAbs16(EmitContext& ctx); | 133 | Id EmitFPAbs16(EmitContext& ctx, Id value); |
| 134 | void EmitFPAbs32(EmitContext& ctx); | 134 | Id EmitFPAbs32(EmitContext& ctx, Id value); |
| 135 | void EmitFPAbs64(EmitContext& ctx); | 135 | Id EmitFPAbs64(EmitContext& ctx, Id value); |
| 136 | Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | 136 | Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); |
| 137 | Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | 137 | Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); |
| 138 | Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | 138 | Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); |
| @@ -146,9 +146,9 @@ void EmitFPMin64(EmitContext& ctx); | |||
| 146 | Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | 146 | Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); |
| 147 | Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | 147 | Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); |
| 148 | Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | 148 | Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); |
| 149 | void EmitFPNeg16(EmitContext& ctx); | 149 | Id EmitFPNeg16(EmitContext& ctx, Id value); |
| 150 | void EmitFPNeg32(EmitContext& ctx); | 150 | Id EmitFPNeg32(EmitContext& ctx, Id value); |
| 151 | void EmitFPNeg64(EmitContext& ctx); | 151 | Id EmitFPNeg64(EmitContext& ctx, Id value); |
| 152 | void EmitFPRecip32(EmitContext& ctx); | 152 | void EmitFPRecip32(EmitContext& ctx); |
| 153 | void EmitFPRecip64(EmitContext& ctx); | 153 | void EmitFPRecip64(EmitContext& ctx); |
| 154 | void EmitFPRecipSqrt32(EmitContext& ctx); | 154 | void EmitFPRecipSqrt32(EmitContext& ctx); |
| @@ -161,9 +161,9 @@ void EmitFPExp2NotReduced(EmitContext& ctx); | |||
| 161 | void EmitFPCos(EmitContext& ctx); | 161 | void EmitFPCos(EmitContext& ctx); |
| 162 | void EmitFPCosNotReduced(EmitContext& ctx); | 162 | void EmitFPCosNotReduced(EmitContext& ctx); |
| 163 | void EmitFPLog2(EmitContext& ctx); | 163 | void EmitFPLog2(EmitContext& ctx); |
| 164 | void EmitFPSaturate16(EmitContext& ctx); | 164 | Id EmitFPSaturate16(EmitContext& ctx, Id value); |
| 165 | void EmitFPSaturate32(EmitContext& ctx); | 165 | Id EmitFPSaturate32(EmitContext& ctx, Id value); |
| 166 | void EmitFPSaturate64(EmitContext& ctx); | 166 | Id EmitFPSaturate64(EmitContext& ctx, Id value); |
| 167 | Id EmitFPRoundEven16(EmitContext& ctx, Id value); | 167 | Id EmitFPRoundEven16(EmitContext& ctx, Id value); |
| 168 | Id EmitFPRoundEven32(EmitContext& ctx, Id value); | 168 | Id EmitFPRoundEven32(EmitContext& ctx, Id value); |
| 169 | Id EmitFPRoundEven64(EmitContext& ctx, Id value); | 169 | Id EmitFPRoundEven64(EmitContext& ctx, Id value); |
| @@ -186,21 +186,21 @@ void EmitIAbs32(EmitContext& ctx); | |||
| 186 | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); | 186 | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); |
| 187 | void EmitShiftRightLogical32(EmitContext& ctx); | 187 | void EmitShiftRightLogical32(EmitContext& ctx); |
| 188 | void EmitShiftRightArithmetic32(EmitContext& ctx); | 188 | void EmitShiftRightArithmetic32(EmitContext& ctx); |
| 189 | void EmitBitwiseAnd32(EmitContext& ctx); | 189 | Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b); |
| 190 | void EmitBitwiseOr32(EmitContext& ctx); | 190 | Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b); |
| 191 | void EmitBitwiseXor32(EmitContext& ctx); | 191 | Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b); |
| 192 | void EmitBitFieldInsert(EmitContext& ctx); | 192 | void EmitBitFieldInsert(EmitContext& ctx); |
| 193 | void EmitBitFieldSExtract(EmitContext& ctx); | 193 | void EmitBitFieldSExtract(EmitContext& ctx); |
| 194 | Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); | 194 | Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); |
| 195 | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); | 195 | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); |
| 196 | void EmitULessThan(EmitContext& ctx); | 196 | Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs); |
| 197 | void EmitIEqual(EmitContext& ctx); | 197 | Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 198 | void EmitSLessThanEqual(EmitContext& ctx); | 198 | Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 199 | void EmitULessThanEqual(EmitContext& ctx); | 199 | Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 200 | Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); | 200 | Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); |
| 201 | void EmitUGreaterThan(EmitContext& ctx); | 201 | Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs); |
| 202 | void EmitINotEqual(EmitContext& ctx); | 202 | Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 203 | void EmitSGreaterThanEqual(EmitContext& ctx); | 203 | Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 204 | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | 204 | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 205 | void EmitLogicalOr(EmitContext& ctx); | 205 | void EmitLogicalOr(EmitContext& ctx); |
| 206 | void EmitLogicalAnd(EmitContext& ctx); | 206 | void EmitLogicalAnd(EmitContext& ctx); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp index c9687de37..47f87054b 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp | |||
| @@ -12,37 +12,21 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) { | |||
| 12 | if (flags.no_contraction) { | 12 | if (flags.no_contraction) { |
| 13 | ctx.Decorate(op, spv::Decoration::NoContraction); | 13 | ctx.Decorate(op, spv::Decoration::NoContraction); |
| 14 | } | 14 | } |
| 15 | switch (flags.rounding) { | ||
| 16 | case IR::FpRounding::DontCare: | ||
| 17 | break; | ||
| 18 | case IR::FpRounding::RN: | ||
| 19 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTE); | ||
| 20 | break; | ||
| 21 | case IR::FpRounding::RM: | ||
| 22 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTN); | ||
| 23 | break; | ||
| 24 | case IR::FpRounding::RP: | ||
| 25 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTP); | ||
| 26 | break; | ||
| 27 | case IR::FpRounding::RZ: | ||
| 28 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTZ); | ||
| 29 | break; | ||
| 30 | } | ||
| 31 | return op; | 15 | return op; |
| 32 | } | 16 | } |
| 33 | 17 | ||
| 34 | } // Anonymous namespace | 18 | } // Anonymous namespace |
| 35 | 19 | ||
| 36 | void EmitFPAbs16(EmitContext&) { | 20 | Id EmitFPAbs16(EmitContext& ctx, Id value) { |
| 37 | throw NotImplementedException("SPIR-V Instruction"); | 21 | return ctx.OpFAbs(ctx.F16[1], value); |
| 38 | } | 22 | } |
| 39 | 23 | ||
| 40 | void EmitFPAbs32(EmitContext&) { | 24 | Id EmitFPAbs32(EmitContext& ctx, Id value) { |
| 41 | throw NotImplementedException("SPIR-V Instruction"); | 25 | return ctx.OpFAbs(ctx.F32[1], value); |
| 42 | } | 26 | } |
| 43 | 27 | ||
| 44 | void EmitFPAbs64(EmitContext&) { | 28 | Id EmitFPAbs64(EmitContext& ctx, Id value) { |
| 45 | throw NotImplementedException("SPIR-V Instruction"); | 29 | return ctx.OpFAbs(ctx.F64[1], value); |
| 46 | } | 30 | } |
| 47 | 31 | ||
| 48 | Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | 32 | Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { |
| @@ -97,16 +81,16 @@ Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | |||
| 97 | return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b)); | 81 | return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b)); |
| 98 | } | 82 | } |
| 99 | 83 | ||
| 100 | void EmitFPNeg16(EmitContext&) { | 84 | Id EmitFPNeg16(EmitContext& ctx, Id value) { |
| 101 | throw NotImplementedException("SPIR-V Instruction"); | 85 | return ctx.OpFNegate(ctx.F16[1], value); |
| 102 | } | 86 | } |
| 103 | 87 | ||
| 104 | void EmitFPNeg32(EmitContext&) { | 88 | Id EmitFPNeg32(EmitContext& ctx, Id value) { |
| 105 | throw NotImplementedException("SPIR-V Instruction"); | 89 | return ctx.OpFNegate(ctx.F32[1], value); |
| 106 | } | 90 | } |
| 107 | 91 | ||
| 108 | void EmitFPNeg64(EmitContext&) { | 92 | Id EmitFPNeg64(EmitContext& ctx, Id value) { |
| 109 | throw NotImplementedException("SPIR-V Instruction"); | 93 | return ctx.OpFNegate(ctx.F64[1], value); |
| 110 | } | 94 | } |
| 111 | 95 | ||
| 112 | void EmitFPRecip32(EmitContext&) { | 96 | void EmitFPRecip32(EmitContext&) { |
| @@ -157,16 +141,22 @@ void EmitFPLog2(EmitContext&) { | |||
| 157 | throw NotImplementedException("SPIR-V Instruction"); | 141 | throw NotImplementedException("SPIR-V Instruction"); |
| 158 | } | 142 | } |
| 159 | 143 | ||
| 160 | void EmitFPSaturate16(EmitContext&) { | 144 | Id EmitFPSaturate16(EmitContext& ctx, Id value) { |
| 161 | throw NotImplementedException("SPIR-V Instruction"); | 145 | const Id zero{ctx.Constant(ctx.F16[1], u16{0})}; |
| 146 | const Id one{ctx.Constant(ctx.F16[1], u16{0x3c00})}; | ||
| 147 | return ctx.OpFClamp(ctx.F32[1], value, zero, one); | ||
| 162 | } | 148 | } |
| 163 | 149 | ||
| 164 | void EmitFPSaturate32(EmitContext&) { | 150 | Id EmitFPSaturate32(EmitContext& ctx, Id value) { |
| 165 | throw NotImplementedException("SPIR-V Instruction"); | 151 | const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})}; |
| 152 | const Id one{ctx.Constant(ctx.F32[1], f32{1.0})}; | ||
| 153 | return ctx.OpFClamp(ctx.F32[1], value, zero, one); | ||
| 166 | } | 154 | } |
| 167 | 155 | ||
| 168 | void EmitFPSaturate64(EmitContext&) { | 156 | Id EmitFPSaturate64(EmitContext& ctx, Id value) { |
| 169 | throw NotImplementedException("SPIR-V Instruction"); | 157 | const Id zero{ctx.Constant(ctx.F64[1], f64{0.0})}; |
| 158 | const Id one{ctx.Constant(ctx.F64[1], f64{1.0})}; | ||
| 159 | return ctx.OpFClamp(ctx.F64[1], value, zero, one); | ||
| 170 | } | 160 | } |
| 171 | 161 | ||
| 172 | Id EmitFPRoundEven16(EmitContext& ctx, Id value) { | 162 | Id EmitFPRoundEven16(EmitContext& ctx, Id value) { |
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) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp index 8d5062724..eb1926a4d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp | |||
| @@ -14,8 +14,8 @@ void EmitSelect16(EmitContext&) { | |||
| 14 | throw NotImplementedException("SPIR-V Instruction"); | 14 | throw NotImplementedException("SPIR-V Instruction"); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | void EmitSelect32(EmitContext&) { | 17 | Id EmitSelect32(EmitContext& ctx, Id cond, Id true_value, Id false_value) { |
| 18 | throw NotImplementedException("SPIR-V Instruction"); | 18 | return ctx.OpSelect(ctx.U32[1], cond, true_value, false_value); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | void EmitSelect64(EmitContext&) { | 21 | void EmitSelect64(EmitContext&) { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 8f120a2f6..34c2f67fb 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -468,11 +468,11 @@ F16F32F64 IREmitter::FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F | |||
| 468 | 468 | ||
| 469 | F16F32F64 IREmitter::FPAbs(const F16F32F64& value) { | 469 | F16F32F64 IREmitter::FPAbs(const F16F32F64& value) { |
| 470 | switch (value.Type()) { | 470 | switch (value.Type()) { |
| 471 | case Type::U16: | 471 | case Type::F16: |
| 472 | return Inst<F16>(Opcode::FPAbs16, value); | 472 | return Inst<F16>(Opcode::FPAbs16, value); |
| 473 | case Type::U32: | 473 | case Type::F32: |
| 474 | return Inst<F32>(Opcode::FPAbs32, value); | 474 | return Inst<F32>(Opcode::FPAbs32, value); |
| 475 | case Type::U64: | 475 | case Type::F64: |
| 476 | return Inst<F64>(Opcode::FPAbs64, value); | 476 | return Inst<F64>(Opcode::FPAbs64, value); |
| 477 | default: | 477 | default: |
| 478 | ThrowInvalidType(value.Type()); | 478 | ThrowInvalidType(value.Type()); |
| @@ -481,11 +481,11 @@ F16F32F64 IREmitter::FPAbs(const F16F32F64& value) { | |||
| 481 | 481 | ||
| 482 | F16F32F64 IREmitter::FPNeg(const F16F32F64& value) { | 482 | F16F32F64 IREmitter::FPNeg(const F16F32F64& value) { |
| 483 | switch (value.Type()) { | 483 | switch (value.Type()) { |
| 484 | case Type::U16: | 484 | case Type::F16: |
| 485 | return Inst<F16>(Opcode::FPNeg16, value); | 485 | return Inst<F16>(Opcode::FPNeg16, value); |
| 486 | case Type::U32: | 486 | case Type::F32: |
| 487 | return Inst<F32>(Opcode::FPNeg32, value); | 487 | return Inst<F32>(Opcode::FPNeg32, value); |
| 488 | case Type::U64: | 488 | case Type::F64: |
| 489 | return Inst<F64>(Opcode::FPNeg64, value); | 489 | return Inst<F64>(Opcode::FPNeg64, value); |
| 490 | default: | 490 | default: |
| 491 | ThrowInvalidType(value.Type()); | 491 | ThrowInvalidType(value.Type()); |
| @@ -495,10 +495,10 @@ F16F32F64 IREmitter::FPNeg(const F16F32F64& value) { | |||
| 495 | F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) { | 495 | F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) { |
| 496 | F16F32F64 result{value}; | 496 | F16F32F64 result{value}; |
| 497 | if (abs) { | 497 | if (abs) { |
| 498 | result = FPAbs(value); | 498 | result = FPAbs(result); |
| 499 | } | 499 | } |
| 500 | if (neg) { | 500 | if (neg) { |
| 501 | result = FPNeg(value); | 501 | result = FPNeg(result); |
| 502 | } | 502 | } |
| 503 | return result; | 503 | return result; |
| 504 | } | 504 | } |
diff --git a/src/shader_recompiler/frontend/ir/pred.h b/src/shader_recompiler/frontend/ir/pred.h index c6f2f82bf..4e7f32423 100644 --- a/src/shader_recompiler/frontend/ir/pred.h +++ b/src/shader_recompiler/frontend/ir/pred.h | |||
| @@ -19,8 +19,8 @@ enum class Pred : u64 { | |||
| 19 | PT, | 19 | PT, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | constexpr size_t NUM_USER_PREDS = 6; | 22 | constexpr size_t NUM_USER_PREDS = 7; |
| 23 | constexpr size_t NUM_PREDS = 7; | 23 | constexpr size_t NUM_PREDS = 8; |
| 24 | 24 | ||
| 25 | [[nodiscard]] constexpr size_t PredIndex(Pred pred) noexcept { | 25 | [[nodiscard]] constexpr size_t PredIndex(Pred pred) noexcept { |
| 26 | return static_cast<size_t>(pred); | 26 | return static_cast<size_t>(pred); |
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp index 16cdc12e2..ed5dbf41f 100644 --- a/src/shader_recompiler/frontend/maxwell/program.cpp +++ b/src/shader_recompiler/frontend/maxwell/program.cpp | |||
| @@ -56,12 +56,12 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 56 | .post_order_blocks{}, | 56 | .post_order_blocks{}, |
| 57 | }); | 57 | }); |
| 58 | } | 58 | } |
| 59 | fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||
| 59 | Optimization::LowerFp16ToFp32(program); | 60 | Optimization::LowerFp16ToFp32(program); |
| 60 | for (IR::Function& function : functions) { | 61 | for (IR::Function& function : functions) { |
| 61 | function.post_order_blocks = PostOrder(function.blocks); | 62 | function.post_order_blocks = PostOrder(function.blocks); |
| 62 | Optimization::SsaRewritePass(function.post_order_blocks); | 63 | Optimization::SsaRewritePass(function.post_order_blocks); |
| 63 | } | 64 | } |
| 64 | fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||
| 65 | Optimization::GlobalMemoryToStorageBufferPass(program); | 65 | Optimization::GlobalMemoryToStorageBufferPass(program); |
| 66 | for (IR::Function& function : functions) { | 66 | for (IR::Function& function : functions) { |
| 67 | Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function); | 67 | Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp index cb3a326cf..219ffcc6a 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | namespace Shader::Maxwell { | 10 | namespace Shader::Maxwell { |
| 11 | namespace { | 11 | namespace { |
| 12 | |||
| 13 | void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding, | 12 | void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding, |
| 14 | const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) { | 13 | const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) { |
| 15 | union { | 14 | union { |
| @@ -18,9 +17,6 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin | |||
| 18 | BitField<8, 8, IR::Reg> src_a; | 17 | BitField<8, 8, IR::Reg> src_a; |
| 19 | } const fadd{insn}; | 18 | } const fadd{insn}; |
| 20 | 19 | ||
| 21 | if (sat) { | ||
| 22 | throw NotImplementedException("FADD SAT"); | ||
| 23 | } | ||
| 24 | if (cc) { | 20 | if (cc) { |
| 25 | throw NotImplementedException("FADD CC"); | 21 | throw NotImplementedException("FADD CC"); |
| 26 | } | 22 | } |
| @@ -31,7 +27,11 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin | |||
| 31 | .rounding{CastFpRounding(fp_rounding)}, | 27 | .rounding{CastFpRounding(fp_rounding)}, |
| 32 | .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None}, | 28 | .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None}, |
| 33 | }; | 29 | }; |
| 34 | v.F(fadd.dest_reg, v.ir.FPAdd(op_a, op_b, control)); | 30 | IR::F32 value{v.ir.FPAdd(op_a, op_b, control)}; |
| 31 | if (sat) { | ||
| 32 | value = v.ir.FPSaturate(value); | ||
| 33 | } | ||
| 34 | v.F(fadd.dest_reg, value); | ||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { | 37 | void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { |
| @@ -53,15 +53,15 @@ void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { | |||
| 53 | } // Anonymous namespace | 53 | } // Anonymous namespace |
| 54 | 54 | ||
| 55 | void TranslatorVisitor::FADD_reg(u64 insn) { | 55 | void TranslatorVisitor::FADD_reg(u64 insn) { |
| 56 | FADD(*this, insn, GetReg20F(insn)); | 56 | FADD(*this, insn, GetRegFloat20(insn)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | void TranslatorVisitor::FADD_cbuf(u64) { | 59 | void TranslatorVisitor::FADD_cbuf(u64 insn) { |
| 60 | throw NotImplementedException("FADD (cbuf)"); | 60 | FADD(*this, insn, GetFloatCbuf(insn)); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | void TranslatorVisitor::FADD_imm(u64) { | 63 | void TranslatorVisitor::FADD_imm(u64 insn) { |
| 64 | throw NotImplementedException("FADD (imm)"); | 64 | FADD(*this, insn, GetFloatImm20(insn)); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | void TranslatorVisitor::FADD32I(u64) { | 67 | void TranslatorVisitor::FADD32I(u64) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp index 4d82a0009..81175627f 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp | |||
| @@ -158,7 +158,7 @@ void TranslatorVisitor::F2I_cbuf(u64 insn) { | |||
| 158 | case SrcFormat::F16: | 158 | case SrcFormat::F16: |
| 159 | return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(GetCbuf(insn)), f2i.half)}; | 159 | return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(GetCbuf(insn)), f2i.half)}; |
| 160 | case SrcFormat::F32: | 160 | case SrcFormat::F32: |
| 161 | return GetCbufF(insn); | 161 | return GetFloatCbuf(insn); |
| 162 | case SrcFormat::F64: { | 162 | case SrcFormat::F64: { |
| 163 | return UnpackCbuf(*this, insn); | 163 | return UnpackCbuf(*this, insn); |
| 164 | } | 164 | } |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp index 1464f2807..758700d3c 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp | |||
| @@ -51,7 +51,7 @@ void FFMA(TranslatorVisitor& v, u64 insn, const IR::F32& src_b, const IR::F32& s | |||
| 51 | } // Anonymous namespace | 51 | } // Anonymous namespace |
| 52 | 52 | ||
| 53 | void TranslatorVisitor::FFMA_reg(u64 insn) { | 53 | void TranslatorVisitor::FFMA_reg(u64 insn) { |
| 54 | FFMA(*this, insn, GetReg20F(insn), GetReg39F(insn)); | 54 | FFMA(*this, insn, GetRegFloat20(insn), GetRegFloat39(insn)); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void TranslatorVisitor::FFMA_rc(u64) { | 57 | void TranslatorVisitor::FFMA_rc(u64) { |
| @@ -59,7 +59,7 @@ void TranslatorVisitor::FFMA_rc(u64) { | |||
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | void TranslatorVisitor::FFMA_cr(u64 insn) { | 61 | void TranslatorVisitor::FFMA_cr(u64 insn) { |
| 62 | FFMA(*this, insn, GetCbufF(insn), GetReg39F(insn)); | 62 | FFMA(*this, insn, GetFloatCbuf(insn), GetRegFloat39(insn)); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void TranslatorVisitor::FFMA_imm(u64) { | 65 | void TranslatorVisitor::FFMA_imm(u64) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp index 1b1d38be7..5c38d3fc1 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp | |||
| @@ -91,7 +91,7 @@ void FMUL(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { | |||
| 91 | } // Anonymous namespace | 91 | } // Anonymous namespace |
| 92 | 92 | ||
| 93 | void TranslatorVisitor::FMUL_reg(u64 insn) { | 93 | void TranslatorVisitor::FMUL_reg(u64 insn) { |
| 94 | return FMUL(*this, insn, GetReg20F(insn)); | 94 | return FMUL(*this, insn, GetRegFloat20(insn)); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | void TranslatorVisitor::FMUL_cbuf(u64) { | 97 | void TranslatorVisitor::FMUL_cbuf(u64) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index 079e3497f..be17bb0d9 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -48,11 +48,11 @@ IR::U32 TranslatorVisitor::GetReg39(u64 insn) { | |||
| 48 | return X(reg.index); | 48 | return X(reg.index); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | IR::F32 TranslatorVisitor::GetReg20F(u64 insn) { | 51 | IR::F32 TranslatorVisitor::GetRegFloat20(u64 insn) { |
| 52 | return ir.BitCast<IR::F32>(GetReg20(insn)); | 52 | return ir.BitCast<IR::F32>(GetReg20(insn)); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | IR::F32 TranslatorVisitor::GetReg39F(u64 insn) { | 55 | IR::F32 TranslatorVisitor::GetRegFloat39(u64 insn) { |
| 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); | 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| @@ -73,7 +73,7 @@ IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | |||
| 73 | return ir.GetCbuf(binding, byte_offset); | 73 | return ir.GetCbuf(binding, byte_offset); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | IR::F32 TranslatorVisitor::GetCbufF(u64 insn) { | 76 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { |
| 77 | return ir.BitCast<IR::F32>(GetCbuf(insn)); | 77 | return ir.BitCast<IR::F32>(GetCbuf(insn)); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| @@ -88,6 +88,17 @@ IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | |||
| 88 | return ir.Imm32(value); | 88 | return ir.Imm32(value); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) { | ||
| 92 | union { | ||
| 93 | u64 raw; | ||
| 94 | BitField<20, 19, u64> value; | ||
| 95 | BitField<56, 1, u64> is_negative; | ||
| 96 | } const imm{insn}; | ||
| 97 | const f32 positive_value{Common::BitCast<f32>(static_cast<u32>(imm.value) << 12)}; | ||
| 98 | const f32 value{imm.is_negative != 0 ? -positive_value : positive_value}; | ||
| 99 | return ir.Imm32(value); | ||
| 100 | } | ||
| 101 | |||
| 91 | IR::U32 TranslatorVisitor::GetImm32(u64 insn) { | 102 | IR::U32 TranslatorVisitor::GetImm32(u64 insn) { |
| 92 | union { | 103 | union { |
| 93 | u64 raw; | 104 | u64 raw; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index 27aba2cf8..4d4cf2ebf 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -304,13 +304,14 @@ public: | |||
| 304 | [[nodiscard]] IR::U32 GetReg8(u64 insn); | 304 | [[nodiscard]] IR::U32 GetReg8(u64 insn); |
| 305 | [[nodiscard]] IR::U32 GetReg20(u64 insn); | 305 | [[nodiscard]] IR::U32 GetReg20(u64 insn); |
| 306 | [[nodiscard]] IR::U32 GetReg39(u64 insn); | 306 | [[nodiscard]] IR::U32 GetReg39(u64 insn); |
| 307 | [[nodiscard]] IR::F32 GetReg20F(u64 insn); | 307 | [[nodiscard]] IR::F32 GetRegFloat20(u64 insn); |
| 308 | [[nodiscard]] IR::F32 GetReg39F(u64 insn); | 308 | [[nodiscard]] IR::F32 GetRegFloat39(u64 insn); |
| 309 | 309 | ||
| 310 | [[nodiscard]] IR::U32 GetCbuf(u64 insn); | 310 | [[nodiscard]] IR::U32 GetCbuf(u64 insn); |
| 311 | [[nodiscard]] IR::F32 GetCbufF(u64 insn); | 311 | [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn); |
| 312 | 312 | ||
| 313 | [[nodiscard]] IR::U32 GetImm20(u64 insn); | 313 | [[nodiscard]] IR::U32 GetImm20(u64 insn); |
| 314 | [[nodiscard]] IR::F32 GetFloatImm20(u64 insn); | ||
| 314 | 315 | ||
| 315 | [[nodiscard]] IR::U32 GetImm32(u64 insn); | 316 | [[nodiscard]] IR::U32 GetImm32(u64 insn); |
| 316 | 317 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp index 623e78ff8..1493e1815 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add.cpp | |||
| @@ -84,8 +84,8 @@ void TranslatorVisitor::IADD_cbuf(u64 insn) { | |||
| 84 | IADD(*this, insn, GetCbuf(insn)); | 84 | IADD(*this, insn, GetCbuf(insn)); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | void TranslatorVisitor::IADD_imm(u64) { | 87 | void TranslatorVisitor::IADD_imm(u64 insn) { |
| 88 | throw NotImplementedException("IADD (imm)"); | 88 | IADD(*this, insn, GetImm20(insn)); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | void TranslatorVisitor::IADD32I(u64 insn) { | 91 | void TranslatorVisitor::IADD32I(u64 insn) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp new file mode 100644 index 000000000..4324fd443 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/move_predicate_to_register.cpp | |||
| @@ -0,0 +1,66 @@ | |||
| 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 "common/bit_field.h" | ||
| 6 | #include "shader_recompiler/exception.h" | ||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 8 | |||
| 9 | namespace Shader::Maxwell { | ||
| 10 | namespace { | ||
| 11 | enum class Mode : u64 { | ||
| 12 | PR, | ||
| 13 | CC, | ||
| 14 | }; | ||
| 15 | } // Anonymous namespace | ||
| 16 | |||
| 17 | void TranslatorVisitor::P2R_reg(u64) { | ||
| 18 | throw NotImplementedException("P2R (reg)"); | ||
| 19 | } | ||
| 20 | |||
| 21 | void TranslatorVisitor::P2R_cbuf(u64) { | ||
| 22 | throw NotImplementedException("P2R (cbuf)"); | ||
| 23 | } | ||
| 24 | |||
| 25 | void TranslatorVisitor::P2R_imm(u64 insn) { | ||
| 26 | union { | ||
| 27 | u64 raw; | ||
| 28 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 29 | BitField<8, 8, IR::Reg> src; | ||
| 30 | BitField<40, 1, Mode> mode; | ||
| 31 | BitField<41, 2, u64> byte_selector; | ||
| 32 | } const p2r{insn}; | ||
| 33 | |||
| 34 | const u32 mask{GetImm20(insn).U32()}; | ||
| 35 | const bool pr_mode{p2r.mode == Mode::PR}; | ||
| 36 | const u32 num_items{pr_mode ? 7U : 4U}; | ||
| 37 | const u32 offset{static_cast<u32>(p2r.byte_selector) * 8}; | ||
| 38 | IR::U32 insert{ir.Imm32(0)}; | ||
| 39 | for (u32 index = 0; index < num_items; ++index) { | ||
| 40 | if (((mask >> index) & 1) == 0) { | ||
| 41 | continue; | ||
| 42 | } | ||
| 43 | const IR::U1 cond{[this, index, pr_mode] { | ||
| 44 | if (pr_mode) { | ||
| 45 | return ir.GetPred(IR::Pred{index}); | ||
| 46 | } | ||
| 47 | switch (index) { | ||
| 48 | case 0: | ||
| 49 | return ir.GetZFlag(); | ||
| 50 | case 1: | ||
| 51 | return ir.GetSFlag(); | ||
| 52 | case 2: | ||
| 53 | return ir.GetCFlag(); | ||
| 54 | case 3: | ||
| 55 | return ir.GetOFlag(); | ||
| 56 | } | ||
| 57 | throw LogicError("Unreachable P2R index"); | ||
| 58 | }()}; | ||
| 59 | const IR::U32 bit{ir.Select(cond, ir.Imm32(1U << (index + offset)), ir.Imm32(0))}; | ||
| 60 | insert = ir.BitwiseOr(insert, bit); | ||
| 61 | } | ||
| 62 | const IR::U32 masked_out{ir.BitwiseAnd(X(p2r.src), ir.Imm32(~(mask << offset)))}; | ||
| 63 | X(p2r.dest_reg, ir.BitwiseOr(masked_out, insert)); | ||
| 64 | } | ||
| 65 | |||
| 66 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 6b2a1356b..628cf1c14 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -633,18 +633,6 @@ void TranslatorVisitor::OUT_imm(u64) { | |||
| 633 | ThrowNotImplemented(Opcode::OUT_imm); | 633 | ThrowNotImplemented(Opcode::OUT_imm); |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | void TranslatorVisitor::P2R_reg(u64) { | ||
| 637 | ThrowNotImplemented(Opcode::P2R_reg); | ||
| 638 | } | ||
| 639 | |||
| 640 | void TranslatorVisitor::P2R_cbuf(u64) { | ||
| 641 | ThrowNotImplemented(Opcode::P2R_cbuf); | ||
| 642 | } | ||
| 643 | |||
| 644 | void TranslatorVisitor::P2R_imm(u64) { | ||
| 645 | ThrowNotImplemented(Opcode::P2R_imm); | ||
| 646 | } | ||
| 647 | |||
| 648 | void TranslatorVisitor::PBK() { | 636 | void TranslatorVisitor::PBK() { |
| 649 | // PBK is a no-op | 637 | // PBK is a no-op |
| 650 | } | 638 | } |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 49ff911d6..b25af6cd3 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -191,12 +191,12 @@ ComputePipeline PipelineCache::CreateComputePipeline(ShaderInfo* shader_info) { | |||
| 191 | .support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE, | 191 | .support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE, |
| 192 | }; | 192 | }; |
| 193 | const auto [info, code]{Shader::RecompileSPIRV(profile, env, qmd.program_start)}; | 193 | const auto [info, code]{Shader::RecompileSPIRV(profile, env, qmd.program_start)}; |
| 194 | 194 | /* | |
| 195 | FILE* file = fopen("D:\\shader.spv", "wb"); | 195 | FILE* file = fopen("D:\\shader.spv", "wb"); |
| 196 | fwrite(code.data(), 4, code.size(), file); | 196 | fwrite(code.data(), 4, code.size(), file); |
| 197 | fclose(file); | 197 | fclose(file); |
| 198 | std::system("spirv-dis D:\\shader.spv"); | 198 | std::system("spirv-dis D:\\shader.spv"); |
| 199 | 199 | */ | |
| 200 | shader_info->unique_hash = env.ComputeHash(); | 200 | shader_info->unique_hash = env.ComputeHash(); |
| 201 | shader_info->size_bytes = env.ShaderSize(); | 201 | shader_info->size_bytes = env.ShaderSize(); |
| 202 | return ComputePipeline{device, descriptor_pool, update_descriptor_queue, info, | 202 | return ComputePipeline{device, descriptor_pool, update_descriptor_queue, info, |