Implement GPU syncpoints (#980)
* Implement GPU syncpoints This adds support for GPU syncpoints on the GPU backend & nvservices. Everything that was implemented here is based on my researches, hardware testing of the GM20B and reversing of nvservices (8.1.0). Thanks to @fincs for the informations about some behaviours of the pusher and for the initial informations about syncpoints. * syncpoint: address gdkchan's comments * Add some missing logic to handle SubmitGpfifo correctly * Handle the NV event API correctly * evnt => hostEvent * Finish addressing gdkchan's comments * nvservices: write the output buffer even when an error is returned * dma pusher: Implemnet prefetch barrier lso fix when the commands should be prefetch. * Partially fix prefetch barrier * Add a missing syncpoint check in QueryEvent of NvHostSyncPt * Address Ac_K's comments and fix GetSyncpoint for ChannelResourcePolicy == Channel * fix SyncptWait & SyncptWaitEx cmds logic * Address ripinperi's comments * Address gdkchan's comments * Move user event management to the control channel * Fix mm implementation, nvdec works again * Address ripinperi's comments * Address gdkchan's comments * Implement nvhost-ctrl close accurately + make nvservices dispose channels when stopping the emulator * Fix typo in MultiMediaOperationType
This commit is contained in:
parent
4960ab85f8
commit
644de99e86
37 changed files with 1576 additions and 386 deletions
|
@ -123,6 +123,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||
|
||||
private SubChannel[] _subChannels;
|
||||
|
||||
private SubChannel _fifoChannel;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the GPU commands FIFO.
|
||||
/// </summary>
|
||||
|
@ -135,76 +137,68 @@ namespace Ryujinx.Graphics.Gpu
|
|||
|
||||
_mme = new int[MmeWords];
|
||||
|
||||
_fifoChannel = new SubChannel();
|
||||
|
||||
_context.Methods.RegisterCallbacksForFifo(_fifoChannel.State);
|
||||
|
||||
_subChannels = new SubChannel[8];
|
||||
|
||||
for (int index = 0; index < _subChannels.Length; index++)
|
||||
{
|
||||
_subChannels[index] = new SubChannel();
|
||||
|
||||
context.Methods.RegisterCallbacks(_subChannels[index].State);
|
||||
_context.Methods.RegisterCallbacks(_subChannels[index].State);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send macro code/data to the MME
|
||||
/// </summary>
|
||||
/// <param name="index">The index in the MME</param>
|
||||
/// <param name="data">The data to use</param>
|
||||
public void SendMacroCodeData(int index, int data)
|
||||
{
|
||||
_mme[index] = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bind a macro index to a position for the MME
|
||||
/// </summary>
|
||||
/// <param name="index">The macro index</param>
|
||||
/// <param name="position">The position of the macro</param>
|
||||
public void BindMacro(int index, int position)
|
||||
{
|
||||
_macros[index] = new CachedMacro(position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change the shadow RAM setting
|
||||
/// </summary>
|
||||
/// <param name="shadowCtrl">The new Shadow RAM setting</param>
|
||||
public void SetMmeShadowRamControl(ShadowRamControl shadowCtrl)
|
||||
{
|
||||
_shadowCtrl = shadowCtrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls a GPU method.
|
||||
/// </summary>
|
||||
/// <param name="meth">GPU method call parameters</param>
|
||||
public void CallMethod(MethodParams meth)
|
||||
{
|
||||
if ((NvGpuFifoMeth)meth.Method == NvGpuFifoMeth.BindChannel)
|
||||
if ((MethodOffset)meth.Method == MethodOffset.BindChannel)
|
||||
{
|
||||
_subChannels[meth.SubChannel].Class = (ClassId)meth.Argument;
|
||||
_subChannels[meth.SubChannel] = new SubChannel
|
||||
{
|
||||
Class = (ClassId)meth.Argument
|
||||
};
|
||||
|
||||
_context.Methods.RegisterCallbacks(_subChannels[meth.SubChannel].State);
|
||||
}
|
||||
else if (meth.Method < 0x60)
|
||||
{
|
||||
switch ((NvGpuFifoMeth)meth.Method)
|
||||
{
|
||||
case NvGpuFifoMeth.WaitForIdle:
|
||||
{
|
||||
_context.Methods.PerformDeferredDraws();
|
||||
|
||||
_context.Renderer.Pipeline.Barrier();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NvGpuFifoMeth.SetMacroUploadAddress:
|
||||
{
|
||||
_currMacroPosition = meth.Argument;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NvGpuFifoMeth.SendMacroCodeData:
|
||||
{
|
||||
_mme[_currMacroPosition++] = meth.Argument;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NvGpuFifoMeth.SetMacroBindingIndex:
|
||||
{
|
||||
_currMacroBindIndex = meth.Argument;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NvGpuFifoMeth.BindMacro:
|
||||
{
|
||||
int position = meth.Argument;
|
||||
|
||||
_macros[_currMacroBindIndex++] = new CachedMacro(position);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NvGpuFifoMeth.SetMmeShadowRamControl:
|
||||
{
|
||||
_shadowCtrl = (ShadowRamControl)meth.Argument;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO: check if macros are shared between subchannels or not. For now let's assume they are.
|
||||
_fifoChannel.State.CallMethod(meth);
|
||||
}
|
||||
else if (meth.Method < 0xe00)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue