diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index ef998fdd84..8dec34997a 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 0000000000..2d99dcfe92
--- /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 0000000000..a058cbbd71
--- /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 0000000000..81e28aa143
--- /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 0000000000..c31fe87b97
--- /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 bdc7ed80c1..87f1de0c48 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 56688161c1..866df56dfb 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 bffdd0fa77..7108112c97 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 e39d8c645a..14675a55d6 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);