diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2019-12-05 17:34:47 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | e25b7c9848b6ec486eb513297b5c536857665c7f (patch) | |
| tree | c1ccb6c58bed0f7ece835359516330104feb8f4d /Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs | |
| parent | 6a98c643cabeea25dc42e19fe475a687a034a532 (diff) | |
Initial support for the guest OpenGL driver (NVIDIA and Nouveau)
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs | 87 |
1 files changed, 81 insertions, 6 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs index 09de992f..8d1ebebe 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs @@ -1,5 +1,8 @@ +using Ryujinx.Common; using Ryujinx.Graphics.Gpu.State; +using Ryujinx.Graphics.Texture; using System; +using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Gpu.Engine { @@ -12,6 +15,10 @@ namespace Ryujinx.Graphics.Gpu.Engine private int _offset; private int _size; + private bool _finished; + + private int[] _buffer; + public void LaunchDma(GpuState state, int argument) { _params = state.Get<Inline2MemoryParams>(MethodOffset.I2mParams); @@ -20,23 +27,91 @@ namespace Ryujinx.Graphics.Gpu.Engine _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; } public void LoadInlineData(GpuState state, int argument) { - if (_isLinear) + if (!_finished) { - for (int shift = 0; shift < 32 && _offset < _size; shift += 8, _offset++) - { - ulong gpuVa = _params.DstAddress.Pack() + (ulong)_offset; + _buffer[_offset++] = argument; - _context.MemoryAccessor.Write(gpuVa, new byte[] { (byte)(argument >> shift) }); + if (_offset * 4 >= _size) + { + FinishTransfer(); } } + } + + 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 { - throw new NotImplementedException(); + 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; } } }
\ No newline at end of file |
