Report 32 bit query result on AMD windows (smo issue)

This commit is contained in:
riperiperi 2022-04-19 18:54:34 +01:00
parent 7838a45772
commit 646be812ed
3 changed files with 28 additions and 12 deletions

View file

@ -11,6 +11,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
{ {
private const int MaxQueryRetries = 5000; private const int MaxQueryRetries = 5000;
private const long DefaultValue = -1; private const long DefaultValue = -1;
private const long DefaultValueInt = 0xFFFFFFFF;
private readonly Vk _api; private readonly Vk _api;
private readonly Device _device; private readonly Device _device;
@ -22,13 +23,17 @@ namespace Ryujinx.Graphics.Vulkan.Queries
private readonly BufferHolder _buffer; private readonly BufferHolder _buffer;
private readonly IntPtr _bufferMap; private readonly IntPtr _bufferMap;
private readonly CounterType _type; private readonly CounterType _type;
private bool _result32Bit;
public unsafe BufferedQuery(VulkanGraphicsDevice gd, Device device, PipelineFull pipeline, CounterType type) private long _defaultValue;
public unsafe BufferedQuery(VulkanGraphicsDevice gd, Device device, PipelineFull pipeline, CounterType type, bool result32Bit)
{ {
_api = gd.Api; _api = gd.Api;
_device = device; _device = device;
_pipeline = pipeline; _pipeline = pipeline;
_type = type; _type = type;
_result32Bit = result32Bit;
QueryPipelineStatisticFlags flags = type == CounterType.PrimitivesGenerated ? QueryPipelineStatisticFlags flags = type == CounterType.PrimitivesGenerated ?
QueryPipelineStatisticFlags.QueryPipelineStatisticGeometryShaderPrimitivesBit : 0; QueryPipelineStatisticFlags.QueryPipelineStatisticGeometryShaderPrimitivesBit : 0;
@ -46,7 +51,8 @@ namespace Ryujinx.Graphics.Vulkan.Queries
var buffer = gd.BufferManager.Create(gd, sizeof(long), forConditionalRendering: true); var buffer = gd.BufferManager.Create(gd, sizeof(long), forConditionalRendering: true);
_bufferMap = buffer.Map(0, sizeof(long)); _bufferMap = buffer.Map(0, sizeof(long));
Marshal.WriteInt64(_bufferMap, DefaultValue); _defaultValue = result32Bit ? DefaultValueInt : DefaultValue;
Marshal.WriteInt64(_bufferMap, _defaultValue);
_buffer = buffer; _buffer = buffer;
} }
@ -84,7 +90,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
if (withResult) if (withResult)
{ {
Marshal.WriteInt64(_bufferMap, DefaultValue); Marshal.WriteInt64(_bufferMap, _defaultValue);
_pipeline.CopyQueryResults(this); _pipeline.CopyQueryResults(this);
} }
else else
@ -98,16 +104,16 @@ namespace Ryujinx.Graphics.Vulkan.Queries
{ {
result = Marshal.ReadInt64(_bufferMap); result = Marshal.ReadInt64(_bufferMap);
return result != DefaultValue; return result != _defaultValue;
} }
public long AwaitResult(AutoResetEvent wakeSignal = null) public long AwaitResult(AutoResetEvent wakeSignal = null)
{ {
long data = DefaultValue; long data = _defaultValue;
if (wakeSignal == null) if (wakeSignal == null)
{ {
while (data == DefaultValue) while (data == _defaultValue)
{ {
data = Marshal.ReadInt64(_bufferMap); data = Marshal.ReadInt64(_bufferMap);
} }
@ -115,10 +121,10 @@ namespace Ryujinx.Graphics.Vulkan.Queries
else else
{ {
int iterations = 0; int iterations = 0;
while (data == DefaultValue && iterations++ < MaxQueryRetries) while (data == _defaultValue && iterations++ < MaxQueryRetries)
{ {
data = Marshal.ReadInt64(_bufferMap); data = Marshal.ReadInt64(_bufferMap);
if (data == DefaultValue) if (data == _defaultValue)
{ {
wakeSignal.WaitOne(1); wakeSignal.WaitOne(1);
} }
@ -143,6 +149,13 @@ namespace Ryujinx.Graphics.Vulkan.Queries
{ {
var buffer = _buffer.GetBuffer(cbs.CommandBuffer, true).Get(cbs, 0, sizeof(long)).Value; var buffer = _buffer.GetBuffer(cbs.CommandBuffer, true).Get(cbs, 0, sizeof(long)).Value;
QueryResultFlags flags = QueryResultFlags.QueryResultWaitBit;
if (!_result32Bit)
{
flags |= QueryResultFlags.QueryResult64Bit;
}
_api.CmdCopyQueryPoolResults( _api.CmdCopyQueryPoolResults(
cbs.CommandBuffer, cbs.CommandBuffer,
_queryPool, _queryPool,
@ -150,8 +163,8 @@ namespace Ryujinx.Graphics.Vulkan.Queries
1, 1,
buffer, buffer,
0, 0,
sizeof(long), (ulong)(_result32Bit ? sizeof(int) : sizeof(long)),
QueryResultFlags.QueryResult64Bit | QueryResultFlags.QueryResultWaitBit); flags);
} }
public unsafe void Dispose() public unsafe void Dispose()

View file

@ -43,7 +43,8 @@ namespace Ryujinx.Graphics.Vulkan.Queries
_queryPool = new Queue<BufferedQuery>(QueryPoolInitialSize); _queryPool = new Queue<BufferedQuery>(QueryPoolInitialSize);
for (int i = 0; i < QueryPoolInitialSize; i++) for (int i = 0; i < QueryPoolInitialSize; i++)
{ {
_queryPool.Enqueue(new BufferedQuery(_gd, _device, _pipeline, type)); // AMD Polaris GPUs on Windows seem to have issues reporting 64-bit query results.
_queryPool.Enqueue(new BufferedQuery(_gd, _device, _pipeline, type, gd.IsAmdWindows));
} }
_current = new CounterQueueEvent(this, type, 0); _current = new CounterQueueEvent(this, type, 0);
@ -96,7 +97,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
} }
else else
{ {
return new BufferedQuery(_gd, _device, _pipeline, Type); return new BufferedQuery(_gd, _device, _pipeline, Type, _gd.IsAmdWindows);
} }
} }
} }

View file

@ -77,6 +77,7 @@ namespace Ryujinx.Graphics.Vulkan
private Func<string[]> GetRequiredExtensions; private Func<string[]> GetRequiredExtensions;
internal Vendor Vendor { get; private set; } internal Vendor Vendor { get; private set; }
internal bool IsAmdWindows { get; private set; }
internal bool IsIntelWindows { get; private set; } internal bool IsIntelWindows { get; private set; }
public string GpuVendor { get; private set; } public string GpuVendor { get; private set; }
public string GpuRenderer { get; private set; } public string GpuRenderer { get; private set; }
@ -385,6 +386,7 @@ namespace Ryujinx.Graphics.Vulkan
_ => Vendor.Unknown _ => Vendor.Unknown
}; };
IsAmdWindows = Vendor == Vendor.Amd && RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
IsIntelWindows = Vendor == Vendor.Intel && RuntimeInformation.IsOSPlatform(OSPlatform.Windows); IsIntelWindows = Vendor == Vendor.Intel && RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
GpuVendor = vendorName; GpuVendor = vendorName;