GPU: Track buffer migrations and flush source on incomplete copy (#3952)

* Track buffer migrations and flush source on incomplete copy

Makes sure that the modified range list is always from the latest iteration of the buffer, and flushes earlier iterations of a buffer if the data has not been migrated yet.

* Cleanup 1

* Reduce cost for redundant signal checks on Vulkan

* Only inherit the range list if there are pending ranges.

* Fix OpenGL

* Address Feedback

* Whoops
This commit is contained in:
riperiperi 2022-12-01 15:30:13 +00:00 committed by GitHub
parent 817b89767a
commit 458452279c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 451 additions and 87 deletions

View file

@ -69,6 +69,12 @@ namespace Ryujinx.Graphics.Gpu
/// </summary>
internal List<Action> SyncpointActions { get; }
/// <summary>
/// Buffer migrations that are currently in-flight. These are checked whenever sync is created to determine if buffer migration
/// copies have completed on the GPU, and their data can be freed.
/// </summary>
internal List<BufferMigration> BufferMigrations { get; }
/// <summary>
/// Queue with deferred actions that must run on the render thread.
/// </summary>
@ -90,6 +96,7 @@ namespace Ryujinx.Graphics.Gpu
public event Action<ShaderCacheState, int, int> ShaderCacheStateChanged;
private Thread _gpuThread;
private bool _pendingSync;
/// <summary>
/// Creates a new instance of the GPU emulation context.
@ -109,6 +116,7 @@ namespace Ryujinx.Graphics.Gpu
SyncActions = new List<Action>();
SyncpointActions = new List<Action>();
BufferMigrations = new List<BufferMigration>();
DeferredActions = new Queue<Action>();
@ -273,6 +281,17 @@ namespace Ryujinx.Graphics.Gpu
SequenceNumber++;
}
/// <summary>
/// Registers a buffer migration. These are checked to see if they can be disposed when the sync number increases,
/// and the migration copy has completed.
/// </summary>
/// <param name="migration">The buffer migration</param>
internal void RegisterBufferMigration(BufferMigration migration)
{
BufferMigrations.Add(migration);
_pendingSync = true;
}
/// <summary>
/// Registers an action to be performed the next time a syncpoint is incremented.
/// This will also ensure a host sync object is created, and <see cref="SyncNumber"/> is incremented.
@ -288,6 +307,7 @@ namespace Ryujinx.Graphics.Gpu
else
{
SyncActions.Add(action);
_pendingSync = true;
}
}
@ -298,7 +318,24 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="syncpoint">True if host sync is being created by a syncpoint</param>
public void CreateHostSyncIfNeeded(bool syncpoint)
{
if (SyncActions.Count > 0 || (syncpoint && SyncpointActions.Count > 0))
if (BufferMigrations.Count > 0)
{
ulong currentSyncNumber = Renderer.GetCurrentSync();
for (int i = 0; i < BufferMigrations.Count; i++)
{
BufferMigration migration = BufferMigrations[i];
long diff = (long)(currentSyncNumber - migration.SyncNumber);
if (diff >= 0)
{
migration.Dispose();
BufferMigrations.RemoveAt(i--);
}
}
}
if (_pendingSync || (syncpoint && SyncpointActions.Count > 0))
{
Renderer.CreateSync(SyncNumber);
@ -317,6 +354,8 @@ namespace Ryujinx.Graphics.Gpu
SyncActions.Clear();
SyncpointActions.Clear();
}
_pendingSync = false;
}
/// <summary>