| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- using System;
- using System.Diagnostics;
- using System.Runtime.Versioning;
- using System.Threading;
- namespace Ryujinx.Graphics.Metal
- {
- interface IAuto
- {
- bool HasCommandBufferDependency(CommandBufferScoped cbs);
- void IncrementReferenceCount();
- void DecrementReferenceCount(int cbIndex);
- void DecrementReferenceCount();
- }
- interface IAutoPrivate : IAuto
- {
- void AddCommandBufferDependencies(CommandBufferScoped cbs);
- }
- [SupportedOSPlatform("macos")]
- class Auto<T> : IAutoPrivate, IDisposable where T : IDisposable
- {
- private int _referenceCount;
- private T _value;
- private readonly BitMap _cbOwnership;
- private readonly MultiFenceHolder _waitable;
- private bool _disposed;
- private bool _destroyed;
- public Auto(T value)
- {
- _referenceCount = 1;
- _value = value;
- _cbOwnership = new BitMap(CommandBufferPool.MaxCommandBuffers);
- }
- public Auto(T value, MultiFenceHolder waitable) : this(value)
- {
- _waitable = waitable;
- }
- public T Get(CommandBufferScoped cbs, int offset, int size, bool write = false)
- {
- _waitable?.AddBufferUse(cbs.CommandBufferIndex, offset, size, write);
- return Get(cbs);
- }
- public T GetUnsafe()
- {
- return _value;
- }
- public T Get(CommandBufferScoped cbs)
- {
- if (!_destroyed)
- {
- AddCommandBufferDependencies(cbs);
- }
- return _value;
- }
- public bool HasCommandBufferDependency(CommandBufferScoped cbs)
- {
- return _cbOwnership.IsSet(cbs.CommandBufferIndex);
- }
- public bool HasRentedCommandBufferDependency(CommandBufferPool cbp)
- {
- return _cbOwnership.AnySet();
- }
- public void AddCommandBufferDependencies(CommandBufferScoped cbs)
- {
- // We don't want to add a reference to this object to the command buffer
- // more than once, so if we detect that the command buffer already has ownership
- // of this object, then we can just return without doing anything else.
- if (_cbOwnership.Set(cbs.CommandBufferIndex))
- {
- if (_waitable != null)
- {
- cbs.AddWaitable(_waitable);
- }
- cbs.AddDependant(this);
- }
- }
- public bool TryIncrementReferenceCount()
- {
- int lastValue;
- do
- {
- lastValue = _referenceCount;
- if (lastValue == 0)
- {
- return false;
- }
- }
- while (Interlocked.CompareExchange(ref _referenceCount, lastValue + 1, lastValue) != lastValue);
- return true;
- }
- public void IncrementReferenceCount()
- {
- if (Interlocked.Increment(ref _referenceCount) == 1)
- {
- Interlocked.Decrement(ref _referenceCount);
- throw new InvalidOperationException("Attempted to increment the reference count of an object that was already destroyed.");
- }
- }
- public void DecrementReferenceCount(int cbIndex)
- {
- _cbOwnership.Clear(cbIndex);
- DecrementReferenceCount();
- }
- public void DecrementReferenceCount()
- {
- if (Interlocked.Decrement(ref _referenceCount) == 0)
- {
- _value.Dispose();
- _value = default;
- _destroyed = true;
- }
- Debug.Assert(_referenceCount >= 0);
- }
- public void Dispose()
- {
- if (!_disposed)
- {
- DecrementReferenceCount();
- _disposed = true;
- }
- }
- }
- }
|