Partial support for shader memory barriers

This commit is contained in:
gdkchan 2019-12-14 14:51:00 -03:00 committed by Thog
parent 1a550e810c
commit 2eccc7023a
9 changed files with 98 additions and 0 deletions

View file

@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.Absolute, InstType.CallUnary, "abs"); Add(Instruction.Absolute, InstType.CallUnary, "abs");
Add(Instruction.Add, InstType.OpBinaryCom, "+", 2); Add(Instruction.Add, InstType.OpBinaryCom, "+", 2);
Add(Instruction.Ballot, InstType.CallUnary, "ballotARB"); Add(Instruction.Ballot, InstType.CallUnary, "ballotARB");
Add(Instruction.Barrier, InstType.CallNullary, "barrier");
Add(Instruction.BitCount, InstType.CallUnary, "bitCount"); Add(Instruction.BitCount, InstType.CallUnary, "bitCount");
Add(Instruction.BitfieldExtractS32, InstType.CallTernary, "bitfieldExtract"); Add(Instruction.BitfieldExtractS32, InstType.CallTernary, "bitfieldExtract");
Add(Instruction.BitfieldExtractU32, 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.FindFirstSetU32, InstType.CallUnary, "findMSB");
Add(Instruction.Floor, InstType.CallUnary, "floor"); Add(Instruction.Floor, InstType.CallUnary, "floor");
Add(Instruction.FusedMultiplyAdd, InstType.CallTernary, "fma"); Add(Instruction.FusedMultiplyAdd, InstType.CallTernary, "fma");
Add(Instruction.GroupMemoryBarrier, InstType.CallNullary, "groupMemoryBarrier");
Add(Instruction.ImageLoad, InstType.Special); Add(Instruction.ImageLoad, InstType.Special);
Add(Instruction.ImageStore, InstType.Special); Add(Instruction.ImageStore, InstType.Special);
Add(Instruction.IsNan, InstType.CallUnary, "isnan"); 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.ShuffleXor, InstType.CallTernary, HelperFunctionNames.ShuffleXor);
Add(Instruction.Maximum, InstType.CallBinary, "max"); Add(Instruction.Maximum, InstType.CallBinary, "max");
Add(Instruction.MaximumU32, InstType.CallBinary, "max"); Add(Instruction.MaximumU32, InstType.CallBinary, "max");
Add(Instruction.MemoryBarrier, InstType.CallNullary, "memoryBarrier");
Add(Instruction.Minimum, InstType.CallBinary, "min"); Add(Instruction.Minimum, InstType.CallBinary, "min");
Add(Instruction.MinimumU32, InstType.CallBinary, "min"); Add(Instruction.MinimumU32, InstType.CallBinary, "min");
Add(Instruction.Multiply, InstType.OpBinaryCom, "*", 1); Add(Instruction.Multiply, InstType.OpBinaryCom, "*", 1);

View file

@ -0,0 +1,10 @@
namespace Ryujinx.Graphics.Shader.Decoders
{
enum BarrierLevel
{
Cta = 0,
Gl = 1,
Sys = 2,
Vc = 3
}
}

View file

