| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- using Ryujinx.Common;
- using Ryujinx.Graphics.Gpu.State;
- using Ryujinx.Graphics.Texture;
- using System;
- using System.Runtime.InteropServices;
- namespace Ryujinx.Graphics.Gpu.Engine
- {
- partial class Methods
- {
- private Inline2MemoryParams _params;
- private bool _isLinear;
- private int _offset;
- private int _size;
- private bool _finished;
- private int[] _buffer;
- /// <summary>
- /// Launches Inline-to-Memory engine DMA copy.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- public void LaunchDma(GpuState state, int argument)
- {
- _params = state.Get<Inline2MemoryParams>(MethodOffset.I2mParams);
- _isLinear = (argument & 1) != 0;
- _offset = 0;
- _size = _params.LineLengthIn * _params.LineCount;
- int count = BitUtils.DivRoundUp(_size, 4);
- if (_buffer == null || _buffer.Length < count)
- {
- _buffer = new int[count];
- }
- ulong dstBaseAddress = _context.MemoryManager.Translate(_params.DstAddress.Pack());
- _context.Methods.TextureManager.Flush(dstBaseAddress, (ulong)_size);
- _finished = false;
- }
- /// <summary>
- /// Pushes a word of data to the Inline-to-Memory engine.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- public void LoadInlineData(GpuState state, 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 && _params.LineCount == 1)
- {
- ulong address = _context.MemoryManager.Translate( _params.DstAddress.Pack());
- _context.PhysicalMemory.Write(address, data);
- }
- else
- {
- var dstCalculator = new OffsetCalculator(
- _params.DstWidth,
- _params.DstHeight,
- _params.DstStride,
- _isLinear,
- _params.DstMemoryLayout.UnpackGobBlocksInY(),
- 1);
- int srcOffset = 0;
- ulong dstBaseAddress = _context.MemoryManager.Translate(_params.DstAddress.Pack());
- for (int y = _params.DstY; y < _params.DstY + _params.LineCount; y++)
- {
- int x1 = _params.DstX;
- int x2 = _params.DstX + _params.LineLengthIn;
- int x2Trunc = _params.DstX + BitUtils.AlignDown(_params.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);
- _context.PhysicalMemory.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);
- _context.PhysicalMemory.Write(dstAddress, pixel);
- }
- }
- }
- _finished = true;
- }
- }
- }
|