From b9200dd734d4201ec9d8e07e203152d32392a69e Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Fri, 8 Jan 2021 22:55:55 -0300
Subject: [PATCH] Support conditional on BRK and SYNC shader instructions
 (#1878)

* Support conditional on BRK and SYNC shader instructions

* Add TODO comment and bump cache version
---
 Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs       |  2 +-
 Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs |  6 +-----
 .../Decoders/OpCodeBranchPop.cs                  |  2 +-
 .../Decoders/OpCodeConditional.cs                | 16 ++++++++++++++++
 Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs   |  5 +----
 .../Instructions/InstEmitFlow.cs                 |  5 +++--
 6 files changed, 23 insertions(+), 13 deletions(-)
 create mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs

diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index d28d73620..40f6d18c5 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// <summary>
         /// Version of the codegen (to be changed when codegen or guest format change).
         /// </summary>
-        private const ulong ShaderCodeGenVersion = 1759;
+        private const ulong ShaderCodeGenVersion = 1878;
 
         /// <summary>
         /// Creates a new instance of the shader cache.
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs
index 71cb9bca9..9ca437b37 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs
@@ -2,10 +2,8 @@ using Ryujinx.Graphics.Shader.Instructions;
 
 namespace Ryujinx.Graphics.Shader.Decoders
 {
-    class OpCodeBranch : OpCode
+    class OpCodeBranch : OpCodeConditional
     {
-        public Condition Condition { get; }
-
         public int Offset { get; }
 
         public bool PushTarget { get; protected set; }
@@ -14,8 +12,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
 
         public OpCodeBranch(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode)
         {
-            Condition = (Condition)(opCode & 0x1f);
-
             Offset = ((int)(opCode >> 20) << 8) >> 8;
 
             PushTarget = false;
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs
index f6c3e4f46..318048709 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
 
 namespace Ryujinx.Graphics.Shader.Decoders
 {
-    class OpCodeBranchPop : OpCode
+    class OpCodeBranchPop : OpCodeConditional
     {
         public Dictionary<OpCodePush, int> Targets { get; }
 
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs
new file mode 100644
index 000000000..f9110707f
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs
@@ -0,0 +1,16 @@
+using Ryujinx.Graphics.Shader.Instructions;
+
+namespace Ryujinx.Graphics.Shader.Decoders
+{
+    class OpCodeConditional : OpCode
+    {
+        public Condition Condition { get; }
+
+        public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeExit(emitter, address, opCode);
+
+        public OpCodeConditional(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode)
+        {
+            Condition = (Condition)opCode.Extract(0, 5);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs
index caad26a3a..f63d5d116 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs
@@ -2,15 +2,12 @@ using Ryujinx.Graphics.Shader.Instructions;
 
 namespace Ryujinx.Graphics.Shader.Decoders
 {
-    class OpCodeExit : OpCode
+    class OpCodeExit : OpCodeConditional
     {
-        public Condition Condition { get; }
-
         public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeExit(emitter, address, opCode);
 
         public OpCodeExit(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode)
         {
-            Condition = (Condition)opCode.Extract(0, 5);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs
index 332074ae2..d4ab5955f 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs
@@ -146,6 +146,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
             }
             else
             {
+                // TODO: Support CC here aswell (condition).
                 foreach (KeyValuePair<OpCodePush, int> kv in op.Targets)
                 {
                     OpCodePush pushOp = kv.Key;
@@ -176,9 +177,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
 
             Operand pred = Register(op.Predicate);
 
-            if (op is OpCodeBranch opBranch && opBranch.Condition != Condition.Always)
+            if (op is OpCodeConditional opCond && opCond.Condition != Condition.Always)
             {
-                Operand cond = GetCondition(context, opBranch.Condition);
+                Operand cond = GetCondition(context, opCond.Condition);
 
                 if (op.Predicate.IsPT)
                 {