diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2021-07-07 20:56:06 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-07 20:56:06 -0300 |
| commit | 8b44eb1c981d7106be37107755c7c71c3c3c0ce4 (patch) | |
| tree | 70c3a8d7286d827941c41dee2ec3cb3273c1e6d7 /Ryujinx.Graphics.Gpu/Engine/InlineToMemory | |
| parent | 31cbd09a75a9d5f4814c3907a060e0961eb2bb15 (diff) | |
Separate GPU engines and make state follow official docs (part 1/2) (#2422)
* Use DeviceState for compute and i2m
* Migrate 2D class, more comments
* Migrate DMA copy engine
* Remove now unused code
* Replace GpuState by GpuAccessorState on GpuAcessor, since compute no longer has a GpuState
* More comments
* Add logging (disabled)
* Add back i2m on 3D engine
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/InlineToMemory')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs | 211 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClassState.cs | 181 |
2 files changed, 392 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs b/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs new file mode 100644 index 00000000..0e7d6fb0 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs @@ -0,0 +1,211 @@ +using Ryujinx.Common; +using Ryujinx.Graphics.Device; +using Ryujinx.Graphics.Texture; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory +{ + /// <summary> + /// Represents a Inline-to-Memory engine class. + /// </summary> + class InlineToMemoryClass : IDeviceState + { + private readonly GpuContext _context; + private readonly GpuChannel _channel; + private readonly DeviceState<InlineToMemoryClassState> _state; + + private bool _isLinear; + + private int _offset; + private int _size; + + private ulong _dstGpuVa; + private int _dstX; + private int _dstY; + private int _dstWidth; + private int _dstHeight; + private int _dstStride; + private int _dstGobBlocksInY; + private int _lineLengthIn; + private int _lineCount; + + private bool _finished; + + private int[] _buffer; + + /// <summary> + /// Creates a new instance of the Inline-to-Memory engine class. + /// </summary> + /// <param name="context">GPU context</param> + /// <param name="channel">GPU channel</param> + /// <param name="initializeState">Indicates if the internal state should be initialized. Set to false if part of another engine</param> + protected InlineToMemoryClass(GpuContext context, GpuChannel channel, bool initializeState) + { + _context = context; + _channel = channel; + + if (initializeState) + { + _state = new DeviceState<InlineToMemoryClassState>(new Dictionary<string, RwCallback> + { + { nameof(InlineToMemoryClassState.LaunchDma), new RwCallback(LaunchDma, null) }, + { nameof(InlineToMemoryClassState.LoadInlineData), new RwCallback(LoadInlineData, null) } + }); + } + } + + /// <summary> + /// Creates a new instance of the inline-to-memory engine class. + /// </summary> + /// <param name="context">GPU context</param> + /// <param name="channel">GPU channel</param> + public InlineToMemoryClass(GpuContext context, GpuChannel channel) : this(context, channel, true) + { + } + + /// <summary> + /// Reads data from the class registers. + /// </summary> + /// <param name="offset">Register byte offset</param> + /// <returns>Data at the specified offset</returns> + public virtual 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 virtual void Write(int offset, int data) => _state.Write(offset, data); + + /// <summary> + /// Launches Inline-to-Memory engine DMA copy. + /// </summary> + /// <param name="argument">Method call argument</param> + protected virtual void LaunchDma(int argument) + { + LaunchDma(ref _state.State, argument); + } + + /// <summary> + /// Launches Inline-to-Memory engine DMA copy. + /// </summary> + /// <param name="state">Current class state</param> + /// <param name="argument">Method call argument</param> + protected void LaunchDma(ref InlineToMemoryClassState state, int argument) + { + _isLinear = (argument & 1) != 0; + + _offset = 0; + _size = (int)(state.LineLengthIn * state.LineCount); + + int count = BitUtils.DivRoundUp(_size, 4); + + if (_buffer == null || _buffer.Length < count) + { + _buffer = new int[count]; + } + + ulong dstGpuVa = ((ulong)state.OffsetOutUpperValue << 32) | state.OffsetOut; + + ulong dstBaseAddress = _channel.MemoryManager.Translate(dstGpuVa); + + // Trigger read tracking, to flush any managed resources in the destination region. + _channel.MemoryManager.Physical.GetSpan(dstBaseAddress, _size, true); + + _dstGpuVa = dstGpuVa; + _dstX = state.SetDstOriginBytesXV; + _dstY = state.SetDstOriginSamplesYV; + _dstWidth = (int)state.SetDstWidth; + _dstHeight = (int)state.SetDstHeight; + _dstStride = (int)state.PitchOut; + _dstGobBlocksInY = 1 << (int)state.SetDstBlockSizeHeight; + _lineLengthIn = (int)state.LineLengthIn; + _lineCount = (int)state.LineCount; + + _finished = false; + } + + /// <summary> + /// Pushes a word of data to the Inline-to-Memory engine. + /// </summary> + /// <param name="argument">Method call argument</param> + protected void LoadInlineData(int argument) + { + if (!_finished) + { + _buffer[_offset++] = argument; + + if (_offset * 4 >= _size) + { + FinishTransfer(); + } + } + } + + /// <summary> + /// Performs actual copy of the inline data after the transfer is finished. + /// </summary> + private void FinishTransfer() + { + Span<byte> data = MemoryMarshal.Cast<int, byte>(_buffer).Slice(0, _size); + + if (_isLinear && _lineCount == 1) + { + ulong address = _channel.MemoryManager.Translate(_dstGpuVa); + + _channel.MemoryManager.Physical.Write(address, data); + } + else + { + var dstCalculator = new OffsetCalculator( + _dstWidth, + _dstHeight, + _dstStride, + _isLinear, + _dstGobBlocksInY, + 1); + + int srcOffset = 0; + + ulong dstBaseAddress = _channel.MemoryManager.Translate(_dstGpuVa); + + for (int y = _dstY; y < _dstY + _lineCount; y++) + { + int x1 = _dstX; + int x2 = _dstX + _lineLengthIn; + int x2Trunc = _dstX + BitUtils.AlignDown(_lineLengthIn, 16); + + int x; + + for (x = x1; x < x2Trunc; x += 16, srcOffset += 16) + { + int dstOffset = dstCalculator.GetOffset(x, y); + + ulong dstAddress = dstBaseAddress + (ulong)dstOffset; + + Span<byte> pixel = data.Slice(srcOffset, 16); + + _channel.MemoryManager.Physical.Write(dstAddress, pixel); + } + + for (; x < x2; x++, srcOffset++) + { + int dstOffset = dstCalculator.GetOffset(x, y); + + ulong dstAddress = dstBaseAddress + (ulong)dstOffset; + + Span<byte> pixel = data.Slice(srcOffset, 1); + + _channel.MemoryManager.Physical.Write(dstAddress, pixel); + } + } + } + + _finished = true; + + _context.AdvanceSequence(); + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClassState.cs b/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClassState.cs new file mode 100644 index 00000000..d0c82a5e --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClassState.cs @@ -0,0 +1,181 @@ +// This file was auto-generated from NVIDIA official Maxwell definitions. + +namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory +{ + /// <summary> + /// Notify type. + /// </summary> + enum NotifyType + { + WriteOnly = 0, + WriteThenAwaken = 1, + } + + /// <summary> + /// Width in GOBs of the destination texture. + /// </summary> + enum SetDstBlockSizeWidth + { + OneGob = 0, + } + + /// <summary> + /// Height in GOBs of the destination texture. + /// </summary> + enum SetDstBlockSizeHeight + { + OneGob = 0, + TwoGobs = 1, + FourGobs = 2, + EightGobs = 3, + SixteenGobs = 4, + ThirtytwoGobs = 5, + } + + /// <summary> + /// Depth in GOBs of the destination texture. + /// </summary> + enum SetDstBlockSizeDepth + { + OneGob = 0, + TwoGobs = 1, + FourGobs = 2, + EightGobs = 3, + SixteenGobs = 4, + ThirtytwoGobs = 5, + } + + /// <summary> + /// Memory layout of the destination texture. + /// </summary> + enum LaunchDmaDstMemoryLayout + { + Blocklinear = 0, + Pitch = 1, + } + + /// <summary> + /// DMA completion type. + /// </summary> + enum LaunchDmaCompletionType + { + FlushDisable = 0, + FlushOnly = 1, + ReleaseSemaphore = 2, + } + + /// <summary> + /// DMA interrupt type. + /// </summary> + enum LaunchDmaInterruptType + { + None = 0, + Interrupt = 1, + } + + /// <summary> + /// DMA semaphore structure size. + /// </summary> + enum LaunchDmaSemaphoreStructSize + { + FourWords = 0, + OneWord = 1, + } + + /// <summary> + /// DMA semaphore reduction operation. + /// </summary> + enum LaunchDmaReductionOp + { + RedAdd = 0, + RedMin = 1, + RedMax = 2, + RedInc = 3, + RedDec = 4, + RedAnd = 5, + RedOr = 6, + RedXor = 7, + } + + /// <summary> + /// DMA semaphore reduction format. + /// </summary> + enum LaunchDmaReductionFormat + { + Unsigned32 = 0, + Signed32 = 1, + } + + /// <summary> + /// Inline-to-Memory class state. + /// </summary> + unsafe struct InlineToMemoryClassState + { +#pragma warning disable CS0649 + public uint SetObject; + public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF); + public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F); + public fixed uint Reserved04[63]; + public uint NoOperation; + public uint SetNotifyA; + public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF); + public uint SetNotifyB; + public uint Notify; + public NotifyType NotifyType => (NotifyType)(Notify); + public uint WaitForIdle; + public fixed uint Reserved114[7]; + public uint SetGlobalRenderEnableA; + public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF); + public uint SetGlobalRenderEnableB; + public uint SetGlobalRenderEnableC; + public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7); + public uint SendGoIdle; + public uint PmTrigger; + public uint PmTriggerWfi; + public fixed uint Reserved148[2]; + public uint SetInstrumentationMethodHeader; + public uint SetInstrumentationMethodData; + public fixed uint Reserved158[10]; + public uint LineLengthIn; + public uint LineCount; + public uint OffsetOutUpper; + public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF); + public uint OffsetOut; + public uint PitchOut; + public uint SetDstBlockSize; + public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF); + public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF); + public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF); + public uint SetDstWidth; + public uint SetDstHeight; + public uint SetDstDepth; + public uint SetDstLayer; + public uint SetDstOriginBytesX; + public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF); + public uint SetDstOriginSamplesY; + public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF); + public uint LaunchDma; + public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1); + public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3); + public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3); + public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1); + public bool LaunchDmaReductionEnable => (LaunchDma & 0x2) != 0; + public LaunchDmaReductionOp LaunchDmaReductionOp => (LaunchDmaReductionOp)((LaunchDma >> 13) & 0x7); + public LaunchDmaReductionFormat LaunchDmaReductionFormat => (LaunchDmaReductionFormat)((LaunchDma >> 2) & 0x3); + public bool LaunchDmaSysmembarDisable => (LaunchDma & 0x40) != 0; + public uint LoadInlineData; + public fixed uint Reserved1B8[9]; + public uint SetI2mSemaphoreA; + public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF); + public uint SetI2mSemaphoreB; + public uint SetI2mSemaphoreC; + public fixed uint Reserved1E8[2]; + public uint SetI2mSpareNoop00; + public uint SetI2mSpareNoop01; + public uint SetI2mSpareNoop02; + public uint SetI2mSpareNoop03; + public fixed uint Reserved200[3200]; + public MmeShadowScratch SetMmeShadowScratch; +#pragma warning restore CS0649 + } +} |
