From e747f5cd836b73661414134b182fc50121e56865 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Thu, 23 Jun 2022 21:41:57 -0300
Subject: [PATCH] Ensure texture ID is valid before getting texture descriptor
 (#3406)

---
 Ryujinx.Graphics.Gpu/Image/Pool.cs            | 10 ++++++++++
 .../Image/TextureBindingsManager.cs           | 17 ++++++++++++++++-
 .../Image/TextureDescriptor.cs                | 19 -------------------
 .../Shader/ShaderSpecializationState.cs       | 12 +++++++-----
 4 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs
index 8e21051344..ddd6980773 100644
--- a/Ryujinx.Graphics.Gpu/Image/Pool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs
@@ -101,6 +101,16 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <returns>The GPU resource with the given ID</returns>
         public abstract T1 Get(int id);
 
+        /// <summary>
+        /// Checks if a given ID is valid and inside the range of the pool.
+        /// </summary>
+        /// <param name="id">ID of the descriptor. This is effectively a zero-based index</param>
+        /// <returns>True if the specified ID is valid, false otherwise</returns>
+        public bool IsValidId(int id)
+        {
+            return (uint)id <= MaximumId;
+        }
+
         /// <summary>
         /// Synchronizes host memory with guest memory.
         /// This causes invalidation of pool entries,
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index 91cadde3ea..a990528ed4 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -738,7 +738,22 @@ namespace Ryujinx.Graphics.Gpu.Image
 
             TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, maximumId);
 
-            return texturePool.GetDescriptor(textureId);
+            TextureDescriptor descriptor;
+
+            if (texturePool.IsValidId(textureId))
+            {
+                descriptor = texturePool.GetDescriptor(textureId);
+            }
+            else
+            {
+                // If the ID is not valid, we just return a default descriptor with the most common state.
+                // Since this is used for shader specialization, doing so might avoid the need for recompilations.
+                descriptor = new TextureDescriptor();
+                descriptor.Word4 |= (uint)TextureTarget.Texture2D << 23;
+                descriptor.Word5 |= 1u << 31; // Coords normalized.
+            }
+
+            return descriptor;
         }
 
         /// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
index 62862e7413..73b1232e5d 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
@@ -241,25 +241,6 @@ namespace Ryujinx.Graphics.Gpu.Image
             return (TextureMsaaMode)((Word7 >> 8) & 0xf);
         }
 
-        /// <summary>
-        /// Create the equivalent of this TextureDescriptor for the shader cache.
-        /// </summary>
-        /// <returns>The equivalent of this TextureDescriptor for the shader cache.</returns>
-        public GuestTextureDescriptor ToCache()
-        {
-            GuestTextureDescriptor result = new GuestTextureDescriptor
-            {
-                Handle = uint.MaxValue,
-                Format = UnpackFormat(),
-                Target = UnpackTextureTarget(),
-                IsSrgb = UnpackSrgb(),
-                IsTextureCoordNormalized = UnpackTextureCoordNormalized(),
-
-            };
-
-            return result;
-        }
-
         /// <summary>
         /// Check if two descriptors are equal.
         /// </summary>
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
index 44ffd687d5..587d60a777 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
@@ -579,14 +579,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
                         textureKey.StageIndex);
 
                     int packedId = TextureHandle.ReadPackedId(textureKey.Handle, cachedTextureBuffer, cachedSamplerBuffer);
-
                     int textureId = TextureHandle.UnpackTextureId(packedId);
 
-                    ref readonly Image.TextureDescriptor descriptor = ref pool.GetDescriptorRef(textureId);
-
-                    if (!MatchesTexture(kv.Value, descriptor))
+                    if (pool.IsValidId(textureId))
                     {
-                        return false;
+                        ref readonly Image.TextureDescriptor descriptor = ref pool.GetDescriptorRef(textureId);
+
+                        if (!MatchesTexture(kv.Value, descriptor))
+                        {
+                            return false;
+                        }
                     }
                 }
             }