* 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>
This commit is contained in:
parent
5cab8ea4ad
commit
8e1adb95cf
22 changed files with 552 additions and 40 deletions
|
@ -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>
|
||||
|
|
|
@ -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,12 +209,24 @@ 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>
|
||||
|
|
|
@ -28,6 +28,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
|||
/// </summary>
|
||||
public MemoryManager MemoryManager => _channel.MemoryManager;
|
||||
|
||||
/// <summary>
|
||||
/// 3D Engine.
|
||||
/// </summary>
|
||||
public ThreedClass ThreedClass => _3dClass;
|
||||
|
||||
/// <summary>
|
||||
/// Internal GPFIFO state.
|
||||
/// </summary>
|
||||
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue