Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
07435ad844 | ||
|
1668ba913f | ||
|
a830eb666b |
@@ -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.IsQualcommProprietary,
|
||||
isLight: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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()
|
||||
|
@@ -196,18 +196,23 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
bool signaled = true;
|
||||
|
||||
if (hasTimeout)
|
||||
try
|
||||
{
|
||||
signaled = FenceHelper.AllSignaled(api, device, fences[..fenceCount], timeout);
|
||||
if (hasTimeout)
|
||||
{
|
||||
signaled = FenceHelper.AllSignaled(api, device, fences[..fenceCount], timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
FenceHelper.WaitAllIndefinitely(api, device, fences[..fenceCount]);
|
||||
}
|
||||
}
|
||||
else
|
||||
finally
|
||||
{
|
||||
FenceHelper.WaitAllIndefinitely(api, device, fences[..fenceCount]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fenceCount; i++)
|
||||
{
|
||||
fenceHolders[i].Put();
|
||||
for (int i = 0; i < fenceCount; i++)
|
||||
{
|
||||
fenceHolders[i].PutLock();
|
||||
}
|
||||
}
|
||||
|
||||
return signaled;
|
||||
|
@@ -1020,6 +1020,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
_newState.RasterizerDiscardEnable = discard;
|
||||
SignalStateChange();
|
||||
|
||||
if (!discard && Gd.IsQualcommProprietary)
|
||||
{
|
||||
// On Adreno, enabling rasterizer discard somehow corrupts the viewport state.
|
||||
// Force it to be updated on next use to work around this bug.
|
||||
DynamicState.ForceAllDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask)
|
||||
|
@@ -47,10 +47,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return;
|
||||
}
|
||||
|
||||
if (componentMask != 0xf)
|
||||
if (componentMask != 0xf || Gd.IsQualcommProprietary)
|
||||
{
|
||||
// We can't use CmdClearAttachments if not writing all components,
|
||||
// because on Vulkan, the pipeline state does not affect clears.
|
||||
// On proprietary Adreno drivers, CmdClearAttachments appears to execute out of order, so it's better to not use it at all.
|
||||
var dstTexture = FramebufferParams.GetColorView(index);
|
||||
if (dstTexture == null)
|
||||
{
|
||||
@@ -87,10 +88,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return;
|
||||
}
|
||||
|
||||
if (stencilMask != 0 && stencilMask != 0xff)
|
||||
if ((stencilMask != 0 && stencilMask != 0xff) || Gd.IsQualcommProprietary)
|
||||
{
|
||||
// We can't use CmdClearAttachments if not clearing all (mask is all ones, 0xFF) or none (mask is 0) of the stencil bits,
|
||||
// because on Vulkan, the pipeline state does not affect clears.
|
||||
// On proprietary Adreno drivers, CmdClearAttachments appears to execute out of order, so it's better to not use it at all.
|
||||
var dstTexture = FramebufferParams.GetDepthStencilView();
|
||||
if (dstTexture == null)
|
||||
{
|
||||
|
@@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Templates = BuildTemplates(usePushDescriptors);
|
||||
|
||||
// Updating buffer texture bindings using template updates crashes the Adreno driver on Windows.
|
||||
UpdateTexturesWithoutTemplate = gd.Vendor == Vendor.Qualcomm && usesBufferTextures;
|
||||
UpdateTexturesWithoutTemplate = gd.IsQualcommProprietary && usesBufferTextures;
|
||||
|
||||
_compileTask = Task.CompletedTask;
|
||||
_firstBackgroundUse = false;
|
||||
|
@@ -87,9 +87,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
internal bool IsAmdGcn { get; private set; }
|
||||
internal bool IsNvidiaPreTuring { get; private set; }
|
||||
internal bool IsIntelArc { get; private set; }
|
||||
internal bool IsQualcommProprietary { get; private set; }
|
||||
internal bool IsMoltenVk { get; private set; }
|
||||
internal bool IsTBDR { get; private set; }
|
||||
internal bool IsSharedMemory { get; private set; }
|
||||
|
||||
public string GpuVendor { get; private set; }
|
||||
public string GpuDriver { get; private set; }
|
||||
public string GpuRenderer { get; private set; }
|
||||
@@ -344,7 +346,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
IsNvidiaPreTuring = gpuNumber < 2000;
|
||||
}
|
||||
else if (GpuDriver.Contains("TITAN") && !GpuDriver.Contains("RTX"))
|
||||
else if (GpuRenderer.Contains("TITAN") && !GpuRenderer.Contains("RTX"))
|
||||
{
|
||||
IsNvidiaPreTuring = true;
|
||||
}
|
||||
@@ -354,6 +356,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
IsIntelArc = GpuRenderer.StartsWith("Intel(R) Arc(TM)");
|
||||
}
|
||||
|
||||
IsQualcommProprietary = hasDriverProperties && driverProperties.DriverID == DriverId.QualcommProprietary;
|
||||
|
||||
ulong minResourceAlignment = Math.Max(
|
||||
Math.Max(
|
||||
properties.Limits.MinStorageBufferOffsetAlignment,
|
||||
@@ -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, IsQualcommProprietary);
|
||||
|
||||
PipelineLayoutCache = new PipelineLayoutCache();
|
||||
|
||||
@@ -688,7 +692,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
GpuVendor,
|
||||
memoryType: memoryType,
|
||||
hasFrontFacingBug: IsIntelWindows,
|
||||
hasVectorIndexingBug: Vendor == Vendor.Qualcomm,
|
||||
hasVectorIndexingBug: IsQualcommProprietary,
|
||||
needsFragmentOutputSpecialization: IsMoltenVk,
|
||||
reduceShaderPrecision: IsMoltenVk,
|
||||
supportsAstcCompression: features2.Features.TextureCompressionAstcLdr && supportsAstcFormats,
|
||||
|
Reference in New Issue
Block a user