aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Engine/GPFifo
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-07-11 17:20:40 -0300
committerGitHub <noreply@github.com>2021-07-11 17:20:40 -0300
commit40b21cc3c4d2622bbd4f88d43073341854d9a671 (patch)
tree6e9dc6a42e7c0bae5b03db468481771d5a6937ef /Ryujinx.Graphics.Gpu/Engine/GPFifo
parentb5190f16810eb77388c861d1d1773e19644808db (diff)
Separate GPU engines (part 2/2) (#2440)
* 3D engine now uses DeviceState too, plus new state modification tracking * Remove old methods code * Remove GpuState and friends * Optimize DeviceState, force inline some functions * This change was not supposed to go in * Proper channel initialization * Optimize state read/write methods even more * Fix debug build * Do not dirty state if the write is redundant * The YControl register should dirty either the viewport or front face state too, to update the host origin * Avoid redundant vertex buffer updates * Move state and get rid of the Ryujinx.Graphics.Gpu.State namespace * Comments and nits * Fix rebase * PR feedback * Move changed = false to improve codegen * PR feedback * Carry RyuJIT a bit more
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/GPFifo')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs7
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs176
2 files changed, 115 insertions, 68 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
index 75b19c37..28822f4e 100644
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs
@@ -1,6 +1,5 @@
using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Engine.MME;
-using Ryujinx.Graphics.Gpu.State;
using System;
using System.Collections.Generic;
using System.Threading;
@@ -150,7 +149,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <param name="argument">Method call argument</param>
public void WaitForIdle(int argument)
{
- _context.Methods.PerformDeferredDraws();
+ _parent.PerformDeferredDraws();
_context.Renderer.Pipeline.Barrier();
_context.CreateHostSyncIfNeeded();
@@ -189,7 +188,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <param name="argument">Method call argument</param>
public void SetMmeShadowRamControl(int argument)
{
- _parent.SetShadowRamControl((ShadowRamControl)argument);
+ _parent.SetShadowRamControl(argument);
}
/// <summary>
@@ -217,7 +216,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// </summary>
/// <param name="index">Index of the macro</param>
/// <param name="state">Current GPU state</param>
- public void CallMme(int index, GpuState state)
+ public void CallMme(int index, IDeviceState state)
{
_macros[index].Execute(_macroCode, state);
}
diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
index c2727f48..dd5e6fe5 100644
--- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoProcessor.cs
@@ -2,9 +2,9 @@
using Ryujinx.Graphics.Gpu.Engine.Compute;
using Ryujinx.Graphics.Gpu.Engine.Dma;
using Ryujinx.Graphics.Gpu.Engine.InlineToMemory;
+using Ryujinx.Graphics.Gpu.Engine.Threed;
using Ryujinx.Graphics.Gpu.Engine.Twod;
using Ryujinx.Graphics.Gpu.Memory;
-using Ryujinx.Graphics.Gpu.State;
using System;
using System.Runtime.CompilerServices;
@@ -18,9 +18,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
private const int MacrosCount = 0x80;
private const int MacroIndexMask = MacrosCount - 1;
- private readonly GpuContext _context;
+ private const int UniformBufferUpdateDataMethodOffset = 0x8e4;
+
private readonly GpuChannel _channel;
+ /// <summary>
+ /// Channel memory manager.
+ /// </summary>
public MemoryManager MemoryManager => _channel.MemoryManager;
/// <summary>
@@ -37,8 +41,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
private DmaState _state;
- private readonly GpuState[] _subChannels;
- private readonly IDeviceState[] _subChannels2;
+ private readonly ThreedClass _3dClass;
+ private readonly ComputeClass _computeClass;
+ private readonly InlineToMemoryClass _i2mClass;
+ private readonly TwodClass _2dClass;
+ private readonly DmaClass _dmaClass;
+
private readonly GPFifoClass _fifoClass;
/// <summary>
@@ -48,29 +56,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// <param name="channel">Channel that the GPFIFO processor belongs to</param>
public GPFifoProcessor(GpuContext context, GpuChannel channel)
{
- _context = context;
_channel = channel;
_fifoClass = new GPFifoClass(context, this);
- _subChannels = new GpuState[8];
- _subChannels2 = new IDeviceState[8]
- {
- null,
- new ComputeClass(context, channel),
- new InlineToMemoryClass(context, channel),
- new TwodClass(channel),
- new DmaClass(context, channel),
- null,
- null,
- null
- };
-
- for (int index = 0; index < _subChannels.Length; index++)
- {
- _subChannels[index] = new GpuState(channel, _subChannels2[index]);
-
- _context.Methods.RegisterCallbacks(_subChannels[index]);
- }
+ _3dClass = new ThreedClass(context, channel);
+ _computeClass = new ComputeClass(context, channel, _3dClass);
+ _i2mClass = new InlineToMemoryClass(context, channel);
+ _2dClass = new TwodClass(channel);
+ _dmaClass = new DmaClass(context, channel, _3dClass);
}
/// <summary>
@@ -85,7 +78,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
if (_state.MethodCount != 0)
{
- Send(new MethodParams(_state.Method, command, _state.SubChannel, _state.MethodCount));
+ Send(_state.Method, command, _state.SubChannel, _state.MethodCount <= 1);
if (!_state.NonIncrementing)
{
@@ -121,13 +114,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
_state.NonIncrementing = meth.SecOp == SecOp.NonIncMethod;
break;
case SecOp.ImmdDataMethod:
- Send(new MethodParams(meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, 1));
+ Send(meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, true);
break;
}
}
}
- _context.Methods.FlushUboDirty(MemoryManager);
+ _3dClass.FlushUboDirty();
}
/// <summary>
@@ -145,11 +138,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
if (meth.MethodCount < availableCount &&
meth.SecOp == SecOp.NonIncMethod &&
- meth.MethodAddress == (int)MethodOffset.UniformBufferUpdateData)
+ meth.MethodAddress == UniformBufferUpdateDataMethodOffset)
{
- GpuState state = _subChannels[meth.MethodSubchannel];
-
- _context.Methods.UniformBufferUpdate(state, commandBuffer.Slice(offset + 1, meth.MethodCount));
+ _3dClass.ConstantBufferUpdate(commandBuffer.Slice(offset + 1, meth.MethodCount));
return true;
}
@@ -161,67 +152,124 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
/// Sends a uncompressed method for processing by the graphics pipeline.
/// </summary>
/// <param name="meth">Method to be processed</param>
- private void Send(MethodParams meth)
+ private void Send(int offset, int argument, int subChannel, bool isLastCall)
{
- if ((MethodOffset)meth.Method == MethodOffset.BindChannel)
- {
- _subChannels[meth.SubChannel].ClearCallbacks();
-
- _context.Methods.RegisterCallbacks(_subChannels[meth.SubChannel]);
- }
- else if (meth.Method < 0x60)
- {
- // TODO: check if macros are shared between subchannels or not. For now let's assume they are.
- _fifoClass.Write(meth.Method * 4, meth.Argument);
- }
- else if (meth.Method < 0xe00)
+ if (offset < 0x60)
{
- _subChannels[meth.SubChannel].CallMethod(meth);
+ _fifoClass.Write(offset * 4, argument);
}
- else
+ else if (offset < 0xe00)
{
- int macroIndex = (meth.Method >> 1) & MacroIndexMask;
+ offset *= 4;
- if ((meth.Method & 1) != 0)
+ switch (subChannel)
{
- _fifoClass.MmePushArgument(macroIndex, meth.Argument);
+ case 0:
+ _3dClass.Write(offset, argument);
+ break;
+ case 1:
+ _computeClass.Write(offset, argument);
+ break;
+ case 2:
+ _i2mClass.Write(offset, argument);
+ break;
+ case 3:
+ _2dClass.Write(offset, argument);
+ break;
+ case 4:
+ _dmaClass.Write(offset, argument);
+ break;
}
- else
+ }
+ else
+ {
+ IDeviceState state = subChannel switch
{
- _fifoClass.MmeStart(macroIndex, meth.Argument);
- }
+ 0 => _3dClass,
+ 3 => _2dClass,
+ _ => null
+ };
- if (meth.IsLastCall)
+ if (state != null)
{
- _fifoClass.CallMme(macroIndex, _subChannels[meth.SubChannel]);
+ int macroIndex = (offset >> 1) & MacroIndexMask;
+
+ if ((offset & 1) != 0)
+ {
+ _fifoClass.MmePushArgument(macroIndex, argument);
+ }
+ else
+ {
+ _fifoClass.MmeStart(macroIndex, argument);
+ }
- _context.Methods.PerformDeferredDraws();
+ if (isLastCall)
+ {
+ _fifoClass.CallMme(macroIndex, state);
+
+ _3dClass.PerformDeferredDraws();
+ }
}
}
}
/// <summary>
- /// Sets the shadow ram control value of all sub-channels.
+ /// Writes data directly to the state of the specified class.
/// </summary>
- /// <param name="control">New shadow ram control value</param>
- public void SetShadowRamControl(ShadowRamControl control)
+ /// <param name="classId">ID of the class to write the data into</param>
+ /// <param name="offset">State offset in bytes</param>
+ /// <param name="value">Value to be written</param>
+ public void Write(ClassId classId, int offset, int value)
{
- for (int i = 0; i < _subChannels.Length; i++)
+ switch (classId)
{
- _subChannels[i].ShadowRamControl = control;
+ case ClassId.Threed:
+ _3dClass.Write(offset, value);
+ break;
+ case ClassId.Compute:
+ _computeClass.Write(offset, value);
+ break;
+ case ClassId.InlineToMemory:
+ _i2mClass.Write(offset, value);
+ break;
+ case ClassId.Twod:
+ _2dClass.Write(offset, value);
+ break;
+ case ClassId.Dma:
+ _dmaClass.Write(offset, value);
+ break;
+ case ClassId.GPFifo:
+ _fifoClass.Write(offset, value);
+ break;
}
}
/// <summary>
+ /// Sets the shadow ram control value of all sub-channels.
+ /// </summary>
+ /// <param name="control">New shadow ram control value</param>
+ public void SetShadowRamControl(int control)
+ {
+ _3dClass.SetShadowRamControl(control);
+ }
+
+ /// <summary>
/// Forces a full host state update by marking all state as modified,
/// and also requests all GPU resources in use to be rebound.
/// </summary>
public void ForceAllDirty()
{
- for (int index = 0; index < _subChannels.Length; index++)
- {
- _subChannels[index].ForceAllDirty();
- }
+ _3dClass.ForceStateDirty();
+ _channel.BufferManager.Rebind();
+ _channel.TextureManager.Rebind();
+ }
+
+ /// <summary>
+ /// Perform any deferred draws.
+ /// </summary>
+ public void PerformDeferredDraws()
+ {
+ _3dClass.PerformDeferredDraws();
}
}
}