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
This commit is contained in:
parent
8cc872fb60
commit
fbb4019ed5
44 changed files with 780 additions and 481 deletions
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}).");
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue