aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan')
-rw-r--r--Ryujinx.Graphics.Vulkan/CommandBufferPool.cs16
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineFull.cs1
-rw-r--r--Ryujinx.Graphics.Vulkan/SyncManager.cs44
-rw-r--r--Ryujinx.Graphics.Vulkan/VulkanRenderer.cs15
4 files changed, 69 insertions, 7 deletions
diff --git a/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs b/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs
index c77b0040..4cbb24ef 100644
--- a/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs
+++ b/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs
@@ -116,6 +116,22 @@ namespace Ryujinx.Graphics.Vulkan
}
}
+ public void AddInUseWaitable(MultiFenceHolder waitable)
+ {
+ lock (_commandBuffers)
+ {
+ for (int i = 0; i < _totalCommandBuffers; i++)
+ {
+ ref var entry = ref _commandBuffers[i];
+
+ if (entry.InUse)
+ {
+ AddWaitable(i, waitable);
+ }
+ }
+ }
+ }
+
public void AddDependency(int cbIndex, CommandBufferScoped dependencyCbs)
{
Debug.Assert(_commandBuffers[cbIndex].InUse);
diff --git a/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/Ryujinx.Graphics.Vulkan/PipelineFull.cs
index 56a49184..2256c542 100644
--- a/Ryujinx.Graphics.Vulkan/PipelineFull.cs
+++ b/Ryujinx.Graphics.Vulkan/PipelineFull.cs
@@ -227,6 +227,7 @@ namespace Ryujinx.Graphics.Vulkan
}
CommandBuffer = (Cbs = Gd.CommandBufferPool.ReturnAndRent(Cbs)).CommandBuffer;
+ Gd.RegisterFlush();
// Restore per-command buffer state.
diff --git a/Ryujinx.Graphics.Vulkan/SyncManager.cs b/Ryujinx.Graphics.Vulkan/SyncManager.cs
index 35e3adf1..c046dc3c 100644
--- a/Ryujinx.Graphics.Vulkan/SyncManager.cs
+++ b/Ryujinx.Graphics.Vulkan/SyncManager.cs
@@ -11,7 +11,13 @@ namespace Ryujinx.Graphics.Vulkan
{
public ulong ID;
public MultiFenceHolder Waitable;
+ public ulong FlushId;
public bool Signalled;
+
+ public bool NeedsFlush(ulong currentFlushId)
+ {
+ return (long)(FlushId - currentFlushId) >= 0;
+ }
}
private ulong _firstHandle = 0;
@@ -19,6 +25,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly VulkanRenderer _gd;
private readonly Device _device;
private List<SyncHandle> _handles;
+ private ulong FlushId;
public SyncManager(VulkanRenderer gd, Device device)
{
@@ -27,17 +34,33 @@ namespace Ryujinx.Graphics.Vulkan
_handles = new List<SyncHandle>();
}
- public void Create(ulong id)
+ public void RegisterFlush()
+ {
+ FlushId++;
+ }
+
+ public void Create(ulong id, bool strict)
{
+ ulong flushId = FlushId;
MultiFenceHolder waitable = new MultiFenceHolder();
+ if (strict || _gd.InterruptAction == null)
+ {
+ _gd.FlushAllCommands();
+ _gd.CommandBufferPool.AddWaitable(waitable);
+ }
+ else
+ {
+ // Don't flush commands, instead wait for the current command buffer to finish.
+ // If this sync is waited on before the command buffer is submitted, interrupt the gpu thread and flush it manually.
- _gd.FlushAllCommands();
- _gd.CommandBufferPool.AddWaitable(waitable);
+ _gd.CommandBufferPool.AddInUseWaitable(waitable);
+ }
SyncHandle handle = new SyncHandle
{
ID = id,
- Waitable = waitable
+ Waitable = waitable,
+ FlushId = flushId
};
lock (_handles)
@@ -107,6 +130,17 @@ namespace Ryujinx.Graphics.Vulkan
return;
}
+ if (result.NeedsFlush(FlushId))
+ {
+ _gd.InterruptAction(() =>
+ {
+ if (result.NeedsFlush(FlushId))
+ {
+ _gd.FlushAllCommands();
+ }
+ });
+ }
+
bool signaled = result.Signalled || result.Waitable.WaitForFences(_gd.Api, _device, 1000000000);
if (!signaled)
{
@@ -132,7 +166,7 @@ namespace Ryujinx.Graphics.Vulkan
first = _handles.FirstOrDefault();
}
- if (first == null) break;
+ if (first == null || first.NeedsFlush(FlushId)) break;
bool signaled = first.Waitable.WaitForFences(_gd.Api, _device, 0);
if (signaled)
diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 3c446abf..5c77cb00 100644
--- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -48,6 +48,7 @@ namespace Ryujinx.Graphics.Vulkan
internal DescriptorSetManager DescriptorSetManager { get; private set; }
internal PipelineLayoutCache PipelineLayoutCache { get; private set; }
internal BackgroundResources BackgroundResources { get; private set; }
+ internal Action<Action> InterruptAction { get; private set; }
internal BufferManager BufferManager { get; private set; }
@@ -354,6 +355,11 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline?.FlushCommandsImpl();
}
+ internal void RegisterFlush()
+ {
+ _syncManager.RegisterFlush();
+ }
+
public ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
{
return BufferManager.GetData(buffer, offset, size);
@@ -593,9 +599,9 @@ namespace Ryujinx.Graphics.Vulkan
action();
}
- public void CreateSync(ulong id)
+ public void CreateSync(ulong id, bool strict)
{
- _syncManager.Create(id);
+ _syncManager.Create(id, strict);
}
public IProgram LoadProgramBinary(byte[] programBinary, bool isFragment, ShaderInfo info)
@@ -613,6 +619,11 @@ namespace Ryujinx.Graphics.Vulkan
return _syncManager.GetCurrent();
}
+ public void SetInterruptAction(Action<Action> interruptAction)
+ {
+ InterruptAction = interruptAction;
+ }
+
public void Screenshot()
{
_window.ScreenCaptureRequested = true;