From e747f5cd836b73661414134b182fc50121e56865 Mon Sep 17 00:00:00 2001 From: gdkchan 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 8e210513..ddd69807 100644 --- a/Ryujinx.Graphics.Gpu/Image/Pool.cs +++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs @@ -101,6 +101,16 @@ namespace Ryujinx.Graphics.Gpu.Image /// The GPU resource with the given ID public abstract T1 Get(int id); + /// + /// Checks if a given ID is valid and inside the range of the pool. + /// + /// ID of the descriptor. This is effectively a zero-based index + /// True if the specified ID is valid, false otherwise + public bool IsValidId(int id) + { + return (uint)id <= MaximumId; + } + /// /// 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 91cadde3..a990528e 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; } /// diff --git a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs index 62862e74..73b1232e 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); } - /// - /// Create the equivalent of this TextureDescriptor for the shader cache. - /// - /// The equivalent of this TextureDescriptor for the shader cache. - public GuestTextureDescriptor ToCache() - { - GuestTextureDescriptor result = new GuestTextureDescriptor - { - Handle = uint.MaxValue, - Format = UnpackFormat(), - Target = UnpackTextureTarget(), - IsSrgb = UnpackSrgb(), - IsTextureCoordNormalized = UnpackTextureCoordNormalized(), - - }; - - return result; - } - /// /// Check if two descriptors are equal. /// diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs index 44ffd687..587d60a7 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; + } } } }