aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2024-07-07 19:33:28 -0300
committerGitHub <noreply@github.com>2024-07-07 19:33:28 -0300
commita830eb666b058df38f734c6369eb18cc7212f36c (patch)
tree5c23278f5452153405975825f640659cb5f7e5bd /src
parentcfc75d7e78a63fe3bde06b6e4896a42e8dedaf82 (diff)
Disallow concurrent fence waits on Adreno (#7001)1.1.1343
* Disallow concurrent fence waits on Adreno * Ensure locks are released if exceptions are thrown
Diffstat (limited to 'src')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs9
-rw-r--r--src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs13
-rw-r--r--src/Ryujinx.Graphics.Vulkan/FenceHolder.cs79
-rw-r--r--src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs23
-rw-r--r--src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs6
5 files changed, 108 insertions, 22 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs
index 24e600a2..b8906a62 100644
--- a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs
+++ b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs
@@ -29,7 +29,14 @@ 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.IsConcurrentFenceWaitUnsupported,
+ isLight: true);
}
}
diff --git a/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs b/src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs
index 278dbecf..80054ce2 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 _concurrentFenceWaitUnsupported;
private readonly CommandPool _pool;
private readonly Thread _owner;
@@ -61,12 +62,20 @@ 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 concurrentFenceWaitUnsupported,
+ bool isLight = false)
{
_api = api;
_device = device;
_queue = queue;
_queueLock = queueLock;
+ _concurrentFenceWaitUnsupported = concurrentFenceWaitUnsupported;
_owner = Thread.CurrentThread;
var commandPoolCreateInfo = new CommandPoolCreateInfo
@@ -357,7 +366,7 @@ namespace Ryujinx.Graphics.Vulkan
if (refreshFence)
{
- entry.Fence = new FenceHolder(_api, _device);
+ entry.Fence = new FenceHolder(_api, _device, _concurrentFenceWaitUnsupported);
}
else
{
diff --git a/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs b/src/Ryujinx.Graphics.Vulkan/FenceHolder.cs
index 4f0a8716..0cdb93f2 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 _concurrentWaitUnsupported;
private bool _disposed;
- public unsafe FenceHolder(Vk api, Device device)
+ public unsafe FenceHolder(Vk api, Device device, bool concurrentWaitUnsupported)
{
_api = api;
_device = device;
+ _concurrentWaitUnsupported = concurrentWaitUnsupported;
var fenceCreateInfo = new FenceCreateInfo
{
@@ -47,6 +50,11 @@ namespace Ryujinx.Graphics.Vulkan
}
while (Interlocked.CompareExchange(ref _referenceCount, lastValue + 1, lastValue) != lastValue);
+ if (_concurrentWaitUnsupported)
+ {
+ AcquireLock();
+ }
+
fence = _fence;
return true;
}
@@ -57,6 +65,16 @@ namespace Ryujinx.Graphics.Vulkan
return _fence;
}
+ public void PutLock()
+ {
+ Put();
+
+ if (_concurrentWaitUnsupported)
+ {
+ ReleaseLock();
+ }
+ }
+
public void Put()
{
if (Interlocked.Decrement(ref _referenceCount) == 0)
@@ -66,24 +84,67 @@ 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<Fence> fences = stackalloc Fence[]
+ if (_concurrentWaitUnsupported)
{
- _fence,
- };
+ AcquireLock();
- FenceHelper.WaitAllIndefinitely(_api, _device, fences);
+ try
+ {
+ FenceHelper.WaitAllIndefinitely(_api, _device, stackalloc Fence[] { _fence });
+ }
+ finally
+ {
+ ReleaseLock();
+ }
+ }
+ else
+ {
+ FenceHelper.WaitAllIndefinitely(_api, _device, stackalloc Fence[] { _fence });
+ }
}
public bool IsSignaled()
{
- Span<Fence> fences = stackalloc Fence[]
+ if (_concurrentWaitUnsupported)
{
- _fence,
- };
+ if (!TryAcquireLock())
+ {
+ return false;
+ }
- return FenceHelper.AllSignaled(_api, _device, fences);
+ try
+ {
+ return FenceHelper.AllSignaled(_api, _device, stackalloc Fence[] { _fence });
+ }
+ finally
+ {
+ ReleaseLock();
+ }
+ }
+ else
+ {
+ return FenceHelper.AllSignaled(_api, _device, stackalloc Fence[] { _fence });
+ }
}
public void Dispose()
diff --git a/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs b/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs
index 806b872b..b4252471 100644
--- a/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs
+++ b/src/Ryujinx.Graphics.Vulkan/MultiFenceHolder.cs
@@ -196,18 +196,23 @@ namespace Ryujinx.Graphics.Vulkan
bool signaled = true;
- if (hasTimeout)
+ try
{
- signaled = FenceHelper.AllSignaled(api, device, fences[..fenceCount], timeout);
- }
- else
- {
- FenceHelper.WaitAllIndefinitely(api, device, fences[..fenceCount]);
+ if (hasTimeout)
+ {
+ signaled = FenceHelper.AllSignaled(api, device, fences[..fenceCount], timeout);
+ }
+ else
+ {
+ FenceHelper.WaitAllIndefinitely(api, device, fences[..fenceCount]);
+ }
}
-
- for (int i = 0; i < fenceCount; i++)
+ finally
{
- fenceHolders[i].Put();
+ for (int i = 0; i < fenceCount; i++)
+ {
+ fenceHolders[i].PutLock();
+ }
}
return signaled;
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 86a347e0..c1689651 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -90,6 +90,8 @@ namespace Ryujinx.Graphics.Vulkan
internal bool IsMoltenVk { get; private set; }
internal bool IsTBDR { get; private set; }
internal bool IsSharedMemory { get; private set; }
+ internal bool IsConcurrentFenceWaitUnsupported { get; private set; }
+
public string GpuVendor { get; private set; }
public string GpuDriver { get; private set; }
public string GpuRenderer { get; private set; }
@@ -323,6 +325,8 @@ namespace Ryujinx.Graphics.Vulkan
Vendor == Vendor.Broadcom ||
Vendor == Vendor.ImgTec;
+ IsConcurrentFenceWaitUnsupported = Vendor == Vendor.Qualcomm;
+
GpuVendor = VendorUtils.GetNameFromId(properties.VendorID);
GpuDriver = hasDriverProperties && !OperatingSystem.IsMacOS() ?
VendorUtils.GetFriendlyDriverName(driverProperties.DriverID) : GpuVendor; // Fallback to vendor name if driver is unavailable or on MacOS where vendor is preferred.
@@ -411,7 +415,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, IsConcurrentFenceWaitUnsupported);
PipelineLayoutCache = new PipelineLayoutCache();