aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Engine/GPFifo
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Gpu/Engine/GPFifo
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/GPFifo')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/CompressedMethod.cs41
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPEntry.cs55
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs248
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClassState.cs233
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs262
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs331
6 files changed, 0 insertions, 1170 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/CompressedMethod.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/CompressedMethod.cs
deleted file mode 100644
index 458dc8f6..00000000
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/CompressedMethod.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-// This file was auto-generated from NVIDIA official Maxwell definitions.
-
-namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
-{
- enum TertOp
- {
- Grp0IncMethod = 0,
- Grp0SetSubDevMask = 1,
- Grp0StoreSubDevMask = 2,
- Grp0UseSubDevMask = 3,
- Grp2NonIncMethod = 0
- }
-
- enum SecOp
- {
- Grp0UseTert = 0,
- IncMethod = 1,
- Grp2UseTert = 2,
- NonIncMethod = 3,
- ImmdDataMethod = 4,
- OneInc = 5,
- Reserved6 = 6,
- EndPbSegment = 7
- }
-
- struct CompressedMethod
- {
-#pragma warning disable CS0649
- public uint Method;
-#pragma warning restore CS0649
- public int MethodAddressOld => (int)((Method >> 2) & 0x7FF);
- public int MethodAddress => (int)((Method >> 0) & 0xFFF);
- public int SubdeviceMask => (int)((Method >> 4) & 0xFFF);
- public int MethodSubchannel => (int)((Method >> 13) & 0x7);
- public TertOp TertOp => (TertOp)((Method >> 16) & 0x3);
- public int MethodCountOld => (int)((Method >> 18) & 0x7FF);
- public int MethodCount => (int)((Method >> 16) & 0x1FFF);
- public int ImmdData => (int)((Method >> 16) & 0x1FFF);
- public SecOp SecOp => (SecOp)((Method >> 29) & 0x7);
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPEntry.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPEntry.cs
deleted file mode 100644
index b1b236e7..00000000
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPEntry.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// This file was auto-generated from NVIDIA official Maxwell definitions.
-
-namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
-{
- enum Entry0Fetch
- {
- Unconditional = 0,
- Conditional = 1,
- }
-
- enum Entry1Priv
- {
- User = 0,
- Kernel = 1,
- }
-
- enum Entry1Level
- {
- Main = 0,
- Subroutine = 1,
- }
-
- enum Entry1Sync
- {
- Proceed = 0,
- Wait = 1,
- }
-
- enum Entry1Opcode
- {
- Nop = 0,
- Illegal = 1,
- Crc = 2,
- PbCrc = 3,
- }
-
- struct GPEntry
- {
-#pragma warning disable CS0649
- public uint Entry0;
-#pragma warning restore CS0649
- public Entry0Fetch Entry0Fetch => (Entry0Fetch)((Entry0 >> 0) & 0x1);
- public int Entry0Get => (int)((Entry0 >> 2) & 0x3FFFFFFF);
- public int Entry0Operand => (int)(Entry0);
-#pragma warning disable CS0649
- public uint Entry1;
-#pragma warning restore CS0649
- public int Entry1GetHi => (int)((Entry1 >> 0) & 0xFF);
- public Entry1Priv Entry1Priv => (Entry1Priv)((Entry1 >> 8) & 0x1);
- public Entry1Level Entry1Level => (Entry1Level)((Entry1 >> 9) & 0x1);
- public int Entry1Length => (int)((Entry1 >> 10) & 0x1FFFFF);
- public Entry1Sync Entry1Sync => (Entry1Sync)((Entry1 >> 31) & 0x1);
- public Entry1Opcode Entry1Opcode => (Entry1Opcode)((Entry1 >> 0) & 0xFF);
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
deleted file mode 100644
index e80d98a1..00000000
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
+++ /dev/null
@@ -1,248 +0,0 @@
-using Ryujinx.Graphics.Device;
-using Ryujinx.Graphics.Gpu.Engine.MME;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
-{
- /// <summary>
- /// Represents a GPU General Purpose FIFO class.
- /// </summary>
- class GPFifoClass : IDeviceState
- {
- private readonly GpuContext _context;
- private readonly GPFifoProcessor _parent;
- private readonly DeviceState<GPFifoClassState> _state;
-
- private int _previousSubChannel;
- private bool _createSyncPending;
-
- private const int MacrosCount = 0x80;
-
- // Note: The size of the macro memory is unknown, we just make
- // a guess here and use 256kb as the size. Increase if needed.
- private const int MacroCodeSize = 256 * 256;
-
- private readonly Macro[] _macros;
- private readonly int[] _macroCode;
-
- /// <summary>
- /// Creates a new instance of the GPU General Purpose FIFO class.
- /// </summary>
- /// <param name="context">GPU context</param>
- /// <param name="parent">Parent GPU General Purpose FIFO processor</param>
- public GPFifoClass(GpuContext context, GPFifoProcessor parent)
- {
- _context = context;
- _parent = parent;
- _state = new DeviceState<GPFifoClassState>(new Dictionary<string, RwCallback>
- {
- { nameof(GPFifoClassState.Semaphored), new RwCallback(Semaphored, null) },
- { nameof(GPFifoClassState.Syncpointb), new RwCallback(Syncpointb, null) },
- { nameof(GPFifoClassState.WaitForIdle), new RwCallback(WaitForIdle, null) },
- { nameof(GPFifoClassState.SetReference), new RwCallback(SetReference, null) },
- { nameof(GPFifoClassState.LoadMmeInstructionRam), new RwCallback(LoadMmeInstructionRam, null) },
- { nameof(GPFifoClassState.LoadMmeStartAddressRam), new RwCallback(LoadMmeStartAddressRam, null) },
- { nameof(GPFifoClassState.SetMmeShadowRamControl), new RwCallback(SetMmeShadowRamControl, null) }
- });
-
- _macros = new Macro[MacrosCount];
- _macroCode = new int[MacroCodeSize];
- }
-
- /// <summary>
- /// Create any syncs from WaitForIdle command that are currently pending.
- /// </summary>
- public void CreatePendingSyncs()
- {
- if (_createSyncPending)
- {
- _createSyncPending = false;
- _context.CreateHostSyncIfNeeded(false, false);
- }
- }
-
- /// <summary>
- /// Reads data from the class registers.
- /// </summary>
- /// <param name="offset">Register byte offset</param>
- /// <returns>Data at the specified offset</returns>
- public int Read(int offset) => _state.Read(offset);
-
- /// <summary>
- /// Writes data to the class registers.
- /// </summary>
- /// <param name="offset">Register byte offset</param>
- /// <param name="data">Data to be written</param>
- public void Write(int offset, int data) => _state.Write(offset, data);
-
- /// <summary>
- /// Writes a GPU counter to guest memory.
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void Semaphored(int argument)
- {
- ulong address = ((ulong)_state.State.SemaphorebOffsetLower << 2) |
- ((ulong)_state.State.SemaphoreaOffsetUpper << 32);
-
- int value = _state.State.SemaphorecPayload;
-
- SemaphoredOperation operation = _state.State.SemaphoredOperation;
-
- if (_state.State.SemaphoredReleaseSize == SemaphoredReleaseSize.SixteenBytes)
- {
- _parent.MemoryManager.Write(address + 4, 0);
- _parent.MemoryManager.Write(address + 8, _context.GetTimestamp());
- }
-
- // TODO: Acquire operations (Wait), interrupts for invalid combinations.
- if (operation == SemaphoredOperation.Release)
- {
- _parent.MemoryManager.Write(address, value);
- }
- else if (operation == SemaphoredOperation.Reduction)
- {
- bool signed = _state.State.SemaphoredFormat == SemaphoredFormat.Signed;
-
- int mem = _parent.MemoryManager.Read<int>(address);
-
- switch (_state.State.SemaphoredReduction)
- {
- case SemaphoredReduction.Min:
- value = signed ? Math.Min(mem, value) : (int)Math.Min((uint)mem, (uint)value);
- break;
- case SemaphoredReduction.Max:
- value = signed ? Math.Max(mem, value) : (int)Math.Max((uint)mem, (uint)value);
- break;
- case SemaphoredReduction.Xor:
- value ^= mem;
- break;
- case SemaphoredReduction.And:
- value &= mem;
- break;
- case SemaphoredReduction.Or:
- value |= mem;
- break;
- case SemaphoredReduction.Add:
- value += mem;
- break;
- case SemaphoredReduction.Inc:
- value = (uint)mem < (uint)value ? mem + 1 : 0;
- break;
- case SemaphoredReduction.Dec:
- value = (uint)mem > 0 && (uint)mem <= (uint)value ? mem - 1 : value;
- break;
- }
-
- _parent.MemoryManager.Write(address, value);
- }
- }
-
- /// <summary>
- /// Apply a fence operation on a syncpoint.
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void Syncpointb(int argument)
- {
- SyncpointbOperation operation = _state.State.SyncpointbOperation;
-
- uint syncpointId = (uint)_state.State.SyncpointbSyncptIndex;
-
- if (operation == SyncpointbOperation.Wait)
- {
- uint threshold = (uint)_state.State.SyncpointaPayload;
-
- _context.Synchronization.WaitOnSyncpoint(syncpointId, threshold, Timeout.InfiniteTimeSpan);
- }
- else if (operation == SyncpointbOperation.Incr)
- {
- _context.CreateHostSyncIfNeeded(true, true);
- _context.Synchronization.IncrementSyncpoint(syncpointId);
- }
-
- _context.AdvanceSequence();
- }
-
- /// <summary>
- /// Waits for the GPU to be idle.
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void WaitForIdle(int argument)
- {
- _parent.PerformDeferredDraws();
- _context.Renderer.Pipeline.Barrier();
-
- _createSyncPending = true;
- }
-
- /// <summary>
- /// Used as an indirect data barrier on NVN. When used, access to previously written data must be coherent.
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void SetReference(int argument)
- {
- _context.Renderer.Pipeline.CommandBufferBarrier();
-
- _context.CreateHostSyncIfNeeded(false, true);
- }
-
- /// <summary>
- /// Sends macro code/data to the MME.
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void LoadMmeInstructionRam(int argument)
- {
- _macroCode[_state.State.LoadMmeInstructionRamPointer++] = argument;
- }
-
- /// <summary>
- /// Binds a macro index to a position for the MME
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void LoadMmeStartAddressRam(int argument)
- {
- _macros[_state.State.LoadMmeStartAddressRamPointer++] = new Macro(argument);
- }
-
- /// <summary>
- /// Changes the shadow RAM control.
- /// </summary>
- /// <param name="argument">Method call argument</param>
- public void SetMmeShadowRamControl(int argument)
- {
- _parent.SetShadowRamControl(argument);
- }
-
- /// <summary>
- /// Pushes an argument to a macro.
- /// </summary>
- /// <param name="index">Index of the macro</param>
- /// <param name="gpuVa">GPU virtual address where the command word is located</param>
- /// <param name="argument">Argument to be pushed to the macro</param>
- public void MmePushArgument(int index, ulong gpuVa, int argument)
- {
- _macros[index].PushArgument(gpuVa, argument);
- }
-
- /// <summary>
- /// Prepares a macro for execution.
- /// </summary>
- /// <param name="index">Index of the macro</param>
- /// <param name="argument">Initial argument passed to the macro</param>
- public void MmeStart(int index, int argument)
- {
- _macros[index].StartExecution(_context, _parent, _macroCode, argument);
- }
-
- /// <summary>
- /// Executes a macro.
- /// </summary>
- /// <param name="index">Index of the macro</param>
- /// <param name="state">Current GPU state</param>
- public void CallMme(int index, IDeviceState state)
- {
- _macros[index].Execute(_macroCode, state);
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClassState.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClassState.cs
deleted file mode 100644
index 07d062eb..00000000
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClassState.cs
+++ /dev/null
@@ -1,233 +0,0 @@
-// This file was auto-generated from NVIDIA official Maxwell definitions.
-
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
-{
- /// <summary>
- /// Semaphore operation.
- /// </summary>
- enum SemaphoredOperation
- {
- Acquire = 1,
- Release = 2,
- AcqGeq = 4,
- AcqAnd = 8,
- Reduction = 16
- }
-
- /// <summary>
- /// Semaphore acquire switch enable.
- /// </summary>
- enum SemaphoredAcquireSwitch
- {
- Disabled = 0,
- Enabled = 1
- }
-
- /// <summary>
- /// Semaphore release interrupt wait enable.
- /// </summary>
- enum SemaphoredReleaseWfi
- {
- En = 0,
- Dis = 1
- }
-
- /// <summary>
- /// Semaphore release structure size.
- /// </summary>
- enum SemaphoredReleaseSize
- {
- SixteenBytes = 0,
- FourBytes = 1
- }
-
- /// <summary>
- /// Semaphore reduction operation.
- /// </summary>
- enum SemaphoredReduction
- {
- Min = 0,
- Max = 1,
- Xor = 2,
- And = 3,
- Or = 4,
- Add = 5,
- Inc = 6,
- Dec = 7
- }
-
- /// <summary>
- /// Semaphore format.
- /// </summary>
- enum SemaphoredFormat
- {
- Signed = 0,
- Unsigned = 1
- }
-
- /// <summary>
- /// Memory Translation Lookaside Buffer Page Directory Buffer invalidation.
- /// </summary>
- enum MemOpCTlbInvalidatePdb
- {
- One = 0,
- All = 1
- }
-
- /// <summary>
- /// Memory Translation Lookaside Buffer GPC invalidation enable.
- /// </summary>
- enum MemOpCTlbInvalidateGpc
- {
- Enable = 0,
- Disable = 1
- }
-
- /// <summary>
- /// Memory Translation Lookaside Buffer invalidation target.
- /// </summary>
- enum MemOpCTlbInvalidateTarget
- {
- VidMem = 0,
- SysMemCoherent = 2,
- SysMemNoncoherent = 3
- }
-
- /// <summary>
- /// Memory operation.
- /// </summary>
- enum MemOpDOperation
- {
- Membar = 5,
- MmuTlbInvalidate = 9,
- L2PeermemInvalidate = 13,
- L2SysmemInvalidate = 14,
- L2CleanComptags = 15,
- L2FlushDirty = 16
- }
-
- /// <summary>
- /// Syncpoint operation.
- /// </summary>
- enum SyncpointbOperation
- {
- Wait = 0,
- Incr = 1
- }
-
- /// <summary>
- /// Syncpoint wait switch enable.
- /// </summary>
- enum SyncpointbWaitSwitch
- {
- Dis = 0,
- En = 1
- }
-
- /// <summary>
- /// Wait for interrupt scope.
- /// </summary>
- enum WfiScope
- {
- CurrentScgType = 0,
- All = 1
- }
-
- /// <summary>
- /// Yield operation.
- /// </summary>
- enum YieldOp
- {
- Nop = 0,
- PbdmaTimeslice = 1,
- RunlistTimeslice = 2,
- Tsg = 3
- }
-
- /// <summary>
- /// General Purpose FIFO class state.
- /// </summary>
- struct GPFifoClassState
- {
-#pragma warning disable CS0649
- public uint SetObject;
- public int SetObjectNvclass => (int)((SetObject >> 0) & 0xFFFF);
- public int SetObjectEngine => (int)((SetObject >> 16) & 0x1F);
- public uint Illegal;
- public int IllegalHandle => (int)(Illegal);
- public uint Nop;
- public int NopHandle => (int)(Nop);
- public uint Reserved0C;
- public uint Semaphorea;
- public int SemaphoreaOffsetUpper => (int)((Semaphorea >> 0) & 0xFF);
- public uint Semaphoreb;
- public int SemaphorebOffsetLower => (int)((Semaphoreb >> 2) & 0x3FFFFFFF);
- public uint Semaphorec;
- public int SemaphorecPayload => (int)(Semaphorec);
- public uint Semaphored;
- public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)((Semaphored >> 0) & 0x1F);
- public SemaphoredAcquireSwitch SemaphoredAcquireSwitch => (SemaphoredAcquireSwitch)((Semaphored >> 12) & 0x1);
- public SemaphoredReleaseWfi SemaphoredReleaseWfi => (SemaphoredReleaseWfi)((Semaphored >> 20) & 0x1);
- public SemaphoredReleaseSize SemaphoredReleaseSize => (SemaphoredReleaseSize)((Semaphored >> 24) & 0x1);
- public SemaphoredReduction SemaphoredReduction => (SemaphoredReduction)((Semaphored >> 27) & 0xF);
- public SemaphoredFormat SemaphoredFormat => (SemaphoredFormat)((Semaphored >> 31) & 0x1);
- public uint NonStallInterrupt;
- public int NonStallInterruptHandle => (int)(NonStallInterrupt);
- public uint FbFlush;
- public int FbFlushHandle => (int)(FbFlush);
- public uint Reserved28;
- public uint Reserved2C;
- public uint MemOpC;
- public int MemOpCOperandLow => (int)((MemOpC >> 2) & 0x3FFFFFFF);
- public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)((MemOpC >> 0) & 0x1);
- public MemOpCTlbInvalidateGpc MemOpCTlbInvalidateGpc => (MemOpCTlbInvalidateGpc)((MemOpC >> 1) & 0x1);
- public MemOpCTlbInvalidateTarget MemOpCTlbInvalidateTarget => (MemOpCTlbInvalidateTarget)((MemOpC >> 10) & 0x3);
- public int MemOpCTlbInvalidateAddrLo => (int)((MemOpC >> 12) & 0xFFFFF);
- public uint MemOpD;
- public int MemOpDOperandHigh => (int)((MemOpD >> 0) & 0xFF);
- public MemOpDOperation MemOpDOperation => (MemOpDOperation)((MemOpD >> 27) & 0x1F);
- public int MemOpDTlbInvalidateAddrHi => (int)((MemOpD >> 0) & 0xFF);
- public uint Reserved38;
- public uint Reserved3C;
- public uint Reserved40;
- public uint Reserved44;
- public uint Reserved48;
- public uint Reserved4C;
- public uint SetReference;
- public int SetReferenceCount => (int)(SetReference);
- public uint Reserved54;
- public uint Reserved58;
- public uint Reserved5C;
- public uint Reserved60;
- public uint Reserved64;
- public uint Reserved68;
- public uint Reserved6C;
- public uint Syncpointa;
- public int SyncpointaPayload => (int)(Syncpointa);
- public uint Syncpointb;
- public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)((Syncpointb >> 0) & 0x1);
- public SyncpointbWaitSwitch SyncpointbWaitSwitch => (SyncpointbWaitSwitch)((Syncpointb >> 4) & 0x1);
- public int SyncpointbSyncptIndex => (int)((Syncpointb >> 8) & 0xFFF);
- public uint Wfi;
- public WfiScope WfiScope => (WfiScope)((Wfi >> 0) & 0x1);
- public uint CrcCheck;
- public int CrcCheckValue => (int)(CrcCheck);
- public uint Yield;
- public YieldOp YieldOp => (YieldOp)((Yield >> 0) & 0x3);
- // TODO: Eventually move this to per-engine state.
- public Array31<uint> Reserved84;
- public uint NoOperation;
- public uint SetNotifyA;
- public uint SetNotifyB;
- public uint Notify;
- public uint WaitForIdle;
- public uint LoadMmeInstructionRamPointer;
- public uint LoadMmeInstructionRam;
- public uint LoadMmeStartAddressRamPointer;
- public uint LoadMmeStartAddressRam;
- public uint SetMmeShadowRamControl;
-#pragma warning restore CS0649
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs
deleted file mode 100644
index cd29a9da..00000000
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs
+++ /dev/null
@@ -1,262 +0,0 @@
-using Ryujinx.Graphics.Gpu.Memory;
-using System;
-using System.Collections.Concurrent;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
-{
- /// <summary>
- /// Represents a GPU General Purpose FIFO device.
- /// </summary>
- public sealed class GPFifoDevice : IDisposable
- {
- /// <summary>
- /// Indicates if the command buffer has pre-fetch enabled.
- /// </summary>
- private enum CommandBufferType
- {
- Prefetch,
- NoPrefetch
- }
-
- /// <summary>
- /// Command buffer data.
- /// </summary>
- private struct CommandBuffer
- {
- /// <summary>
- /// Processor used to process the command buffer. Contains channel state.
- /// </summary>
- public GPFifoProcessor Processor;
-
- /// <summary>
- /// The type of the command buffer.
- /// </summary>
- public CommandBufferType Type;
-
- /// <summary>
- /// Fetched data.
- /// </summary>
- public int[] Words;
-
- /// <summary>
- /// The GPFIFO entry address (used in <see cref="CommandBufferType.NoPrefetch"/> mode).
- /// </summary>
- public ulong EntryAddress;
-
- /// <summary>
- /// The count of entries inside this GPFIFO entry.
- /// </summary>
- public uint EntryCount;
-
- /// <summary>
- /// Get the entries for the command buffer from memory.
- /// </summary>
- /// <param name="memoryManager">The memory manager used to fetch the data</param>
- /// <param name="flush">If true, flushes potential GPU written data before reading the command buffer</param>
- /// <returns>The fetched data</returns>
- private ReadOnlySpan<int> GetWords(MemoryManager memoryManager, bool flush)
- {
- return MemoryMarshal.Cast<byte, int>(memoryManager.GetSpan(EntryAddress, (int)EntryCount * 4, flush));
- }
-
- /// <summary>
- /// Prefetch the command buffer.
- /// </summary>
- /// <param name="memoryManager">The memory manager used to fetch the data</param>
- public void Prefetch(MemoryManager memoryManager)
- {
- Words = GetWords(memoryManager, true).ToArray();
- }
-
- /// <summary>
- /// Fetch the command buffer.
- /// </summary>
- /// <param name="memoryManager">The memory manager used to fetch the data</param>
- /// <param name="flush">If true, flushes potential GPU written data before reading the command buffer</param>
- /// <returns>The command buffer words</returns>
- public ReadOnlySpan<int> Fetch(MemoryManager memoryManager, bool flush)
- {
- return Words ?? GetWords(memoryManager, flush);
- }
- }
-
- private readonly ConcurrentQueue<CommandBuffer> _commandBufferQueue;
-
- private CommandBuffer _currentCommandBuffer;
- private GPFifoProcessor _prevChannelProcessor;
-
- private readonly bool _ibEnable;
- private readonly GpuContext _context;
- private readonly AutoResetEvent _event;
-
- private bool _interrupt;
- private int _flushSkips;
-
- /// <summary>
- /// Creates a new instance of the GPU General Purpose FIFO device.
- /// </summary>
- /// <param name="context">GPU context that the GPFIFO belongs to</param>
- internal GPFifoDevice(GpuContext context)
- {
- _commandBufferQueue = new ConcurrentQueue<CommandBuffer>();
- _ibEnable = true;
- _context = context;
- _event = new AutoResetEvent(false);
- }
-
- /// <summary>
- /// Signal the FIFO that there are new entries to process.
- /// </summary>
- public void SignalNewEntries()
- {
- _event.Set();
- }
-
- /// <summary>
- /// Push a GPFIFO entry in the form of a prefetched command buffer.
- /// It is intended to be used by nvservices to handle special cases.
- /// </summary>
- /// <param name="processor">Processor used to process <paramref name="commandBuffer"/></param>
- /// <param name="commandBuffer">The command buffer containing the prefetched commands</param>
- internal void PushHostCommandBuffer(GPFifoProcessor processor, int[] commandBuffer)
- {
- _commandBufferQueue.Enqueue(new CommandBuffer
- {
- Processor = processor,
- Type = CommandBufferType.Prefetch,
- Words = commandBuffer,
- EntryAddress = ulong.MaxValue,
- EntryCount = (uint)commandBuffer.Length
- });
- }
-
- /// <summary>
- /// Create a CommandBuffer from a GPFIFO entry.
- /// </summary>
- /// <param name="processor">Processor used to process the command buffer pointed to by <paramref name="entry"/></param>
- /// <param name="entry">The GPFIFO entry</param>
- /// <returns>A new CommandBuffer based on the GPFIFO entry</returns>
- private static CommandBuffer CreateCommandBuffer(GPFifoProcessor processor, GPEntry entry)
- {
- CommandBufferType type = CommandBufferType.Prefetch;
-
- if (entry.Entry1Sync == Entry1Sync.Wait)
- {
- type = CommandBufferType.NoPrefetch;
- }
-
- ulong startAddress = ((ulong)entry.Entry0Get << 2) | ((ulong)entry.Entry1GetHi << 32);
-
- return new CommandBuffer
- {
- Processor = processor,
- Type = type,
- Words = null,
- EntryAddress = startAddress,
- EntryCount = (uint)entry.Entry1Length
- };
- }
-
- /// <summary>
- /// Pushes GPFIFO entries.
- /// </summary>
- /// <param name="processor">Processor used to process the command buffers pointed to by <paramref name="entries"/></param>
- /// <param name="entries">GPFIFO entries</param>
- internal void PushEntries(GPFifoProcessor processor, ReadOnlySpan<ulong> entries)
- {
- bool beforeBarrier = true;
-
- for (int index = 0; index < entries.Length; index++)
- {
- ulong entry = entries[index];
-
- CommandBuffer commandBuffer = CreateCommandBuffer(processor, Unsafe.As<ulong, GPEntry>(ref entry));
-
- if (beforeBarrier && commandBuffer.Type == CommandBufferType.Prefetch)
- {
- commandBuffer.Prefetch(processor.MemoryManager);
- }
-
- if (commandBuffer.Type == CommandBufferType.NoPrefetch)
- {
- beforeBarrier = false;
- }
-
- _commandBufferQueue.Enqueue(commandBuffer);
- }
- }
-
- /// <summary>
- /// Waits until commands are pushed to the FIFO.
- /// </summary>
- /// <returns>True if commands were received, false if wait timed out</returns>
- public bool WaitForCommands()
- {
- return !_commandBufferQueue.IsEmpty || (_event.WaitOne(8) && !_commandBufferQueue.IsEmpty);
- }
-
- /// <summary>
- /// Processes commands pushed to the FIFO.
- /// </summary>
- public void DispatchCalls()
- {
- // Use this opportunity to also dispose any pending channels that were closed.
- _context.RunDeferredActions();
-
- // Process command buffers.
- while (_ibEnable && !_interrupt && _commandBufferQueue.TryDequeue(out CommandBuffer entry))
- {
- bool flushCommandBuffer = true;
-
- if (_flushSkips != 0)
- {
- _flushSkips--;
- flushCommandBuffer = false;
- }
-
- _currentCommandBuffer = entry;
- ReadOnlySpan<int> words = entry.Fetch(entry.Processor.MemoryManager, flushCommandBuffer);
-
- // If we are changing the current channel,
- // we need to force all the host state to be updated.
- if (_prevChannelProcessor != entry.Processor)
- {
- _prevChannelProcessor = entry.Processor;
- entry.Processor.ForceAllDirty();
- }
-
- entry.Processor.Process(entry.EntryAddress, words);
- }
-
- _interrupt = false;
- }
-
- /// <summary>
- /// Sets the number of flushes that should be skipped for subsequent command buffers.
- /// </summary>
- /// <remarks>
- /// This can improve performance when command buffer data only needs to be consumed by the GPU.
- /// </remarks>
- /// <param name="count">The amount of flushes that should be skipped</param>
- internal void SetFlushSkips(int count)
- {
- _flushSkips = count;
- }
-
- /// <summary>
- /// Interrupts command processing. This will break out of the DispatchCalls loop.
- /// </summary>
- public void Interrupt()
- {
- _interrupt = true;
- }
-
- /// <summary>
- /// Disposes of resources used for GPFifo command processing.
- /// </summary>
- public void Dispose() => _event.Dispose();
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
deleted file mode 100644
index 3fb3feee..00000000
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
+++ /dev/null
@@ -1,331 +0,0 @@
-using Ryujinx.Graphics.Device;
-using Ryujinx.Graphics.Gpu.Engine.Compute;
-using Ryujinx.Graphics.Gpu.Engine.Dma;
-using Ryujinx.Graphics.Gpu.Engine.InlineToMemory;
-using Ryujinx.Graphics.Gpu.Engine.Threed;
-using Ryujinx.Graphics.Gpu.Engine.Twod;
-using Ryujinx.Graphics.Gpu.Memory;
-using System;
-using System.Runtime.CompilerServices;
-
-namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
-{
- /// <summary>
- /// Represents a GPU General Purpose FIFO command processor.
- /// </summary>
- class GPFifoProcessor
- {
- private const int MacrosCount = 0x80;
- private const int MacroIndexMask = MacrosCount - 1;
-
- private const int LoadInlineDataMethodOffset = 0x6d;
- private const int UniformBufferUpdateDataMethodOffset = 0x8e4;
-
- private readonly GpuChannel _channel;
-
- /// <summary>
- /// Channel memory manager.
- /// </summary>
- public MemoryManager MemoryManager => _channel.MemoryManager;
-
- /// <summary>
- /// 3D Engine.
- /// </summary>
- public ThreedClass ThreedClass => _3dClass;
-
- /// <summary>
- /// Internal GPFIFO state.
- /// </summary>
- private struct DmaState
- {
- public int Method;
- public int SubChannel;
- public int MethodCount;
- public bool NonIncrementing;
- public bool IncrementOnce;
- }
-
- private DmaState _state;
-
- private readonly ThreedClass _3dClass;
- private readonly ComputeClass _computeClass;
- private readonly InlineToMemoryClass _i2mClass;
- private readonly TwodClass _2dClass;
- private readonly DmaClass _dmaClass;
-
- private readonly GPFifoClass _fifoClass;
-
- /// <summary>
- /// Creates a new instance of the GPU General Purpose FIFO command processor.
- /// </summary>
- /// <param name="context">GPU context</param>
- /// <param name="channel">Channel that the GPFIFO processor belongs to</param>
- public GPFifoProcessor(GpuContext context, GpuChannel channel)
- {
- _channel = channel;
-
- _fifoClass = new GPFifoClass(context, this);
- _3dClass = new ThreedClass(context, channel, _fifoClass);
- _computeClass = new ComputeClass(context, channel, _3dClass);
- _i2mClass = new InlineToMemoryClass(context, channel);
- _2dClass = new TwodClass(channel);
- _dmaClass = new DmaClass(context, channel, _3dClass);
- }
-
- /// <summary>
- /// Processes a command buffer.
- /// </summary>
- /// <param name="baseGpuVa">Base GPU virtual address of the command buffer</param>
- /// <param name="commandBuffer">Command buffer</param>
- public void Process(ulong baseGpuVa, ReadOnlySpan<int> commandBuffer)
- {
- for (int index = 0; index < commandBuffer.Length; index++)
- {
- int command = commandBuffer[index];
-
- ulong gpuVa = baseGpuVa + (ulong)index * 4;
-
- if (_state.MethodCount != 0)
- {
- if (TryFastI2mBufferUpdate(commandBuffer, ref index))
- {
- continue;
- }
-
- Send(gpuVa, _state.Method, command, _state.SubChannel, _state.MethodCount <= 1);
-
- if (!_state.NonIncrementing)
- {
- _state.Method++;
- }
-
- if (_state.IncrementOnce)
- {
- _state.NonIncrementing = true;
- }
-
- _state.MethodCount--;
- }
- else
- {
- CompressedMethod meth = Unsafe.As<int, CompressedMethod>(ref command);
-
- if (TryFastUniformBufferUpdate(meth, commandBuffer, index))
- {
- index += meth.MethodCount;
- continue;
- }
-
- switch (meth.SecOp)
- {
- case SecOp.IncMethod:
- case SecOp.NonIncMethod:
- case SecOp.OneInc:
- _state.Method = meth.MethodAddress;
- _state.SubChannel = meth.MethodSubchannel;
- _state.MethodCount = meth.MethodCount;
- _state.IncrementOnce = meth.SecOp == SecOp.OneInc;
- _state.NonIncrementing = meth.SecOp == SecOp.NonIncMethod;
- break;
- case SecOp.ImmdDataMethod:
- Send(gpuVa, meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, true);
- break;
- }
- }
- }
-
- _3dClass.FlushUboDirty();
- }
-
- /// <summary>
- /// Tries to perform a fast Inline-to-Memory data update.
- /// If successful, all data will be copied at once, and <see cref="DmaState.MethodCount"/>
- /// command buffer entries will be consumed.
- /// </summary>
- /// <param name="commandBuffer">Command buffer where the data is contained</param>
- /// <param name="offset">Offset at <paramref name="commandBuffer"/> where the data is located, auto-incremented on success</param>
- /// <returns>True if the fast copy was successful, false otherwise</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private bool TryFastI2mBufferUpdate(ReadOnlySpan<int> commandBuffer, ref int offset)
- {
- if (_state.Method == LoadInlineDataMethodOffset && _state.NonIncrementing && _state.SubChannel <= 2)
- {
- int availableCount = commandBuffer.Length - offset;
- int consumeCount = Math.Min(_state.MethodCount, availableCount);
-
- var data = commandBuffer.Slice(offset, consumeCount);
-
- if (_state.SubChannel == 0)
- {
- _3dClass.LoadInlineData(data);
- }
- else if (_state.SubChannel == 1)
- {
- _computeClass.LoadInlineData(data);
- }
- else /* if (_state.SubChannel == 2) */
- {
- _i2mClass.LoadInlineData(data);
- }
-
- offset += consumeCount - 1;
- _state.MethodCount -= consumeCount;
-
- return true;
- }
-
- return false;
- }
-
- /// <summary>
- /// Tries to perform a fast constant buffer data update.
- /// If successful, all data will be copied at once, and <see cref="CompressedMethod.MethodCount"/> + 1
- /// command buffer entries will be consumed.
- /// </summary>
- /// <param name="meth">Compressed method to be checked</param>
- /// <param name="commandBuffer">Command buffer where <paramref name="meth"/> is contained</param>
- /// <param name="offset">Offset at <paramref name="commandBuffer"/> where <paramref name="meth"/> is located</param>
- /// <returns>True if the fast copy was successful, false otherwise</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private bool TryFastUniformBufferUpdate(CompressedMethod meth, ReadOnlySpan<int> commandBuffer, int offset)
- {
- int availableCount = commandBuffer.Length - offset;
-
- if (meth.MethodAddress == UniformBufferUpdateDataMethodOffset &&
- meth.MethodCount < availableCount &&
- meth.SecOp == SecOp.NonIncMethod)
- {
- _3dClass.ConstantBufferUpdate(commandBuffer.Slice(offset + 1, meth.MethodCount));
-
- return true;
- }
-
- return false;
- }
-
- /// <summary>
- /// Sends a uncompressed method for processing by the graphics pipeline.
- /// </summary>
- /// <param name="gpuVa">GPU virtual address where the command word is located</param>
- /// <param name="meth">Method to be processed</param>
- private void Send(ulong gpuVa, int offset, int argument, int subChannel, bool isLastCall)
- {
- if (offset < 0x60)
- {
- _fifoClass.Write(offset * 4, argument);
- }
- else if (offset < 0xe00)
- {
- offset *= 4;
-
- switch (subChannel)
- {
- case 0:
- _3dClass.Write(offset, argument);
- break;
- case 1:
- _computeClass.Write(offset, argument);
- break;
- case 2:
- _i2mClass.Write(offset, argument);
- break;
- case 3:
- _2dClass.Write(offset, argument);
- break;
- case 4:
- _dmaClass.Write(offset, argument);
- break;
- }
- }
- else
- {
- IDeviceState state = subChannel switch
- {
- 0 => _3dClass,
- 3 => _2dClass,
- _ => null
- };
-
- if (state != null)
- {
- int macroIndex = (offset >> 1) & MacroIndexMask;
-
- if ((offset & 1) != 0)
- {
- _fifoClass.MmePushArgument(macroIndex, gpuVa, argument);
- }
- else
- {
- _fifoClass.MmeStart(macroIndex, argument);
- }
-
- if (isLastCall)
- {
- _fifoClass.CallMme(macroIndex, state);
-
- _3dClass.PerformDeferredDraws();
- }
- }
- }
- }
-
- /// <summary>
- /// Writes data directly to the state of the specified class.
- /// </summary>
- /// <param name="classId">ID of the class to write the data into</param>
- /// <param name="offset">State offset in bytes</param>
- /// <param name="value">Value to be written</param>
- public void Write(ClassId classId, int offset, int value)
- {
- switch (classId)
- {
- case ClassId.Threed:
- _3dClass.Write(offset, value);
- break;
- case ClassId.Compute:
- _computeClass.Write(offset, value);
- break;
- case ClassId.InlineToMemory:
- _i2mClass.Write(offset, value);
- break;
- case ClassId.Twod:
- _2dClass.Write(offset, value);
- break;
- case ClassId.Dma:
- _dmaClass.Write(offset, value);
- break;
- case ClassId.GPFifo:
- _fifoClass.Write(offset, value);
- break;
- }
- }
-
- /// <summary>
- /// Sets the shadow ram control value of all sub-channels.
- /// </summary>
- /// <param name="control">New shadow ram control value</param>
- public void SetShadowRamControl(int control)
- {
- _3dClass.SetShadowRamControl(control);
- }
-
- /// <summary>
- /// Forces a full host state update by marking all state as modified,
- /// and also requests all GPU resources in use to be rebound.
- /// </summary>
- public void ForceAllDirty()
- {
- _3dClass.ForceStateDirty();
- _channel.BufferManager.Rebind();
- _channel.TextureManager.Rebind();
- }
-
- /// <summary>
- /// Perform any deferred draws.
- /// </summary>
- public void PerformDeferredDraws()
- {
- _3dClass.PerformDeferredDraws();
- }
- }
-}