@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.Shader.Decoders
{
enum BarrierMode
{
ReductionPopCount = 2,
Scan = 3,
ReductionAnd = 0xa,
ReductionOr = 0x12,
Sync = 0x80,
Arrive = 0x81
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("1110111111011x", InstEmit.Ald, typeof(OpCodeAttribute)); Set("1110111111011x", InstEmit.Ald, typeof(OpCodeAttribute));
Set("1110111111110x", InstEmit.Ast, typeof(OpCodeAttribute)); Set("1110111111110x", InstEmit.Ast, typeof(OpCodeAttribute));
Set("11101100xxxxxx", InstEmit.Atoms, typeof(OpCodeAtom)); Set("11101100xxxxxx", InstEmit.Atoms, typeof(OpCodeAtom));
Set("1111000010101x", InstEmit.Bar, typeof(OpCodeBarrier));
Set("0100110000000x", InstEmit.Bfe, typeof(OpCodeAluCbuf)); Set("0100110000000x", InstEmit.Bfe, typeof(OpCodeAluCbuf));
Set("0011100x00000x", InstEmit.Bfe, typeof(OpCodeAluImm)); Set("0011100x00000x", InstEmit.Bfe, typeof(OpCodeAluImm));
Set("0101110000000x", InstEmit.Bfe, typeof(OpCodeAluReg)); Set("0101110000000x", InstEmit.Bfe, typeof(OpCodeAluReg));
@ -140,6 +141,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("0010000xxxxxxx", InstEmit.Lop3, typeof(OpCodeLopCbuf)); Set("0010000xxxxxxx", InstEmit.Lop3, typeof(OpCodeLopCbuf));
Set("001111xxxxxxxx", InstEmit.Lop3, typeof(OpCodeLopImm)); Set("001111xxxxxxxx", InstEmit.Lop3, typeof(OpCodeLopImm));
Set("0101101111100x", InstEmit.Lop3, typeof(OpCodeLopReg)); Set("0101101111100x", InstEmit.Lop3, typeof(OpCodeLopReg));
Set("1110111110011x", InstEmit.Membar, typeof(OpCodeMemoryBarrier));
Set("0100110010011x", InstEmit.Mov, typeof(OpCodeAluCbuf)); Set("0100110010011x", InstEmit.Mov, typeof(OpCodeAluCbuf));
Set("0011100x10011x", InstEmit.Mov, typeof(OpCodeAluImm)); Set("0011100x10011x", InstEmit.Mov, typeof(OpCodeAluImm));
Set("000000010000xx", InstEmit.Mov, typeof(OpCodeAluImm32)); Set("000000010000xx", InstEmit.Mov, typeof(OpCodeAluImm32));

View file

@ -77,6 +77,17 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetDest(context), res); 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) public static void Ipa(EmitterContext context)
{ {
OpCodeIpa op = (OpCodeIpa)context.CurrOp; OpCodeIpa op = (OpCodeIpa)context.CurrOp;
@ -162,6 +173,20 @@ namespace Ryujinx.Graphics.Shader.Instructions
EmitLoad(context, MemoryRegion.Shared); 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) public static void Out(EmitterContext context)
{ {
OpCode op = context.CurrOp; OpCode op = context.CurrOp;

View file

@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
AtomicSwap, AtomicSwap,
AtomicXor, AtomicXor,
Ballot, Ballot,
Barrier,
BitCount, BitCount,
BitfieldExtractS32, BitfieldExtractS32,
BitfieldExtractU32, BitfieldExtractU32,
@ -62,6 +63,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
FindFirstSetU32, FindFirstSetU32,
Floor, Floor,
FusedMultiplyAdd, FusedMultiplyAdd,
GroupMemoryBarrier,
ImageLoad, ImageLoad,
ImageStore, ImageStore,
IsNan, IsNan,
@ -82,6 +84,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
MarkLabel, MarkLabel,
Maximum, Maximum,
MaximumU32, MaximumU32,
MemoryBarrier,
Minimum, Minimum,
MinimumU32, MinimumU32,
Multiply, Multiply,

View file

@ -61,6 +61,11 @@ namespace Ryujinx.Graphics.Shader.Translation
return context.Add(Instruction.Ballot, Local(), a); 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) public static Operand BitCount(this EmitterContext context, Operand a)
{ {
return context.Add(Instruction.BitCount, Local(), 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)); 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) public static Operand IAbsNeg(this EmitterContext context, Operand a, bool abs, bool neg)
{ {
return context.INegate(context.IAbsolute(a, abs), 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); 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) public static Operand MultiplyHighS32(this EmitterContext context, Operand a, Operand b)
{ {
return context.Add(Instruction.MultiplyHighS32, Local(), a, b); return context.Add(Instruction.MultiplyHighS32, Local(), a, b);