diff --git a/externals/sirit b/externals/sirit index 6cecb95d6..e12b6b592 160000 --- a/externals/sirit +++ b/externals/sirit @@ -1 +1 @@ -Subproject commit 6cecb95d679c82c413d1f989e0b7ad9af130600d +Subproject commit e12b6b592ce9917a85303c555259488643c56f47 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 1e8f31ddc..a63be87e2 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp @@ -225,10 +225,34 @@ Id EmitFPTrunc64(EmitContext& ctx, Id value) { return ctx.OpTrunc(ctx.F64[1], value); } -Id EmitFPFract(EmitContext& ctx, Id value) { +Id EmitFPFract32(EmitContext& ctx, Id value) { return ctx.OpFract(ctx.F32[1], value); } +Id EmitFPFract64(EmitContext& ctx, Id value) { + return ctx.OpFract(ctx.F64[1], value); +} + +Id EmitFPFrexpSig32(EmitContext& ctx, Id value) { + const auto frexp = ctx.OpFrexpStruct(ctx.frexp_result_f32, value); + return ctx.OpCompositeExtract(ctx.F32[1], frexp, 0); +} + +Id EmitFPFrexpSig64(EmitContext& ctx, Id value) { + const auto frexp = ctx.OpFrexpStruct(ctx.frexp_result_f64, value); + return ctx.OpCompositeExtract(ctx.F64[1], frexp, 0); +} + +Id EmitFPFrexpExp32(EmitContext& ctx, Id value) { + const auto frexp = ctx.OpFrexpStruct(ctx.frexp_result_f32, value); + return ctx.OpCompositeExtract(ctx.U32[1], frexp, 1); +} + +Id EmitFPFrexpExp64(EmitContext& ctx, Id value) { + const auto frexp = ctx.OpFrexpStruct(ctx.frexp_result_f64, value); + return ctx.OpCompositeExtract(ctx.U32[1], frexp, 1); +} + Id EmitFPOrdEqual16(EmitContext& ctx, Id lhs, Id rhs) { return ctx.OpFOrdEqual(ctx.U1[1], lhs, rhs); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 071b430d5..4ff53670e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -222,7 +222,12 @@ Id EmitFPCeil64(EmitContext& ctx, Id value); Id EmitFPTrunc16(EmitContext& ctx, Id value); Id EmitFPTrunc32(EmitContext& ctx, Id value); Id EmitFPTrunc64(EmitContext& ctx, Id value); -Id EmitFPFract(EmitContext& ctx, Id value); +Id EmitFPFract32(EmitContext& ctx, Id value); +Id EmitFPFract64(EmitContext& ctx, Id value); +Id EmitFPFrexpSig32(EmitContext& ctx, Id value); +Id EmitFPFrexpSig64(EmitContext& ctx, Id value); +Id EmitFPFrexpExp32(EmitContext& ctx, Id value); +Id EmitFPFrexpExp64(EmitContext& ctx, Id value); Id EmitFPOrdEqual16(EmitContext& ctx, Id lhs, Id rhs); Id EmitFPOrdEqual32(EmitContext& ctx, Id lhs, Id rhs); Id EmitFPOrdEqual64(EmitContext& ctx, Id lhs, Id rhs); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 5c7278c6b..1ada2f1f9 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -147,6 +147,10 @@ void EmitContext::DefineArithmeticTypes() { full_result_i32x2 = Name(TypeStruct(S32[1], S32[1]), "full_result_i32x2"); full_result_u32x2 = Name(TypeStruct(U32[1], U32[1]), "full_result_u32x2"); + frexp_result_f32 = Name(TypeStruct(F32[1], U32[1]), "frexp_result_f32"); + if (info.uses_fp64) { + frexp_result_f64 = Name(TypeStruct(F64[1], U32[1]), "frexp_result_f64"); + } } void EmitContext::DefineInterfaces() { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 4e5e7dd3b..cd1293328 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -148,6 +148,8 @@ public: Id full_result_i32x2; Id full_result_u32x2; + Id frexp_result_f32; + Id frexp_result_f64; Id pi_x2; diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 43f3ccef2..2f320a6c7 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -200,6 +200,11 @@ public: void V_BFREV_B32(const GcnInst& inst); void V_FFBH_U32(const GcnInst& inst); void V_FFBL_B32(const GcnInst& inst); + void V_FREXP_EXP_I32_F64(const GcnInst& inst); + void V_FREXP_MANT_F64(const GcnInst& inst); + void V_FRACT_F64(const GcnInst& inst); + void V_FREXP_EXP_I32_F32(const GcnInst& inst); + void V_FREXP_MANT_F32(const GcnInst& inst); void V_MOVRELD_B32(const GcnInst& inst); void V_MOVRELS_B32(const GcnInst& inst); void V_MOVRELSD_B32(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 8149230db..3e9e677a7 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -179,6 +179,16 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_FFBH_U32(inst); case Opcode::V_FFBL_B32: return V_FFBL_B32(inst); + case Opcode::V_FREXP_EXP_I32_F64: + return V_FREXP_EXP_I32_F64(inst); + case Opcode::V_FREXP_MANT_F64: + return V_FREXP_MANT_F64(inst); + case Opcode::V_FRACT_F64: + return V_FRACT_F64(inst); + case Opcode::V_FREXP_EXP_I32_F32: + return V_FREXP_EXP_I32_F32(inst); + case Opcode::V_FREXP_MANT_F32: + return V_FREXP_MANT_F32(inst); case Opcode::V_MOVRELD_B32: return V_MOVRELD_B32(inst); case Opcode::V_MOVRELS_B32: @@ -733,7 +743,7 @@ void Translator::V_CVT_F32_UBYTE(u32 index, const GcnInst& inst) { void Translator::V_FRACT_F32(const GcnInst& inst) { const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.Fract(src0)); + SetDst(inst.dst[0], ir.FPFract(src0)); } void Translator::V_TRUNC_F32(const GcnInst& inst) { @@ -822,6 +832,31 @@ void Translator::V_FFBL_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.FindILsb(src0)); } +void Translator::V_FREXP_EXP_I32_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + SetDst(inst.dst[0], ir.FPFrexpExp(src0)); +} + +void Translator::V_FREXP_MANT_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + SetDst64(inst.dst[0], ir.FPFrexpSig(src0)); +} + +void Translator::V_FRACT_F64(const GcnInst& inst) { + const IR::F32 src0{GetSrc64(inst.src[0])}; + SetDst64(inst.dst[0], ir.FPFract(src0)); +} + +void Translator::V_FREXP_EXP_I32_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPFrexpExp(src0)); +} + +void Translator::V_FREXP_MANT_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPFrexpSig(src0)); +} + void Translator::V_MOVRELD_B32(const GcnInst& inst) { const IR::U32 src_val{GetSrc(inst.src[0])}; u32 dst_vgprno = inst.dst[0].code - static_cast(IR::VectorReg::V0); diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 5fa20b744..29b406699 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -869,8 +869,37 @@ F32F64 IREmitter::FPTrunc(const F32F64& value) { } } -F32 IREmitter::Fract(const F32& value) { - return Inst(Opcode::FPFract, value); +F32F64 IREmitter::FPFract(const F32F64& value) { + switch (value.Type()) { + case Type::F32: + return Inst(Opcode::FPFract32, value); + case Type::F64: + return Inst(Opcode::FPFract64, value); + default: + ThrowInvalidType(value.Type()); + } +} + +F32F64 IREmitter::FPFrexpSig(const F32F64& value) { + switch (value.Type()) { + case Type::F32: + return Inst(Opcode::FPFrexpSig32, value); + case Type::F64: + return Inst(Opcode::FPFrexpSig64, value); + default: + ThrowInvalidType(value.Type()); + } +} + +U32 IREmitter::FPFrexpExp(const F32F64& value) { + switch (value.Type()) { + case Type::F32: + return Inst(Opcode::FPFrexpExp32, value); + case Type::F64: + return Inst(Opcode::FPFrexpExp64, value); + default: + ThrowInvalidType(value.Type()); + } } U1 IREmitter::FPEqual(const F32F64& lhs, const F32F64& rhs, bool ordered) { diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index e6608cba7..f77e22b82 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -180,7 +180,9 @@ public: [[nodiscard]] F32F64 FPFloor(const F32F64& value); [[nodiscard]] F32F64 FPCeil(const F32F64& value); [[nodiscard]] F32F64 FPTrunc(const F32F64& value); - [[nodiscard]] F32 Fract(const F32& value); + [[nodiscard]] F32F64 FPFract(const F32F64& value); + [[nodiscard]] F32F64 FPFrexpSig(const F32F64& value); + [[nodiscard]] U32 FPFrexpExp(const F32F64& value); [[nodiscard]] U1 FPEqual(const F32F64& lhs, const F32F64& rhs, bool ordered = true); [[nodiscard]] U1 FPNotEqual(const F32F64& lhs, const F32F64& rhs, bool ordered = true); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 60232a3a1..8f40ed985 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -210,7 +210,12 @@ OPCODE(FPCeil32, F32, F32, OPCODE(FPCeil64, F64, F64, ) OPCODE(FPTrunc32, F32, F32, ) OPCODE(FPTrunc64, F64, F64, ) -OPCODE(FPFract, F32, F32, ) +OPCODE(FPFract32, F32, F32, ) +OPCODE(FPFract64, F64, F64, ) +OPCODE(FPFrexpSig32, F32, F32, ) +OPCODE(FPFrexpSig64, F64, F64, ) +OPCODE(FPFrexpExp32, U32, F32, ) +OPCODE(FPFrexpExp64, U32, F64, ) OPCODE(FPOrdEqual32, U1, F32, F32, ) OPCODE(FPOrdEqual64, U1, F64, F64, )