aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Engine/GPFifo
diff options
context:
space:
mode:
authormpnico <mpnico@gmail.com>2021-08-26 23:50:28 +0200
committerGitHub <noreply@github.com>2021-08-26 23:50:28 +0200
commit8e1adb95cf7f67b976f105f4cac26d3ff2986057 (patch)
treef56ee0f92495fc1bd1e307c3bd51a2d1240d197b /Ryujinx.Graphics.Gpu/Engine/GPFifo
parent5cab8ea4ad2388bd035150e79f241ae5df95ab3b (diff)
Add support for HLE macros and accelerate MultiDrawElementsIndirectCount #2 (#2557)
* Add support for HLE macros and accelerate MultiDrawElementsIndirectCount * Add missing barrier * Fix index buffer count * Add support check for each macro hle before use * Add missing xml doc Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/GPFifo')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs30
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs19
3 files changed, 46 insertions, 12 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
index 28822f4e..fe49b0f2 100644
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
@@ -161,6 +161,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <param name="argument">Method call argument</param>
public void SetReference(int argument)
{
+ _context.Renderer.Pipeline.CommandBufferBarrier();
+
_context.CreateHostSyncIfNeeded();
}
@@ -195,10 +197,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// Pushes an argument to a macro.
/// </summary>
/// <param name="index">Index of the macro</param>
+ /// <param name="gpuVa">GPU virtual address where the command word is located</param>
/// <param name="argument">Argument to be pushed to the macro</param>
- public void MmePushArgument(int index, int argument)
+ public void MmePushArgument(int index, ulong gpuVa, int argument)
{
- _macros[index].PushArgument(argument);
+ _macros[index].PushArgument(gpuVa, argument);
}
/// <summary>
@@ -208,7 +211,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <param name="argument">Initial argument passed to the macro</param>
public void MmeStart(int index, int argument)
{
- _macros[index].StartExecution(argument);
+ _macros[index].StartExecution(_context, _parent, _macroCode, argument);
}
/// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs
index ada3bc4b..b3de738d 100644
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs
@@ -54,11 +54,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <summary>
/// Fetch the command buffer.
/// </summary>
- public void Fetch(MemoryManager memoryManager)
+ /// <param name="flush">If true, flushes potential GPU written data before reading the command buffer</param>
+ public void Fetch(MemoryManager memoryManager, bool flush = true)
{
if (Words == null)
{
- Words = MemoryMarshal.Cast<byte, int>(memoryManager.GetSpan(EntryAddress, (int)EntryCount * 4, true)).ToArray();
+ Words = MemoryMarshal.Cast<byte, int>(memoryManager.GetSpan(EntryAddress, (int)EntryCount * 4, flush)).ToArray();
}
}
}
@@ -73,6 +74,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
private readonly AutoResetEvent _event;
private bool _interrupt;
+ private int _flushSkips;
/// <summary>
/// Creates a new instance of the GPU General Purpose FIFO device.
@@ -188,8 +190,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
// Process command buffers.
while (_ibEnable && !_interrupt && _commandBufferQueue.TryDequeue(out CommandBuffer entry))
{
+ bool flushCommandBuffer = true;
+
+ if (_flushSkips != 0)
+ {
+ _flushSkips--;
+ flushCommandBuffer = false;
+ }
+
_currentCommandBuffer = entry;
- _currentCommandBuffer.Fetch(entry.Processor.MemoryManager);
+ _currentCommandBuffer.Fetch(entry.Processor.MemoryManager, flushCommandBuffer);
// If we are changing the current channel,
// we need to force all the host state to be updated.
@@ -199,13 +209,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
entry.Processor.ForceAllDirty();
}
- entry.Processor.Process(_currentCommandBuffer.Words);
+ entry.Processor.Process(entry.EntryAddress, _currentCommandBuffer.Words);
}
_interrupt = false;
}
/// <summary>
+ /// Sets the number of flushes that should be skipped for subsequent command buffers.
+ /// </summary>
+ /// <remarks>
+ /// This can improve performance when command buffer data only needs to be consumed by the GPU.
+ /// </remarks>
+ /// <param name="count">The amount of flushes that should be skipped</param>
+ internal void SetFlushSkips(int count)
+ {
+ _flushSkips = count;
+ }
+
+ /// <summary>
/// Interrupts command processing. This will break out of the DispatchCalls loop.
/// </summary>
public void Interrupt()
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
index ea34d6cd..096b795c 100644
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
@@ -29,6 +29,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public MemoryManager MemoryManager => _channel.MemoryManager;
/// <summary>
+ /// 3D Engine.
+ /// </summary>
+ public ThreedClass ThreedClass => _3dClass;
+
+ /// <summary>
/// Internal GPFIFO state.
/// </summary>
private struct DmaState
@@ -70,13 +75,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <summary>
/// Processes a command buffer.
/// </summary>
+ /// <param name="baseGpuVa">Base GPU virtual address of the command buffer</param>
/// <param name="commandBuffer">Command buffer</param>
- public void Process(ReadOnlySpan<int> commandBuffer)
+ public void Process(ulong baseGpuVa, ReadOnlySpan<int> commandBuffer)
{
for (int index = 0; index < commandBuffer.Length; index++)
{
int command = commandBuffer[index];
+ ulong gpuVa = baseGpuVa + (ulong)index * 4;
+
if (_state.MethodCount != 0)
{
if (TryFastI2mBufferUpdate(commandBuffer, ref index))
@@ -84,7 +92,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
continue;
}
- Send(_state.Method, command, _state.SubChannel, _state.MethodCount <= 1);
+ Send(gpuVa, _state.Method, command, _state.SubChannel, _state.MethodCount <= 1);
if (!_state.NonIncrementing)
{
@@ -120,7 +128,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
_state.NonIncrementing = meth.SecOp == SecOp.NonIncMethod;
break;
case SecOp.ImmdDataMethod:
- Send(meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, true);
+ Send(gpuVa, meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, true);
break;
}
}
@@ -198,8 +206,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <summary>
/// Sends a uncompressed method for processing by the graphics pipeline.
/// </summary>
+ /// <param name="gpuVa">GPU virtual address where the command word is located</param>
/// <param name="meth">Method to be processed</param>
- private void Send(int offset, int argument, int subChannel, bool isLastCall)
+ private void Send(ulong gpuVa, int offset, int argument, int subChannel, bool isLastCall)
{
if (offset < 0x60)
{
@@ -243,7 +252,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
if ((offset & 1) != 0)
{
- _fifoClass.MmePushArgument(macroIndex, argument);
+ _fifoClass.MmePushArgument(macroIndex, gpuVa, argument);
}
else
{