mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2026-01-02 15:32:32 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3c41fa4bb | ||
|
|
356e480bf5 |
73
Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs
Normal file
73
Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
internal class AutoFlushCounter
|
||||
{
|
||||
// How often to flush on framebuffer change.
|
||||
private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000;
|
||||
|
||||
private const int MinDrawCountForFlush = 10;
|
||||
private const int InitialQueryCountForFlush = 32;
|
||||
|
||||
private long _lastFlush;
|
||||
private ulong _lastDrawCount;
|
||||
private bool _hasPendingQuery;
|
||||
private int _queryCount;
|
||||
|
||||
public void RegisterFlush(ulong drawCount)
|
||||
{
|
||||
_lastFlush = Stopwatch.GetTimestamp();
|
||||
_lastDrawCount = drawCount;
|
||||
|
||||
_hasPendingQuery = false;
|
||||
}
|
||||
|
||||
public bool RegisterPendingQuery()
|
||||
{
|
||||
_hasPendingQuery = true;
|
||||
|
||||
// Interrupt render passes to flush queries, so that early results arrive sooner.
|
||||
if (++_queryCount == InitialQueryCountForFlush)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ShouldFlushQuery()
|
||||
{
|
||||
return _hasPendingQuery;
|
||||
}
|
||||
|
||||
public bool ShouldFlush(ulong drawCount)
|
||||
{
|
||||
_queryCount = 0;
|
||||
|
||||
if (_hasPendingQuery)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long draws = (long)(drawCount - _lastDrawCount);
|
||||
|
||||
if (draws < MinDrawCountForFlush)
|
||||
{
|
||||
if (draws == 0)
|
||||
{
|
||||
_lastFlush = Stopwatch.GetTimestamp();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
long flushTimeout = FramebufferFlushTimer;
|
||||
|
||||
long now = Stopwatch.GetTimestamp();
|
||||
|
||||
return now > _lastFlush + flushTimeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
protected readonly Device Device;
|
||||
public readonly PipelineCache PipelineCache;
|
||||
|
||||
protected readonly AutoFlushCounter AutoFlush;
|
||||
|
||||
private PipelineDynamicState _dynamicState;
|
||||
private PipelineState _newState;
|
||||
private bool _stateDirty;
|
||||
@@ -70,6 +72,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Gd = gd;
|
||||
Device = device;
|
||||
|
||||
AutoFlush = new AutoFlushCounter();
|
||||
|
||||
var pipelineCacheCreateInfo = new PipelineCacheCreateInfo()
|
||||
{
|
||||
SType = StructureType.PipelineCacheCreateInfo
|
||||
|
||||
@@ -10,8 +10,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
private const ulong MinByteWeightForFlush = 256 * 1024 * 1024; // MB
|
||||
|
||||
private bool _hasPendingQuery;
|
||||
|
||||
private readonly List<QueryPool> _activeQueries;
|
||||
private CounterQueueEvent _activeConditionalRender;
|
||||
|
||||
@@ -158,9 +156,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private void FlushPendingQuery()
|
||||
{
|
||||
if (_hasPendingQuery)
|
||||
if (AutoFlush.ShouldFlushQuery())
|
||||
{
|
||||
_hasPendingQuery = false;
|
||||
FlushCommandsImpl();
|
||||
}
|
||||
}
|
||||
@@ -211,6 +208,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void FlushCommandsImpl()
|
||||
{
|
||||
AutoFlush.RegisterFlush(DrawCount);
|
||||
EndRenderPass();
|
||||
|
||||
foreach (var queryPool in _activeQueries)
|
||||
@@ -277,12 +275,18 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
_pendingQueryCopies.Add(query);
|
||||
|
||||
_hasPendingQuery = true;
|
||||
if (AutoFlush.RegisterPendingQuery())
|
||||
{
|
||||
FlushCommandsImpl();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SignalAttachmentChange()
|
||||
{
|
||||
FlushPendingQuery();
|
||||
if (AutoFlush.ShouldFlush(DrawCount))
|
||||
{
|
||||
FlushCommandsImpl();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SignalRenderPassEnd()
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
|
||||
lock (_protections)
|
||||
{
|
||||
_protections.Add(new RangeNode<MemoryPermission>(address, size, MemoryPermission.None));
|
||||
_protections.Add(new RangeNode<MemoryPermission>(address, address + size, MemoryPermission.None));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
try
|
||||
{
|
||||
UnmapViewInternal(sharedMemory, location, size, owner, updateProtection: false);
|
||||
MapViewInternal(sharedMemory, srcOffset, location, size);
|
||||
MapViewInternal(sharedMemory, srcOffset, location, size, updateProtection: true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -147,8 +147,9 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
/// <param name="srcOffset">Offset in the shared memory to map</param>
|
||||
/// <param name="location">Address to map the view into</param>
|
||||
/// <param name="size">Size of the view in bytes</param>
|
||||
/// <param name="updateProtection">Indicates if the memory protections should be updated after the map</param>
|
||||
/// <exception cref="WindowsApiException">Thrown when the Windows API returns an error mapping the memory</exception>
|
||||
private void MapViewInternal(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size)
|
||||
private void MapViewInternal(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size, bool updateProtection)
|
||||
{
|
||||
SplitForMap((ulong)location, (ulong)size, srcOffset);
|
||||
|
||||
@@ -168,7 +169,10 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
throw new WindowsApiException("MapViewOfFile3");
|
||||
}
|
||||
|
||||
UpdateProtection((ulong)location, (ulong)size, MemoryPermission.ReadAndWrite);
|
||||
if (updateProtection)
|
||||
{
|
||||
UpdateProtection((ulong)location, (ulong)size, MemoryPermission.ReadAndWrite);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -330,7 +334,7 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
{
|
||||
ulong remapSize = startAddress - overlap.Start;
|
||||
|
||||
MapViewInternal(sharedMemory, overlap.Value, (IntPtr)overlap.Start, (IntPtr)remapSize);
|
||||
MapViewInternal(sharedMemory, overlap.Value, (IntPtr)overlap.Start, (IntPtr)remapSize, updateProtection: false);
|
||||
RestoreRangeProtection(overlap.Start, remapSize);
|
||||
}
|
||||
|
||||
@@ -341,7 +345,7 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
ulong remapAddress = overlap.Start + overlappedSize;
|
||||
ulong remapSize = overlap.End - endAddress;
|
||||
|
||||
MapViewInternal(sharedMemory, remapBackingOffset, (IntPtr)remapAddress, (IntPtr)remapSize);
|
||||
MapViewInternal(sharedMemory, remapBackingOffset, (IntPtr)remapAddress, (IntPtr)remapSize, updateProtection: false);
|
||||
RestoreRangeProtection(remapAddress, remapSize);
|
||||
}
|
||||
}
|
||||
@@ -606,7 +610,7 @@ namespace Ryujinx.Memory.WindowsShared
|
||||
|
||||
_protections.Remove(protection);
|
||||
|
||||
if (protection.Value == permission)
|
||||
if (protPermission == permission)
|
||||
{
|
||||
if (startAddress > protAddress)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user