aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-12-05 17:34:47 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commite25b7c9848b6ec486eb513297b5c536857665c7f (patch)
treec1ccb6c58bed0f7ece835359516330104feb8f4d /Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs
parent6a98c643cabeea25dc42e19fe475a687a034a532 (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.cs87
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