diff --git a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs index 24e600a26..cb8a62cf4 100644 --- a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs +++ b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs @@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Vulkan lock (queueLock) { - _pool = new CommandBufferPool(_gd.Api, _device, queue, queueLock, _gd.QueueFamilyIndex, isLight: true); + _pool = new CommandBufferPool(_gd.Api, _device, queue, queueLock, _gd.QueueFamilyIndex, _gd.Vendor == Vendor.Qualcomm, isLight: true); } } diff --git a/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs b/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs index 61cfbb6ec..98da59861 100644 --- a/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs +++ b/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs @@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly Device _device; private readonly Queue _queue; private readonly object _queueLock; + private readonly bool _fenceNeedsLock; private readonly CommandPool _pool; private readonly Thread _owner; @@ -61,12 +62,13 @@ namespace Ryujinx.Graphics.Vulkan private int _queuedCount; private int _inUseCount; - public unsafe CommandBufferPool(Vk api, Device device, Queue queue, object queueLock, uint queueFamilyIndex, bool isLight = false) + public unsafe CommandBufferPool(Vk api, Device device, Queue queue, object queueLock, uint queueFamilyIndex, bool fenceNeedsLock, bool isLight = false) { _api = api; _device = device; _queue = queue; _queueLock = queueLock; + _fenceNeedsLock = fenceNeedsLock; _owner = Thread.CurrentThread; var commandPoolCreateInfo = new CommandPoolCreateInfo @@ -357,7 +359,7 @@ namespace Ryujinx.Graphics.Vulkan if (refreshFence) { - entry.Fence = new FenceHolder(_api, _device); + entry.Fence = new FenceHolder(_api, _device, _fenceNeedsLock); } else { diff --git a/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs b/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs index 4f0a87160..eb4c3b0ef 100644 --- a/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs @@ -10,12 +10,15 @@ namespace Ryujinx.Graphics.Vulkan private readonly Device _device; private Fence _fence; private int _referenceCount; + private int _lock; + private readonly bool _needsLock; private bool _disposed; - public unsafe FenceHolder(Vk api, Device device) + public unsafe FenceHolder(Vk api, Device device, bool needsLock) { _api = api; _device = device; + _needsLock = needsLock; var fenceCreateInfo = new FenceCreateInfo { @@ -47,6 +50,11 @@ namespace Ryujinx.Graphics.Vulkan } while (Interlocked.CompareExchange(ref _referenceCount, lastValue + 1, lastValue) != lastValue); + if (_needsLock) + { + AcquireLock(); + } + fence = _fence; return true; } @@ -57,6 +65,16 @@ namespace Ryujinx.Graphics.Vulkan return _fence; } + public void PutLock() + { + Put(); + + if (_needsLock) + { + ReleaseLock(); + } + } + public void Put() { if (Interlocked.Decrement(ref _referenceCount) == 0) @@ -66,24 +84,54 @@ namespace Ryujinx.Graphics.Vulkan } } + private void AcquireLock() + { + while (!TryAcquireLock()) + { + Thread.SpinWait(32); + } + } + + private bool TryAcquireLock() + { + return Interlocked.Exchange(ref _lock, 1) == 0; + } + + private void ReleaseLock() + { + Interlocked.Exchange(ref _lock, 0); + } + public void Wait() { - Span fences = stackalloc Fence[] + if (_needsLock) { - _fence, - }; + AcquireLock(); + } - FenceHelper.WaitAllIndefinitely(_api, _device, fences); + FenceHelper.WaitAllIndefinitely(_api, _device, stackalloc Fence[] { _fence }); + + if (_needsLock) + { + ReleaseLock(); + } } public bool IsSignaled() { - Span fences = stackalloc Fence[] + if (_needsLock && !TryAcquireLock()) { - _fence, - }; + return false; + } - return FenceHelper.AllSignaled(_api, _device, fences); + bool result = FenceHelper.AllSignaled(_api, _device, stackalloc Fence[] { _fence }); + + if (_needsLock) + { + ReleaseLock(); + } + + return result; } public void Dispose() diff --git a/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs b/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs index 0bce3b72d..5638a9baa 100644 --- a/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs @@ -205,7 +205,7 @@ namespace Ryujinx.Graphics.Vulkan for (int i = 0; i < fenceCount; i++) { - fenceHolders[i].Put(); + fenceHolders[i].PutLock(); } return signaled; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 3b9b30340..1db104f83 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -291,6 +291,8 @@ namespace Ryujinx.Graphics.Vulkan ref var properties = ref properties2.Properties; + Vendor = VendorUtils.FromId(properties.VendorID); + ulong minResourceAlignment = Math.Max( Math.Max( properties.Limits.MinStorageBufferOffsetAlignment, @@ -347,7 +349,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); + CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, Vendor == Vendor.Qualcomm); DescriptorSetManager = new DescriptorSetManager(_device, PipelineBase.DescriptorSetLayouts); @@ -697,8 +699,6 @@ namespace Ryujinx.Graphics.Vulkan string vendorName = VendorUtils.GetNameFromId(properties.VendorID); - Vendor = VendorUtils.FromId(properties.VendorID); - IsAmdWindows = Vendor == Vendor.Amd && OperatingSystem.IsWindows(); IsIntelWindows = Vendor == Vendor.Intel && OperatingSystem.IsWindows(); IsTBDR =