diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs | 554 |
1 files changed, 0 insertions, 554 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs deleted file mode 100644 index ebb4e9ae..00000000 --- a/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs +++ /dev/null @@ -1,554 +0,0 @@ -using Ryujinx.Cpu.Tracking; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -namespace Ryujinx.Graphics.Gpu.Image -{ - /// <summary> - /// A tracking handle for a texture group, which represents a range of views in a storage texture. - /// Retains a list of overlapping texture views, a modified flag, and tracking for each - /// CPU VA range that the views cover. - /// Also tracks copy dependencies for the handle - references to other handles that must be kept - /// in sync with this one before use. - /// </summary> - class TextureGroupHandle : IDisposable - { - private TextureGroup _group; - private int _bindCount; - private int _firstLevel; - private int _firstLayer; - - // Sync state for texture flush. - - /// <summary> - /// The sync number last registered. - /// </summary> - private ulong _registeredSync; - - /// <summary> - /// The sync number when the texture was last modified by GPU. - /// </summary> - private ulong _modifiedSync; - - /// <summary> - /// Whether a tracking action is currently registered or not. (0/1) - /// </summary> - private int _actionRegistered; - - /// <summary> - /// Whether a sync action is currently registered or not. - /// </summary> - private bool _syncActionRegistered; - - /// <summary> - /// The byte offset from the start of the storage of this handle. - /// </summary> - public int Offset { get; } - - /// <summary> - /// The size in bytes covered by this handle. - /// </summary> - public int Size { get; } - - /// <summary> - /// The base slice index for this handle. - /// </summary> - public int BaseSlice { get; } - - /// <summary> - /// The number of slices covered by this handle. - /// </summary> - public int SliceCount { get; } - - /// <summary> - /// The textures which this handle overlaps with. - /// </summary> - public List<Texture> Overlaps { get; } - - /// <summary> - /// The CPU memory tracking handles that cover this handle. - /// </summary> - public CpuRegionHandle[] Handles { get; } - - /// <summary> - /// True if a texture overlapping this handle has been modified. Is set false when the flush action is called. - /// </summary> - public bool Modified { get; set; } - - /// <summary> - /// Dependencies to handles from other texture groups. - /// </summary> - public List<TextureDependency> Dependencies { get; } - - /// <summary> - /// A flag indicating that a copy is required from one of the dependencies. - /// </summary> - public bool NeedsCopy => DeferredCopy != null; - - /// <summary> - /// A data copy that must be acknowledged the next time this handle is used. - /// </summary> - public TextureGroupHandle DeferredCopy { get; set; } - - /// <summary> - /// Create a new texture group handle, representing a range of views in a storage texture. - /// </summary> - /// <param name="group">The TextureGroup that the handle belongs to</param> - /// <param name="offset">The byte offset from the start of the storage of the handle</param> - /// <param name="size">The size in bytes covered by the handle</param> - /// <param name="views">All views of the storage texture, used to calculate overlaps</param> - /// <param name="firstLayer">The first layer of this handle in the storage texture</param> - /// <param name="firstLevel">The first level of this handle in the storage texture</param> - /// <param name="baseSlice">The base slice index of this handle</param> - /// <param name="sliceCount">The number of slices this handle covers</param> - /// <param name="handles">The memory tracking handles that cover this handle</param> - public TextureGroupHandle(TextureGroup group, - int offset, - ulong size, - List<Texture> views, - int firstLayer, - int firstLevel, - int baseSlice, - int sliceCount, - CpuRegionHandle[] handles) - { - _group = group; - _firstLayer = firstLayer; - _firstLevel = firstLevel; - - Offset = offset; - Size = (int)size; - Overlaps = new List<Texture>(); - Dependencies = new List<TextureDependency>(); - - BaseSlice = baseSlice; - SliceCount = sliceCount; - - if (views != null) - { - RecalculateOverlaps(group, views); - } - - Handles = handles; - } - - /// <summary> - /// Calculate a list of which views overlap this handle. - /// </summary> - /// <param name="group">The parent texture group, used to find a view's base CPU VA offset</param> - /// <param name="views">The list of views to search for overlaps</param> - public void RecalculateOverlaps(TextureGroup group, List<Texture> views) - { - // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic. - lock (Overlaps) - { - int endOffset = Offset + Size; - - Overlaps.Clear(); - - foreach (Texture view in views) - { - int viewOffset = group.FindOffset(view); - if (viewOffset < endOffset && Offset < viewOffset + (int)view.Size) - { - Overlaps.Add(view); - } - } - } - } - - /// <summary> - /// Adds a single texture view as an overlap if its range overlaps. - /// </summary> - /// <param name="offset">The offset of the view in the group</param> - /// <param name="view">The texture to add as an overlap</param> - public void AddOverlap(int offset, Texture view) - { - // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic. - - if (OverlapsWith(offset, (int)view.Size)) - { - lock (Overlaps) - { - Overlaps.Add(view); - } - } - } - - /// <summary> - /// Removes a single texture view as an overlap if its range overlaps. - /// </summary> - /// <param name="offset">The offset of the view in the group</param> - /// <param name="view">The texture to add as an overlap</param> - public void RemoveOverlap(int offset, Texture view) - { - // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic. - - if (OverlapsWith(offset, (int)view.Size)) - { - lock (Overlaps) - { - Overlaps.Remove(view); - } - } - } - - /// <summary> - /// Registers a sync action to happen for this handle, and an interim flush action on the tracking handle. - /// </summary> - /// <param name="context">The GPU context to register a sync action on</param> - private void RegisterSync(GpuContext context) - { - if (!_syncActionRegistered) - { - _modifiedSync = context.SyncNumber; - context.RegisterSyncAction(SyncAction, true); - _syncActionRegistered = true; - } - - if (Interlocked.Exchange(ref _actionRegistered, 1) == 0) - { - _group.RegisterAction(this); - } - } - - /// <summary> - /// Signal that this handle has been modified to any existing dependencies, and set the modified flag. - /// </summary> - /// <param name="context">The GPU context to register a sync action on</param> - public void SignalModified(GpuContext context) - { - Modified = true; - - // If this handle has any copy dependencies, notify the other handle that a copy needs to be performed. - - foreach (TextureDependency dependency in Dependencies) - { - dependency.SignalModified(); - } - - RegisterSync(context); - } - - /// <summary> - /// Signal that this handle has either started or ended being modified. - /// </summary> - /// <param name="bound">True if this handle is being bound, false if unbound</param> - /// <param name="context">The GPU context to register a sync action on</param> - public void SignalModifying(bool bound, GpuContext context) - { - SignalModified(context); - - // Note: Bind count currently resets to 0 on inherit for safety, as the handle <-> view relationship can change. - _bindCount = Math.Max(0, _bindCount + (bound ? 1 : -1)); - } - - /// <summary> - /// Synchronize dependent textures, if any of them have deferred a copy from this texture. - /// </summary> - public void SynchronizeDependents() - { - foreach (TextureDependency dependency in Dependencies) - { - TextureGroupHandle otherHandle = dependency.Other.Handle; - - if (otherHandle.DeferredCopy == this) - { - otherHandle._group.Storage.SynchronizeMemory(); - } - } - } - - /// <summary> - /// Wait for the latest sync number that the texture handle was written to, - /// removing the modified flag if it was reached, or leaving it set if it has not yet been created. - /// </summary> - /// <param name="context">The GPU context used to wait for sync</param> - public void Sync(GpuContext context) - { - ulong registeredSync = _registeredSync; - long diff = (long)(context.SyncNumber - registeredSync); - - if (diff > 0) - { - context.Renderer.WaitSync(registeredSync); - - if ((long)(_modifiedSync - registeredSync) > 0) - { - // Flush the data in a previous state. Do not remove the modified flag - it will be removed to ignore following writes. - return; - } - - Modified = false; - } - - // If the difference is <= 0, no data is not ready yet. Flush any data we can without waiting or removing modified flag. - } - - /// <summary> - /// Clears the action registered variable, indicating that the tracking action should be - /// re-registered on the next modification. - /// </summary> - public void ClearActionRegistered() - { - Interlocked.Exchange(ref _actionRegistered, 0); - } - - /// <summary> - /// Action to perform when a sync number is registered after modification. - /// This action will register a read tracking action on the memory tracking handle so that a flush from CPU can happen. - /// </summary> - private void SyncAction() - { - // The storage will need to signal modified again to update the sync number in future. - _group.Storage.SignalModifiedDirty(); - - lock (Overlaps) - { - foreach (Texture texture in Overlaps) - { - texture.SignalModifiedDirty(); - } - } - - // Register region tracking for CPU? (again) - _registeredSync = _modifiedSync; - _syncActionRegistered = false; - - if (Interlocked.Exchange(ref _actionRegistered, 1) == 0) - { - _group.RegisterAction(this); - } - } - - /// <summary> - /// Signal that a copy dependent texture has been modified, and must have its data copied to this one. - /// </summary> - /// <param name="copyFrom">The texture handle that must defer a copy to this one</param> - public void DeferCopy(TextureGroupHandle copyFrom) - { - Modified = false; - - DeferredCopy = copyFrom; - - _group.Storage.SignalGroupDirty(); - - foreach (Texture overlap in Overlaps) - { - overlap.SignalGroupDirty(); - } - } - - /// <summary> - /// Create a copy dependency between this handle, and another. - /// </summary> - /// <param name="other">The handle to create a copy dependency to</param> - /// <param name="copyToOther">True if a copy should be deferred to all of the other handle's dependencies</param> - public void CreateCopyDependency(TextureGroupHandle other, bool copyToOther = false) - { - // Does this dependency already exist? - foreach (TextureDependency existing in Dependencies) - { - if (existing.Other.Handle == other) - { - // Do not need to create it again. May need to set the dirty flag. - return; - } - } - - _group.HasCopyDependencies = true; - other._group.HasCopyDependencies = true; - - TextureDependency dependency = new TextureDependency(this); - TextureDependency otherDependency = new TextureDependency(other); - - dependency.Other = otherDependency; - otherDependency.Other = dependency; - - Dependencies.Add(dependency); - other.Dependencies.Add(otherDependency); - - // Recursively create dependency: - // All of this handle's dependencies must depend on the other. - foreach (TextureDependency existing in Dependencies.ToArray()) - { - if (existing != dependency && existing.Other.Handle != other) - { - existing.Other.Handle.CreateCopyDependency(other); - } - } - - // All of the other handle's dependencies must depend on this. - foreach (TextureDependency existing in other.Dependencies.ToArray()) - { - if (existing != otherDependency && existing.Other.Handle != this) - { - existing.Other.Handle.CreateCopyDependency(this); - - if (copyToOther) - { - existing.Other.Handle.DeferCopy(this); - } - } - } - } - - /// <summary> - /// Remove a dependency from this handle's dependency list. - /// </summary> - /// <param name="dependency">The dependency to remove</param> - public void RemoveDependency(TextureDependency dependency) - { - Dependencies.Remove(dependency); - } - - /// <summary> - /// Check if any of this handle's memory tracking handles are dirty. - /// </summary> - /// <returns>True if at least one of the handles is dirty</returns> - private bool CheckDirty() - { - return Handles.Any(handle => handle.Dirty); - } - - /// <summary> - /// Perform a copy from the provided handle to this one, or perform a deferred copy if none is provided. - /// </summary> - /// <param name="context">GPU context to register sync for modified handles</param> - /// <param name="fromHandle">The handle to copy from. If not provided, this method will copy from and clear the deferred copy instead</param> - /// <returns>True if the copy was performed, false otherwise</returns> - public bool Copy(GpuContext context, TextureGroupHandle fromHandle = null) - { - bool result = false; - bool shouldCopy = false; - - if (fromHandle == null) - { - fromHandle = DeferredCopy; - - if (fromHandle != null) - { - // Only copy if the copy texture is still modified. - // It will be set as unmodified if new data is written from CPU, as the data previously in the texture will flush. - // It will also set as unmodified if a copy is deferred to it. - - shouldCopy = fromHandle.Modified; - - if (fromHandle._bindCount == 0) - { - // Repeat the copy in future if the bind count is greater than 0. - DeferredCopy = null; - } - } - } - else - { - // Copies happen directly when initializing a copy dependency. - // If dirty, do not copy. Its data no longer matters, and this handle should also be dirty. - // Also, only direct copy if the data in this handle is not already modified (can be set by copies from modified handles). - shouldCopy = !fromHandle.CheckDirty() && (fromHandle.Modified || !Modified); - } - - if (shouldCopy) - { - Texture from = fromHandle._group.Storage; - Texture to = _group.Storage; - - if (from.ScaleFactor != to.ScaleFactor) - { - to.PropagateScale(from); - } - - from.HostTexture.CopyTo( - to.HostTexture, - fromHandle._firstLayer, - _firstLayer, - fromHandle._firstLevel, - _firstLevel); - - if (fromHandle.Modified) - { - Modified = true; - - RegisterSync(context); - } - - result = true; - } - - return result; - } - - /// <summary> - /// Check if this handle has a dependency to a given texture group. - /// </summary> - /// <param name="group">The texture group to check for</param> - /// <returns>True if there is a dependency, false otherwise</returns> - public bool HasDependencyTo(TextureGroup group) - { - foreach (TextureDependency dep in Dependencies) - { - if (dep.Other.Handle._group == group) - { - return true; - } - } - - return false; - } - - /// <summary> - /// Inherit modified flags and dependencies from another texture handle. - /// </summary> - /// <param name="old">The texture handle to inherit from</param> - /// <param name="withCopies">Whether the handle should inherit copy dependencies or not</param> - public void Inherit(TextureGroupHandle old, bool withCopies) - { - Modified |= old.Modified; - - if (withCopies) - { - foreach (TextureDependency dependency in old.Dependencies.ToArray()) - { - CreateCopyDependency(dependency.Other.Handle); - - if (dependency.Other.Handle.DeferredCopy == old) - { - dependency.Other.Handle.DeferredCopy = this; - } - } - - DeferredCopy = old.DeferredCopy; - } - } - - /// <summary> - /// Check if this region overlaps with another. - /// </summary> - /// <param name="address">Base address</param> - /// <param name="size">Size of the region</param> - /// <returns>True if overlapping, false otherwise</returns> - public bool OverlapsWith(int offset, int size) - { - return Offset < offset + size && offset < Offset + Size; - } - - /// <summary> - /// Dispose this texture group handle, removing all its dependencies and disposing its memory tracking handles. - /// </summary> - public void Dispose() - { - foreach (CpuRegionHandle handle in Handles) - { - handle.Dispose(); - } - - foreach (TextureDependency dependency in Dependencies.ToArray()) - { - dependency.Other.Handle.RemoveDependency(dependency.Other); - } - } - } -} |
