diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp index c864e6830..0c5e517f8 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp @@ -210,10 +210,23 @@ uint32_t EmitCompositeExtractU32x2(EmitterState& state, uint32_t arg0, IR::Value } uint32_t EmitPackFloat2x16Rtz(EmitterState& state, uint32_t arg0, uint32_t arg1) { - const auto low = EmitF32ToF16RtzBits(state, arg0); - const auto high = Binary(state, spv::OpShiftLeftLogical, TypeU32(state), - EmitF32ToF16RtzBits(state, arg1), ConstantU32(state, 16)); - return Binary(state, spv::OpBitwiseOr, TypeU32(state), low, high); + const auto pair = state.builder.AllocateId(); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(state, 2), pair, arg0, arg1); + const auto packed = EmitPackHalf2x16(state, pair); + const auto back = EmitExt(state, TypeF32Vector(state, 2), GLSLstd450UnpackHalf2x16, {packed}); + auto result = packed; + for (uint32_t i = 0; i < 2; i++) { + const auto rounded = state.builder.AllocateId(); + state.builder.AddFunction(spv::OpCompositeExtract, TypeF32(state), rounded, back, i); + const auto above = + Binary(state, spv::OpFOrdGreaterThan, TypeBool(state), + EmitExt(state, TypeF32(state), GLSLstd450FAbs, {rounded}), + EmitExt(state, TypeF32(state), GLSLstd450FAbs, {i == 0 ? arg0 : arg1})); + result = Binary(state, spv::OpISub, TypeU32(state), result, + Select(state, TypeU32(state), above, + ConstantU32(state, i == 0 ? 1u : 0x10000u), ConstantU32(state, 0))); + } + return result; } uint32_t EmitFPSaturate32(EmitterState& state, uint32_t arg0) { diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp index 6048f58d3..b72f7e7f0 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp @@ -9,13 +9,6 @@ uint32_t EmitAndConstant(EmitterState& state, uint32_t value, uint32_t mask) { return ret; } -uint32_t EmitShiftRightConstant(EmitterState& state, uint32_t value, uint32_t shift) { - const auto ret = state.builder.AllocateId(); - state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), ret, value, - ConstantU32(state, shift)); - return ret; -} - uint32_t EmitCompareU32Constant(EmitterState& state, spv::Op opcode, uint32_t value, uint32_t constant) { const auto ret = state.builder.AllocateId(); @@ -23,65 +16,6 @@ uint32_t EmitCompareU32Constant(EmitterState& state, spv::Op opcode, uint32_t va return ret; } -uint32_t EmitSubConstantMinusU32(EmitterState& state, uint32_t constant, uint32_t value) { - const auto ret = state.builder.AllocateId(); - state.builder.AddFunction(spv::OpISub, TypeU32(state), ret, ConstantU32(state, constant), - value); - return ret; -} - -uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32) { - const auto bits = state.builder.AllocateId(); - state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, f32); - - const auto sign = EmitAndConstant(state, EmitShiftRightConstant(state, bits, 16), 0x8000u); - const auto exp = EmitAndConstant(state, EmitShiftRightConstant(state, bits, 23), 0xffu); - const auto mant = EmitAndConstant(state, bits, 0x007fffffu); - - const auto half_exp = state.builder.AllocateId(); - const auto normal_exp = state.builder.AllocateId(); - const auto normal_mant = EmitShiftRightConstant(state, mant, 13); - const auto normal_payload = state.builder.AllocateId(); - const auto normal = state.builder.AllocateId(); - state.builder.AddFunction(spv::OpISub, TypeU32(state), half_exp, exp, ConstantU32(state, 112)); - state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), normal_exp, half_exp, - ConstantU32(state, 10)); - state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), normal_payload, normal_exp, - normal_mant); - state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), normal, sign, normal_payload); - - const auto mant_with_hidden = EmitOrU32(state, mant, ConstantU32(state, 0x00800000u)); - const auto raw_sub_shift = EmitSubConstantMinusU32(state, 126, exp); - const auto exp_lt_103 = EmitCompareU32Constant(state, spv::OpULessThan, exp, 103); - const auto exp_gt_112 = EmitCompareU32Constant(state, spv::OpUGreaterThan, exp, 112); - const auto sub_shift_low = - EmitSelectValueU32(state, exp_lt_103, ConstantU32(state, 31), raw_sub_shift); - const auto sub_shift = - EmitSelectValueU32(state, exp_gt_112, ConstantU32(state, 14), sub_shift_low); - const auto sub_mant = state.builder.AllocateId(); - const auto subnormal = state.builder.AllocateId(); - state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), sub_mant, mant_with_hidden, - sub_shift); - state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), subnormal, sign, sub_mant); - - const auto nan_payload = - EmitOrU32(state, EmitShiftRightConstant(state, mant, 13), ConstantU32(state, 0x0200u)); - const auto nan = - EmitOrU32(state, sign, EmitOrU32(state, ConstantU32(state, 0x7c00u), nan_payload)); - const auto inf = EmitOrU32(state, sign, ConstantU32(state, 0x7c00u)); - const auto max_finite = EmitOrU32(state, sign, ConstantU32(state, 0x7bffu)); - const auto mant_zero = EmitCompareU32Constant(state, spv::OpIEqual, mant, 0); - const auto special = EmitSelectValueU32(state, mant_zero, inf, nan); - - const auto exp_le_112 = EmitCompareU32Constant(state, spv::OpULessThanEqual, exp, 112); - const auto exp_ge_143 = EmitCompareU32Constant(state, spv::OpUGreaterThanEqual, exp, 143); - const auto exp_eq_255 = EmitCompareU32Constant(state, spv::OpIEqual, exp, 255); - const auto finite0 = EmitSelectValueU32(state, exp_le_112, subnormal, normal); - const auto finite1 = EmitSelectValueU32(state, exp_lt_103, sign, finite0); - const auto finite2 = EmitSelectValueU32(state, exp_ge_143, max_finite, finite1); - return EmitAndConstant(state, EmitSelectValueU32(state, exp_eq_255, special, finite2), 0xffffu); -} - F32Class EmitClassifyF32Bits(EmitterState& state, uint32_t bits) { F32Class cls; cls.bits = bits; diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h index 6dc28ad2e..4a2f942f5 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h @@ -488,17 +488,11 @@ inline constexpr auto EmitSelectValueU32 = uint32_t EmitAndConstant(EmitterState& state, uint32_t value, uint32_t mask); -uint32_t EmitShiftRightConstant(EmitterState& state, uint32_t value, uint32_t shift); - inline constexpr auto EmitOrU32 = EmitNative; uint32_t EmitCompareU32Constant(EmitterState& state, spv::Op opcode, uint32_t value, uint32_t constant); -uint32_t EmitSubConstantMinusU32(EmitterState& state, uint32_t constant, uint32_t value); - -uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32); - inline constexpr auto EmitBitcastF32ToU32 = EmitNative; inline constexpr auto EmitBitcastU32ToF32 = EmitNative;