diff --git a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
index 33ed78818..fc30d03c7 100644
--- a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
@@ -3,17 +3,31 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// A texture cache that automatically removes older textures that are not used for some time.
+ /// The cache works with a rotated list with a fixed size. When new textures are added, the
+ /// old ones at the bottom of the list are deleted.
+ ///
class AutoDeleteCache : IEnumerable
{
private const int MaxCapacity = 2048;
- private LinkedList _textures;
+ private readonly LinkedList _textures;
+ ///
+ /// Creates a new instance of the automatic deletion cache.
+ ///
public AutoDeleteCache()
{
_textures = new LinkedList();
}
+ ///
+ /// Adds a new texture to the cache, even if the texture added is already on the cache.
+ /// Using this method is only recommended if you know that the texture is not yet on the cache,
+ /// otherwise it would store the same texture more than once.
+ ///
+ /// The texture to be added to the cache
public void Add(Texture texture)
{
texture.IncrementReferenceCount();
@@ -32,6 +46,12 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Adds a new texture to the cache, or just moves it to the top of the list if the
+ /// texture is already on the cache. Moving the texture to the top of the list prevents
+ /// it from being deleted, as the textures on the bottom of the list are deleted when new ones are added.
+ ///
+ /// The texture to be added, or moved to the top
public void Lift(Texture texture)
{
if (texture.CacheNode != null)
diff --git a/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs b/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
index a728c66e1..4f73bfa86 100644
--- a/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
+++ b/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
@@ -2,20 +2,48 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Represents texture format information.
+ ///
struct FormatInfo
{
- private static FormatInfo _rgba8 = new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4);
-
- public static FormatInfo Default => _rgba8;
+ ///
+ /// A default, generic RGBA8 texture format.
+ ///
+ public static FormatInfo Default { get; } = new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4);
+ ///
+ /// The format of the texture data.
+ ///
public Format Format { get; }
- public int BlockWidth { get; }
- public int BlockHeight { get; }
+ ///
+ /// The block width for compressed formats. Must be 1 for non-compressed formats.
+ ///
+ public int BlockWidth { get; }
+
+ ///
+ /// The block height for compressed formats. Must be 1 for non-compressed formats.
+ ///
+ public int BlockHeight { get; }
+
+ ///
+ /// The number of bytes occupied by a single pixel in memory of the texture data.
+ ///
public int BytesPerPixel { get; }
+ ///
+ /// Whenever or not the texture format is a compressed format. Determined from block size.
+ ///
public bool IsCompressed => (BlockWidth | BlockHeight) != 1;
+ ///
+ /// Constructs the texture format info structure.
+ ///
+ /// The format of the texture data
+ /// The block width for compressed formats. Must be 1 for non-compressed formats
+ /// The block height for compressed formats. Must be 1 for non-compressed formats
+ /// The number of bytes occupied by a single pixel in memory of the texture data
public FormatInfo(
Format format,
int blockWidth,
diff --git a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
index baff2e4fc..468a1ed5c 100644
--- a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
+++ b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
@@ -3,6 +3,9 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Contains format tables, for texture and vertex attribute formats.
+ ///
static class FormatTable
{
private static Dictionary _textureFormats = new Dictionary()
@@ -186,6 +189,13 @@ namespace Ryujinx.Graphics.Gpu.Image
{ 0x36000000, Format.R10G10B10A2Sscaled }
};
+ ///
+ /// Try getting the texture format from a encoded format integer from the Maxwell texture descriptor.
+ ///
+ /// The encoded format integer from the texture descriptor
+ /// Indicates if the format is a sRGB format
+ /// The output texture format
+ /// True if the format is valid, false otherwise
public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format)
{
encoded |= (isSrgb ? 1u << 19 : 0u);
@@ -193,6 +203,12 @@ namespace Ryujinx.Graphics.Gpu.Image
return _textureFormats.TryGetValue(encoded, out format);
}
+ ///
+ /// Try getting the vertex attribute format from a encoded format integer from Maxwell attribute registers.
+ ///
+ /// The encoded format integer from the attribute registers
+ /// The output vertex attribute format
+ /// True if the format is valid, false otherwise
public static bool TryGetAttribFormat(uint encoded, out Format format)
{
return _attribFormats.TryGetValue(encoded, out format);
diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs
index 5ce8d7f68..bb55d40e1 100644
--- a/Ryujinx.Graphics.Gpu/Image/Pool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs
@@ -3,6 +3,10 @@ using System;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Represents a pool of GPU resources, such as samplers or textures.
+ ///
+ /// GPU resource type
abstract class Pool : IDisposable
{
protected const int DescriptorSize = 0x20;
@@ -11,10 +15,21 @@ namespace Ryujinx.Graphics.Gpu.Image
protected T[] Items;
+ ///
+ /// The maximum ID value of resources on the pool (inclusive).
+ /// The maximum amount of resources on the pool is equal to this value plus one.
+ ///
public int MaximumId { get; }
+ ///
+ /// The address of the pool in guest memory.
+ ///
public ulong Address { get; }
- public ulong Size { get; }
+
+ ///
+ /// The size of the pool in bytes.
+ ///
+ public ulong Size { get; }
public Pool(GpuContext context, ulong address, int maximumId)
{
@@ -31,8 +46,18 @@ namespace Ryujinx.Graphics.Gpu.Image
Size = size;
}
+ ///
+ /// Gets the GPU resource with the given ID.
+ ///
+ /// ID of the resource. This is effectively a zero-based index
+ /// The GPU resource with the given ID
public abstract T Get(int id);
+ ///
+ /// Synchronizes host memory with guest memory.
+ /// This causes a invalidation of pool entries,
+ /// if a modification of entries by the CPU is detected.
+ ///
public void SynchronizeMemory()
{
(ulong, ulong)[] modifiedRanges = Context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.TexturePool);
@@ -57,6 +82,13 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Invalidates a range of memory of the GPU resource pool.
+ /// Entries that falls inside the speicified range will be invalidated,
+ /// causing all the data to be reloaded from guest memory.
+ ///
+ /// The start address of the range to invalidate
+ /// The size of the range to invalidate
public void InvalidateRange(ulong address, ulong size)
{
ulong endAddress = address + size;
@@ -80,6 +112,8 @@ namespace Ryujinx.Graphics.Gpu.Image
endAddress = texturePoolEndAddress;
}
+ size = endAddress - address;
+
InvalidateRangeImpl(address, size);
}
@@ -87,6 +121,10 @@ namespace Ryujinx.Graphics.Gpu.Image
protected abstract void Delete(T item);
+ ///
+ /// Performs the disposal of all resources stored on the pool.
+ /// It's an error to try using the pool after disposal.
+ ///
public void Dispose()
{
if (Items != null)
diff --git a/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs b/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs
index f14a17f2e..94b3f5425 100644
--- a/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs
+++ b/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs
@@ -1,5 +1,9 @@
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Represents a filter used with texture minification linear filtering.
+ /// This feature is only supported on NVIDIA GPUs.
+ ///
enum ReductionFilter
{
Average,
diff --git a/Ryujinx.Graphics.Gpu/Image/Sampler.cs b/Ryujinx.Graphics.Gpu/Image/Sampler.cs
index 80790bd51..23c6160e3 100644
--- a/Ryujinx.Graphics.Gpu/Image/Sampler.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Sampler.cs
@@ -3,10 +3,21 @@ using System;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Cached sampler entry for sampler pools.
+ ///
class Sampler : IDisposable
{
+ ///
+ /// Host sampler object.
+ ///
public ISampler HostSampler { get; }
+ ///
+ /// Creates a new instance of the cached sampler.
+ ///
+ /// The GPU context the sampler belongs to
+ /// The Maxwell sampler descriptor
public Sampler(GpuContext context, SamplerDescriptor descriptor)
{
MinFilter minFilter = descriptor.UnpackMinFilter();
@@ -42,6 +53,9 @@ namespace Ryujinx.Graphics.Gpu.Image
maxAnisotropy));
}
+ ///
+ /// Disposes the host sampler object.
+ ///
public void Dispose()
{
HostSampler.Dispose();
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs b/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
index 00b4ecb46..80b1b70fd 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
@@ -2,6 +2,10 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Maxwell sampler descriptor structure.
+ /// This structure defines the sampler descriptor as it is packed on the GPU sampler pool region.
+ ///
struct SamplerDescriptor
{
private static readonly float[] _f5ToF32ConversionLut = new float[]
@@ -56,41 +60,81 @@ namespace Ryujinx.Graphics.Gpu.Image
public uint BorderColorB;
public uint BorderColorA;
+ ///
+ /// Unpacks the texture wrap mode along the X axis.
+ ///
+ /// The texture wrap mode enum
public AddressMode UnpackAddressU()
{
return (AddressMode)(Word0 & 7);
}
+ //
+ /// Unpacks the texture wrap mode along the Y axis.
+ ///
+ /// The texture wrap mode enum
public AddressMode UnpackAddressV()
{
return (AddressMode)((Word0 >> 3) & 7);
}
+ //
+ /// Unpacks the texture wrap mode along the Z axis.
+ ///
+ /// The texture wrap mode enum
public AddressMode UnpackAddressP()
{
return (AddressMode)((Word0 >> 6) & 7);
}
+ ///
+ /// Unpacks the compare mode used for depth comparison on the shader, for
+ /// depth buffer texture.
+ /// This is only relevant for shaders with shadow samplers.
+ ///
+ /// The depth comparison mode enum
public CompareMode UnpackCompareMode()
{
return (CompareMode)((Word0 >> 9) & 1);
}
+ ///
+ /// Unpacks the compare operation used for depth comparison on the shader, for
+ /// depth buffer texture.
+ /// This is only relevant for shaders with shadow samplers.
+ ///
+ /// The depth comparison operation enum
public CompareOp UnpackCompareOp()
{
return (CompareOp)(((Word0 >> 10) & 7) + 1);
}
+ ///
+ /// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering.
+ ///
+ /// The maximum anisotropy
public float UnpackMaxAnisotropy()
{
return _maxAnisotropyLut[(Word0 >> 20) & 7];
}
+ ///
+ /// Unpacks the texture magnification filter.
+ /// This defines the filtering used when the texture covers an area on the screen
+ /// that is larger than the texture size.
+ ///
+ /// The magnification filter
public MagFilter UnpackMagFilter()
{
return (MagFilter)(Word1 & 3);
}
+ ///
+ /// Unpacks the texture minification filter.
+ /// This defines the filtering used when the texture covers an area on the screen
+ /// that is smaller than the texture size.
+ ///
+ /// The minification filter
public MinFilter UnpackMinFilter()
{
SamplerMinFilter minFilter = (SamplerMinFilter)((Word1 >> 4) & 3);
@@ -99,6 +143,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return ConvertFilter(minFilter, mipFilter);
}
+ ///
+ /// Converts two minification and filter enum, to a single minification enum,
+ /// including mipmap filtering information, as expected from the host API.
+ ///
+ /// The minification filter
+ /// The mipmap level filter
+ /// The combined, host API compatible filter enum
private static MinFilter ConvertFilter(SamplerMinFilter minFilter, SamplerMipFilter mipFilter)
{
switch (mipFilter)
@@ -131,11 +182,22 @@ namespace Ryujinx.Graphics.Gpu.Image
return MinFilter.Nearest;
}
+ ///
+ /// Unpacks the reduction filter, used with texture minification linear filtering.
+ /// This describes how the final value will be computed from neighbouring pixels.
+ ///
+ /// The reduction filter
public ReductionFilter UnpackReductionFilter()
{
return (ReductionFilter)((Word1 >> 10) & 3);
}
+ ///
+ /// Unpacks the level-of-detail bias value.
+ /// This is a bias added to the level-of-detail value as computed by the GPU, used to select
+ /// which mipmap level to use from a given texture.
+ ///
+ /// The level-of-detail bias value
public float UnpackMipLodBias()
{
int fixedValue = (int)(Word1 >> 12) & 0x1fff;
@@ -145,16 +207,28 @@ namespace Ryujinx.Graphics.Gpu.Image
return fixedValue * Frac8ToF32;
}
+ ///
+ /// Unpacks the level-of-detail snap value.
+ ///
+ /// The level-of-detail snap value
public float UnpackLodSnap()
{
return _f5ToF32ConversionLut[(Word1 >> 26) & 0x1f];
}
+ ///
+ /// Unpacks the minimum level-of-detail value.
+ ///
+ /// The minimum level-of-detail value
public float UnpackMinLod()
{
return (Word2 & 0xfff) * Frac8ToF32;
}
+ ///
+ /// Unpacks the maximum level-of-detail value.
+ ///
+ /// The maximum level-of-detail value
public float UnpackMaxLod()
{
return ((Word2 >> 12) & 0xfff) * Frac8ToF32;
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerMinFilter.cs b/Ryujinx.Graphics.Gpu/Image/SamplerMinFilter.cs
index b3274b649..17beb1293 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerMinFilter.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerMinFilter.cs
@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Sampler texture minification filter.
+ ///
enum SamplerMinFilter
{
Nearest = 1,
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerMipFilter.cs b/Ryujinx.Graphics.Gpu/Image/SamplerMipFilter.cs
index 0bc9eb92c..319d41960 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerMipFilter.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerMipFilter.cs
@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Sampler texture mipmap level filter.
+ ///
enum SamplerMipFilter
{
None = 1,
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
index 555551095..f10f800cd 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
@@ -3,12 +3,26 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Sampler pool.
+ ///
class SamplerPool : Pool
{
private int _sequenceNumber;
+ ///
+ /// Constructs a new instance of the sampler pool.
+ ///
+ /// GPU context that the sampler pool belongs to
+ /// Address of the sampler pool in guest memory
+ /// Maximum sampler ID of the sampler pool (equal to maximum samplers minus one)
public SamplerPool(GpuContext context, ulong address, int maximumId) : base(context, address, maximumId) { }
+ ///
+ /// Gets the sampler with the given ID.
+ ///
+ /// ID of the sampler. This is effectively a zero-based index
+ /// The sampler with the given ID
public override Sampler Get(int id)
{
if ((uint)id >= Items.Length)
@@ -41,6 +55,11 @@ namespace Ryujinx.Graphics.Gpu.Image
return sampler;
}
+ ///
+ /// Implementation of the sampler pool range invalidation.
+ ///
+ /// Start address of the range of the sampler pool
+ /// Size of the range being invalidated
protected override void InvalidateRangeImpl(ulong address, ulong size)
{
ulong endAddress = address + size;
@@ -60,6 +79,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Deletes a given sampler pool entry.
+ /// The host memory used by the sampler is released by the driver.
+ ///
+ /// The entry to be deleted
protected override void Delete(Sampler item)
{
item?.Dispose();
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 544c49af5..9e5bea908 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -10,14 +10,23 @@ using System.Diagnostics;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Represents a cached GPU texture.
+ ///
class Texture : IRange
{
private GpuContext _context;
private SizeInfo _sizeInfo;
+ ///
+ /// Texture format.
+ ///
public Format Format => Info.FormatInfo.Format;
+ ///
+ /// Texture information.
+ ///
public TextureInfo Info { get; private set; }
private int _depth;
@@ -34,21 +43,48 @@ namespace Ryujinx.Graphics.Gpu.Image
private List _views;
+ ///
+ /// Host texture.
+ ///
public ITexture HostTexture { get; private set; }
+ ///
+ /// Intrusive linked list node used on the auto deletion texture cache.
+ ///
public LinkedListNode CacheNode { get; set; }
+ ///
+ /// Texture data modified by the GPU.
+ ///
public bool Modified { get; set; }
- public ulong Address => Info.Address;
+ ///
+ /// Start address of the texture in guest memory.
+ ///
+ public ulong Address => Info.Address;
+
+ ///
+ /// End address of the texture in guest memory.
+ ///
public ulong EndAddress => Info.Address + Size;
+ ///
+ /// Texture size in bytes.
+ ///
public ulong Size => (ulong)_sizeInfo.TotalSize;
private int _referenceCount;
private int _sequenceNumber;
+ ///
+ /// Constructs a new instance of the cached GPU texture.
+ ///
+ /// GPU context that the texture belongs to
+ /// Texture information
+ /// Size information of the texture
+ /// The first layer of the texture, or 0 if the texture has no parent
+ /// The first mipmap level of the texture, or 0 if the texture has no parent
private Texture(
GpuContext context,
TextureInfo info,
@@ -64,6 +100,12 @@ namespace Ryujinx.Graphics.Gpu.Image
_hasData = true;
}
+ ///
+ /// Constructs a new instance of the cached GPU texture.
+ ///
+ /// GPU context that the texture belongs to
+ /// Texture information
+ /// Size information of the texture
public Texture(GpuContext context, TextureInfo info, SizeInfo sizeInfo)
{
InitializeTexture(context, info, sizeInfo);
@@ -73,6 +115,14 @@ namespace Ryujinx.Graphics.Gpu.Image
HostTexture = _context.Renderer.CreateTexture(createInfo);
}
+ ///
+ /// Common texture initialization method.
+ /// This sets the context, info and sizeInfo fields.
+ /// Other fields are initialized with their default values.
+ ///
+ /// GPU context that the texture belongs to
+ /// Texture information
+ /// Size information of the texture
private void InitializeTexture(GpuContext context, TextureInfo info, SizeInfo sizeInfo)
{
_context = context;
@@ -85,6 +135,17 @@ namespace Ryujinx.Graphics.Gpu.Image
_views = new List();
}
+ ///
+ /// Create a texture view from this texture.
+ /// A texture view is defined as a child texture, from a sub-range of their parent texture.
+ /// For example, the initial layer and mipmap level of the view can be defined, so the texture
+ /// will start at the given layer/level of the parent texture.
+ ///
+ /// Child texture information
+ /// Child texture size information
+ /// Start layer of the child texture on the parent texture
+ /// Start mipmap level of the child texture on the parent texture
+ /// The child texture
public Texture CreateView(TextureInfo info, SizeInfo sizeInfo, int firstLayer, int firstLevel)
{
Texture texture = new Texture(
@@ -103,6 +164,10 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
+ ///
+ /// Adds a child texture to this texture.
+ ///
+ /// The child texture
private void AddView(Texture texture)
{
_views.Add(texture);
@@ -110,6 +175,10 @@ namespace Ryujinx.Graphics.Gpu.Image
texture._viewStorage = this;
}
+ ///
+ /// Removes a child texture from this texture.
+ ///
+ /// The child texture
private void RemoveView(Texture texture)
{
_views.Remove(texture);
@@ -119,6 +188,14 @@ namespace Ryujinx.Graphics.Gpu.Image
DeleteIfNotUsed();
}
+ ///
+ /// Changes the texture size.
+ /// This operation may also change the size of all mipmap levels, including from the parent
+ /// and other possible child textures, to ensure that all sizes are consistent.
+ ///
+ /// The new texture width
+ /// The new texture height
+ /// The new texture depth (for 3D textures) or layers (for layered textures)
public void ChangeSize(int width, int height, int depthOrLayers)
{
width <<= _firstLevel;
@@ -155,6 +232,14 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Recreates the texture storage (or view, in the case of child textures) of this texture.
+ /// This allows recreating the texture with a new size.
+ /// A copy is automatically performed from the old to the new texture.
+ ///
+ /// The new texture width
+ /// The new texture height
+ /// The new texture depth (for 3D textures) or layers (for layered textures)
private void RecreateStorageOrView(int width, int height, int depthOrLayers)
{
SetInfo(new TextureInfo(
@@ -194,6 +279,13 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Synchronizes guest and host memory.
+ /// This will overwrite the texture data with the texture data on the guest memory, if a CPU
+ /// modification is detected.
+ /// Be aware that this can cause texture data written by the GPU to be lost, this is just a
+ /// one way copy (from CPU owned to GPU owned memory).
+ ///
public void SynchronizeMemory()
{
if (_sequenceNumber == _context.SequenceNumber && _hasData)
@@ -266,6 +358,14 @@ namespace Ryujinx.Graphics.Gpu.Image
_hasData = true;
}
+ ///
+ /// Flushes the texture data.
+ /// This causes the texture data to be written back to guest memory.
+ /// If the texture was written by the GPU, this includes all modification made by the GPU
+ /// up to this point.
+ /// Be aware that this is a expensive operation, avoid calling it unless strictly needed.
+ /// This may cause data corruption if the memory is already being used for something else on the CPU side.
+ ///
public void Flush()
{
Span data = HostTexture.GetData();
@@ -302,6 +402,13 @@ namespace Ryujinx.Graphics.Gpu.Image
_context.PhysicalMemory.Write(Address, data);
}
+ ///
+ /// Performs a comparison of this texture information, with the specified texture information.
+ /// This performs a strict comparison, used to check if two textures are equal.
+ ///
+ /// Texture information to compare with
+ /// Comparison flags
+ /// True if the textures are strictly equal or similar, false otherwise
public bool IsPerfectMatch(TextureInfo info, TextureSearchFlags flags)
{
if (!FormatMatches(info, (flags & TextureSearchFlags.Strict) != 0))
@@ -344,6 +451,12 @@ namespace Ryujinx.Graphics.Gpu.Image
return Info.Address == info.Address && Info.Levels == info.Levels;
}
+ ///
+ /// Checks if the texture format matches with the specified texture information.
+ ///
+ /// Texture information to compare with
+ /// True to perform a strict comparison (formats must be exactly equal)
+ /// True if the format matches, with the given comparison rules
private bool FormatMatches(TextureInfo info, bool strict)
{
// D32F and R32F texture have the same representation internally,
@@ -356,6 +469,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return Info.FormatInfo.Format == info.FormatInfo.Format;
}
+ ///
+ /// Checks if the texture layout specified matches with this texture layout.
+ /// The layout information is composed of the Stride for linear textures, or GOB block size
+ /// for block linear textures.
+ ///
+ /// Texture information to compare with
+ /// True if the layout matches, false otherwise
private bool LayoutMatches(TextureInfo info)
{
if (Info.IsLinear != info.IsLinear)
@@ -376,11 +496,23 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Checks if the texture sizes of the supplied texture information matches this texture.
+ ///
+ /// Texture information to compare with
+ /// True if the size matches, false otherwise
public bool SizeMatches(TextureInfo info)
{
return SizeMatches(info, alignSizes: false);
}
+ ///
+ /// Checks if the texture sizes of the supplied texture information matches the given level of
+ /// this texture.
+ ///
+ /// Texture information to compare with
+ /// Mipmap level of this texture to compare with
+ /// True if the size matches with the level, false otherwise
public bool SizeMatches(TextureInfo info, int level)
{
return Math.Max(1, Info.Width >> level) == info.Width &&
@@ -388,6 +520,12 @@ namespace Ryujinx.Graphics.Gpu.Image
Math.Max(1, Info.GetDepth() >> level) == info.GetDepth();
}
+ ///
+ /// Checks if the texture sizes of the supplied texture information matches this texture.
+ ///
+ /// Texture information to compare with
+ /// True to align the sizes according to the texture layout for comparison
+ /// True if the sizes matches, false otherwise
private bool SizeMatches(TextureInfo info, bool alignSizes)
{
if (Info.GetLayers() != info.GetLayers())
@@ -412,6 +550,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Checks if the texture shader sampling parameters matches.
+ ///
+ /// Texture information to compare with
+ /// True if the texture shader sampling parameters matches, false otherwise
private bool SamplerParamsMatches(TextureInfo info)
{
return Info.DepthStencilMode == info.DepthStencilMode &&
@@ -421,6 +564,11 @@ namespace Ryujinx.Graphics.Gpu.Image
Info.SwizzleA == info.SwizzleA;
}
+ ///
+ /// Check if the texture target and samples count (for multisampled textures) matches.
+ ///
+ /// Texture information to compare with
+ /// True if the texture target and samples count matches, false otherwise
private bool TargetAndSamplesCompatible(TextureInfo info)
{
return Info.Target == info.Target &&
@@ -428,6 +576,14 @@ namespace Ryujinx.Graphics.Gpu.Image
Info.SamplesInY == info.SamplesInY;
}
+ ///
+ /// Check if it's possible to create a view, with the given parameters, from this texture.
+ ///
+ /// Texture view information
+ /// Texture view size
+ /// Texture view initial layer on this texture
+ /// Texture view first mipmap level on this texture
+ /// True if a view with the given parameters can be created from this texture, false otherwise
public bool IsViewCompatible(
TextureInfo info,
ulong size,
@@ -437,6 +593,15 @@ namespace Ryujinx.Graphics.Gpu.Image
return IsViewCompatible(info, size, isCopy: false, out firstLayer, out firstLevel);
}
+ ///
+ /// Check if it's possible to create a view, with the given parameters, from this texture.
+ ///
+ /// Texture view information
+ /// Texture view size
+ /// True to check for copy compability, instead of view compatibility
+ /// Texture view initial layer on this texture
+ /// Texture view first mipmap level on this texture
+ /// True if a view with the given parameters can be created from this texture, false otherwise
public bool IsViewCompatible(
TextureInfo info,
ulong size,
@@ -484,6 +649,14 @@ namespace Ryujinx.Graphics.Gpu.Image
Info.SamplesInY == info.SamplesInY;
}
+ ///
+ /// Check it's possible to create a view with the specified layout.
+ /// The layout information is composed of the Stride for linear textures, or GOB block size
+ /// for block linear textures.
+ ///
+ /// Texture information of the texture view
+ /// Start level of the texture view, in relation with this texture
+ /// True if the layout is compatible, false otherwise
private bool ViewLayoutCompatible(TextureInfo info, int level)
{
if (Info.IsLinear != info.IsLinear)
@@ -520,11 +693,26 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Checks if the view format is compatible with this texture format.
+ /// In general, the formats are considered compatible if the bytes per pixel value is equal,
+ /// but there are more complex rules for some formats, like compressed or depth-stencil formats.
+ /// This follows the host API copy compatibility rules.
+ ///
+ /// Texture information of the texture view
+ /// True if the formats are compatible, false otherwise
private bool ViewFormatCompatible(TextureInfo info)
{
return TextureCompatibility.FormatCompatible(Info.FormatInfo, info.FormatInfo);
}
+ ///
+ /// Checks if the size of a given texture view is compatible with this texture.
+ ///
+ /// Texture information of the texture view
+ /// Mipmap level of the texture view in relation to this texture
+ /// True to check for copy compatibility rather than view compatibility
+ /// True if the sizes are compatible, false otherwise
private bool ViewSizeMatches(TextureInfo info, int level, bool isCopy)
{
Size size = GetAlignedSize(Info, level);
@@ -542,6 +730,14 @@ namespace Ryujinx.Graphics.Gpu.Image
size.Height == otherSize.Height;
}
+ ///
+ /// Check if the target of the specified texture view information is compatible with this
+ /// texture.
+ /// This follows the host API target compatibility rules.
+ ///
+ /// Texture information of the texture view
+ /// True to check for copy rather than view compatibility
+ /// True if the targets are compatible, false otherwise
private bool ViewTargetCompatible(TextureInfo info, bool isCopy)
{
switch (Info.Target)
@@ -576,6 +772,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return false;
}
+ ///
+ /// Gets the aligned sizes of the specified texture information.
+ /// The alignment depends on the texture layout and format bytes per pixel.
+ ///
+ /// Texture information to calculate the aligned size from
+ /// Mipmap level for texture views
+ /// The aligned texture size
private static Size GetAlignedSize(TextureInfo info, int level = 0)
{
int width = Math.Max(1, info.Width >> level);
@@ -614,6 +817,13 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Gets a texture of the specified target type from this texture.
+ /// This can be used to get an array texture from a non-array texture and vice-versa.
+ /// If this texture and the requested targets are equal, then this texture Host texture is returned directly.
+ ///
+ /// The desired target type
+ /// A view of this texture with the requested target, or null if the target is invalid for this texture
public ITexture GetTargetTexture(Target target)
{
if (target == Info.Target)
@@ -655,6 +865,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return null;
}
+ ///
+ /// Check if this texture and the specified target have the same number of dimensions.
+ /// For the purposes of this comparison, 2D and 2D Multisample textures are not considered to have
+ /// the same number of dimensions. Same for Cubemap and 3D textures.
+ ///
+ /// The target to compare with
+ /// True if both targets have the same number of dimensions, false otherwise
private bool IsSameDimensionsTarget(Target target)
{
switch (Info.Target)
@@ -686,6 +903,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return false;
}
+ ///
+ /// Replaces view texture information.
+ /// This should only be used for child textures with a parent.
+ ///
+ /// The parent texture
+ /// The new view texture information
+ /// The new host texture
public void ReplaceView(Texture parent, TextureInfo info, ITexture hostTexture)
{
ReplaceStorage(hostTexture);
@@ -695,6 +919,10 @@ namespace Ryujinx.Graphics.Gpu.Image
SetInfo(info);
}
+ ///
+ /// Sets the internal texture information structure.
+ ///
+ /// The new texture information
private void SetInfo(TextureInfo info)
{
Info = info;
@@ -703,6 +931,10 @@ namespace Ryujinx.Graphics.Gpu.Image
_layers = info.GetLayers();
}
+ ///
+ /// Replaces the host texture, while disposing of the old one if needed.
+ ///
+ /// The new host texture
private void ReplaceStorage(ITexture hostTexture)
{
DisposeTextures();
@@ -710,16 +942,29 @@ namespace Ryujinx.Graphics.Gpu.Image
HostTexture = hostTexture;
}
+ ///
+ /// Checks if the texture overlaps with a memory range.
+ ///
+ /// Start address of the range
+ /// Size of the range
+ /// True if the texture overlaps with the range, false otherwise
public bool OverlapsWith(ulong address, ulong size)
{
return Address < address + size && address < EndAddress;
}
+ ///
+ /// Increments the texture reference count.
+ ///
public void IncrementReferenceCount()
{
_referenceCount++;
}
+ ///
+ /// Decrements the texture reference count.
+ /// When the reference count hits zero, the texture may be deleted and can't be used anymore.
+ ///
public void DecrementReferenceCount()
{
int newRefCount = --_referenceCount;
@@ -739,6 +984,11 @@ namespace Ryujinx.Graphics.Gpu.Image
DeleteIfNotUsed();
}
+ ///
+ /// Delete the texture if it is not used anymore.
+ /// The texture is considered unused when the reference count is zero,
+ /// and it has no child views.
+ ///
private void DeleteIfNotUsed()
{
// We can delete the texture as long it is not being used
@@ -751,6 +1001,9 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Performs texture disposal, deleting the texture.
+ ///
private void DisposeTextures()
{
HostTexture.Dispose();
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
index cf922ac5a..94225406e 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
@@ -2,17 +2,44 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture binding information.
+ /// This is used for textures that needs to be accessed from shaders.
+ ///
struct TextureBindingInfo
{
+ ///
+ /// Shader sampler target type.
+ ///
public Target Target { get; }
+ ///
+ /// Shader texture handle.
+ /// This is a index into the texture constant buffer.
+ ///
public int Handle { get; }
+ ///
+ /// Indicates if the texture is a bindless texture.
+ /// For those textures, Handle is ignored.
+ ///
public bool IsBindless { get; }
- public int CbufSlot { get; }
+ ///
+ /// Constant buffer slot with the bindless texture handle, for bindless texture.
+ ///
+ public int CbufSlot { get; }
+
+ ///
+ /// Constant buffer offset of the bindless texture handle, for bindless texture.
+ ///
public int CbufOffset { get; }
+ ///
+ /// Constructs the texture binding information structure.
+ ///
+ /// The shader sampler target type
+ /// The shader texture handle (read index into the texture constant buffer)
public TextureBindingInfo(Target target, int handle)
{
Target = target;
@@ -24,6 +51,12 @@ namespace Ryujinx.Graphics.Gpu.Image
CbufOffset = 0;
}
+ ///
+ /// Constructs the bindless texture binding information structure.
+ ///
+ /// The shader sampler target type
+ /// Constant buffer slot where the bindless texture handle is located
+ /// Constant buffer offset of the bindless texture handle
public TextureBindingInfo(Target target, int cbufSlot, int cbufOffset)
{
Target = target;
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index 0ea7aec27..4d50c46e3 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -6,6 +6,9 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture bindings manager.
+ ///
class TextureBindingsManager
{
private GpuContext _context;
@@ -37,6 +40,12 @@ namespace Ryujinx.Graphics.Gpu.Image
private bool _rebind;
+ ///
+ /// Constructs a new instance of the texture bindings manager.
+ ///
+ /// The GPU context that the texture bindings manager belongs to
+ /// Texture pools cache used to get texture pools from
+ /// True if the bindings manager is used for the compute engine
public TextureBindingsManager(GpuContext context, TexturePoolCache texturePoolCache, bool isCompute)
{
_context = context;
@@ -52,6 +61,11 @@ namespace Ryujinx.Graphics.Gpu.Image
_imageState = new TextureStatePerStage[stages][];
}
+ ///
+ /// Binds textures for a given shader stage.
+ ///
+ /// Shader stage number, or 0 for compute shaders
+ /// Texture bindings
public void SetTextures(int stage, TextureBindingInfo[] bindings)
{
_textureBindings[stage] = bindings;
@@ -59,6 +73,11 @@ namespace Ryujinx.Graphics.Gpu.Image
_textureState[stage] = new TextureStatePerStage[bindings.Length];
}
+ ///
+ /// Binds images for a given shader stage.
+ ///
+ /// Shader stage number, or 0 for compute shaders
+ /// Image bindings
public void SetImages(int stage, TextureBindingInfo[] bindings)
{
_imageBindings[stage] = bindings;
@@ -66,11 +85,22 @@ namespace Ryujinx.Graphics.Gpu.Image
_imageState[stage] = new TextureStatePerStage[bindings.Length];
}
+ ///
+ /// Sets the textures constant buffer index.
+ /// The constant buffer specified holds the texture handles.
+ ///
+ /// Constant buffer index
public void SetTextureBufferIndex(int index)
{
_textureBufferIndex = index;
}
+ ///
+ /// Sets the current texture sampler pool to be used.
+ ///
+ /// Start GPU virtual address of the pool
+ /// Maximum ID of the pool (total count minus one)
+ /// Type of the sampler pool indexing used for bound samplers
public void SetSamplerPool(ulong gpuVa, int maximumId, SamplerIndex samplerIndex)
{
ulong address = _context.MemoryManager.Translate(gpuVa);
@@ -90,6 +120,11 @@ namespace Ryujinx.Graphics.Gpu.Image
_samplerIndex = samplerIndex;
}
+ ///
+ /// Sets the current texture pool to be used.
+ ///
+ /// Start GPU virtual address of the pool
+ /// Maximum ID of the pool (total count minus one)
public void SetTexturePool(ulong gpuVa, int maximumId)
{
ulong address = _context.MemoryManager.Translate(gpuVa);
@@ -98,6 +133,10 @@ namespace Ryujinx.Graphics.Gpu.Image
_texturePoolMaximumId = maximumId;
}
+ ///
+ /// Ensures that the bindings are visible to the host GPU.
+ /// This actually performs the binding using the host graphics API.
+ ///
public void CommitBindings()
{
TexturePool texturePool = _texturePoolCache.FindOrCreate(
@@ -123,6 +162,13 @@ namespace Ryujinx.Graphics.Gpu.Image
_rebind = false;
}
+ ///
+ /// Ensures that the texture bindings are visible to the host GPU.
+ /// This actually performs the binding using the host graphics API.
+ ///
+ /// The current texture pool
+ /// The shader stage using the textures to be bound
+ /// The stage number of the specified shader stage
private void CommitTextureBindings(TexturePool pool, ShaderStage stage, int stageIndex)
{
if (_textureBindings[stageIndex] == null)
@@ -194,6 +240,13 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Ensures that the image bindings are visible to the host GPU.
+ /// This actually performs the binding using the host graphics API.
+ ///
+ /// The current texture pool
+ /// The shader stage using the textures to be bound
+ /// The stage number of the specified shader stage
private void CommitImageBindings(TexturePool pool, ShaderStage stage, int stageIndex)
{
if (_imageBindings[stageIndex] == null)
@@ -222,6 +275,13 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Gets the texture descriptor for a given texture handle.
+ ///
+ /// The current GPU state
+ /// The stage number where the texture is bound
+ /// The texture handle
+ /// The texture descriptor for the specified texture
public TextureDescriptor GetTextureDescriptor(GpuState state, int stageIndex, int handle)
{
int packedId = ReadPackedId(stageIndex, handle);
@@ -237,7 +297,14 @@ namespace Ryujinx.Graphics.Gpu.Image
return texturePool.GetDescriptor(textureId);
}
- private int ReadPackedId(int stage, int wordOffset)
+ ///
+ /// Reads a packed texture and sampler ID (basically, the real texture handle)
+ /// from the texture constant buffer.
+ ///
+ /// The number of the shader stage where the texture is bound
+ /// A word offset of the handle on the buffer (the "fake" shader handle)
+ /// The packed texture and sampler ID (the real texture handle)
+ private int ReadPackedId(int stageIndex, int wordOffset)
{
ulong address;
@@ -249,7 +316,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
else
{
- address = bufferManager.GetGraphicsUniformBufferAddress(stage, _textureBufferIndex);
+ address = bufferManager.GetGraphicsUniformBufferAddress(stageIndex, _textureBufferIndex);
}
address += (uint)wordOffset * 4;
@@ -257,16 +324,31 @@ namespace Ryujinx.Graphics.Gpu.Image
return BitConverter.ToInt32(_context.PhysicalMemory.Read(address, 4));
}
+ ///
+ /// Unpacks the texture ID from the real texture handle.
+ ///
+ /// The real texture handle
+ /// The texture ID
private static int UnpackTextureId(int packedId)
{
return (packedId >> 0) & 0xfffff;
}
+ ///
+ /// Unpacks the sampler ID from the real texture handle.
+ ///
+ /// The real texture handle
+ /// The sampler ID
private static int UnpackSamplerId(int packedId)
{
return (packedId >> 20) & 0xfff;
}
+ ///
+ /// Invalidates a range of memory on all GPU resource pools (both texture and sampler pools).
+ ///
+ /// Start address of the range to invalidate
+ /// Size of the range to invalidate
public void InvalidatePoolRange(ulong address, ulong size)
{
_samplerPool?.InvalidateRange(address, size);
@@ -274,6 +356,9 @@ namespace Ryujinx.Graphics.Gpu.Image
_texturePoolCache.InvalidateRange(address, size);
}
+ ///
+ /// Force all bound textures and images to be rebound the next time CommitBindings is called.
+ ///
public void Rebind()
{
_rebind = true;
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index 524721647..5b8696209 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -2,6 +2,9 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture format compatibility checks.
+ ///
static class TextureCompatibility
{
private enum FormatClass
@@ -19,6 +22,12 @@ namespace Ryujinx.Graphics.Gpu.Image
Bc7
}
+ ///
+ /// Checks if two formats are compatible, according to the host API copy format compatibility rules.
+ ///
+ /// First comparand
+ /// Second comparand
+ /// True if the formats are compatible, false otherwise
public static bool FormatCompatible(FormatInfo lhs, FormatInfo rhs)
{
if (IsDsFormat(lhs.Format) || IsDsFormat(rhs.Format))
@@ -44,6 +53,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Gets the texture format class, for compressed textures, or Unclassified otherwise.
+ ///
+ /// The format
+ /// Format class
private static FormatClass GetFormatClass(Format format)
{
switch (format)
@@ -77,6 +91,11 @@ namespace Ryujinx.Graphics.Gpu.Image
return FormatClass.Unclassified;
}
+ ///
+ /// Checks if the format is a depth-stencil texture format.
+ ///
+ /// Format to check
+ /// True if the format is a depth-stencil format (including depth only), false otherwise
private static bool IsDsFormat(Format format)
{
switch (format)
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureComponent.cs b/Ryujinx.Graphics.Gpu/Image/TextureComponent.cs
index db9b9dae6..359069bcf 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureComponent.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureComponent.cs
@@ -2,6 +2,9 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture swizzle color component.
+ ///
enum TextureComponent
{
Zero = 0,
@@ -15,6 +18,11 @@ namespace Ryujinx.Graphics.Gpu.Image
static class TextureComponentConverter
{
+ ///
+ /// Converts the texture swizzle color component enum to the respective Graphics Abstraction Layer enum.
+ ///
+ /// Texture swizzle color component
+ /// Converted enum
public static SwizzleComponent Convert(this TextureComponent component)
{
switch (component)
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
index 6d1f0fb18..5dbd1a082 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Maxwell texture descriptor, as stored on the GPU texture pool memory region.
+ ///
struct TextureDescriptor
{
public uint Word0;
@@ -11,111 +14,213 @@ namespace Ryujinx.Graphics.Gpu.Image
public uint Word6;
public uint Word7;
+ ///
+ /// Unpacks Maxwell texture format integer.
+ ///
+ /// The texture format integer
public uint UnpackFormat()
{
return Word0 & 0x8007ffff;
}
+ ///
+ /// Unpacks the swizzle component for the texture red color channel.
+ ///
+ /// The swizzle component
public TextureComponent UnpackSwizzleR()
{
return(TextureComponent)((Word0 >> 19) & 7);
}
+ ///
+ /// Unpacks the swizzle component for the texture green color channel.
+ ///
+ /// The swizzle component
public TextureComponent UnpackSwizzleG()
{
return(TextureComponent)((Word0 >> 22) & 7);
}
+ ///
+ /// Unpacks the swizzle component for the texture blue color channel.
+ ///
+ /// The swizzle component
public TextureComponent UnpackSwizzleB()
{
return(TextureComponent)((Word0 >> 25) & 7);
}
+ ///
+ /// Unpacks the swizzle component for the texture alpha color channel.
+ ///
+ /// The swizzle component
public TextureComponent UnpackSwizzleA()
{
return(TextureComponent)((Word0 >> 28) & 7);
}
+ ///
+ /// Unpacks the 40-bits texture GPU virtual address.
+ ///
+ /// The GPU virtual address
public ulong UnpackAddress()
{
return Word1 | ((ulong)(Word2 & 0xffff) << 32);
}
+ ///
+ /// Unpacks texture descriptor type for this texture descriptor.
+ /// This defines the texture layout, among other things.
+ ///
+ /// The texture descriptor type
public TextureDescriptorType UnpackTextureDescriptorType()
{
return (TextureDescriptorType)((Word2 >> 21) & 7);
}
+ ///
+ /// Unpacks the texture stride (bytes per line) for linear textures only.
+ /// Always 32-bytes aligned.
+ ///
+ /// The linear texture stride
public int UnpackStride()
{
return (int)(Word3 & 0xffff) << 5;
}
+ ///
+ /// Unpacks the GOB block size in X (width) for block linear textures.
+ /// Must be always 1, ignored by the GPU.
+ ///
+ /// THe GOB block X size
public int UnpackGobBlocksInX()
{
return 1 << (int)(Word3 & 7);
}
+ ///
+ /// 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.
+ ///
+ /// THe GOB block Y size
public int UnpackGobBlocksInY()
{
return 1 << (int)((Word3 >> 3) & 7);
}
+ ///
+ /// 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.
+ ///
+ /// The GOB block Z size
public int UnpackGobBlocksInZ()
{
return 1 << (int)((Word3 >> 6) & 7);
}
+ ///
+ /// Number of GOB blocks per tile in the X direction.
+ /// This is only used for sparse textures, should be 1 otherwise.
+ ///
+ /// The number of GOB blocks per tile
public int UnpackGobBlocksInTileX()
{
return 1 << (int)((Word3 >> 10) & 7);
}
+ ///
+ /// Unpacks the number of mipmap levels of the texture.
+ ///
+ /// The number of mipmap levels
public int UnpackLevels()
{
return (int)(Word3 >> 28) + 1;
}
+ ///
+ /// Unpack the base level texture width size.
+ ///
+ /// The texture width
public int UnpackWidth()
{
return (int)(Word4 & 0xffff) + 1;
}
+ ///
+ /// Unpacks the texture sRGB format flag.
+ ///
+ /// True if the texture is sRGB, false otherwise
public bool UnpackSrgb()
{
return (Word4 & (1 << 22)) != 0;
}
+ ///
+ /// Unpacks the texture target.
+ ///
+ /// The texture target
public TextureTarget UnpackTextureTarget()
{
return (TextureTarget)((Word4 >> 23) & 0xf);
}
+ ///
+ /// Unpack the base level texture height size, or array layers for 1D array textures.
+ /// Should be ignored for 1D or buffer textures.
+ ///
+ /// The texture height or layers count
public int UnpackHeight()
{
return (int)(Word5 & 0xffff) + 1;
}
+ ///
+ /// Unpack the base level texture depth size, number of array layers or cubemap faces.
+ /// The meaning of this value depends on the texture target.
+ ///
+ /// The texture depth, layer or faces count
public int UnpackDepth()
{
return (int)((Word5 >> 16) & 0x3fff) + 1;
}
+ ///
+ /// 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.
+ ///
+ /// The texture coordinates normalized flag
public bool UnpackTextureCoordNormalized()
{
return (Word5 & (1 << 31)) != 0;
}
+ ///
+ /// Unpacks the base mipmap level of the texture.
+ ///
+ /// The base mipmap level of the texture
public int UnpackBaseLevel()
{
return (int)(Word7 & 0xf);
}
+ ///
+ /// Unpacks the maximum mipmap level (inclusive) of the texture.
+ /// Usually equal to Levels minus 1.
+ ///
+ /// The maximum mipmap level (inclusive) of the texture
public int UnpackMaxLevelInclusive()
{
return (int)((Word7 >> 4) & 0xf);
}
+ ///
+ /// Unpacks the multisampled texture samples count in each direction.
+ /// Must be ignored for non-multisample textures.
+ ///
+ /// The multisample counts enum
public TextureMsaaMode UnpackTextureMsaaMode()
{
return (TextureMsaaMode)((Word7 >> 8) & 0xf);
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureDescriptorType.cs b/Ryujinx.Graphics.Gpu/Image/TextureDescriptorType.cs
index 6f6048a61..8e7d40bbe 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureDescriptorType.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureDescriptorType.cs
@@ -1,5 +1,10 @@
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// The texture descriptor type.
+ /// This specifies the texture memory layout.
+ /// The texture descriptor structure depends on the type.
+ ///
enum TextureDescriptorType
{
Buffer,
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs b/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs
index 19110dcf6..784ff0e97 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs
@@ -2,35 +2,131 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture information.
+ ///
struct TextureInfo
{
+ ///
+ /// Address of the texture in guest memory.
+ ///
public ulong Address { get; }
- public int Width { get; }
- public int Height { get; }
- public int DepthOrLayers { get; }
- public int Levels { get; }
- public int SamplesInX { get; }
- public int SamplesInY { get; }
- public int Stride { get; }
- public bool IsLinear { get; }
- public int GobBlocksInY { get; }
- public int GobBlocksInZ { get; }
- public int GobBlocksInTileX { get; }
+ ///
+ /// The width of the texture.
+ ///
+ public int Width { get; }
+ ///
+ /// The height of the texture, or layers count for 1D array textures.
+ ///
+ public int Height { get; }
+
+ ///
+ /// The depth of the texture (for 3D textures), or layers count for array textures.
+ ///
+ public int DepthOrLayers { get; }
+
+ ///
+ /// The number of mipmap levels of the texture.
+ ///
+ public int Levels { get; }
+
+ ///
+ /// The number of samples in the X direction for multisampled textures.
+ ///
+ public int SamplesInX { get; }
+
+ ///
+ /// The number of samples in the Y direction for multisampled textures.
+ ///
+ public int SamplesInY { get; }
+
+ ///
+ /// The number of bytes per line for linear textures.
+ ///
+ public int Stride { get; }
+
+ ///
+ /// Indicates whenever or not the texture is a linear texture.
+ ///
+ public bool IsLinear { get; }
+
+ ///
+ /// GOB blocks in the Y direction, for block linear textures.
+ ///
+ public int GobBlocksInY { get; }
+
+ ///
+ /// GOB blocks in the Z direction, for block linear textures.
+ ///
+ public int GobBlocksInZ { get; }
+
+ ///
+ /// Number of GOB blocks per tile in the X direction, for block linear textures.
+ ///
+ public int GobBlocksInTileX { get; }
+
+ ///
+ /// Total number of samples for multisampled textures.
+ ///
public int Samples => SamplesInX * SamplesInY;
+ ///
+ /// Texture target type.
+ ///
public Target Target { get; }
+ ///
+ /// Texture format information.
+ ///
public FormatInfo FormatInfo { get; }
+ ///
+ /// Depth-stencil mode of the texture. This defines whenever the depth or stencil value is read from shaders,
+ /// for depth-stencil texture formats.
+ ///
public DepthStencilMode DepthStencilMode { get; }
+ ///
+ /// Texture swizzle for the red color channel.
+ ///
public SwizzleComponent SwizzleR { get; }
+ ///
+ /// Texture swizzle for the green color channel.
+ ///
public SwizzleComponent SwizzleG { get; }
+ ///
+ /// Texture swizzle for the blue color channel.
+ ///
public SwizzleComponent SwizzleB { get; }
+ ///
+ /// Texture swizzle for the alpha color channel.
+ ///
public SwizzleComponent SwizzleA { get; }
+ ///
+ /// Constructs the texture information structure.
+ ///
+ /// The address of the texture
+ /// The width of the texture
+ /// The height or the texture
+ /// The depth or layers count of the texture
+ /// The amount if mipmap levels of the texture
+ /// The number of samples in the X direction for multisample textures, should be 1 otherwise
+ /// The number of samples in the Y direction for multisample textures, should be 1 otherwise
+ /// The stride for linear textures
+ /// Whenever the texture is linear or block linear
+ /// Number of GOB blocks in the Y direction
+ /// Number of GOB blocks in the Z direction
+ /// Number of GOB blocks per tile in the X direction
+ /// Texture target type
+ /// Texture format information
+ /// Depth-stencil mode
+ /// Swizzle for the red color channel
+ /// Swizzle for the green color channel
+ /// Swizzle for the blue color channel
+ /// Swizzle for the alpha color channel
public TextureInfo(
ulong address,
int width,
@@ -73,11 +169,21 @@ namespace Ryujinx.Graphics.Gpu.Image
SwizzleA = swizzleA;
}
+ ///
+ /// Gets the real texture depth.
+ /// Returns 1 for any target other than 3D textures.
+ ///
+ /// Texture depth
public int GetDepth()
{
return Target == Target.Texture3D ? DepthOrLayers : 1;
}
+ ///
+ /// Gets the number of layers of the texture.
+ /// Returns 1 for non-array textures, 6 for cubemap textures, and layer faces for cubemap array textures.
+ ///
+ /// The number of texture layers
public int GetLayers()
{
if (Target == Target.Texture2DArray || Target == Target.Texture2DMultisampleArray)
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 6e1b8c60a..4f6d5e588 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -8,28 +8,37 @@ using System;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture manager.
+ ///
class TextureManager
{
private const int OverlapsBufferInitialCapacity = 10;
private const int OverlapsBufferMaxCapacity = 10000;
- private GpuContext _context;
+ private readonly GpuContext _context;
- private TextureBindingsManager _cpBindingsManager;
- private TextureBindingsManager _gpBindingsManager;
+ private readonly TextureBindingsManager _cpBindingsManager;
+ private readonly TextureBindingsManager _gpBindingsManager;
- private Texture[] _rtColors;
- private Texture _rtDepthStencil;
+ private readonly Texture[] _rtColors;
- private ITexture[] _rtHostColors;
- private ITexture _rtHostDs;
+ private Texture _rtDepthStencil;
- private RangeList _textures;
+ private readonly ITexture[] _rtHostColors;
+
+ private ITexture _rtHostDs;
+
+ private readonly RangeList _textures;
private Texture[] _textureOverlaps;
- private AutoDeleteCache _cache;
+ private readonly AutoDeleteCache _cache;
+ ///
+ /// Constructs a new instance of the texture manager.
+ ///
+ /// The GPU context that the texture manager belongs to
public TextureManager(GpuContext context)
{
_context = context;
@@ -50,66 +59,126 @@ namespace Ryujinx.Graphics.Gpu.Image
_cache = new AutoDeleteCache();
}
+ ///
+ /// Sets texture bindings on the compute pipeline.
+ ///
+ /// The texture bindings
public void SetComputeTextures(TextureBindingInfo[] bindings)
{
_cpBindingsManager.SetTextures(0, bindings);
}
+ ///
+ /// Sets texture bindings on the graphics pipeline.
+ ///
+ /// The index of the shader stage to bind the textures
+ /// The texture bindings
public void SetGraphicsTextures(int stage, TextureBindingInfo[] bindings)
{
_gpBindingsManager.SetTextures(stage, bindings);
}
+ ///
+ /// Sets image bindings on the compute pipeline.
+ ///
+ /// The image bindings
public void SetComputeImages(TextureBindingInfo[] bindings)
{
_cpBindingsManager.SetImages(0, bindings);
}
+ ///
+ /// Sets image bindings on the graphics pipeline.
+ ///
+ /// The index of the shader stage to bind the images
+ /// The image bindings
public void SetGraphicsImages(int stage, TextureBindingInfo[] bindings)
{
_gpBindingsManager.SetImages(stage, bindings);
}
+ ///
+ /// Sets the texture constant buffer index on the compute pipeline.
+ ///
+ /// The texture constant buffer index
public void SetComputeTextureBufferIndex(int index)
{
_cpBindingsManager.SetTextureBufferIndex(index);
}
+ ///
+ /// Sets the texture constant buffer index on the graphics pipeline.
+ ///
+ /// The texture constant buffer index
public void SetGraphicsTextureBufferIndex(int index)
{
_gpBindingsManager.SetTextureBufferIndex(index);
}
+ ///
+ /// Sets the current sampler pool on the compute pipeline.
+ ///
+ /// The start GPU virtual address of the sampler pool
+ /// The maximum ID of the sampler pool
+ /// The indexing type of the sampler
public void SetComputeSamplerPool(ulong gpuVa, int maximumId, SamplerIndex samplerIndex)
{
_cpBindingsManager.SetSamplerPool(gpuVa, maximumId, samplerIndex);
}
+ ///
+ /// Sets the current sampler pool on the graphics pipeline.
+ ///
+ /// The start GPU virtual address of the sampler pool
+ /// The maximum ID of the sampler pool
+ /// The indexing type of the sampler
public void SetGraphicsSamplerPool(ulong gpuVa, int maximumId, SamplerIndex samplerIndex)
{
_gpBindingsManager.SetSamplerPool(gpuVa, maximumId, samplerIndex);
}
+ ///
+ /// Sets the current texture pool on the compute pipeline.
+ ///
+ /// The start GPU virtual address of the texture pool
+ /// The maximum ID of the texture pool
public void SetComputeTexturePool(ulong gpuVa, int maximumId)
{
_cpBindingsManager.SetTexturePool(gpuVa, maximumId);
}
+ ///
+ /// Sets the current texture pool on the graphics pipeline.
+ ///
+ /// The start GPU virtual address of the texture pool
+ /// The maximum ID of the texture pool
public void SetGraphicsTexturePool(ulong gpuVa, int maximumId)
{
_gpBindingsManager.SetTexturePool(gpuVa, maximumId);
}
+ ///
+ /// Sets the render target color buffer.
+ ///
+ /// The index of the color buffer to set (up to 8)
+ /// The color buffer texture
public void SetRenderTargetColor(int index, Texture color)
{
_rtColors[index] = color;
}
+ ///
+ /// Sets the render target depth-stencil buffer.
+ ///
+ /// The depth-stencil buffer texture
public void SetRenderTargetDepthStencil(Texture depthStencil)
{
_rtDepthStencil = depthStencil;
}
+ ///
+ /// Commits bindings on the compute pipeline.
+ ///
public void CommitComputeBindings()
{
// Every time we switch between graphics and compute work,
@@ -121,6 +190,9 @@ namespace Ryujinx.Graphics.Gpu.Image
_gpBindingsManager.Rebind();
}
+ ///
+ /// Commits bindings on the graphics pipeline.
+ ///
public void CommitGraphicsBindings()
{
_gpBindingsManager.CommitBindings();
@@ -128,11 +200,21 @@ namespace Ryujinx.Graphics.Gpu.Image
UpdateRenderTargets();
}
+ ///
+ /// Gets a texture descriptor used on the graphics pipeline.
+ ///
+ /// Current GPU state
+ /// Index of the shader stage where the texture is bound
+ /// Shader "fake" handle of the texture
+ /// The texture descriptor
public TextureDescriptor GetGraphicsTextureDescriptor(GpuState state, int stageIndex, int handle)
{
return _gpBindingsManager.GetTextureDescriptor(state, stageIndex, handle);
}
+ ///
+ /// Update host framebuffer attachments based on currently bound render target buffers.
+ ///
private void UpdateRenderTargets()
{
bool anyChanged = false;
@@ -162,6 +244,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Tries to find a existing texture, or create a new one if not found.
+ ///
+ /// Copy texture to find or create
+ /// The texture
public Texture FindOrCreateTexture(CopyTexture copyTexture)
{
ulong address = _context.MemoryManager.Translate(copyTexture.Address.Pack());
@@ -210,6 +297,13 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
+ ///
+ /// Tries to find a existing texture, or create a new one if not found.
+ ///
+ /// Color buffer texture to find or create
+ /// Number of samples in the X direction, for MSAA
+ /// Number of samples in the Y direction, for MSAA
+ /// The texture
public Texture FindOrCreateTexture(RtColorState colorState, int samplesInX, int samplesInY)
{
ulong address = _context.MemoryManager.Translate(colorState.Address.Pack());
@@ -286,6 +380,14 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
+ ///
+ /// Tries to find a existing texture, or create a new one if not found.
+ ///
+ /// Depth-stencil buffer texture to find or create
+ /// Size of the depth-stencil texture
+ /// Number of samples in the X direction, for MSAA
+ /// Number of samples in the Y direction, for MSAA
+ /// The texture
public Texture FindOrCreateTexture(RtDepthStencilState dsState, Size3D size, int samplesInX, int samplesInY)
{
ulong address = _context.MemoryManager.Translate(dsState.Address.Pack());
@@ -327,6 +429,12 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
+ ///
+ /// Tries to find a existing texture, or create a new one if not found.
+ ///
+ /// Texture information of the texture to be found or created
+ /// The texture search flags, defines texture comparison rules
+ /// The texture
public Texture FindOrCreateTexture(TextureInfo info, TextureSearchFlags flags = TextureSearchFlags.None)
{
bool isSamplerTexture = (flags & TextureSearchFlags.Sampler) != 0;
@@ -480,6 +588,9 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
+ ///
+ /// Resizes the temporary buffer used for range list intersection results, if it has grown too much.
+ ///
private void ShrinkOverlapsBufferIfNeeded()
{
if (_textureOverlaps.Length > OverlapsBufferMaxCapacity)
@@ -488,6 +599,14 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Adjusts the size of the texture information for a given mipmap level,
+ /// based on the size of a parent texture.
+ ///
+ /// The parent texture
+ /// The texture information to be adjusted
+ /// The first level of the texture view
+ /// The adjusted texture information with the new size
private static TextureInfo AdjustSizes(Texture parent, TextureInfo info, int firstLevel)
{
// When the texture is used as view of another texture, we must
@@ -551,6 +670,14 @@ namespace Ryujinx.Graphics.Gpu.Image
info.SwizzleA);
}
+
+ ///
+ /// Gets a texture creation information from texture information.
+ /// This can be used to create new host textures.
+ ///
+ /// Texture information
+ /// GPU capabilities
+ /// The texture creation information
public static TextureCreateInfo GetCreateInfo(TextureInfo info, Capabilities caps)
{
FormatInfo formatInfo = info.FormatInfo;
@@ -590,6 +717,9 @@ namespace Ryujinx.Graphics.Gpu.Image
info.SwizzleA);
}
+ ///
+ /// Flushes all the textures in the cache that have been modified since the last call.
+ ///
public void Flush()
{
foreach (Texture texture in _cache)
@@ -603,6 +733,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Flushes textures in the cache inside a given range that have been modified since the last call.
+ ///
+ /// The range start address
+ /// The range size
public void Flush(ulong address, ulong size)
{
foreach (Texture texture in _cache)
@@ -616,6 +751,12 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Removes a texture from the cache.
+ /// This only removes the texture from the internal list, not from the auto-deletion cache.
+ /// It may still have live references after the removal.
+ ///
+ /// The texture to be removed
public void RemoveTextureFromCache(Texture texture)
{
_textures.Remove(texture);
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureMsaaMode.cs b/Ryujinx.Graphics.Gpu/Image/TextureMsaaMode.cs
index 134210671..0461888f1 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureMsaaMode.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureMsaaMode.cs
@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Multisampled texture samples count.
+ ///
enum TextureMsaaMode
{
Ms1x1 = 0,
@@ -11,43 +14,55 @@ namespace Ryujinx.Graphics.Gpu.Image
static class TextureMsaaModeConverter
{
+ ///
+ /// Returns the total number of samples from the MSAA mode.
+ ///
+ /// The MSAA mode
+ /// The total number of samples
public static int SamplesCount(this TextureMsaaMode msaaMode)
{
- switch (msaaMode)
+ return msaaMode switch
{
- case TextureMsaaMode.Ms2x1: return 2;
- case TextureMsaaMode.Ms2x2: return 4;
- case TextureMsaaMode.Ms4x2: return 8;
- case TextureMsaaMode.Ms4x4: return 16;
- }
-
- return 1;
+ TextureMsaaMode.Ms2x1 => 2,
+ TextureMsaaMode.Ms2x2 => 4,
+ TextureMsaaMode.Ms4x2 => 8,
+ TextureMsaaMode.Ms4x4 => 16,
+ _ => 1
+ };
}
+ ///
+ /// Returns the number of samples in the X direction from the MSAA mode.
+ ///
+ /// The MSAA mode
+ /// The number of samples in the X direction
public static int SamplesInX(this TextureMsaaMode msaaMode)
{
- switch (msaaMode)
+ return msaaMode switch
{
- case TextureMsaaMode.Ms2x1: return 2;
- case TextureMsaaMode.Ms2x2: return 2;
- case TextureMsaaMode.Ms4x2: return 4;
- case TextureMsaaMode.Ms4x4: return 4;
- }
-
- return 1;
+ TextureMsaaMode.Ms2x1 => 2,
+ TextureMsaaMode.Ms2x2 => 2,
+ TextureMsaaMode.Ms4x2 => 4,
+ TextureMsaaMode.Ms4x4 => 4,
+ _ => 1
+ };
}
+ ///
+ /// Returns the number of samples in the Y direction from the MSAA mode.
+ ///
+ /// The MSAA mode
+ /// The number of samples in the Y direction
public static int SamplesInY(this TextureMsaaMode msaaMode)
{
- switch (msaaMode)
+ return msaaMode switch
{
- case TextureMsaaMode.Ms2x1: return 1;
- case TextureMsaaMode.Ms2x2: return 2;
- case TextureMsaaMode.Ms4x2: return 2;
- case TextureMsaaMode.Ms4x4: return 4;
- }
-
- return 1;
+ TextureMsaaMode.Ms2x1 => 1,
+ TextureMsaaMode.Ms2x2 => 2,
+ TextureMsaaMode.Ms4x2 => 2,
+ TextureMsaaMode.Ms4x4 => 4,
+ _ => 1
+ };
}
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index f6fa50692..91f6338f3 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -7,17 +7,31 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture pool.
+ ///
class TexturePool : Pool
{
- public LinkedListNode CacheNode { get; set; }
-
private int _sequenceNumber;
- public TexturePool(
- GpuContext context,
- ulong address,
- int maximumId) : base(context, address, maximumId) { }
+ ///
+ /// Intrusive linked list node used on the texture pool cache.
+ ///
+ public LinkedListNode CacheNode { get; set; }
+ ///
+ /// Constructs a new instance of the texture pool.
+ ///
+ /// GPU context that the texture pool belongs to
+ /// Address of the texture pool in guest memory
+ /// Maximum texture ID of the texture pool (equal to maximum textures minus one)
+ public TexturePool(GpuContext context, ulong address, int maximumId) : base(context, address, maximumId) { }
+
+ ///
+ /// Gets the texture with the given ID.
+ ///
+ /// ID of the texture. This is effectively a zero-based index
+ /// The texture with the given ID
public override Texture Get(int id)
{
if ((uint)id >= Items.Length)
@@ -62,6 +76,11 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
+ ///
+ /// Gets the texture descriptor from a given texture ID.
+ ///
+ /// ID of the texture. This is effectively a zero-based index
+ /// The texture descriptor
public TextureDescriptor GetDescriptor(int id)
{
ulong address = Address + (ulong)(uint)id * DescriptorSize;
@@ -71,6 +90,11 @@ namespace Ryujinx.Graphics.Gpu.Image
return MemoryMarshal.Cast(data)[0];
}
+ ///
+ /// Implementation of the texture pool range invalidation.
+ ///
+ /// Start address of the range of the texture pool
+ /// Size of the range being invalidated
protected override void InvalidateRangeImpl(ulong address, ulong size)
{
ulong endAddress = address + size;
@@ -101,6 +125,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Gets texture information from a texture descriptor.
+ ///
+ /// The texture descriptor
+ /// The texture information
private TextureInfo GetInfo(TextureDescriptor descriptor)
{
ulong address = Context.MemoryManager.Translate(descriptor.UnpackAddress());
@@ -172,6 +201,13 @@ namespace Ryujinx.Graphics.Gpu.Image
swizzleA);
}
+ ///
+ /// Gets the texture depth-stencil mode, based on the swizzle components of each color channel.
+ /// The depth-stencil mode is determined based on how the driver sets those parameters.
+ ///
+ /// The format of the texture
+ /// The texture swizzle components
+ /// The depth-stencil mode
private static DepthStencilMode GetDepthStencilMode(Format format, params SwizzleComponent[] components)
{
// R = Depth, G = Stencil.
@@ -205,12 +241,22 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Checks if the swizzle component is equal to the red or green channels.
+ ///
+ /// The swizzle component to check
+ /// True if the swizzle component is equal to the red or blue, false otherwise
private static bool IsRG(SwizzleComponent component)
{
return component == SwizzleComponent.Red ||
component == SwizzleComponent.Green;
}
+ ///
+ /// Decrements the reference count of the texture.
+ /// This indicates that the texture pool is not using it anymore.
+ ///
+ /// The texture to be deleted
protected override void Delete(Texture item)
{
item?.DecrementReferenceCount();
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs b/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs
index 9ab7e292d..6c249ca65 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs
@@ -2,6 +2,11 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture pool cache.
+ /// This can keep multiple texture pools, and return the current one as needed.
+ /// It is useful for applications that uses multiple texture pools.
+ ///
class TexturePoolCache
{
private const int MaxCapacity = 4;
@@ -10,6 +15,10 @@ namespace Ryujinx.Graphics.Gpu.Image
private LinkedList _pools;
+ ///
+ /// Constructs a new instance of the texture pool.
+ ///
+ ///
public TexturePoolCache(GpuContext context)
{
_context = context;
@@ -17,6 +26,12 @@ namespace Ryujinx.Graphics.Gpu.Image
_pools = new LinkedList();
}
+ ///
+ /// Finds a cache texture pool, or creates a new one if not found.
+ ///
+ /// Start address of the texture pool
+ /// Maximum ID of the texture pool
+ /// The found or newly created texture pool
public TexturePool FindOrCreate(ulong address, int maximumId)
{
TexturePool pool;
@@ -58,6 +73,11 @@ namespace Ryujinx.Graphics.Gpu.Image
return pool;
}
+ ///
+ /// Invalidates a memory range of all intersecting texture pools on the cache.
+ ///
+ /// Start address of the range to invalidate
+ /// Size of the range to invalidate
public void InvalidateRange(ulong address, ulong size)
{
for (LinkedListNode node = _pools.First; node != null; node = node.Next)
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs b/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs
index a5c951b53..daf726f1d 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs
@@ -2,6 +2,9 @@ using System;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture search flags, defines texture information comparison rules.
+ ///
[Flags]
enum TextureSearchFlags
{
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs b/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs
index 96a814c62..301fc87b2 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs
@@ -2,6 +2,9 @@ using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.Gpu.Image
{
+ ///
+ /// Texture target.
+ ///
enum TextureTarget
{
Texture1D,
@@ -17,6 +20,12 @@ namespace Ryujinx.Graphics.Gpu.Image
static class TextureTargetConverter
{
+ ///
+ /// Converts the texture target enum to a host compatible, Graphics Abstraction Layer enum.
+ ///
+ /// The target enum to convert
+ /// True if the texture is a multisampled texture
+ /// The host compatible texture target
public static Target Convert(this TextureTarget target, bool isMultisample)
{
if (isMultisample)