Rework Query stuff a bit to avoid render pass end

Tries to reset returned queries in background when possible, rather than ending the render pass.

Still ends render pass when resetting a counter after draws, but maybe that can be solved too. (by just pulling an empty object off the pool?)
This commit is contained in:
riperiperi 2022-03-13 01:32:10 +00:00
parent eda65c8dd3
commit 4cc0c2132c
5 changed files with 77 additions and 25 deletions

View file

@ -13,31 +13,33 @@ namespace Ryujinx.Graphics.Vulkan
private readonly List<QueryPool> _activeQueries; private readonly List<QueryPool> _activeQueries;
private CounterQueueEvent _activeConditionalRender; private CounterQueueEvent _activeConditionalRender;
private readonly List<(QueryPool Pool, BufferHolder Holder)> _pendingQueryCopies; private readonly List<BufferedQuery> _pendingQueryCopies;
private readonly List<BufferedQuery> _pendingQueryResets;
public PipelineFull(VulkanGraphicsDevice gd, Device device) : base(gd, device) public PipelineFull(VulkanGraphicsDevice gd, Device device) : base(gd, device)
{ {
_activeQueries = new List<QueryPool>(); _activeQueries = new List<QueryPool>();
_pendingQueryCopies = new(); _pendingQueryCopies = new();
_pendingQueryResets = new List<BufferedQuery>();
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer; CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
} }
private void CopyPendingQuery() private void CopyPendingQuery()
{ {
foreach (var item in _pendingQueryCopies) foreach (var query in _pendingQueryCopies)
{ {
var buffer = item.Holder.GetBuffer(CommandBuffer, true).Get(Cbs, 0, sizeof(long)).Value; query.PoolCopy(Cbs);
}
Gd.Api.CmdCopyQueryPoolResults( lock (_pendingQueryResets)
CommandBuffer, {
item.Pool, foreach (var query in _pendingQueryResets)
0, {
1, query.PoolReset(CommandBuffer);
buffer, }
0,
sizeof(long), _pendingQueryResets.Clear();
QueryResultFlags.QueryResult64Bit | QueryResultFlags.QueryResultWaitBit);
} }
_pendingQueryCopies.Clear(); _pendingQueryCopies.Clear();
@ -295,18 +297,26 @@ namespace Ryujinx.Graphics.Vulkan
foreach (var queryPool in _activeQueries) foreach (var queryPool in _activeQueries)
{ {
Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0); Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0);
} }
SignalCommandBufferChange(); SignalCommandBufferChange();
} }
public void BeginQuery(QueryPool pool) public void BeginQuery(BufferedQuery query, QueryPool pool, bool needsReset)
{ {
EndRenderPass(); if (needsReset)
{
EndRenderPass();
Gd.Api.CmdResetQueryPool(CommandBuffer, pool, 0, 1);
lock (_pendingQueryResets)
{
_pendingQueryResets.Remove(query); // Might be present on here.
}
}
Gd.Api.CmdResetQueryPool(CommandBuffer, pool, 0, 1);
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, 0); Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, 0);
_activeQueries.Add(pool); _activeQueries.Add(pool);
@ -319,9 +329,17 @@ namespace Ryujinx.Graphics.Vulkan
_activeQueries.Remove(pool); _activeQueries.Remove(pool);
} }
public void CopyQueryResults(QueryPool pool, BufferHolder holder) public void ResetQuery(BufferedQuery query)
{ {
_pendingQueryCopies.Add((pool, holder)); lock (_pendingQueryResets)
{
_pendingQueryResets.Add(query);
}
}
public void CopyQueryResults(BufferedQuery query)
{
_pendingQueryCopies.Add(query);
_hasPendingQuery = true; _hasPendingQuery = true;
} }

View file

@ -17,6 +17,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
private readonly PipelineFull _pipeline; private readonly PipelineFull _pipeline;
private QueryPool _queryPool; private QueryPool _queryPool;
private bool _isReset;
private readonly BufferHolder _buffer; private readonly BufferHolder _buffer;
private readonly IntPtr _bufferMap; private readonly IntPtr _bufferMap;
@ -73,7 +74,8 @@ namespace Ryujinx.Graphics.Vulkan.Queries
public void Begin() public void Begin()
{ {
_pipeline.BeginQuery(_queryPool); _pipeline.BeginQuery(this, _queryPool, !_isReset);
_isReset = false;
} }
public unsafe void End(bool withResult) public unsafe void End(bool withResult)
@ -83,7 +85,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
if (withResult) if (withResult)
{ {
Marshal.WriteInt64(_bufferMap, DefaultValue); Marshal.WriteInt64(_bufferMap, DefaultValue);
_pipeline.CopyQueryResults(_queryPool, _buffer); _pipeline.CopyQueryResults(this);
} }
else else
{ {
@ -131,6 +133,27 @@ namespace Ryujinx.Graphics.Vulkan.Queries
return data; return data;
} }
public void PoolReset(CommandBuffer cmd)
{
_api.CmdResetQueryPool(cmd, _queryPool, 0, 1);
_isReset = true;
}
public void PoolCopy(CommandBufferScoped cbs)
{
var buffer = _buffer.GetBuffer(cbs.CommandBuffer, true).Get(cbs, 0, sizeof(long)).Value;
_api.CmdCopyQueryPoolResults(
cbs.CommandBuffer,
_queryPool,
0,
1,
buffer,
0,
sizeof(long),
QueryResultFlags.QueryResult64Bit | QueryResultFlags.QueryResultWaitBit);
}
public unsafe void Dispose() public unsafe void Dispose()
{ {
_buffer.Dispose(); _buffer.Dispose();

View file

@ -105,6 +105,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
{ {
lock (_lock) lock (_lock)
{ {
_pipeline.ResetQuery(query);
_queryPool.Enqueue(query); _queryPool.Enqueue(query);
} }
} }
@ -140,11 +141,13 @@ namespace Ryujinx.Graphics.Vulkan.Queries
return result; return result;
} }
public void QueueReset() public void QueueReset(ulong lastDrawIndex)
{ {
ulong draws = lastDrawIndex - _current.DrawIndex;
lock (_lock) lock (_lock)
{ {
_current.Clear(); _current.Clear(draws != 0);
} }
} }

View file

@ -42,9 +42,13 @@ namespace Ryujinx.Graphics.Vulkan.Queries
return _counter.GetBuffer(); return _counter.GetBuffer();
} }
internal void Clear() internal void Clear(bool counterReset)
{ {
_counter.Reset(); if (counterReset)
{
_counter.Reset();
}
ClearCounter = true; ClearCounter = true;
} }
@ -110,6 +114,10 @@ namespace Ryujinx.Graphics.Vulkan.Queries
{ {
DisposeInternal(); DisposeInternal();
} }
else
{
}
} }
public bool ReserveForHostAccess() public bool ReserveForHostAccess()

View file

@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
public void QueueReset(CounterType type) public void QueueReset(CounterType type)
{ {
_counterQueues[(int)type].QueueReset(); _counterQueues[(int)type].QueueReset(_pipeline.DrawCount);
} }
public void Update() public void Update()