From 69ced3a6e8636cfe7ea2f7333dd7cb4512def241 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 19 Nov 2022 06:24:23 -0300
Subject: [PATCH] Fix shader cache on Vulkan when geometry shaders are inserted
 (#3868)

---
 .../Shader/DiskCache/DiskCacheHostStorage.cs  |  4 +--
 .../DiskCache/ShaderBinarySerializer.cs       | 36 +++++++++++++------
 2 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index 69067fe6f3..a91ab9e4fa 100644
--- a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
         private const ushort FileFormatVersionMajor = 1;
         private const ushort FileFormatVersionMinor = 2;
         private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
-        private const uint CodeGenVersion = 3866;
+        private const uint CodeGenVersion = 3868;
 
         private const string SharedTocFileName = "shared.toc";
         private const string SharedDataFileName = "shared.data";
@@ -379,7 +379,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
 
                             if (context.Capabilities.Api == TargetApi.Vulkan)
                             {
-                                ShaderSource[] shaderSources = ShaderBinarySerializer.Unpack(shaders, hostCode, isCompute);
+                                ShaderSource[] shaderSources = ShaderBinarySerializer.Unpack(shaders, hostCode);
 
                                 hostProgram = context.Renderer.CreateProgram(shaderSources, shaderInfo);
                             }
diff --git a/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs b/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs
index 11e54220f7..0e5ce292c3 100644
--- a/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs
@@ -1,5 +1,7 @@
 using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Shader;
 using Ryujinx.Graphics.Shader.Translation;
+using System;
 using System.Collections.Generic;
 using System.IO;
 
@@ -12,8 +14,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
             using MemoryStream output = new MemoryStream();
             using BinaryWriter writer = new BinaryWriter(output);
 
+            writer.Write(sources.Length);
+
             for (int i = 0; i < sources.Length; i++)
             {
+                writer.Write((int)sources[i].Stage);
                 writer.Write(sources[i].BinaryCode.Length);
                 writer.Write(sources[i].BinaryCode);
             }
@@ -21,29 +26,40 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
             return output.ToArray();
         }
 
-        public static ShaderSource[] Unpack(CachedShaderStage[] stages, byte[] code, bool compute)
+        public static ShaderSource[] Unpack(CachedShaderStage[] stages, byte[] code)
         {
             using MemoryStream input = new MemoryStream(code);
             using BinaryReader reader = new BinaryReader(input);
 
             List<ShaderSource> output = new List<ShaderSource>();
 
-            for (int i = compute ? 0 : 1; i < stages.Length; i++)
+            int count = reader.ReadInt32();
+
+            for (int i = 0; i < count; i++)
             {
-                CachedShaderStage stage = stages[i];
-
-                if (stage == null)
-                {
-                    continue;
-                }
-
+                ShaderStage stage = (ShaderStage)reader.ReadInt32();
                 int binaryCodeLength = reader.ReadInt32();
                 byte[] binaryCode = reader.ReadBytes(binaryCodeLength);
 
-                output.Add(new ShaderSource(binaryCode, ShaderCache.GetBindings(stage.Info), stage.Info.Stage, TargetLanguage.Spirv));
+                output.Add(new ShaderSource(binaryCode, GetBindings(stages, stage), stage, TargetLanguage.Spirv));
             }
 
             return output.ToArray();
         }
+
+        private static ShaderBindings GetBindings(CachedShaderStage[] stages, ShaderStage stage)
+        {
+            for (int i = 0; i < stages.Length; i++)
+            {
+                CachedShaderStage currentStage = stages[i];
+
+                if (currentStage != null && currentStage.Info.Stage == stage && currentStage.Info != null)
+                {
+                    return ShaderCache.GetBindings(currentStage.Info);
+                }
+            }
+
+            return new ShaderBindings(Array.Empty<int>(), Array.Empty<int>(), Array.Empty<int>(), Array.Empty<int>());
+        }
     }
 }
\ No newline at end of file