diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Memory')
| -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 |
4 files changed, 92 insertions, 22 deletions
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> |
