diff --git a/core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterHelpers.hpp b/core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterHelpers.hpp index 25813bb5f..7321f46db 100644 --- a/core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterHelpers.hpp +++ b/core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterHelpers.hpp @@ -131,7 +131,6 @@ F32Class EmitClassifyF32(SpirvEmitterState& state, std::uint32_t value); std::uint32_t EmitClassMaskBitMatch(SpirvEmitterState& state, std::uint32_t mask, std::uint32_t bit, std::uint32_t classMatch); std::uint32_t EmitClassMaskF32(SpirvEmitterState& state, std::uint32_t value, std::uint32_t mask); std::uint32_t EmitMinMaxF32Value(SpirvEmitterState& state, std::uint32_t lhs, std::uint32_t rhs, bool maxValue); -std::uint32_t EmitFlushF32DenormToSignedZero(SpirvEmitterState& state, std::uint32_t value); std::uint32_t EmitTrigCycleF32(SpirvEmitterState& state, std::uint32_t src, bool preserveSignedZero); void EmitF16DenormPreserve(SpirvEmitterState& state); std::uint32_t EmitF16BitsToF32(SpirvEmitterState& state, std::uint32_t bits); diff --git a/core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp b/core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp index 7a4b02ea5..69ff59f2f 100644 --- a/core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp +++ b/core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp @@ -842,8 +842,7 @@ std::uint32_t EmitFPMedTri32(SpirvEmitterState& state, std::uint32_t arg0, std:: } std::uint32_t EmitFPRecip32(SpirvEmitterState& state, std::uint32_t arg0) { - const auto source = EmitFlushF32DenormToSignedZero(state, arg0); - return Binary(state, spv::OpFDiv, TypeF32(state), ConstantF32(state, 0x3f800000u), source); + return Binary(state, spv::OpFDiv, TypeF32(state), ConstantF32(state, 0x3f800000u), arg0); } std::uint32_t EmitFPRecipIFlag32(SpirvEmitterState& state, std::uint32_t arg0) { @@ -851,15 +850,15 @@ std::uint32_t EmitFPRecipIFlag32(SpirvEmitterState& state, std::uint32_t arg0) { } std::uint32_t EmitFPRecipSqrt32(SpirvEmitterState& state, std::uint32_t arg0) { - return EmitExt(state, TypeF32(state), GLSLstd450InverseSqrt, {EmitFlushF32DenormToSignedZero(state, arg0)}); + return EmitExt(state, TypeF32(state), GLSLstd450InverseSqrt, {arg0}); } std::uint32_t EmitFPSqrt(SpirvEmitterState& state, std::uint32_t arg0) { - return EmitExt(state, TypeF32(state), GLSLstd450Sqrt, {EmitFlushF32DenormToSignedZero(state, arg0)}); + return EmitExt(state, TypeF32(state), GLSLstd450Sqrt, {arg0}); } std::uint32_t EmitFPExp2(SpirvEmitterState& state, std::uint32_t arg0) { - return EmitExt(state, TypeF32(state), GLSLstd450Exp2, {EmitFlushF32DenormToSignedZero(state, arg0)}); + return EmitExt(state, TypeF32(state), GLSLstd450Exp2, {arg0}); } std::uint32_t Log2SeriesNearOne(SpirvEmitterState& state, std::uint32_t difference) { @@ -872,9 +871,8 @@ std::uint32_t Log2SeriesNearOne(SpirvEmitterState& state, std::uint32_t differen } std::uint32_t EmitFPLog2(SpirvEmitterState& state, std::uint32_t arg0) { - const auto source = EmitFlushF32DenormToSignedZero(state, arg0); - const auto value = EmitExt(state, TypeF32(state), GLSLstd450Log2, {source}); - const auto difference = Exact(state, Binary(state, spv::OpFSub, TypeF32(state), source, ConstantF32(state, 0x3f800000u))); + const auto value = EmitExt(state, TypeF32(state), GLSLstd450Log2, {arg0}); + const auto difference = Exact(state, Binary(state, spv::OpFSub, TypeF32(state), arg0, ConstantF32(state, 0x3f800000u))); const auto series = Log2SeriesNearOne(state, difference); const auto valueBits = Unary(state, spv::OpBitcast, TypeU32(state), value); const auto seriesBits = Unary(state, spv::OpBitcast, TypeU32(state), series); diff --git a/core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp b/core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp index 35bdbd6ae..debd3304b 100644 --- a/core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp +++ b/core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp @@ -945,26 +945,6 @@ std::uint32_t EmitMinMaxF32Value(SpirvEmitterState& state, std::uint32_t lhs, st return Unary(state, spv::OpBitcast, TypeF32(state), resultBits); } -std::uint32_t EmitFlushF32DenormToSignedZero(SpirvEmitterState& state, std::uint32_t value) { - const auto bits = state.module.AllocateId(); - const auto absBits = state.module.AllocateId(); - const auto signBits = state.module.AllocateId(); - const auto nonZero = state.module.AllocateId(); - const auto subnormal = state.module.AllocateId(); - const auto flush = state.module.AllocateId(); - const auto selected = state.module.AllocateId(); - const auto result = state.module.AllocateId(); - state.module.AddFunction(spv::OpBitcast, TypeU32(state), bits, value); - state.module.AddFunction(spv::OpBitwiseAnd, TypeU32(state), absBits, bits, ConstantU32(state, 0x7fffffffu)); - state.module.AddFunction(spv::OpBitwiseAnd, TypeU32(state), signBits, bits, ConstantU32(state, 0x80000000u)); - state.module.AddFunction(spv::OpINotEqual, TypeBool(state), nonZero, absBits, ConstantU32(state, 0u)); - state.module.AddFunction(spv::OpULessThan, TypeBool(state), subnormal, absBits, ConstantU32(state, 0x00800000u)); - state.module.AddFunction(spv::OpLogicalAnd, TypeBool(state), flush, nonZero, subnormal); - state.module.AddFunction(spv::OpSelect, TypeU32(state), selected, flush, signBits, bits); - state.module.AddFunction(spv::OpBitcast, TypeF32(state), result, selected); - return result; -} - std::uint32_t EmitTrigCycleF32(SpirvEmitterState& state, std::uint32_t src, bool preserveSignedZero) { const auto rounded = state.module.AllocateId(); const auto reduced = state.module.AllocateId(); diff --git a/core/shader/recompiler/Translation/src/InstructionTranslator.cpp b/core/shader/recompiler/Translation/src/InstructionTranslator.cpp index 247197f83..0de004a63 100644 --- a/core/shader/recompiler/Translation/src/InstructionTranslator.cpp +++ b/core/shader/recompiler/Translation/src/InstructionTranslator.cpp @@ -356,8 +356,9 @@ void emitEntryPrologue(IrProgram& program, IrBlock& entryBlock, const TranslateO setVector(static_cast(vgpr(PixelInput::PositionZ)), builtin(StageInputKind::FragCoord, 2u)); } if (loaded(PixelInput::PositionW)) { - IrValue& reciprocalW = entryIr.BitCastF32(builtin(StageInputKind::FragCoord, 3u)); - IrValue& w = entryIr.Emit(IrOpcode::FPRecip32, IrOpcodeType(IrOpcode::FPRecip32), {&reciprocalW}); + IrValue& reciprocalBits = builtin(StageInputKind::FragCoord, 3u); + IrValue& flushed = entryIr.Select(entryIr.IEqual(entryIr.BitwiseAnd(reciprocalBits, entryIr.Constant(0x7f800000u)), entryIr.Constant(0u)), entryIr.BitwiseAnd(reciprocalBits, entryIr.Constant(0x80000000u)), reciprocalBits); + IrValue& w = entryIr.Emit(IrOpcode::FPRecip32, IrOpcodeType(IrOpcode::FPRecip32), {&entryIr.BitCastF32(flushed)}); setVector(static_cast(vgpr(PixelInput::PositionW)), entryIr.BitCastU32(w)); } if (loaded(PixelInput::FrontFace)) {