diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2021-06-29 14:32:02 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-29 19:32:02 +0200 |
| commit | fbb4019ed5c12c4a888c7b09db648ac595366896 (patch) | |
| tree | a8be6bf5fc4f8b844683f1ef2ade588f3bb9bb0a /Ryujinx.Graphics.Gpu/Image | |
| parent | 8cc872fb60ec1b825655ba8dba06cc978fcd7e66 (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.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/SamplerPool.cs | 5 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 56 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs | 17 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 86 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureGroup.cs | 12 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 13 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TexturePoolCache.cs | 27 |
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 |
