Ryujinx/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
riperiperi f0e27a23a5
Add short duration texture cache (#3754)
* Add short duration texture cache

This texture cache takes textures that lose their last pool reference and keeps them alive until the next frame, or until an incompatible overlap removes it. This is done since under certain circumstances, a texture's reference can be wiped from a pool despite it still being in use - though typically the reference will return when rendering the next frame.

While this may slightly increase texture memory usage when quickly going through a bunch of temporary textures, it's still bounded due to the overlap removal rule.

This greatly increases performance in Hyrule Warriors: Age of Calamity. It may positively affect some UE4 games which dip framerate severely under certain circumstances.

* Small optimization

* Don't forget this.

* Add short cache dictionary

* Address feedback

* Address some feedback
2023-01-17 04:39:46 +01:00

274 lines
9.1 KiB
C#

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
namespace Ryujinx.Graphics.Gpu.Image
{
/// <summary>
/// Maxwell texture descriptor, as stored on the GPU texture pool memory region.
/// </summary>
struct TextureDescriptor : ITextureDescriptor, IEquatable<TextureDescriptor>
{
#pragma warning disable CS0649
public uint Word0;
public uint Word1;
public uint Word2;
public uint Word3;
public uint Word4;
public uint Word5;
public uint Word6;
public uint Word7;
#pragma warning restore CS0649
/// <summary>
/// Unpacks Maxwell texture format integer.
/// </summary>
/// <returns>The texture format integer</returns>
public uint UnpackFormat()
{
return Word0 & 0x8007ffff;
}
/// <summary>
/// Unpacks the swizzle component for the texture red color channel.
/// </summary>
/// <returns>The swizzle component</returns>
public TextureComponent UnpackSwizzleR()
{
return(TextureComponent)((Word0 >> 19) & 7);
}
/// <summary>
/// Unpacks the swizzle component for the texture green color channel.
/// </summary>
/// <returns>The swizzle component</returns>
public TextureComponent UnpackSwizzleG()
{
return(TextureComponent)((Word0 >> 22) & 7);
}
/// <summary>
/// Unpacks the swizzle component for the texture blue color channel.
/// </summary>
/// <returns>The swizzle component</returns>
public TextureComponent UnpackSwizzleB()
{
return(TextureComponent)((Word0 >> 25) & 7);
}
/// <summary>
/// Unpacks the swizzle component for the texture alpha color channel.
/// </summary>
/// <returns>The swizzle component</returns>
public TextureComponent UnpackSwizzleA()
{
return(TextureComponent)((Word0 >> 28) & 7);
}
/// <summary>
/// Unpacks the 40-bits texture GPU virtual address.
/// </summary>
/// <returns>The GPU virtual address</returns>
public ulong UnpackAddress()
{
return Word1 | ((ulong)(Word2 & 0xffff) << 32);
}
/// <summary>
/// Unpacks texture descriptor type for this texture descriptor.
/// This defines the texture layout, among other things.
/// </summary>
/// <returns>The texture descriptor type</returns>
public TextureDescriptorType UnpackTextureDescriptorType()
{
return (TextureDescriptorType)((Word2 >> 21) & 7);
}
/// <summary>
/// Unpacks the texture stride (bytes per line) for linear textures only.
/// Always 32-bytes aligned.
/// </summary>
/// <returns>The linear texture stride</returns>
public int UnpackStride()
{
return (int)(Word3 & 0xffff) << 5;
}
/// <summary>
/// Unpacks the GOB block size in X (width) for block linear textures.
/// Must be always 1, ignored by the GPU.
/// </summary>
/// <returns>THe GOB block X size</returns>
public int UnpackGobBlocksInX()
{
return 1 << (int)(Word3 & 7);
}
/// <summary>
/// Unpacks the GOB block size in Y (height) for block linear textures.
/// Must be always a power of 2, with a maximum value of 32.
/// </summary>
/// <returns>THe GOB block Y size</returns>
public int UnpackGobBlocksInY()
{
return 1 << (int)((Word3 >> 3) & 7);
}
/// <summary>
/// Unpacks the GOB block size in Z (depth) for block linear textures.
/// Must be always a power of 2, with a maximum value of 32.
/// Must be 1 for any texture target other than 3D textures.
/// </summary>
/// <returns>The GOB block Z size</returns>
public int UnpackGobBlocksInZ()
{
return 1 << (int)((Word3 >> 6) & 7);
}
/// <summary>
/// Number of GOB blocks per tile in the X direction.
/// This is only used for sparse textures, should be 1 otherwise.
/// </summary>
/// <returns>The number of GOB blocks per tile</returns>
public int UnpackGobBlocksInTileX()
{
return 1 << (int)((Word3 >> 10) & 7);
}
/// <summary>
/// Unpacks the number of mipmap levels of the texture.
/// </summary>
/// <returns>The number of mipmap levels</returns>
public int UnpackLevels()
{
return (int)(Word3 >> 28) + 1;
}
/// <summary>
/// Unpack the base level texture width size.
/// </summary>
/// <returns>The texture width</returns>
public int UnpackWidth()
{
return (int)(Word4 & 0xffff) + 1;
}
/// <summary>
/// Unpack the width of a buffer texture.
/// </summary>
/// <returns>The texture width</returns>
public int UnpackBufferTextureWidth()
{
return (int)((Word4 & 0xffff) | (Word3 << 16)) + 1;
}
/// <summary>
/// Unpacks the texture sRGB format flag.
/// </summary>
/// <returns>True if the texture is sRGB, false otherwise</returns>
public bool UnpackSrgb()
{
return (Word4 & (1 << 22)) != 0;
}
/// <summary>
/// Unpacks the texture target.
/// </summary>
/// <returns>The texture target</returns>
public TextureTarget UnpackTextureTarget()
{
return (TextureTarget)((Word4 >> 23) & 0xf);
}
/// <summary>
/// Unpack the base level texture height size, or array layers for 1D array textures.
/// Should be ignored for 1D or buffer textures.
/// </summary>
/// <returns>The texture height or layers count</returns>
public int UnpackHeight()
{
return (int)(Word5 & 0xffff) + 1;
}
/// <summary>
/// Unpack the base level texture depth size, number of array layers or cubemap faces.
/// The meaning of this value depends on the texture target.
/// </summary>
/// <returns>The texture depth, layer or faces count</returns>
public int UnpackDepth()
{
return (int)((Word5 >> 16) & 0x3fff) + 1;
}
/// <summary>
/// Unpacks the texture coordinates normalized flag.
/// When this is true, texture coordinates are expected to be in the [0, 1] range on the shader.
/// When this is false, texture coordinates are expected to be in the [0, W], [0, H] and [0, D] range.
/// It must be set to false (by the guest driver) for rectangle textures.
/// </summary>
/// <returns>The texture coordinates normalized flag</returns>
public bool UnpackTextureCoordNormalized()
{
return (Word5 & (1 << 31)) != 0;
}
/// <summary>
/// Unpacks the base mipmap level of the texture.
/// </summary>
/// <returns>The base mipmap level of the texture</returns>
public int UnpackBaseLevel()
{
return (int)(Word7 & 0xf);
}
/// <summary>
/// Unpacks the maximum mipmap level (inclusive) of the texture.
/// Usually equal to Levels minus 1.
/// </summary>
/// <returns>The maximum mipmap level (inclusive) of the texture</returns>
public int UnpackMaxLevelInclusive()
{
return (int)((Word7 >> 4) & 0xf);
}
/// <summary>
/// Unpacks the multisampled texture samples count in each direction.
/// Must be ignored for non-multisample textures.
/// </summary>
/// <returns>The multisample counts enum</returns>
public TextureMsaaMode UnpackTextureMsaaMode()
{
return (TextureMsaaMode)((Word7 >> 8) & 0xf);
}
/// <summary>
/// Check if two descriptors are equal.
/// </summary>
/// <param name="other">The descriptor to compare against</param>
/// <returns>True if they are equal, false otherwise</returns>
public bool Equals(ref TextureDescriptor other)
{
return Unsafe.As<TextureDescriptor, Vector256<byte>>(ref this).Equals(Unsafe.As<TextureDescriptor, Vector256<byte>>(ref other));
}
/// <summary>
/// Check if two descriptors are equal.
/// </summary>
/// <param name="other">The descriptor to compare against</param>
/// <returns>True if they are equal, false otherwise</returns>
public bool Equals(TextureDescriptor other)
{
return Equals(ref other);
}
/// <summary>
/// Gets a hash code for this descriptor.
/// </summary>
/// <returns>The hash code for this descriptor.</returns>
public override int GetHashCode()
{
return Unsafe.As<TextureDescriptor, Vector256<byte>>(ref this).GetHashCode();
}
}
}