| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- using System;
- using System.Diagnostics;
- using System.Threading;
- namespace Ryujinx.Graphics.Vulkan
- {
- interface IAuto
- {
- bool HasCommandBufferDependency(CommandBufferScoped cbs);
- void IncrementReferenceCount();
- void DecrementReferenceCount(int cbIndex);
- void DecrementReferenceCount();
- }
- interface IAutoPrivate : IAuto
- {
- void AddCommandBufferDependencies(CommandBufferScoped cbs);
- }
- class Auto<T> : IAutoPrivate, IDisposable where T : IDisposable
- {
- private int _referenceCount;
- private T _value;
- private readonly BitMap _cbOwnership;
- private readonly MultiFenceHolder _waitable;
- private readonly IAutoPrivate[] _referencedObjs;
- 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, params IAutoPrivate[] referencedObjs) : this(value)
- {
- _waitable = waitable;
- _referencedObjs = referencedObjs;
- for (int i = 0; i < referencedObjs.Length; i++)
- {
- referencedObjs[i].IncrementReferenceCount();
- }
- }
- public T Get(CommandBufferScoped cbs, int offset, int size)
- {
- _waitable?.AddBufferUse(cbs.CommandBufferIndex, offset, size);
- 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);
- // We need to add a dependency on the command buffer to all objects this object
- // references aswell.
- if (_referencedObjs != null)
- {
- for (int i = 0; i < _referencedObjs.Length; i++)
- {
- _referencedObjs[i].AddCommandBufferDependencies(cbs);
- }
- }
- }
- }
- 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;
- // Value is no longer in use by the GPU, dispose all other
- // resources that it references.
- if (_referencedObjs != null)
- {
- for (int i = 0; i < _referencedObjs.Length; i++)
- {
- _referencedObjs[i].DecrementReferenceCount();
- }
- }
- }
- Debug.Assert(_referenceCount >= 0);
- }
- public void Dispose()
- {
- if (!_disposed)
- {
- DecrementReferenceCount();
- _disposed = true;
- }
- }
- }
- }
|