Texture Cache: "Texture Groups" and "Texture Dependencies" (#2001)

* Initial implementation (3d tex mips broken)

This works rather well for most games, just need to fix 3d texture mips.

* Cleanup

* Address feedback

* Copy Dependencies and various other fixes

* Fix layer/level offset for copy from view<->view.

* Remove dirty flag from dependency

The dirty flag behaviour is not needed - DeferredCopy is all we need.

* Fix tracking mip slices.

* Propagate granularity (fix astral chain)

* Address Feedback pt 1

* Save slice sizes as part of SizeInfo

* Fix nits

* Fix disposing multiple dependencies causing a crash

This list is obviously modified when removing dependencies, so create a copy of it.
This commit is contained in:
riperiperi 2021-03-02 22:30:54 +00:00 committed by GitHub
parent 7a90abc035
commit b530f0e110
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1915 additions and 220 deletions

View file

@ -1,4 +1,5 @@
using Ryujinx.Memory.Range;
using System;
using System.Collections.Generic;
using System.Threading;
@ -19,9 +20,12 @@ namespace Ryujinx.Memory.Tracking
internal IMultiRegionHandle Parent { get; set; }
internal int SequenceNumber { get; set; }
private event Action _onDirty;
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
private readonly List<VirtualRegion> _regions;
private readonly MemoryTracking _tracking;
private bool _disposed;
internal MemoryPermission RequiredPermission => _preAction != null ? MemoryPermission.None : (Dirty ? MemoryPermission.ReadAndWrite : MemoryPermission.Read);
internal RegionSignal PreAction => _preAction;
@ -60,7 +64,12 @@ namespace Ryujinx.Memory.Tracking
if (write)
{
bool oldDirty = Dirty;
Dirty = true;
if (!oldDirty)
{
_onDirty?.Invoke();
}
Parent?.SignalWrite();
}
}
@ -68,9 +77,9 @@ namespace Ryujinx.Memory.Tracking
/// <summary>
/// Consume the dirty flag for this handle, and reprotect so it can be set on the next write.
/// </summary>
public void Reprotect()
public void Reprotect(bool asDirty = false)
{
Dirty = false;
Dirty = asDirty;
lock (_tracking.TrackingLock)
{
foreach (VirtualRegion region in _regions)
@ -100,6 +109,16 @@ namespace Ryujinx.Memory.Tracking
}
}
/// <summary>
/// Register an action to perform when the region is written to.
/// This action will not be removed when it is called - it is called each time the dirty flag is set.
/// </summary>
/// <param name="action">Action to call on dirty</param>
public void RegisterDirtyEvent(Action action)
{
_onDirty += action;
}
/// <summary>
/// Add a child virtual region to this handle.
/// </summary>
@ -125,6 +144,13 @@ namespace Ryujinx.Memory.Tracking
/// </summary>
public void Dispose()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().FullName);
}
_disposed = true;
lock (_tracking.TrackingLock)
{
foreach (VirtualRegion region in _regions)