From 8ccf83d9a34d916b556be16dc59d7a4b80665da4 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 6 Feb 2024 11:03:39 -0300 Subject: [PATCH] Prevent waits with zero timeout on Turnip --- src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs | 1 + src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs | 7 +++++-- src/Ryujinx.Graphics.Vulkan/FenceHolder.cs | 14 +++++++++++++- src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs | 2 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 5 ++++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs index 5260c5d8b..d8c569ac2 100644 --- a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs +++ b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs @@ -36,6 +36,7 @@ namespace Ryujinx.Graphics.Vulkan queueLock, _gd.QueueFamilyIndex, _gd.IsQualcommProprietary, + _gd.IsTurnip, isLight: true); } } diff --git a/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs b/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs index 311cc2397..ef81e6405 100644 --- a/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs +++ b/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs @@ -19,6 +19,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly Queue _queue; private readonly Lock _queueLock; private readonly bool _concurrentFenceWaitUnsupported; + private readonly bool _fenceAlwaysWaits; private readonly CommandPool _pool; private readonly Thread _owner; @@ -66,6 +67,7 @@ namespace Ryujinx.Graphics.Vulkan Lock queueLock, uint queueFamilyIndex, bool concurrentFenceWaitUnsupported, + bool fenceAlwaysWaits, bool isLight = false) { _api = api; @@ -73,6 +75,7 @@ namespace Ryujinx.Graphics.Vulkan _queue = queue; _queueLock = queueLock; _concurrentFenceWaitUnsupported = concurrentFenceWaitUnsupported; + _fenceAlwaysWaits = fenceAlwaysWaits; _owner = Thread.CurrentThread; CommandPoolCreateInfo commandPoolCreateInfo = new() @@ -207,7 +210,7 @@ namespace Ryujinx.Graphics.Vulkan ref ReservedCommandBuffer entry = ref _commandBuffers[index]; - if (wait || !entry.InConsumption || entry.Fence.IsSignaled()) + if (wait || !entry.InConsumption || entry.Fence.IsSignaledLazy()) { WaitAndDecrementRef(index); @@ -349,7 +352,7 @@ namespace Ryujinx.Graphics.Vulkan if (refreshFence) { - entry.Fence = new FenceHolder(_api, _device, _concurrentFenceWaitUnsupported); + entry.Fence = new FenceHolder(_api, _device, _concurrentFenceWaitUnsupported, _fenceAlwaysWaits); } else { diff --git a/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs b/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs index 63737f355..3670b10a6 100644 --- a/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs @@ -12,13 +12,15 @@ namespace Ryujinx.Graphics.Vulkan private int _referenceCount; private int _lock; private readonly bool _concurrentWaitUnsupported; + private readonly bool _alwaysWaits; private bool _disposed; - public unsafe FenceHolder(Vk api, Device device, bool concurrentWaitUnsupported) + public unsafe FenceHolder(Vk api, Device device, bool concurrentWaitUnsupported, bool alwaysWaits) { _api = api; _device = device; _concurrentWaitUnsupported = concurrentWaitUnsupported; + _alwaysWaits = alwaysWaits; FenceCreateInfo fenceCreateInfo = new() { @@ -123,6 +125,16 @@ namespace Ryujinx.Graphics.Vulkan } } + public bool IsSignaledLazy() + { + if (_alwaysWaits) + { + return false; + } + + return IsSignaled(); + } + public bool IsSignaled() { if (_concurrentWaitUnsupported) diff --git a/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs b/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs index 7a8801def..dc1c15d1f 100644 --- a/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs +++ b/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs @@ -266,7 +266,7 @@ namespace Ryujinx.Graphics.Vulkan public void FreeCompleted() { FenceHolder signalledFence = null; - while (_pendingCopies.TryPeek(out PendingCopy pc) && pc.Fence != null && (pc.Fence == signalledFence || pc.Fence.IsSignaled())) + while (_pendingCopies.TryPeek(out PendingCopy pc) && pc.Fence != null && (pc.Fence == signalledFence || pc.Fence.IsSignaledLazy())) { signalledFence = pc.Fence; // Already checked - don't need to do it again. PendingCopy dequeued = _pendingCopies.Dequeue(); diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 69c6dc5c4..ad8f86160 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -106,6 +106,7 @@ namespace Ryujinx.Graphics.Vulkan internal bool IsNvidiaPreTuring { get; private set; } internal bool IsIntelArc { get; private set; } internal bool IsQualcommProprietary { get; private set; } + internal bool IsTurnip { get; private set; } internal bool IsMoltenVk { get; private set; } internal bool IsTBDR { get; private set; } internal bool IsSharedMemory { get; private set; } @@ -393,6 +394,8 @@ namespace Ryujinx.Graphics.Vulkan IsFeedbackLoopDevice = IsAmdRdna3 || IsAdreno6xx || IsAdreno7xx; + IsTurnip = GpuRenderer.StartsWith("Turnip"); + if (Vendor == Vendor.Nvidia) { Match match = VendorUtils.NvidiaConsumerClassRegex().Match(GpuRenderer); @@ -473,7 +476,7 @@ namespace Ryujinx.Graphics.Vulkan Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExternalMemoryHost hostMemoryApi); HostMemoryAllocator = new HostMemoryAllocator(MemoryAllocator, Api, hostMemoryApi, _device); - CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, IsQualcommProprietary); + CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, IsQualcommProprietary, IsTurnip); PipelineLayoutCache = new PipelineLayoutCache();