diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs | 3 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs | 1 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Pool.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/SamplerPool.cs | 6 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 12 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 5 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/Buffer.cs | 37 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/GpuRegionHandle.cs | 34 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs | 10 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs | 33 |
10 files changed, 118 insertions, 42 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs b/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs index e3e8d5ba..9649841f 100644 --- a/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs +++ b/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs @@ -171,7 +171,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory if (_isLinear && _lineCount == 1) { - memoryManager.Physical.CacheResourceWrite(memoryManager, _dstGpuVa, data); + memoryManager.WriteTrackedResource(_dstGpuVa, data); + _context.AdvanceSequence(); } else { diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs index d4f228e9..52637c20 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs @@ -211,6 +211,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { uint syncpointId = (uint)argument & 0xFFFF; + _context.AdvanceSequence(); _context.CreateHostSyncIfNeeded(); _context.Renderer.UpdateCounters(); // Poll the query counters, the game may want an updated result. _context.Synchronization.IncrementSyncpoint(syncpointId); diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs index a06a7ccf..f54ce1d7 100644 --- a/Ryujinx.Graphics.Gpu/Image/Pool.cs +++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs @@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Image protected GpuContext Context; protected PhysicalMemory PhysicalMemory; + protected int SequenceNumber; protected T1[] Items; protected T2[] DescriptorCache; @@ -64,6 +65,7 @@ namespace Ryujinx.Graphics.Gpu.Image Size = size; _memoryTracking = physicalMemory.BeginGranularTracking(address, size); + _memoryTracking.RegisterPreciseAction(address, size, PreciseAction); _modifiedDelegate = RegionModified; } @@ -116,6 +118,23 @@ namespace Ryujinx.Graphics.Gpu.Image InvalidateRangeImpl(mAddress, mSize); } + /// <summary> + /// An action to be performed when a precise memory access occurs to this resource. + /// Makes sure that the dirty flags are checked. + /// </summary> + /// <param name="address">Address of the memory action</param> + /// <param name="size">Size in bytes</param> + /// <param name="write">True if the access was a write, false otherwise</param> + private bool PreciseAction(ulong address, ulong size, bool write) + { + if (write && Context.SequenceNumber == SequenceNumber) + { + SequenceNumber--; + } + + return false; + } + protected abstract void InvalidateRangeImpl(ulong address, ulong size); protected abstract void Delete(T1 item); diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs index aed6cb9c..5a84bd84 100644 --- a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs +++ b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs @@ -7,8 +7,6 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> class SamplerPool : Pool<Sampler, SamplerDescriptor> { - private int _sequenceNumber; - /// <summary> /// Constructs a new instance of the sampler pool. /// </summary> @@ -30,9 +28,9 @@ namespace Ryujinx.Graphics.Gpu.Image return null; } - if (_sequenceNumber != Context.SequenceNumber) + if (SequenceNumber != Context.SequenceNumber) { - _sequenceNumber = Context.SequenceNumber; + SequenceNumber = Context.SequenceNumber; SynchronizeMemory(); } diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs index cc6867a6..1aa09b90 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -100,18 +100,6 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> - /// Determines if any texture exists within the target memory range. - /// </summary> - /// <param name="memoryManager">The GPU memory manager</param> - /// <param name="gpuVa">GPU virtual address to search for textures</param> - /// <param name="size">The size of the range</param> - /// <returns>True if any texture exists in the range, false otherwise</returns> - public bool IsTextureInRange(MemoryManager memoryManager, ulong gpuVa, ulong size) - { - return _textures.FindOverlaps(memoryManager.GetPhysicalRegions(gpuVa, size), ref _textureOverlaps) != 0; - } - - /// <summary> /// Determines if a given texture is "safe" for upscaling from its info. /// Note that this is different from being compatible - this elilinates targets that would have detrimental effects when scaled. /// </summary> diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index 5b5c5ab0..66cd9d4d 100644 --- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -12,7 +12,6 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> class TexturePool : Pool<Texture, TextureDescriptor> { - private int _sequenceNumber; private readonly GpuChannel _channel; private readonly ConcurrentQueue<Texture> _dereferenceQueue = new ConcurrentQueue<Texture>(); @@ -45,9 +44,9 @@ namespace Ryujinx.Graphics.Gpu.Image return null; } - if (_sequenceNumber != Context.SequenceNumber) + if (SequenceNumber != Context.SequenceNumber) { - _sequenceNumber = Context.SequenceNumber; + SequenceNumber = Context.SequenceNumber; SynchronizeMemory(); } diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index af69e693..76125e31 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Cpu.Tracking; using Ryujinx.Graphics.GAL; using Ryujinx.Memory.Range; @@ -104,6 +105,8 @@ namespace Ryujinx.Graphics.Gpu.Memory if (_useGranular) { _memoryTrackingGranular = physicalMemory.BeginGranularTracking(address, size, baseHandles); + + _memoryTrackingGranular.RegisterPreciseAction(address, size, PreciseAction); } else { @@ -123,6 +126,8 @@ namespace Ryujinx.Graphics.Gpu.Memory handle.Dispose(); } } + + _memoryTracking.RegisterPreciseAction(PreciseAction); } _externalFlushDelegate = new RegionSignal(ExternalFlush); @@ -453,6 +458,38 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// <summary> + /// An action to be performed when a precise memory access occurs to this resource. + /// For buffers, this skips flush-on-write by punching holes directly into the modified range list. + /// </summary> + /// <param name="address">Address of the memory action</param> + /// <param name="size">Size in bytes</param> + /// <param name="write">True if the access was a write, false otherwise</param> + private bool PreciseAction(ulong address, ulong size, bool write) + { + if (!write) + { + // We only want to skip flush-on-write. + return false; + } + + if (address < Address) + { + address = Address; + } + + ulong maxSize = Address + Size - address; + + if (size > maxSize) + { + size = maxSize; + } + + ForceDirty(address, size); + + return true; + } + + /// <summary> /// Called when part of the memory for this buffer has been unmapped. /// Calls are from non-GPU threads. /// </summary> diff --git a/Ryujinx.Graphics.Gpu/Memory/GpuRegionHandle.cs b/Ryujinx.Graphics.Gpu/Memory/GpuRegionHandle.cs index 8a9c6767..bc07bfad 100644 --- a/Ryujinx.Graphics.Gpu/Memory/GpuRegionHandle.cs +++ b/Ryujinx.Graphics.Gpu/Memory/GpuRegionHandle.cs @@ -4,6 +4,9 @@ using System; namespace Ryujinx.Graphics.Gpu.Memory { + /// <summary> + /// A tracking handle for a region of GPU VA, represented by one or more tracking handles in CPU VA. + /// </summary> class GpuRegionHandle : IRegionHandle { private readonly CpuRegionHandle[] _cpuRegionHandles; @@ -28,11 +31,18 @@ namespace Ryujinx.Graphics.Gpu.Memory public ulong Size => throw new NotSupportedException(); public ulong EndAddress => throw new NotSupportedException(); + /// <summary> + /// Create a new GpuRegionHandle, made up of mulitple CpuRegionHandles. + /// </summary> + /// <param name="cpuRegionHandles">The CpuRegionHandles that make up this handle</param> public GpuRegionHandle(CpuRegionHandle[] cpuRegionHandles) { _cpuRegionHandles = cpuRegionHandles; } + /// <summary> + /// Dispose the child handles. + /// </summary> public void Dispose() { foreach (var regionHandle in _cpuRegionHandles) @@ -41,6 +51,11 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// <summary> + /// Register an action to perform when the tracked region is read or written. + /// The action is automatically removed after it runs. + /// </summary> + /// <param name="action">Action to call on read or write</param> public void RegisterAction(RegionSignal action) { foreach (var regionHandle in _cpuRegionHandles) @@ -49,6 +64,22 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// <summary> + /// Register an action to perform when a precise access occurs (one with exact address and size). + /// If the action returns true, read/write tracking are skipped. + /// </summary> + /// <param name="action">Action to call on read or write</param> + public void RegisterPreciseAction(PreciseRegionSignal action) + { + foreach (var regionHandle in _cpuRegionHandles) + { + regionHandle.RegisterPreciseAction(action); + } + } + + /// <summary> + /// Consume the dirty flag for the handles, and reprotect so it can be set on the next write. + /// </summary> public void Reprotect(bool asDirty = false) { foreach (var regionHandle in _cpuRegionHandles) @@ -57,6 +88,9 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// <summary> + /// Force the handles to be dirty, without reprotecting. + /// </summary> public void ForceDirty() { foreach (var regionHandle in _cpuRegionHandles) diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs index 2dc1edd2..3968cb96 100644 --- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -195,6 +195,16 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// <summary> + /// Writes data to GPU mapped memory, destined for a tracked resource. + /// </summary> + /// <param name="va">GPU virtual address to write the data into</param> + /// <param name="data">The data to be written</param> + public void WriteTrackedResource(ulong va, ReadOnlySpan<byte> data) + { + WriteImpl(va, data, Physical.WriteTrackedResource); + } + + /// <summary> /// Writes data to GPU mapped memory without write tracking. /// </summary> /// <param name="va">GPU virtual address to write the data into</param> diff --git a/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs b/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs index 0ec41a8f..d292fab0 100644 --- a/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs +++ b/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs @@ -81,28 +81,6 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// <summary> - /// Write data to memory that is destined for a resource in a cache. - /// This avoids triggering write tracking when possible, which can avoid flushes and incrementing sequence number. - /// </summary> - /// <param name="memoryManager">The GPU memory manager</param> - /// <param name="gpuVa">GPU virtual address to write the data into</param> - /// <param name="data">The data to be written</param> - public void CacheResourceWrite(MemoryManager memoryManager, ulong gpuVa, ReadOnlySpan<byte> data) - { - if (TextureCache.IsTextureInRange(memoryManager, gpuVa, (ulong)data.Length)) - { - // No fast path yet - copy the data back and trigger write tracking. - memoryManager.Write(gpuVa, data); - _context.AdvanceSequence(); - } - else - { - BufferCache.ForceDirty(memoryManager, gpuVa, (ulong)data.Length); - memoryManager.WriteUntracked(gpuVa, data); - } - } - - /// <summary> /// Gets a span of data from the application process. /// </summary> /// <param name="address">Start address of the range</param> @@ -180,6 +158,17 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// <summary> + /// Writes data to the application process, triggering a precise memory tracking event. + /// </summary> + /// <param name="address">Address to write into</param> + /// <param name="data">Data to be written</param> + public void WriteTrackedResource(ulong address, ReadOnlySpan<byte> data) + { + _cpuMemory.SignalMemoryTracking(address, (ulong)data.Length, true, precise: true); + _cpuMemory.WriteUntracked(address, data); + } + + /// <summary> /// Writes data to the application process. /// </summary> /// <param name="address">Address to write into</param> |
