From 1a888ae0871c5ef590c92b992b87f01f05a19637 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sun, 24 Jul 2022 15:33:30 -0300
Subject: [PATCH] Add support for conditional (with CC) shader Exit
 instructions (#3470)

* Add support for conditional (with CC) shader Exit instructions

* Shader cache version bump

* Make CSM conditions default to false for EXIT.CC
---
 .../Shader/DiskCache/DiskCacheHostStorage.cs  |  2 +-
 .../Instructions/InstEmitFlowControl.cs       | 19 +++++++++++++++----
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index 33a87fa50d..a47af94256 100644
--- a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
         private const ushort FileFormatVersionMajor = 1;
         private const ushort FileFormatVersionMinor = 1;
         private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
-        private const uint CodeGenVersion = 3472;
+        private const uint CodeGenVersion = 3469;
 
         private const string SharedTocFileName = "shared.toc";
         private const string SharedDataFileName = "shared.data";
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs
index 3cb8fe727b..aee52c517c 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs
@@ -104,12 +104,23 @@ namespace Ryujinx.Graphics.Shader.Instructions
                 return;
             }
 
-            // TODO: Figure out how this is supposed to work in the
-            // presence of other condition codes.
             if (op.Ccc == Ccc.T)
             {
                 context.Return();
             }
+            else
+            {
+                Operand cond = GetCondition(context, op.Ccc, IrConsts.False);
+
+                // If the condition is always false, we don't need to do anything.
+                if (cond.Type != OperandType.Constant || cond.Value != IrConsts.False)
+                {
+                    Operand lblSkip = Label();
+                    context.BranchIfFalse(lblSkip, cond);
+                    context.Return();
+                    context.MarkLabel(lblSkip);
+                }
+            }
         }
 
         public static void Kil(EmitterContext context)
@@ -250,7 +261,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
             }
         }
 
-        private static Operand GetCondition(EmitterContext context, Ccc cond)
+        private static Operand GetCondition(EmitterContext context, Ccc cond, int defaultCond = IrConsts.True)
         {
             // TODO: More condition codes, figure out how they work.
             switch (cond)
@@ -263,7 +274,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
                     return context.BitwiseNot(GetZF());
             }
 
-            return Const(IrConsts.True);
+            return Const(defaultCond);
         }
     }
 }
\ No newline at end of file