aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-06-29 14:32:02 -0300
committerGitHub <noreply@github.com>2021-06-29 19:32:02 +0200
commitfbb4019ed5c12c4a888c7b09db648ac595366896 (patch)
treea8be6bf5fc4f8b844683f1ef2ade588f3bb9bb0a /Ryujinx.Graphics.Gpu/Image
parent8cc872fb60ec1b825655ba8dba06cc978fcd7e66 (diff)
Initial support for separate GPU address spaces (#2394)
* Make GPU memory manager a member of GPU channel * Move physical memory instance to the memory manager, and the caches to the physical memory * PR feedback
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image')
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Pool.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/Image/SamplerPool.cs5
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Texture.cs56
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs17
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureCache.cs86
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureGroup.cs12
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TexturePool.cs13
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs27
8 files changed, 144 insertions, 91 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs
index 0b4c2993..a06a7ccf 100644
--- a/Ryujinx.Graphics.Gpu/Image/Pool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs
@@ -1,4 +1,5 @@
using Ryujinx.Cpu.Tracking;
+using Ryujinx.Graphics.Gpu.Memory;
using System;
namespace Ryujinx.Graphics.Gpu.Image
@@ -13,6 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Image
protected const int DescriptorSize = 0x20;
protected GpuContext Context;
+ protected PhysicalMemory PhysicalMemory;
protected T1[] Items;
protected T2[] DescriptorCache;
@@ -38,9 +40,17 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly CpuMultiRegionHandle _memoryTracking;
private readonly Action<ulong, ulong> _modifiedDelegate;
- public Pool(GpuContext context, ulong address, int maximumId)
+ /// <summary>
+ /// Creates a new instance of the GPU resource pool.
+ /// </summary>
+ /// <param name="context">GPU context that the pool belongs to</param>
+ /// <param name="physicalMemory">Physical memory where the resource descriptors are mapped</param>
+ /// <param name="address">Address of the pool in physical memory</param>
+ /// <param name="maximumId">Maximum index of an item on the pool (inclusive)</param>
+ public Pool(GpuContext context, PhysicalMemory physicalMemory, ulong address, int maximumId)
{
- Context = context;
+ Context = context;
+ PhysicalMemory = physicalMemory;
MaximumId = maximumId;
int count = maximumId + 1;
@@ -53,11 +63,10 @@ namespace Ryujinx.Graphics.Gpu.Image
Address = address;
Size = size;
- _memoryTracking = context.PhysicalMemory.BeginGranularTracking(address, size);
+ _memoryTracking = physicalMemory.BeginGranularTracking(address, size);
_modifiedDelegate = RegionModified;
}
-
/// <summary>
/// Gets the descriptor for a given ID.
/// </summary>
@@ -65,7 +74,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <returns>The descriptor</returns>
public T2 GetDescriptor(int id)
{
- return Context.PhysicalMemory.Read<T2>(Address + (ulong)id * DescriptorSize);
+ return PhysicalMemory.Read<T2>(Address + (ulong)id * DescriptorSize);
}
/// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
index 1395aea2..aed6cb9c 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Graphics.Gpu.Memory;
+
namespace Ryujinx.Graphics.Gpu.Image
{
/// <summary>
@@ -11,9 +13,10 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs a new instance of the sampler pool.
/// </summary>
/// <param name="context">GPU context that the sampler pool belongs to</param>
+ /// <param name="physicalMemory">Physical memory where the sampler descriptors are mapped</param>
/// <param name="address">Address of the sampler pool in guest memory</param>
/// <param name="maximumId">Maximum sampler ID of the sampler pool (equal to maximum samplers minus one)</param>
- public SamplerPool(GpuContext context, ulong address, int maximumId) : base(context, address, maximumId) { }
+ public SamplerPool(GpuContext context, PhysicalMemory physicalMemory, ulong address, int maximumId) : base(context, physicalMemory, address, maximumId) { }
/// <summary>
/// Gets the sampler with the given ID.
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 0948c494..6ca15ea1 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -28,6 +28,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
private GpuContext _context;
+ private PhysicalMemory _physicalMemory;
private SizeInfo _sizeInfo;
@@ -139,6 +140,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs a new instance of the cached GPU texture.
/// </summary>
/// <param name="context">GPU context that the texture belongs to</param>
+ /// <param name="physicalMemory">Physical memory where the texture is mapped</param>
/// <param name="info">Texture information</param>
/// <param name="sizeInfo">Size information of the texture</param>
/// <param name="range">Physical memory ranges where the texture data is located</param>
@@ -147,16 +149,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="scaleFactor">The floating point scale factor to initialize with</param>
/// <param name="scaleMode">The scale mode to initialize with</param>
private Texture(
- GpuContext context,
- TextureInfo info,
- SizeInfo sizeInfo,
- MultiRange range,
- int firstLayer,
- int firstLevel,
- float scaleFactor,
+ GpuContext context,
+ PhysicalMemory physicalMemory,
+ TextureInfo info,
+ SizeInfo sizeInfo,
+ MultiRange range,
+ int firstLayer,
+ int firstLevel,
+ float scaleFactor,
TextureScaleMode scaleMode)
{
- InitializeTexture(context, info, sizeInfo, range);
+ InitializeTexture(context, physicalMemory, info, sizeInfo, range);
FirstLayer = firstLayer;
FirstLevel = firstLevel;
@@ -171,16 +174,23 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs a new instance of the cached GPU texture.
/// </summary>
/// <param name="context">GPU context that the texture belongs to</param>
+ /// <param name="physicalMemory">Physical memory where the texture is mapped</param>
/// <param name="info">Texture information</param>
/// <param name="sizeInfo">Size information of the texture</param>
/// <param name="range">Physical memory ranges where the texture data is located</param>
/// <param name="scaleMode">The scale mode to initialize with. If scaled, the texture's data is loaded immediately and scaled up</param>
- public Texture(GpuContext context, TextureInfo info, SizeInfo sizeInfo, MultiRange range, TextureScaleMode scaleMode)
+ public Texture(
+ GpuContext context,
+ PhysicalMemory physicalMemory,
+ TextureInfo info,
+ SizeInfo sizeInfo,
+ MultiRange range,
+ TextureScaleMode scaleMode)
{
ScaleFactor = 1f; // Texture is first loaded at scale 1x.
ScaleMode = scaleMode;
- InitializeTexture(context, info, sizeInfo, range);
+ InitializeTexture(context, physicalMemory, info, sizeInfo, range);
}
/// <summary>
@@ -189,14 +199,21 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Other fields are initialized with their default values.
/// </summary>
/// <param name="context">GPU context that the texture belongs to</param>
+ /// <param name="physicalMemory">Physical memory where the texture is mapped</param>
/// <param name="info">Texture information</param>
/// <param name="sizeInfo">Size information of the texture</param>
/// <param name="range">Physical memory ranges where the texture data is located</param>
- private void InitializeTexture(GpuContext context, TextureInfo info, SizeInfo sizeInfo, MultiRange range)
+ private void InitializeTexture(
+ GpuContext context,
+ PhysicalMemory physicalMemory,
+ TextureInfo info,
+ SizeInfo sizeInfo,
+ MultiRange range)
{
- _context = context;
+ _context = context;
+ _physicalMemory = physicalMemory;
_sizeInfo = sizeInfo;
- Range = range;
+ Range = range;
SetInfo(info);
@@ -255,7 +272,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="hasMipViews">True if the texture will have mip views</param>
public void InitializeGroup(bool hasLayerViews, bool hasMipViews)
{
- Group = new TextureGroup(_context, this);
+ Group = new TextureGroup(_context, _physicalMemory, this);
Group.Initialize(ref _sizeInfo, hasLayerViews, hasMipViews);
}
@@ -276,6 +293,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
Texture texture = new Texture(
_context,
+ _physicalMemory,
info,
sizeInfo,
range,
@@ -638,7 +656,7 @@ namespace Ryujinx.Graphics.Gpu.Image
BlacklistScale();
}
- ReadOnlySpan<byte> data = _context.PhysicalMemory.GetSpan(Range);
+ ReadOnlySpan<byte> data = _physicalMemory.GetSpan(Range);
IsModified = false;
@@ -805,11 +823,11 @@ namespace Ryujinx.Graphics.Gpu.Image
if (tracked)
{
- _context.PhysicalMemory.Write(Range, GetTextureDataFromGpu(tracked));
+ _physicalMemory.Write(Range, GetTextureDataFromGpu(tracked));
}
else
{
- _context.PhysicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(tracked));
+ _physicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(tracked));
}
}
@@ -846,7 +864,7 @@ namespace Ryujinx.Graphics.Gpu.Image
texture = _flushHostTexture = GetScaledHostTexture(1f, _flushHostTexture);
}
- _context.PhysicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(false, texture));
+ _physicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(false, texture));
});
}
@@ -1280,7 +1298,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_viewStorage.RemoveView(this);
}
- _context.Methods.TextureCache.RemoveTextureFromCache(this);
+ _physicalMemory.TextureCache.RemoveTextureFromCache(this);
}
Debug.Assert(newRefCount >= 0);
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index 3689975d..14bc27a9 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -119,7 +119,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="samplerIndex">Type of the sampler pool indexing used for bound samplers</param>
public void SetSamplerPool(ulong gpuVa, int maximumId, SamplerIndex samplerIndex)
{
- ulong address = _context.MemoryManager.Translate(gpuVa);
+ ulong address = _channel.MemoryManager.Translate(gpuVa);
if (_samplerPool != null)
{
@@ -131,7 +131,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_samplerPool.Dispose();
}
- _samplerPool = new SamplerPool(_context, address, maximumId);
+ _samplerPool = new SamplerPool(_context, _channel.MemoryManager.Physical, address, maximumId);
_samplerIndex = samplerIndex;
}
@@ -142,7 +142,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="maximumId">Maximum ID of the pool (total count minus one)</param>
public void SetTexturePool(ulong gpuVa, int maximumId)
{
- ulong address = _context.MemoryManager.Translate(gpuVa);
+ ulong address = _channel.MemoryManager.Translate(gpuVa);
_texturePoolAddress = address;
_texturePoolMaximumId = maximumId;
@@ -228,6 +228,7 @@ namespace Ryujinx.Graphics.Gpu.Image
public void CommitBindings()
{
TexturePool texturePool = _texturePoolCache.FindOrCreate(
+ _channel,
_texturePoolAddress,
_texturePoolMaximumId);
@@ -437,9 +438,9 @@ namespace Ryujinx.Graphics.Gpu.Image
var poolState = state.Get<PoolState>(MethodOffset.TexturePoolState);
- ulong poolAddress = _context.MemoryManager.Translate(poolState.Address.Pack());
+ ulong poolAddress = _channel.MemoryManager.Translate(poolState.Address.Pack());
- TexturePool texturePool = _texturePoolCache.FindOrCreate(poolAddress, poolState.MaximumId);
+ TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, poolState.MaximumId);
return texturePool.GetDescriptor(textureId);
}
@@ -455,12 +456,11 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <returns>The packed texture and sampler ID (the real texture handle)</returns>
private int ReadPackedId(int stageIndex, int wordOffset, int textureBufferIndex, int samplerBufferIndex)
{
- var bufferManager = _context.Methods.BufferCache;
ulong textureBufferAddress = _isCompute
? _channel.BufferManager.GetComputeUniformBufferAddress(textureBufferIndex)
: _channel.BufferManager.GetGraphicsUniformBufferAddress(stageIndex, textureBufferIndex);
- int handle = _context.PhysicalMemory.Read<int>(textureBufferAddress + (ulong)(wordOffset & HandleMask) * 4);
+ int handle = _channel.MemoryManager.Physical.Read<int>(textureBufferAddress + (ulong)(wordOffset & HandleMask) * 4);
// The "wordOffset" (which is really the immediate value used on texture instructions on the shader)
// is a 13-bit value. However, in order to also support separate samplers and textures (which uses
@@ -474,7 +474,7 @@ namespace Ryujinx.Graphics.Gpu.Image
? _channel.BufferManager.GetComputeUniformBufferAddress(samplerBufferIndex)
: _channel.BufferManager.GetGraphicsUniformBufferAddress(stageIndex, samplerBufferIndex);
- handle |= _context.PhysicalMemory.Read<int>(samplerBufferAddress + (ulong)((wordOffset >> HandleHigh) - 1) * 4);
+ handle |= _channel.MemoryManager.Physical.Read<int>(samplerBufferAddress + (ulong)((wordOffset >> HandleHigh) - 1) * 4);
}
return handle;
@@ -514,7 +514,6 @@ namespace Ryujinx.Graphics.Gpu.Image
public void Dispose()
{
_samplerPool?.Dispose();
- _texturePoolCache.Dispose();
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 24fa723a..37a2219f 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -32,6 +32,7 @@ namespace Ryujinx.Graphics.Gpu.Image
private const int OverlapsBufferMaxCapacity = 10000;
private readonly GpuContext _context;
+ private readonly PhysicalMemory _physicalMemory;
private readonly MultiRangeList<Texture> _textures;
@@ -44,9 +45,11 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs a new instance of the texture manager.
/// </summary>
/// <param name="context">The GPU context that the texture manager belongs to</param>
- public TextureCache(GpuContext context)
+ /// <param name="physicalMemory">Physical memory where the textures managed by this cache are mapped</param>
+ public TextureCache(GpuContext context, PhysicalMemory physicalMemory)
{
_context = context;
+ _physicalMemory = physicalMemory;
_textures = new MultiRangeList<Texture>();
@@ -68,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.Image
lock (_textures)
{
- overlapCount = _textures.FindOverlaps(_context.MemoryManager.Translate(e.Address), e.Size, ref overlaps);
+ overlapCount = _textures.FindOverlaps(((MemoryManager)sender).Translate(e.Address), e.Size, ref overlaps);
}
for (int i = 0; i < overlapCount; i++)
@@ -139,13 +142,20 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Tries to find an existing texture, or create a new one if not found.
/// </summary>
+ /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
/// <param name="copyTexture">Copy texture to find or create</param>
/// <param name="offset">Offset to be added to the physical texture address</param>
/// <param name="formatInfo">Format information of the copy texture</param>
/// <param name="preferScaling">Indicates if the texture should be scaled from the start</param>
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
/// <returns>The texture</returns>
- public Texture FindOrCreateTexture(CopyTexture copyTexture, ulong offset, FormatInfo formatInfo, bool preferScaling = true, Size? sizeHint = null)
+ public Texture FindOrCreateTexture(
+ MemoryManager memoryManager,
+ CopyTexture copyTexture,
+ ulong offset,
+ FormatInfo formatInfo,
+ bool preferScaling = true,
+ Size? sizeHint = null)
{
int gobBlocksInY = copyTexture.MemoryLayout.UnpackGobBlocksInY();
int gobBlocksInZ = copyTexture.MemoryLayout.UnpackGobBlocksInZ();
@@ -184,7 +194,7 @@ namespace Ryujinx.Graphics.Gpu.Image
flags |= TextureSearchFlags.WithUpscale;
}
- Texture texture = FindOrCreateTexture(flags, info, 0, sizeHint);
+ Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0, sizeHint);
texture?.SynchronizeMemory();
@@ -194,12 +204,13 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Tries to find an existing texture, or create a new one if not found.
/// </summary>
+ /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
/// <param name="colorState">Color buffer texture to find or create</param>
/// <param name="samplesInX">Number of samples in the X direction, for MSAA</param>
/// <param name="samplesInY">Number of samples in the Y direction, for MSAA</param>
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
/// <returns>The texture</returns>
- public Texture FindOrCreateTexture(RtColorState colorState, int samplesInX, int samplesInY, Size sizeHint)
+ public Texture FindOrCreateTexture(MemoryManager memoryManager, RtColorState colorState, int samplesInX, int samplesInY, Size sizeHint)
{
bool isLinear = colorState.MemoryLayout.UnpackIsLinear();
@@ -263,7 +274,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int layerSize = !isLinear ? colorState.LayerSize * 4 : 0;
- Texture texture = FindOrCreateTexture(TextureSearchFlags.WithUpscale, info, layerSize, sizeHint);
+ Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, layerSize, sizeHint);
texture?.SynchronizeMemory();
@@ -273,13 +284,20 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Tries to find an existing texture, or create a new one if not found.
/// </summary>
+ /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
/// <param name="dsState">Depth-stencil buffer texture to find or create</param>
/// <param name="size">Size of the depth-stencil texture</param>
/// <param name="samplesInX">Number of samples in the X direction, for MSAA</param>
/// <param name="samplesInY">Number of samples in the Y direction, for MSAA</param>
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
/// <returns>The texture</returns>
- public Texture FindOrCreateTexture(RtDepthStencilState dsState, Size3D size, int samplesInX, int samplesInY, Size sizeHint)
+ public Texture FindOrCreateTexture(
+ MemoryManager memoryManager,
+ RtDepthStencilState dsState,
+ Size3D size,
+ int samplesInX,
+ int samplesInY,
+ Size sizeHint)
{
int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY();
int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ();
@@ -306,7 +324,7 @@ namespace Ryujinx.Graphics.Gpu.Image
target,
formatInfo);
- Texture texture = FindOrCreateTexture(TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4, sizeHint);
+ Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4, sizeHint);
texture?.SynchronizeMemory();
@@ -316,13 +334,20 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Tries to find an existing texture, or create a new one if not found.
/// </summary>
+ /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
/// <param name="flags">The texture search flags, defines texture comparison rules</param>
/// <param name="info">Texture information of the texture to be found or created</param>
/// <param name="layerSize">Size in bytes of a single texture layer</param>
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
/// <param name="range">Optional ranges of physical memory where the texture data is located</param>
/// <returns>The texture</returns>
- public Texture FindOrCreateTexture(TextureSearchFlags flags, TextureInfo info, int layerSize = 0, Size? sizeHint = null, MultiRange? range = null)
+ public Texture FindOrCreateTexture(
+ MemoryManager memoryManager,
+ TextureSearchFlags flags,
+ TextureInfo info,
+ int layerSize = 0,
+ Size? sizeHint = null,
+ MultiRange? range = null)
{
bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0;
@@ -342,7 +367,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
else
{
- address = _context.MemoryManager.Translate(info.GpuAddress);
+ address = memoryManager.Translate(info.GpuAddress);
if (address == MemoryManager.PteUnmapped)
{
@@ -371,22 +396,26 @@ namespace Ryujinx.Graphics.Gpu.Image
if (matchQuality != TextureMatchQuality.NoMatch)
{
// If the parameters match, we need to make sure the texture is mapped to the same memory regions.
-
- // If a range of memory was supplied, just check if the ranges match.
- if (range != null && !overlap.Range.Equals(range.Value))
+ if (range != null)
{
- continue;
+ // If a range of memory was supplied, just check if the ranges match.
+ if (!overlap.Range.Equals(range.Value))
+ {
+ continue;
+ }
}
-
- // If no range was supplied, we can check if the GPU virtual address match. If they do,
- // we know the textures are located at the same memory region.
- // If they don't, it may still be mapped to the same physical region, so we
- // do a more expensive check to tell if they are mapped into the same physical regions.
- // If the GPU VA for the texture has ever been unmapped, then the range must be checked regardless.
- if ((overlap.Info.GpuAddress != info.GpuAddress || overlap.ChangedMapping) &&
- !_context.MemoryManager.CompareRange(overlap.Range, info.GpuAddress))
+ else
{
- continue;
+ // If no range was supplied, we can check if the GPU virtual address match. If they do,
+ // we know the textures are located at the same memory region.
+ // If they don't, it may still be mapped to the same physical region, so we
+ // do a more expensive check to tell if they are mapped into the same physical regions.
+ // If the GPU VA for the texture has ever been unmapped, then the range must be checked regardless.
+ if ((overlap.Info.GpuAddress != info.GpuAddress || overlap.ChangedMapping) &&
+ !memoryManager.CompareRange(overlap.Range, info.GpuAddress))
+ {
+ continue;
+ }
}
}
@@ -426,7 +455,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (range == null)
{
- range = _context.MemoryManager.GetPhysicalRegions(info.GpuAddress, size);
+ range = memoryManager.GetPhysicalRegions(info.GpuAddress, size);
}
// Find view compatible matches.
@@ -495,7 +524,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
// Only copy compatible. If there's another choice for a FULLY compatible texture, choose that instead.
- texture = new Texture(_context, info, sizeInfo, range.Value, scaleMode);
+ texture = new Texture(_context, _physicalMemory, info, sizeInfo, range.Value, scaleMode);
texture.InitializeGroup(true, true);
texture.InitializeData(false, false);
@@ -531,7 +560,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// No match, create a new texture.
if (texture == null)
{
- texture = new Texture(_context, info, sizeInfo, range.Value, scaleMode);
+ texture = new Texture(_context, _physicalMemory, info, sizeInfo, range.Value, scaleMode);
// Step 1: Find textures that are view compatible with the new texture.
// Any textures that are incompatible will contain garbage data, so they should be removed where possible.
@@ -722,14 +751,15 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Tries to find an existing texture matching the given buffer copy destination. If none is found, returns null.
/// </summary>
+ /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
/// <param name="tex">The texture information</param>
/// <param name="cbp">The copy buffer parameters</param>
/// <param name="swizzle">The copy buffer swizzle</param>
/// <param name="linear">True if the texture has a linear layout, false otherwise</param>
/// <returns>A matching texture, or null if there is no match</returns>
- public Texture FindTexture(CopyBufferTexture tex, CopyBufferParams cbp, CopyBufferSwizzle swizzle, bool linear)
+ public Texture FindTexture(MemoryManager memoryManager, CopyBufferTexture tex, CopyBufferParams cbp, CopyBufferSwizzle swizzle, bool linear)
{
- ulong address = _context.MemoryManager.Translate(cbp.DstAddress.Pack());
+ ulong address = memoryManager.Translate(cbp.DstAddress.Pack());
if (address == MemoryManager.PteUnmapped)
{
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
index 30ca59d4..a43eccd6 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
@@ -1,5 +1,6 @@
using Ryujinx.Cpu.Tracking;
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture;
using Ryujinx.Memory.Range;
using System;
@@ -28,7 +29,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
public bool HasCopyDependencies { get; set; }
- private GpuContext _context;
+ private readonly GpuContext _context;
+ private readonly PhysicalMemory _physicalMemory;
private int[] _allOffsets;
private int[] _sliceSizes;
@@ -51,11 +53,13 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Create a new texture group.
/// </summary>
/// <param name="context">GPU context that the texture group belongs to</param>
+ /// <param name="physicalMemory">Physical memory where the <paramref name="storage"/> texture is mapped</param>
/// <param name="storage">The storage texture for this group</param>
- public TextureGroup(GpuContext context, Texture storage)
+ public TextureGroup(GpuContext context, PhysicalMemory physicalMemory, Texture storage)
{
Storage = storage;
_context = context;
+ _physicalMemory = physicalMemory;
_is3D = storage.Info.Target == Target.Texture3D;
_layers = storage.Info.GetSlices();
@@ -211,7 +215,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int endOffset = (offsetIndex + 1 == _allOffsets.Length) ? (int)Storage.Size : _allOffsets[offsetIndex + 1];
int size = endOffset - offset;
- ReadOnlySpan<byte> data = _context.PhysicalMemory.GetSpan(Storage.Range.GetSlice((ulong)offset, (ulong)size));
+ ReadOnlySpan<byte> data = _physicalMemory.GetSpan(Storage.Range.GetSlice((ulong)offset, (ulong)size));
data = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel, true);
@@ -561,7 +565,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <returns>A CpuRegionHandle covering the given range</returns>
private CpuRegionHandle GenerateHandle(ulong address, ulong size)
{
- return _context.PhysicalMemory.BeginTracking(address, size);
+ return _physicalMemory.BeginTracking(address, size);
}
/// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index 128dd89e..bcce443c 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Image
class TexturePool : Pool<Texture, TextureDescriptor>
{
private int _sequenceNumber;
+ private readonly GpuChannel _channel;
private readonly ConcurrentQueue<Texture> _dereferenceQueue = new ConcurrentQueue<Texture>();
/// <summary>
@@ -24,9 +25,13 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs a new instance of the texture pool.
/// </summary>
/// <param name="context">GPU context that the texture pool belongs to</param>
+ /// <param name="channel">GPU channel that the texture pool belongs to</param>
/// <param name="address">Address of the texture pool in guest memory</param>
/// <param name="maximumId">Maximum texture ID of the texture pool (equal to maximum textures minus one)</param>
- public TexturePool(GpuContext context, ulong address, int maximumId) : base(context, address, maximumId) { }
+ public TexturePool(GpuContext context, GpuChannel channel, ulong address, int maximumId) : base(context, channel.MemoryManager.Physical, address, maximumId)
+ {
+ _channel = channel;
+ }
/// <summary>
/// Gets the texture with the given ID.
@@ -57,7 +62,7 @@ namespace Ryujinx.Graphics.Gpu.Image
ProcessDereferenceQueue();
- texture = Context.Methods.TextureCache.FindOrCreateTexture(TextureSearchFlags.ForSampler, info, layerSize);
+ texture = PhysicalMemory.TextureCache.FindOrCreateTexture(_channel.MemoryManager, TextureSearchFlags.ForSampler, info, layerSize);
// If this happens, then the texture address is invalid, we can't add it to the cache.
if (texture == null)
@@ -148,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (texture != null)
{
- TextureDescriptor descriptor = Context.PhysicalMemory.Read<TextureDescriptor>(address);
+ TextureDescriptor descriptor = PhysicalMemory.Read<TextureDescriptor>(address);
// If the descriptors are the same, the texture is the same,
// we don't need to remove as it was not modified. Just continue.
@@ -214,7 +219,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
{
- if (Context.MemoryManager.IsMapped(gpuVa) && (int)format > 0)
+ if (gpuVa != 0 && (int)format > 0)
{
Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb}).");
}
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs b/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs
index c9eebf8b..99c5a88b 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs
@@ -8,13 +8,12 @@ namespace Ryujinx.Graphics.Gpu.Image
/// This can keep multiple texture pools, and return the current one as needed.
/// It is useful for applications that uses multiple texture pools.
/// </summary>
- class TexturePoolCache : IDisposable
+ class TexturePoolCache
{
private const int MaxCapacity = 4;
- private GpuContext _context;
-
- private LinkedList<TexturePool> _pools;
+ private readonly GpuContext _context;
+ private readonly LinkedList<TexturePool> _pools;
/// <summary>
/// Constructs a new instance of the texture pool.
@@ -23,17 +22,17 @@ namespace Ryujinx.Graphics.Gpu.Image
public TexturePoolCache(GpuContext context)
{
_context = context;
-
_pools = new LinkedList<TexturePool>();
}
/// <summary>
/// Finds a cache texture pool, or creates a new one if not found.
/// </summary>
+ /// <param name="channel">GPU channel that the texture pool cache belongs to</param>
/// <param name="address">Start address of the texture pool</param>
/// <param name="maximumId">Maximum ID of the texture pool</param>
/// <returns>The found or newly created texture pool</returns>
- public TexturePool FindOrCreate(ulong address, int maximumId)
+ public TexturePool FindOrCreate(GpuChannel channel, ulong address, int maximumId)
{
TexturePool pool;
@@ -56,7 +55,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
// If not found, create a new one.
- pool = new TexturePool(_context, address, maximumId);
+ pool = new TexturePool(_context, channel, address, maximumId);
pool.CacheNode = _pools.AddLast(pool);
@@ -73,19 +72,5 @@ namespace Ryujinx.Graphics.Gpu.Image
return pool;
}
-
- /// <summary>
- /// Disposes the texture pool cache.
- /// It's an error to use the texture pool cache after disposal.
- /// </summary>
- public void Dispose()
- {
- foreach (TexturePool pool in _pools)
- {
- pool.Dispose();
- }
-
- _pools.Clear();
- }
}
} \ No newline at end of file