Compare commits
9 commits
d11c191ee5
...
004aeaba70
Author | SHA1 | Date | |
---|---|---|---|
|
004aeaba70 | ||
|
6ce49a2dc7 | ||
|
ccd330ba0f | ||
|
a46b1bd88c | ||
|
1a85c9a00b | ||
|
71901a54b8 | ||
|
711360f775 | ||
|
0aa6b31b39 | ||
|
14b2395290 |
22 changed files with 193 additions and 93 deletions
|
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
void TextureBarrier();
|
||||
void TextureBarrierTiled();
|
||||
|
||||
bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual);
|
||||
bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false);
|
||||
bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual);
|
||||
void EndHostConditionalRendering();
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
|
||||
void PreFrame();
|
||||
|
||||
ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved);
|
||||
ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, int hostReserved);
|
||||
|
||||
void ResetCounter(CounterType type);
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
|
|||
private CounterType _type;
|
||||
private TableRef<EventHandler<ulong>> _resultHandler;
|
||||
private float _divisor;
|
||||
private bool _hostReserved;
|
||||
private int _hostReserved;
|
||||
|
||||
public void Set(TableRef<ThreadedCounterEvent> evt, CounterType type, TableRef<EventHandler<ulong>> resultHandler, float divisor, bool hostReserved)
|
||||
public void Set(TableRef<ThreadedCounterEvent> evt, CounterType type, TableRef<EventHandler<ulong>> resultHandler, float divisor, int hostReserved)
|
||||
{
|
||||
_event = evt;
|
||||
_type = type;
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
|||
|
||||
public static void Run(ref TryHostConditionalRenderingCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||
{
|
||||
renderer.Pipeline.TryHostConditionalRendering(command._value.Get(threaded)?.Base, command._compare, command._isEqual);
|
||||
renderer.Pipeline.TryHostConditionalRendering(command._value.Get(threaded)?.Base, command._compare, command._isEqual, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
public CounterType Type { get; }
|
||||
public bool ClearCounter { get; }
|
||||
|
||||
private bool _reserved;
|
||||
private int _reserved;
|
||||
private int _createLock;
|
||||
|
||||
public ThreadedCounterEvent(ThreadedRenderer renderer, CounterType type, bool clearCounter)
|
||||
|
@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
}
|
||||
else
|
||||
{
|
||||
_reserved = true;
|
||||
Interlocked.Increment(ref _reserved);
|
||||
}
|
||||
|
||||
Volatile.Write(ref _createLock, 0);
|
||||
|
@ -70,10 +70,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
}
|
||||
}
|
||||
|
||||
public void Create(IRenderer renderer, CounterType type, System.EventHandler<ulong> eventHandler, float divisor, bool hostReserved)
|
||||
public void Create(IRenderer renderer, CounterType type, System.EventHandler<ulong> eventHandler, float divisor, int hostReserved)
|
||||
{
|
||||
ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0);
|
||||
Base = renderer.ReportCounter(type, eventHandler, divisor, hostReserved || _reserved);
|
||||
Base = renderer.ReportCounter(type, eventHandler, divisor, hostReserved + _reserved);
|
||||
Volatile.Write(ref _createLock, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,7 +357,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false)
|
||||
{
|
||||
var evt = value as ThreadedCounterEvent;
|
||||
if (evt != null)
|
||||
|
|
|
@ -427,7 +427,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||
QueueCommand();
|
||||
}
|
||||
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, int hostReserved)
|
||||
{
|
||||
ThreadedCounterEvent evt = new(this, type, _lastSampleCounterClear);
|
||||
New<ReportCounterCommand>().Set(Ref(evt), type, Ref(resultHandler), divisor, hostReserved);
|
||||
|
|
|
@ -179,13 +179,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
case ReportCounterType.SamplesPassed:
|
||||
float scale = _channel.TextureManager.RenderTargetScale;
|
||||
float divisor = scale * scale;
|
||||
counter = _context.Renderer.ReportCounter(CounterType.SamplesPassed, resultHandler, divisor, false);
|
||||
counter = _context.Renderer.ReportCounter(CounterType.SamplesPassed, resultHandler, divisor, 0);
|
||||
break;
|
||||
case ReportCounterType.PrimitivesGenerated:
|
||||
counter = _context.Renderer.ReportCounter(CounterType.PrimitivesGenerated, resultHandler, 1f, false);
|
||||
counter = _context.Renderer.ReportCounter(CounterType.PrimitivesGenerated, resultHandler, 1f, 0);
|
||||
break;
|
||||
case ReportCounterType.TransformFeedbackPrimitivesWritten:
|
||||
counter = _context.Renderer.ReportCounter(CounterType.TransformFeedbackPrimitivesWritten, resultHandler, 1f, false);
|
||||
counter = _context.Renderer.ReportCounter(CounterType.TransformFeedbackPrimitivesWritten, resultHandler, 1f, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public OpenGLRenderer()
|
||||
{
|
||||
_pipeline = new Pipeline();
|
||||
_counters = new Counters();
|
||||
_pipeline = new Pipeline(_counters);
|
||||
_window = new Window(this);
|
||||
_textureCopy = new TextureCopy(this);
|
||||
_backgroundTextureCopy = new TextureCopy(this);
|
||||
|
@ -221,7 +221,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
ResourcePool.Tick();
|
||||
}
|
||||
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, int hostReserved)
|
||||
{
|
||||
return _counters.QueueReport(type, resultHandler, divisor, _pipeline.DrawCount, hostReserved);
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public void ResetCounter(CounterType type)
|
||||
{
|
||||
_counters.QueueReset(type);
|
||||
_counters.QueueReset(type, _pipeline.DrawCount);
|
||||
}
|
||||
|
||||
public void BackgroundContextAction(Action action, bool alwaysBackground = false)
|
||||
|
@ -299,6 +299,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public void CreateSync(ulong id, bool strict)
|
||||
{
|
||||
_counters.CopyPending();
|
||||
_sync.Create(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
private const int SavedImages = 2;
|
||||
|
||||
private readonly Counters _counters;
|
||||
|
||||
private readonly DrawTextureEmulation _drawTexture;
|
||||
|
||||
internal ulong DrawCount { get; private set; }
|
||||
|
@ -68,8 +70,10 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
private ColorF _blendConstant;
|
||||
|
||||
internal Pipeline()
|
||||
internal Pipeline(Counters counters)
|
||||
{
|
||||
_counters = counters;
|
||||
|
||||
_drawTexture = new DrawTextureEmulation();
|
||||
_rasterizerDiscard = false;
|
||||
_clipOrigin = ClipOrigin.LowerLeft;
|
||||
|
@ -1164,10 +1168,14 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
RestoreComponentMask(index, force: false);
|
||||
}
|
||||
|
||||
_counters.CopyPending();
|
||||
}
|
||||
|
||||
public void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
|
||||
{
|
||||
_counters.CopyPending();
|
||||
|
||||
EnsureFramebuffer();
|
||||
|
||||
for (int index = 0; index < colors.Length; index++)
|
||||
|
@ -1523,6 +1531,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
private void PreDraw(int vertexCount)
|
||||
{
|
||||
_counters.PreDraw();
|
||||
_vertexArray.PreDraw(vertexCount);
|
||||
PreDraw();
|
||||
}
|
||||
|
@ -1639,7 +1648,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false)
|
||||
{
|
||||
// Compare an event and a constant value.
|
||||
if (value is CounterQueueEvent evt)
|
||||
|
@ -1652,7 +1661,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
if (compare == 0 && evt.Type == QueryTarget.SamplesPassed && evt.ClearCounter)
|
||||
{
|
||||
if (!value.ReserveForHostAccess())
|
||||
// If the call is forwarded from backend threading, then we have already reserved host access.
|
||||
if (!forwarded && !value.ReserveForHostAccess())
|
||||
{
|
||||
// If the event has been flushed, then just use the values on the CPU.
|
||||
// The query object may already be repurposed for another draw (eg. begin + end).
|
||||
|
@ -1668,12 +1678,14 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
// The GPU will flush the queries to CPU and evaluate the condition there instead.
|
||||
|
||||
_counters.CopyPending(false);
|
||||
GL.Flush(); // The thread will be stalled manually flushing the counter, so flush GL commands now.
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual)
|
||||
{
|
||||
_counters.CopyPending(false);
|
||||
GL.Flush(); // The GPU thread will be stalled manually flushing the counter, so flush GL commands now.
|
||||
return false; // We don't currently have a way to compare two counters for conditional rendering.
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
private readonly IntPtr _bufferMap;
|
||||
private readonly QueryTarget _type;
|
||||
|
||||
public BufferedQuery(QueryTarget type)
|
||||
private readonly Counters _parent;
|
||||
|
||||
public BufferedQuery(Counters parent, QueryTarget type)
|
||||
{
|
||||
_parent = parent;
|
||||
_buffer = GL.GenBuffer();
|
||||
Query = GL.GenQuery();
|
||||
_type = type;
|
||||
|
@ -42,20 +45,31 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
|
||||
public void Begin()
|
||||
{
|
||||
Marshal.WriteInt64(_bufferMap, -1L);
|
||||
GL.BeginQuery(_type, Query);
|
||||
}
|
||||
|
||||
public unsafe void End(bool withResult)
|
||||
public unsafe void CopyQueryResult(bool withBarrier)
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.QueryBuffer, _buffer);
|
||||
GL.GetQueryObject(Query, GetQueryObjectParam.QueryResult, (long*)0);
|
||||
|
||||
if (withBarrier)
|
||||
{
|
||||
GL.MemoryBarrier(MemoryBarrierFlags.QueryBufferBarrierBit | MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
||||
}
|
||||
}
|
||||
|
||||
public void End(bool withResult)
|
||||
{
|
||||
GL.EndQuery(_type);
|
||||
|
||||
if (withResult)
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.QueryBuffer, _buffer);
|
||||
|
||||
Marshal.WriteInt64(_bufferMap, -1L);
|
||||
GL.GetQueryObject(Query, GetQueryObjectParam.QueryResult, (long*)0);
|
||||
GL.MemoryBarrier(MemoryBarrierFlags.QueryBufferBarrierBit | MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
||||
if (!_parent.QueueCopy(this))
|
||||
{
|
||||
CopyQueryResult(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
public CounterType Type { get; }
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
private readonly Counters _parent;
|
||||
|
||||
private readonly Queue<CounterQueueEvent> _events = new();
|
||||
private CounterQueueEvent _current;
|
||||
|
||||
|
@ -28,8 +30,9 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
|
||||
private readonly Thread _consumerThread;
|
||||
|
||||
internal CounterQueue(CounterType type)
|
||||
internal CounterQueue(Counters parent, CounterType type)
|
||||
{
|
||||
_parent = parent;
|
||||
Type = type;
|
||||
|
||||
QueryTarget glType = GetTarget(Type);
|
||||
|
@ -37,7 +40,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
_queryPool = new Queue<BufferedQuery>(QueryPoolInitialSize);
|
||||
for (int i = 0; i < QueryPoolInitialSize; i++)
|
||||
{
|
||||
_queryPool.Enqueue(new BufferedQuery(glType));
|
||||
_queryPool.Enqueue(new BufferedQuery(parent, glType));
|
||||
}
|
||||
|
||||
_current = new CounterQueueEvent(this, glType, 0);
|
||||
|
@ -90,7 +93,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
}
|
||||
else
|
||||
{
|
||||
return new BufferedQuery(GetTarget(Type));
|
||||
return new BufferedQuery(_parent, GetTarget(Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +106,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
}
|
||||
}
|
||||
|
||||
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
|
||||
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, int hostReserved)
|
||||
{
|
||||
CounterQueueEvent result;
|
||||
ulong draws = lastDrawIndex - _current.DrawIndex;
|
||||
|
@ -113,9 +116,9 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
// A query's result only matters if more than one draw was performed during it.
|
||||
// Otherwise, dummy it out and return 0 immediately.
|
||||
|
||||
if (hostReserved)
|
||||
while (hostReserved-- > 0)
|
||||
{
|
||||
// This counter event is guaranteed to be available for host conditional rendering.
|
||||
// This counter event is guaranteed to be available for host conditional rendering for the given number of uses.
|
||||
_current.ReserveForHostAccess();
|
||||
}
|
||||
|
||||
|
@ -134,11 +137,11 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
return result;
|
||||
}
|
||||
|
||||
public void QueueReset()
|
||||
public void QueueReset(ulong lastDrawIndex)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_current.Clear();
|
||||
_current.Clear(lastDrawIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
public bool Disposed { get; private set; }
|
||||
public bool Invalid { get; set; }
|
||||
|
||||
public ulong DrawIndex { get; }
|
||||
public ulong DrawIndex { get; private set; }
|
||||
|
||||
private readonly CounterQueue _queue;
|
||||
private readonly BufferedQuery _counter;
|
||||
|
||||
private bool _hostAccessReserved = false;
|
||||
private int _hostAccessReserved = 0;
|
||||
private int _refCount = 1; // Starts with a reference from the counter queue.
|
||||
|
||||
private readonly object _lock = new();
|
||||
|
@ -40,10 +40,11 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
_counter.Begin();
|
||||
}
|
||||
|
||||
internal void Clear()
|
||||
internal void Clear(ulong drawIndex)
|
||||
{
|
||||
_counter.Reset();
|
||||
ClearCounter = true;
|
||||
DrawIndex = drawIndex;
|
||||
}
|
||||
|
||||
internal void Complete(bool withResult, double divisor)
|
||||
|
@ -114,12 +115,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
|
||||
public bool ReserveForHostAccess()
|
||||
{
|
||||
if (_hostAccessReserved)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsValueAvailable())
|
||||
if (_hostAccessReserved == 0 && IsValueAvailable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -131,14 +127,14 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
return false;
|
||||
}
|
||||
|
||||
_hostAccessReserved = true;
|
||||
Interlocked.Increment(ref _hostAccessReserved);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ReleaseHostAccess()
|
||||
{
|
||||
_hostAccessReserved = false;
|
||||
Interlocked.Decrement(ref _hostAccessReserved);
|
||||
|
||||
DecrementRefCount();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.OpenGL.Queries
|
||||
{
|
||||
class Counters : IDisposable
|
||||
{
|
||||
private const int ForceCopyThreshold = 32;
|
||||
|
||||
private readonly CounterQueue[] _counterQueues;
|
||||
private readonly List<BufferedQuery> _queuedCopies;
|
||||
private bool _flushedThisPass;
|
||||
|
||||
public Counters()
|
||||
{
|
||||
int count = Enum.GetNames<CounterType>().Length;
|
||||
|
||||
_counterQueues = new CounterQueue[count];
|
||||
_queuedCopies = new List<BufferedQuery>();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
|
@ -19,18 +25,18 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
for (int index = 0; index < _counterQueues.Length; index++)
|
||||
{
|
||||
CounterType type = (CounterType)index;
|
||||
_counterQueues[index] = new CounterQueue(type);
|
||||
_counterQueues[index] = new CounterQueue(this, type);
|
||||
}
|
||||
}
|
||||
|
||||
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
|
||||
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, int hostReserved)
|
||||
{
|
||||
return _counterQueues[(int)type].QueueReport(resultHandler, divisor, lastDrawIndex, hostReserved);
|
||||
}
|
||||
|
||||
public void QueueReset(CounterType type)
|
||||
public void QueueReset(CounterType type, ulong lastDrawIndex)
|
||||
{
|
||||
_counterQueues[(int)type].QueueReset();
|
||||
_counterQueues[(int)type].QueueReset(lastDrawIndex);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
|
@ -46,6 +52,51 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
_counterQueues[(int)type].Flush(true);
|
||||
}
|
||||
|
||||
public void PreDraw()
|
||||
{
|
||||
// Force results to be copied some time into an occlusion query pass.
|
||||
if (!_flushedThisPass && _queuedCopies.Count > ForceCopyThreshold)
|
||||
{
|
||||
_flushedThisPass = true;
|
||||
CopyPending(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyPending(bool newPass = true)
|
||||
{
|
||||
if (_queuedCopies.Count > 0)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (BufferedQuery query in _queuedCopies)
|
||||
{
|
||||
query.CopyQueryResult(_queuedCopies.Count == ++i);
|
||||
}
|
||||
|
||||
_queuedCopies.Clear();
|
||||
}
|
||||
|
||||
if (newPass)
|
||||
{
|
||||
_flushedThisPass = false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool QueueCopy(BufferedQuery query)
|
||||
{
|
||||
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Nvidia)
|
||||
{
|
||||
// NVIDIA seems to make up a rule where query results can't be copied to buffers
|
||||
// when unrelated query objects are in use.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_queuedCopies.Add(query);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var queue in _counterQueues)
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
_activeConditionalRender = null;
|
||||
}
|
||||
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false)
|
||||
{
|
||||
// Compare an event and a constant value.
|
||||
if (value is CounterQueueEvent evt)
|
||||
|
@ -146,7 +146,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
if (compare == 0 && evt.Type == CounterType.SamplesPassed && evt.ClearCounter)
|
||||
{
|
||||
if (!value.ReserveForHostAccess())
|
||||
// If the call is forwarded from backend threading, then we have already reserved host access.
|
||||
if (!forwarded && !value.ReserveForHostAccess())
|
||||
{
|
||||
// If the event has been flushed, then just use the values on the CPU.
|
||||
// The query object may already be repurposed for another draw (eg. begin + end).
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||
}
|
||||
}
|
||||
|
||||
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
|
||||
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, int hostReserved)
|
||||
{
|
||||
CounterQueueEvent result;
|
||||
ulong draws = lastDrawIndex - _current.DrawIndex;
|
||||
|
@ -149,9 +149,9 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||
// A query's result only matters if more than one draw was performed during it.
|
||||
// Otherwise, dummy it out and return 0 immediately.
|
||||
|
||||
if (hostReserved)
|
||||
while (hostReserved-- > 0)
|
||||
{
|
||||
// This counter event is guaranteed to be available for host conditional rendering.
|
||||
// This counter event is guaranteed to be available for host conditional rendering for the given number of uses.
|
||||
_current.ReserveForHostAccess();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||
private readonly CounterQueue _queue;
|
||||
private readonly BufferedQuery _counter;
|
||||
|
||||
private bool _hostAccessReserved;
|
||||
private int _hostAccessReserved;
|
||||
private int _refCount = 1; // Starts with a reference from the counter queue.
|
||||
|
||||
private readonly object _lock = new();
|
||||
|
@ -121,12 +121,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||
|
||||
public bool ReserveForHostAccess()
|
||||
{
|
||||
if (_hostAccessReserved)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsValueAvailable())
|
||||
if (_hostAccessReserved == 0 && IsValueAvailable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -138,14 +133,14 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||
return false;
|
||||
}
|
||||
|
||||
_hostAccessReserved = true;
|
||||
Interlocked.Increment(ref _hostAccessReserved);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ReleaseHostAccess()
|
||||
{
|
||||
_hostAccessReserved = false;
|
||||
Interlocked.Decrement(ref _hostAccessReserved);
|
||||
|
||||
DecrementRefCount();
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||
_counterQueues[(int)CounterType.SamplesPassed].ResetFutureCounters(cmd, count);
|
||||
}
|
||||
|
||||
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
|
||||
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, int hostReserved)
|
||||
{
|
||||
return _counterQueues[(int)type].QueueReport(resultHandler, divisor, _pipeline.DrawCount, hostReserved);
|
||||
}
|
||||
|
|
|
@ -667,8 +667,36 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
if (PrepareOutputBuffer(cbs, hostSize, buffer, out VkBuffer copyToBuffer, out BufferHolder tempCopyHolder))
|
||||
{
|
||||
// No barrier necessary, as this is a temporary copy buffer.
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferHolder.InsertBufferBarrier(
|
||||
_gd,
|
||||
cbs.CommandBuffer,
|
||||
copyToBuffer,
|
||||
BufferHolder.DefaultAccessFlags,
|
||||
AccessFlags.TransferWriteBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
offset,
|
||||
outSize);
|
||||
}
|
||||
|
||||
InsertImageBarrier(
|
||||
_gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
image,
|
||||
TextureStorage.DefaultAccessMask,
|
||||
AccessFlags.TransferReadBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
Info.Format.ConvertAspectFlags(),
|
||||
FirstLayer + layer,
|
||||
FirstLevel + level,
|
||||
1,
|
||||
1);
|
||||
|
||||
CopyFromOrToBuffer(cbs.CommandBuffer, copyToBuffer, image, hostSize, true, layer, level, 1, 1, singleSlice: true, offset, stride);
|
||||
|
||||
|
@ -677,6 +705,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
CopyDataToOutputBuffer(cbs, tempCopyHolder, autoBuffer, hostSize, range.Offset);
|
||||
tempCopyHolder.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferHolder.InsertBufferBarrier(
|
||||
_gd,
|
||||
cbs.CommandBuffer,
|
||||
copyToBuffer,
|
||||
AccessFlags.TransferWriteBit,
|
||||
BufferHolder.DefaultAccessFlags,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
offset,
|
||||
outSize);
|
||||
}
|
||||
}
|
||||
|
||||
private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer)
|
||||
|
|
|
@ -869,7 +869,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
SyncManager.Cleanup();
|
||||
}
|
||||
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, int hostReserved)
|
||||
{
|
||||
return _counters.QueueReport(type, resultHandler, divisor, hostReserved);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
using LibHac.Ns;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class TitleUpdateModel
|
||||
{
|
||||
public ApplicationControlProperty Control { get; }
|
||||
public uint Version { get; }
|
||||
public string Path { get; }
|
||||
public string Label { get; }
|
||||
|
||||
public string Label => LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||
System.IO.Path.GetExtension(Path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel,
|
||||
Control.DisplayVersionString.ToString()
|
||||
);
|
||||
|
||||
public TitleUpdateModel(ApplicationControlProperty control, string path)
|
||||
public TitleUpdateModel(uint version, string displayVersion, string path)
|
||||
{
|
||||
Control = control;
|
||||
Version = version;
|
||||
Label = LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||
System.IO.Path.GetExtension(path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel,
|
||||
displayVersion
|
||||
);
|
||||
Path = path;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,26 +131,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public void SortUpdates()
|
||||
{
|
||||
var list = TitleUpdates.ToList();
|
||||
|
||||
list.Sort((first, second) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(first.Control.DisplayVersionString.ToString()))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString()))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Version.Parse(first.Control.DisplayVersionString.ToString()).CompareTo(Version.Parse(second.Control.DisplayVersionString.ToString())) * -1;
|
||||
});
|
||||
var sortedUpdates = TitleUpdates.OrderByDescending(update => update.Version);
|
||||
|
||||
Views.Clear();
|
||||
Views.Add(new BaseModel());
|
||||
Views.AddRange(list);
|
||||
Views.AddRange(sortedUpdates);
|
||||
|
||||
if (SelectedUpdate == null)
|
||||
{
|
||||
|
@ -204,7 +189,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
|
||||
|
||||
var update = new TitleUpdateModel(controlData, path);
|
||||
var displayVersion = controlData.DisplayVersionString.ToString();
|
||||
var update = new TitleUpdateModel(content.Version.Version, displayVersion, path);
|
||||
|
||||
TitleUpdates.Add(update);
|
||||
|
||||
if (selected)
|
||||
|
|
Loading…
Add table
Reference in a new issue