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/Engine/GPFifo | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/GPFifo')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/GPFifo/CompressedMethod.cs | 41 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/GPFifo/GPEntry.cs | 55 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs | 248 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClassState.cs | 233 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs | 262 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs | 331 |
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(); - } - } -} |
