diff --git a/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs b/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs index 065a57c44..199551925 100644 --- a/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs +++ b/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs @@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.Shader.Decoders BitwiseAnd = 5, BitwiseOr = 6, BitwiseExclusiveOr = 7, - Swap = 8 + Swap = 8, + SafeAdd = 10 // Only supported by ATOM. } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs index 1bf5d0cd1..006a91f3f 100644 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs @@ -8,10 +8,6 @@ namespace Ryujinx.Graphics.Shader.Decoders public Register Ra { get; } public Register Rb { get; } - public ReductionType Type { get; } - - public int Offset { get; } - public bool Extended { get; } public AtomicOp AtomicOp { get; } @@ -24,15 +20,6 @@ namespace Ryujinx.Graphics.Shader.Decoders Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - Type = (ReductionType)opCode.Extract(28, 2); - - if (Type == ReductionType.FP32FtzRn) - { - Type = ReductionType.S64; - } - - Offset = opCode.Extract(30, 22); - Extended = opCode.Extract(48); AtomicOp = (AtomicOp)opCode.Extract(52, 4); diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs index 302f1fc40..8b9cb20dd 100644 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs @@ -34,6 +34,7 @@ namespace Ryujinx.Graphics.Shader.Decoders #region Instructions Set("1110111111011x", InstEmit.Ald, OpCodeAttribute.Create); Set("1110111111110x", InstEmit.Ast, OpCodeAttribute.Create); + Set("11101101xxxxxx", InstEmit.Atom, OpCodeAtom.Create); Set("11101100xxxxxx", InstEmit.Atoms, OpCodeAtom.Create); Set("1111000010101x", InstEmit.Bar, OpCodeBarrier.Create); Set("0100110000000x", InstEmit.Bfe, OpCodeAluCbuf.Create); diff --git a/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs b/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs index aaa2186e7..4c8bd37e0 100644 --- a/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs +++ b/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs @@ -2,11 +2,11 @@ namespace Ryujinx.Graphics.Shader.Decoders { enum ReductionType { - U32 = 0, - S32 = 1, - U64 = 2, - FP32FtzRn = 3, - U128 = 4, - S64 = 5 + U32 = 0, + S32 = 1, + U64 = 2, + FP32FtzRn = 3, + FP16x2FtzRn = 4, + S64 = 5 } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs index 2a2c8927f..63f9cff78 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs @@ -57,13 +57,47 @@ namespace Ryujinx.Graphics.Shader.Instructions } } + public static void Atom(EmitterContext context) + { + OpCodeAtom op = (OpCodeAtom)context.CurrOp; + + ReductionType type = (ReductionType)op.RawOpCode.Extract(49, 2); + + int sOffset = (op.RawOpCode.Extract(28, 20) << 12) >> 12; + + (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, op.Ra, op.Extended, sOffset); + + Operand value = GetSrcB(context); + + Operand res = EmitAtomicOp( + context, + Instruction.MrGlobal, + op.AtomicOp, + type, + addrLow, + addrHigh, + value); + + context.Copy(GetDest(context), res); + } + public static void Atoms(EmitterContext context) { OpCodeAtom op = (OpCodeAtom)context.CurrOp; + ReductionType type = op.RawOpCode.Extract(28, 2) switch + { + 0 => ReductionType.U32, + 1 => ReductionType.S32, + 2 => ReductionType.U64, + _ => ReductionType.S64 + }; + Operand offset = context.ShiftRightU32(GetSrcA(context), Const(2)); - offset = context.IAdd(offset, Const(op.Offset)); + int sOffset = (op.RawOpCode.Extract(30, 22) << 10) >> 10; + + offset = context.IAdd(offset, Const(sOffset)); Operand value = GetSrcB(context); @@ -71,7 +105,7 @@ namespace Ryujinx.Graphics.Shader.Instructions context, Instruction.MrShared, op.AtomicOp, - op.Type, + type, offset, Const(0), value);