mirror of
https://github.com/GreemDev/Ryujinx
synced 2024-11-22 17:56:59 +01:00
Implement a fast path for I2M transfers (#2467)
This commit is contained in:
parent
9b08abc644
commit
04dce402ac
4 changed files with 88 additions and 3 deletions
|
@ -68,6 +68,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||||
_i2mClass.LaunchDma(ref Unsafe.As<ComputeClassState, InlineToMemoryClassState>(ref _state.State), argument);
|
_i2mClass.LaunchDma(ref Unsafe.As<ComputeClassState, InlineToMemoryClassState>(ref _state.State), argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes a block of data to the Inline-to-Memory engine.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Data to push</param>
|
||||||
|
public void LoadInlineData(ReadOnlySpan<int> data)
|
||||||
|
{
|
||||||
|
_i2mClass.LoadInlineData(data);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pushes a word of data to the Inline-to-Memory engine.
|
/// Pushes a word of data to the Inline-to-Memory engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||||
private const int MacrosCount = 0x80;
|
private const int MacrosCount = 0x80;
|
||||||
private const int MacroIndexMask = MacrosCount - 1;
|
private const int MacroIndexMask = MacrosCount - 1;
|
||||||
|
|
||||||
|
private const int LoadInlineDataMethodOffset = 0x6d;
|
||||||
private const int UniformBufferUpdateDataMethodOffset = 0x8e4;
|
private const int UniformBufferUpdateDataMethodOffset = 0x8e4;
|
||||||
|
|
||||||
private readonly GpuChannel _channel;
|
private readonly GpuChannel _channel;
|
||||||
|
@ -78,6 +79,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||||
|
|
||||||
if (_state.MethodCount != 0)
|
if (_state.MethodCount != 0)
|
||||||
{
|
{
|
||||||
|
if (TryFastI2mBufferUpdate(commandBuffer, ref index))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Send(_state.Method, command, _state.SubChannel, _state.MethodCount <= 1);
|
Send(_state.Method, command, _state.SubChannel, _state.MethodCount <= 1);
|
||||||
|
|
||||||
if (!_state.NonIncrementing)
|
if (!_state.NonIncrementing)
|
||||||
|
@ -123,6 +129,46 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||||
_3dClass.FlushUboDirty();
|
_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>
|
/// <summary>
|
||||||
/// Tries to perform a fast constant buffer data update.
|
/// Tries to perform a fast constant buffer data update.
|
||||||
/// If successful, all data will be copied at once, and <see cref="CompressedMethod.MethodCount"/> + 1
|
/// If successful, all data will be copied at once, and <see cref="CompressedMethod.MethodCount"/> + 1
|
||||||
|
@ -132,13 +178,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||||
/// <param name="commandBuffer">Command buffer where <paramref name="meth"/> is contained</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>
|
/// <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>
|
/// <returns>True if the fast copy was successful, false otherwise</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private bool TryFastUniformBufferUpdate(CompressedMethod meth, ReadOnlySpan<int> commandBuffer, int offset)
|
private bool TryFastUniformBufferUpdate(CompressedMethod meth, ReadOnlySpan<int> commandBuffer, int offset)
|
||||||
{
|
{
|
||||||
int availableCount = commandBuffer.Length - offset;
|
int availableCount = commandBuffer.Length - offset;
|
||||||
|
|
||||||
if (meth.MethodCount < availableCount &&
|
if (meth.MethodAddress == UniformBufferUpdateDataMethodOffset &&
|
||||||
meth.SecOp == SecOp.NonIncMethod &&
|
meth.MethodCount < availableCount &&
|
||||||
meth.MethodAddress == UniformBufferUpdateDataMethodOffset)
|
meth.SecOp == SecOp.NonIncMethod)
|
||||||
{
|
{
|
||||||
_3dClass.ConstantBufferUpdate(commandBuffer.Slice(offset + 1, meth.MethodCount));
|
_3dClass.ConstantBufferUpdate(commandBuffer.Slice(offset + 1, meth.MethodCount));
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,26 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||||
_finished = false;
|
_finished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes a block of data to the Inline-to-Memory engine.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Data to push</param>
|
||||||
|
public void LoadInlineData(ReadOnlySpan<int> data)
|
||||||
|
{
|
||||||
|
if (!_finished)
|
||||||
|
{
|
||||||
|
int copySize = Math.Min(data.Length, _buffer.Length - _offset);
|
||||||
|
data.Slice(0, copySize).CopyTo(new Span<int>(_buffer).Slice(_offset, copySize));
|
||||||
|
|
||||||
|
_offset += copySize;
|
||||||
|
|
||||||
|
if (_offset * 4 >= _size)
|
||||||
|
{
|
||||||
|
FinishTransfer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pushes a word of data to the Inline-to-Memory engine.
|
/// Pushes a word of data to the Inline-to-Memory engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -183,6 +183,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
_i2mClass.LaunchDma(ref Unsafe.As<ThreedClassState, InlineToMemoryClassState>(ref _state.State), argument);
|
_i2mClass.LaunchDma(ref Unsafe.As<ThreedClassState, InlineToMemoryClassState>(ref _state.State), argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes a block of data to the Inline-to-Memory engine.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Data to push</param>
|
||||||
|
public void LoadInlineData(ReadOnlySpan<int> data)
|
||||||
|
{
|
||||||
|
_i2mClass.LoadInlineData(data);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pushes a word of data to the Inline-to-Memory engine.
|
/// Pushes a word of data to the Inline-to-Memory engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue