aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs3
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs1
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Pool.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/Image/SamplerPool.cs6
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureCache.cs12
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TexturePool.cs5
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/Buffer.cs37
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/GpuRegionHandle.cs34
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs33
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>