diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/CommandBufferPool.cs | 16 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineFull.cs | 1 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/SyncManager.cs | 44 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 15 |
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; |