shader cache: Fix invalid virtual address clean up (#1717)

* shader cache: Fix invalid virtual address clean up

This fix an issue causing the virtual address of texture descriptors to
not be cleaned up when caching and instead cleaning texture format and swizzle.

This should fix duplicate high duplication in the cache for certain
games and possible texture corruption issues.

**THIS WILL INVALIDATE ALL SHADER CACHE LEVELS CONSIDERING THE NATURE OF THE ISSUE**

* shader cache: Address gdk's comment
This commit is contained in:
Mary 2020-11-17 22:20:17 +01:00 committed by GitHub
parent 787e20937f
commit 383c039037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 58 additions and 22 deletions

View File

@ -0,0 +1,10 @@
namespace Ryujinx.Graphics.Gpu.Image
{
interface ITextureDescriptor
{
public uint UnpackFormat();
public TextureTarget UnpackTextureTarget();
public bool UnpackSrgb();
public bool UnpackTextureCoordNormalized();
}
}

View File

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary> /// <summary>
/// Maxwell texture descriptor, as stored on the GPU texture pool memory region. /// Maxwell texture descriptor, as stored on the GPU texture pool memory region.
/// </summary> /// </summary>
struct TextureDescriptor struct TextureDescriptor : ITextureDescriptor
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public uint Word0; public uint Word0;
@ -239,12 +239,12 @@ namespace Ryujinx.Graphics.Gpu.Image
GuestTextureDescriptor result = new GuestTextureDescriptor GuestTextureDescriptor result = new GuestTextureDescriptor
{ {
Handle = uint.MaxValue, Handle = uint.MaxValue,
Descriptor = this Format = UnpackFormat(),
}; Target = UnpackTextureTarget(),
IsSrgb = UnpackSrgb(),
IsTextureCoordNormalized = UnpackTextureCoordNormalized(),
// Clear the virtual address };
result.Descriptor.Word0 = 0;
result.Descriptor.Word2 &= 0xFFFF0000;
return result; return result;
} }

View File

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary> /// <summary>
/// Texture target. /// Texture target.
/// </summary> /// </summary>
enum TextureTarget enum TextureTarget : byte
{ {
Texture1D, Texture1D,
Texture2D, Texture2D,

View File

@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
/// <summary> /// <summary>
/// Version of the guest cache shader (to increment when guest cache structure change). /// Version of the guest cache shader (to increment when guest cache structure change).
/// </summary> /// </summary>
private const ulong GuestCacheVersion = 1; private const ulong GuestCacheVersion = 1717;
/// <summary> /// <summary>
/// Create a new cache manager instance /// Create a new cache manager instance

View File

@ -4,12 +4,38 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
{ {
/// <summary> /// <summary>
/// Mostly identical to TextureDescriptor from <see cref="Image"/> but we don't store the address of the texture and store its handle instead. /// Contains part of TextureDescriptor from <see cref="Image"/> used for shader codegen.
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential, Size = 0x20, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = 0xC, Pack = 1)]
struct GuestTextureDescriptor struct GuestTextureDescriptor : ITextureDescriptor
{ {
public uint Handle; public uint Handle;
internal TextureDescriptor Descriptor; public uint Format;
public TextureTarget Target;
[MarshalAs(UnmanagedType.I1)]
public bool IsSrgb;
[MarshalAs(UnmanagedType.I1)]
public bool IsTextureCoordNormalized;
public byte Reserved;
public uint UnpackFormat()
{
return Format;
}
public bool UnpackSrgb()
{
return IsSrgb;
}
public bool UnpackTextureCoordNormalized()
{
return IsTextureCoordNormalized;
}
public TextureTarget UnpackTextureTarget()
{
return Target;
}
} }
} }

View File

@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
private readonly GpuContext _context; private readonly GpuContext _context;
private readonly ReadOnlyMemory<byte> _data; private readonly ReadOnlyMemory<byte> _data;
private readonly GuestGpuAccessorHeader _header; private readonly GuestGpuAccessorHeader _header;
private readonly Dictionary<int, Image.TextureDescriptor> _textureDescriptors; private readonly Dictionary<int, GuestTextureDescriptor> _textureDescriptors;
/// <summary> /// <summary>
/// Creates a new instance of the cached GPU state accessor for shader translation. /// Creates a new instance of the cached GPU state accessor for shader translation.
@ -26,11 +26,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
_context = context; _context = context;
_data = data; _data = data;
_header = header; _header = header;
_textureDescriptors = new Dictionary<int, Image.TextureDescriptor>(); _textureDescriptors = new Dictionary<int, GuestTextureDescriptor>();
foreach (KeyValuePair<int, GuestTextureDescriptor> guestTextureDescriptor in guestTextureDescriptors) foreach (KeyValuePair<int, GuestTextureDescriptor> guestTextureDescriptor in guestTextureDescriptors)
{ {
_textureDescriptors.Add(guestTextureDescriptor.Key, guestTextureDescriptor.Value.Descriptor); _textureDescriptors.Add(guestTextureDescriptor.Key, guestTextureDescriptor.Value);
} }
} }
@ -141,9 +141,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary> /// </summary>
/// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param> /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param>
/// <returns>Texture descriptor</returns> /// <returns>Texture descriptor</returns>
public override Image.TextureDescriptor GetTextureDescriptor(int handle) public override Image.ITextureDescriptor GetTextureDescriptor(int handle)
{ {
if (!_textureDescriptors.TryGetValue(handle, out Image.TextureDescriptor textureDescriptor)) if (!_textureDescriptors.TryGetValue(handle, out GuestTextureDescriptor textureDescriptor))
{ {
throw new ArgumentException(); throw new ArgumentException();
} }

View File

@ -185,7 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary> /// </summary>
/// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param> /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param>
/// <returns>Texture descriptor</returns> /// <returns>Texture descriptor</returns>
public override Image.TextureDescriptor GetTextureDescriptor(int handle) public override Image.ITextureDescriptor GetTextureDescriptor(int handle)
{ {
if (_compute) if (_compute)
{ {

View File

@ -35,9 +35,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
private Dictionary<Hash128, ShaderBundle> _cpProgramsDiskCache; private Dictionary<Hash128, ShaderBundle> _cpProgramsDiskCache;
/// <summary> /// <summary>
/// Version of the codegen (to be incremented when codegen changes). /// Version of the codegen (to be changed when codegen or guest format change).
/// </summary> /// </summary>
private const ulong ShaderCodeGenVersion = 1; private const ulong ShaderCodeGenVersion = 1717;
/// <summary> /// <summary>
/// Creates a new instance of the shader cache. /// Creates a new instance of the shader cache.
@ -888,7 +888,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
foreach (int textureHandle in textureHandlesInUse) foreach (int textureHandle in textureHandlesInUse)
{ {
GuestTextureDescriptor textureDescriptor = gpuAccessor.GetTextureDescriptor(textureHandle).ToCache(); GuestTextureDescriptor textureDescriptor = ((Image.TextureDescriptor)gpuAccessor.GetTextureDescriptor(textureHandle)).ToCache();
textureDescriptor.Handle = (uint)textureHandle; textureDescriptor.Handle = (uint)textureHandle;

View File

@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
{ {
public abstract T MemoryRead<T>(ulong address) where T : unmanaged; public abstract T MemoryRead<T>(ulong address) where T : unmanaged;
public abstract Image.TextureDescriptor GetTextureDescriptor(int handle); public abstract ITextureDescriptor GetTextureDescriptor(int handle);
/// <summary> /// <summary>
/// Queries texture format information, for shaders using image load or store. /// Queries texture format information, for shaders using image load or store.