[SpirvTranslator] Match guest F32 denormal and trigonometric semantics
Co-authored-by: Sekai <140012992+SekaixX@users.noreply.github.com>
This commit is contained in:
parent
c566dba5a1
commit
b368247d64
|
|
@ -442,6 +442,15 @@ public static partial class Gen5SpirvTranslator
|
|||
break;
|
||||
}
|
||||
case "VRcpF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
_module.AddInstruction(
|
||||
SpirvOp.FDiv,
|
||||
_floatType,
|
||||
Float(1),
|
||||
EmitFlushF32DenormToSignedZero(
|
||||
GetFloatSource(instruction, 0))));
|
||||
break;
|
||||
case "VRcpIflagF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
|
|
@ -454,7 +463,11 @@ public static partial class Gen5SpirvTranslator
|
|||
case "VLogF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
Ext(30, _floatType, GetFloatSource(instruction, 0)));
|
||||
Ext(
|
||||
30,
|
||||
_floatType,
|
||||
EmitFlushF32DenormToSignedZero(
|
||||
GetFloatSource(instruction, 0))));
|
||||
break;
|
||||
case "VLdexpF32":
|
||||
result = EmitFloatResult(
|
||||
|
|
@ -468,12 +481,20 @@ public static partial class Gen5SpirvTranslator
|
|||
case "VExpF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
Ext(29, _floatType, GetFloatSource(instruction, 0)));
|
||||
Ext(
|
||||
29,
|
||||
_floatType,
|
||||
EmitFlushF32DenormToSignedZero(
|
||||
GetFloatSource(instruction, 0))));
|
||||
break;
|
||||
case "VRsqF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
Ext(32, _floatType, GetFloatSource(instruction, 0)));
|
||||
Ext(
|
||||
32,
|
||||
_floatType,
|
||||
EmitFlushF32DenormToSignedZero(
|
||||
GetFloatSource(instruction, 0))));
|
||||
break;
|
||||
case "VRcpF16":
|
||||
result = EmitFloat16Result(instruction, destination, _module.AddInstruction(SpirvOp.FDiv, _floatType, Float(1), GetFloat16Source(instruction, 0)));
|
||||
|
|
@ -542,7 +563,11 @@ public static partial class Gen5SpirvTranslator
|
|||
case "VSqrtF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
Ext(31, _floatType, GetFloatSource(instruction, 0)));
|
||||
Ext(
|
||||
31,
|
||||
_floatType,
|
||||
EmitFlushF32DenormToSignedZero(
|
||||
GetFloatSource(instruction, 0))));
|
||||
break;
|
||||
case "VSinF32":
|
||||
result = EmitFloatResult(
|
||||
|
|
@ -553,7 +578,9 @@ public static partial class Gen5SpirvTranslator
|
|||
_module.AddInstruction(
|
||||
SpirvOp.FMul,
|
||||
_floatType,
|
||||
GetFloatSource(instruction, 0),
|
||||
EmitTrigCycleF32(
|
||||
GetFloatSource(instruction, 0),
|
||||
preserveSignedZero: true),
|
||||
Float(MathF.Tau))));
|
||||
break;
|
||||
case "VCosF32":
|
||||
|
|
@ -565,7 +592,9 @@ public static partial class Gen5SpirvTranslator
|
|||
_module.AddInstruction(
|
||||
SpirvOp.FMul,
|
||||
_floatType,
|
||||
GetFloatSource(instruction, 0),
|
||||
EmitTrigCycleF32(
|
||||
GetFloatSource(instruction, 0),
|
||||
preserveSignedZero: false),
|
||||
Float(MathF.Tau))));
|
||||
break;
|
||||
case "VAddF32":
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
namespace SharpEmu.ShaderCompiler.Vulkan;
|
||||
|
||||
public static partial class Gen5SpirvTranslator
|
||||
{
|
||||
private sealed partial class CompilationContext
|
||||
{
|
||||
private uint EmitFlushF32DenormToSignedZero(uint value)
|
||||
{
|
||||
var bits = Bitcast(_uintType, value);
|
||||
var absolute = _module.AddInstruction(
|
||||
SpirvOp.BitwiseAnd,
|
||||
_uintType,
|
||||
bits,
|
||||
UInt(0x7FFF_FFFF));
|
||||
var sign = _module.AddInstruction(
|
||||
SpirvOp.BitwiseAnd,
|
||||
_uintType,
|
||||
bits,
|
||||
UInt(0x8000_0000));
|
||||
var nonZero = IsNotZero(absolute);
|
||||
var subnormal = _module.AddInstruction(
|
||||
SpirvOp.ULessThan,
|
||||
_boolType,
|
||||
absolute,
|
||||
UInt(0x0080_0000));
|
||||
var flush = _module.AddInstruction(
|
||||
SpirvOp.LogicalAnd,
|
||||
_boolType,
|
||||
nonZero,
|
||||
subnormal);
|
||||
var selected = _module.AddInstruction(
|
||||
SpirvOp.Select,
|
||||
_uintType,
|
||||
flush,
|
||||
sign,
|
||||
bits);
|
||||
return Bitcast(_floatType, selected);
|
||||
}
|
||||
|
||||
private uint EmitTrigCycleF32(uint source, bool preserveSignedZero)
|
||||
{
|
||||
var fraction = Ext(10, _floatType, source);
|
||||
var bits = Bitcast(_uintType, source);
|
||||
var absolute = _module.AddInstruction(
|
||||
SpirvOp.BitwiseAnd,
|
||||
_uintType,
|
||||
bits,
|
||||
UInt(0x7FFF_FFFF));
|
||||
var large = _module.AddInstruction(
|
||||
SpirvOp.UGreaterThanEqual,
|
||||
_boolType,
|
||||
absolute,
|
||||
UInt(0x4B00_0000));
|
||||
var finite = _module.AddInstruction(
|
||||
SpirvOp.ULessThan,
|
||||
_boolType,
|
||||
absolute,
|
||||
UInt(0x7F80_0000));
|
||||
var largeFinite = _module.AddInstruction(
|
||||
SpirvOp.LogicalAnd,
|
||||
_boolType,
|
||||
large,
|
||||
finite);
|
||||
var reduced = _module.AddInstruction(
|
||||
SpirvOp.Select,
|
||||
_floatType,
|
||||
largeFinite,
|
||||
Float(0),
|
||||
fraction);
|
||||
if (!preserveSignedZero)
|
||||
{
|
||||
return reduced;
|
||||
}
|
||||
|
||||
var zero = _module.AddInstruction(
|
||||
SpirvOp.IEqual,
|
||||
_boolType,
|
||||
absolute,
|
||||
UInt(0));
|
||||
return _module.AddInstruction(
|
||||
SpirvOp.Select,
|
||||
_floatType,
|
||||
zero,
|
||||
source,
|
||||
reduced);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue