diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs index ef998fdd..8dec3499 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs @@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions Add(Instruction.Absolute, InstType.CallUnary, "abs"); Add(Instruction.Add, InstType.OpBinaryCom, "+", 2); Add(Instruction.Ballot, InstType.CallUnary, "ballotARB"); + Add(Instruction.Barrier, InstType.CallNullary, "barrier"); Add(Instruction.BitCount, InstType.CallUnary, "bitCount"); Add(Instruction.BitfieldExtractS32, InstType.CallTernary, "bitfieldExtract"); Add(Instruction.BitfieldExtractU32, InstType.CallTernary, "bitfieldExtract"); @@ -65,6 +66,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions Add(Instruction.FindFirstSetU32, InstType.CallUnary, "findMSB"); Add(Instruction.Floor, InstType.CallUnary, "floor"); Add(Instruction.FusedMultiplyAdd, InstType.CallTernary, "fma"); + Add(Instruction.GroupMemoryBarrier, InstType.CallNullary, "groupMemoryBarrier"); Add(Instruction.ImageLoad, InstType.Special); Add(Instruction.ImageStore, InstType.Special); Add(Instruction.IsNan, InstType.CallUnary, "isnan"); @@ -91,6 +93,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions Add(Instruction.ShuffleXor, InstType.CallTernary, HelperFunctionNames.ShuffleXor); Add(Instruction.Maximum, InstType.CallBinary, "max"); Add(Instruction.MaximumU32, InstType.CallBinary, "max"); + Add(Instruction.MemoryBarrier, InstType.CallNullary, "memoryBarrier"); Add(Instruction.Minimum, InstType.CallBinary, "min"); Add(Instruction.MinimumU32, InstType.CallBinary, "min"); Add(Instruction.Multiply, InstType.OpBinaryCom, "*", 1); diff --git a/Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs b/Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs new file mode 100644 index 00000000..2d99dcfe --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.Graphics.Shader.Decoders +{ + enum BarrierLevel + { + Cta = 0, + Gl = 1, + Sys = 2, + Vc = 3 + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs b/Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs new file mode 100644 index 00000000..a058cbbd --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Graphics.Shader.Decoders +{ + enum BarrierMode + { + ReductionPopCount = 2, + Scan = 3, + ReductionAnd = 0xa, + ReductionOr = 0x12, + Sync = 0x80, + Arrive = 0x81 + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs new file mode 100644 index 00000000..81e28aa1 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs @@ -0,0 +1,14 @@ +using Ryujinx.Graphics.Shader.Instructions; + +namespace Ryujinx.Graphics.Shader.Decoders +{ + class OpCodeBarrier : OpCode + { + public BarrierMode Mode { get; } + + public OpCodeBarrier(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) + { + Mode = (BarrierMode)((opCode >> 32) & 0x9b); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs new file mode 100644 index 00000000..c31fe87b --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs @@ -0,0 +1,14 @@ +using Ryujinx.Graphics.Shader.Instructions; + +namespace Ryujinx.Graphics.Shader.Decoders +{ + class OpCodeMemoryBarrier : OpCode + { + public BarrierLevel Level { get; } + + public OpCodeMemoryBarrier(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) + { + Level = (BarrierLevel)opCode.Extract(8, 2); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs index bdc7ed80..87f1de0c 100644 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs @@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Shader.Decoders Set("1110111111011x", InstEmit.Ald, typeof(OpCodeAttribute)); Set("1110111111110x", InstEmit.Ast, typeof(OpCodeAttribute)); Set("11101100xxxxxx", InstEmit.Atoms, typeof(OpCodeAtom)); + Set("1111000010101x", InstEmit.Bar, typeof(OpCodeBarrier)); Set("0100110000000x", InstEmit.Bfe, typeof(OpCodeAluCbuf)); Set("0011100x00000x", InstEmit.Bfe, typeof(OpCodeAluImm)); Set("0101110000000x", InstEmit.Bfe, typeof(OpCodeAluReg)); @@ -140,6 +141,7 @@ namespace Ryujinx.Graphics.Shader.Decoders Set("0010000xxxxxxx", InstEmit.Lop3, typeof(OpCodeLopCbuf)); Set("001111xxxxxxxx", InstEmit.Lop3, typeof(OpCodeLopImm)); Set("0101101111100x", InstEmit.Lop3, typeof(OpCodeLopReg)); + Set("1110111110011x", InstEmit.Membar, typeof(OpCodeMemoryBarrier)); Set("0100110010011x", InstEmit.Mov, typeof(OpCodeAluCbuf)); Set("0011100x10011x", InstEmit.Mov, typeof(OpCodeAluImm)); Set("000000010000xx", InstEmit.Mov, typeof(OpCodeAluImm32)); diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs index 56688161..866df56d 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs @@ -77,6 +77,17 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(GetDest(context), res); } + public static void Bar(EmitterContext context) + { + OpCodeBarrier op = (OpCodeBarrier)context.CurrOp; + + // TODO: Support other modes. + if (op.Mode == BarrierMode.Sync) + { + context.Barrier(); + } + } + public static void Ipa(EmitterContext context) { OpCodeIpa op = (OpCodeIpa)context.CurrOp; @@ -162,6 +173,20 @@ namespace Ryujinx.Graphics.Shader.Instructions EmitLoad(context, MemoryRegion.Shared); } + public static void Membar(EmitterContext context) + { + OpCodeMemoryBarrier op = (OpCodeMemoryBarrier)context.CurrOp; + + if (op.Level == BarrierLevel.Cta) + { + context.GroupMemoryBarrier(); + } + else + { + context.MemoryBarrier(); + } + } + public static void Out(EmitterContext context) { OpCode op = context.CurrOp; diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs index bffdd0fa..7108112c 100644 --- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs +++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs @@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation AtomicSwap, AtomicXor, Ballot, + Barrier, BitCount, BitfieldExtractS32, BitfieldExtractU32, @@ -62,6 +63,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation FindFirstSetU32, Floor, FusedMultiplyAdd, + GroupMemoryBarrier, ImageLoad, ImageStore, IsNan, @@ -82,6 +84,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation MarkLabel, Maximum, MaximumU32, + MemoryBarrier, Minimum, MinimumU32, Multiply, diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs index e39d8c64..14675a55 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs @@ -61,6 +61,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.Ballot, Local(), a); } + public static Operand Barrier(this EmitterContext context) + { + return context.Add(Instruction.Barrier); + } + public static Operand BitCount(this EmitterContext context, Operand a) { return context.Add(Instruction.BitCount, Local(), a); @@ -336,6 +341,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.SwizzleAdd, Local(), a, b, Const(mask)); } + public static Operand GroupMemoryBarrier(this EmitterContext context) + { + return context.Add(Instruction.GroupMemoryBarrier); + } + public static Operand IAbsNeg(this EmitterContext context, Operand a, bool abs, bool neg) { return context.INegate(context.IAbsolute(a, abs), neg); @@ -476,6 +486,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.LoadShared, Local(), a); } + public static Operand MemoryBarrier(this EmitterContext context) + { + return context.Add(Instruction.MemoryBarrier); + } + public static Operand MultiplyHighS32(this EmitterContext context, Operand a, Operand b) { return context.Add(Instruction.MultiplyHighS32, Local(), a, b);