2018-09-08 10:51:50 -07:00
|
|
|
using Ryujinx.Graphics.Memory;
|
2018-04-08 12:17:35 -07:00
|
|
|
using System.Collections.Concurrent;
|
2018-07-12 10:03:52 -07:00
|
|
|
using System.Threading;
|
2018-04-08 12:17:35 -07:00
|
|
|
|
2018-09-08 10:51:50 -07:00
|
|
|
namespace Ryujinx.Graphics
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
2018-09-08 10:51:50 -07:00
|
|
|
public class NvGpuFifo
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
|
|
|
private const int MacrosCount = 0x80;
|
|
|
|
private const int MacroIndexMask = MacrosCount - 1;
|
|
|
|
|
2018-06-17 21:32:11 -07:00
|
|
|
//Note: The size of the macro memory is unknown, we just make
|
|
|
|
//a guess here and use 256kb as the size. Increase if needed.
|
|
|
|
private const int MmeWords = 256 * 256;
|
|
|
|
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
private NvGpu Gpu;
|
2018-04-08 12:17:35 -07:00
|
|
|
|
2018-08-14 18:27:05 -07:00
|
|
|
private ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry[])> BufferQueue;
|
2018-04-08 12:17:35 -07:00
|
|
|
|
|
|
|
private NvGpuEngine[] SubChannels;
|
|
|
|
|
2018-07-12 10:03:52 -07:00
|
|
|
public AutoResetEvent Event { get; private set; }
|
|
|
|
|
2018-04-08 12:17:35 -07:00
|
|
|
private struct CachedMacro
|
|
|
|
{
|
2018-06-17 21:32:11 -07:00
|
|
|
public int Position { get; private set; }
|
2018-04-08 12:17:35 -07:00
|
|
|
|
|
|
|
private MacroInterpreter Interpreter;
|
|
|
|
|
2018-06-17 21:32:11 -07:00
|
|
|
public CachedMacro(NvGpuFifo PFifo, INvGpuEngine Engine, int Position)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
|
|
|
this.Position = Position;
|
|
|
|
|
|
|
|
Interpreter = new MacroInterpreter(PFifo, Engine);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void PushParam(int Param)
|
|
|
|
{
|
|
|
|
Interpreter?.Fifo.Enqueue(Param);
|
|
|
|
}
|
|
|
|
|
2018-06-17 21:32:11 -07:00
|
|
|
public void Execute(NvGpuVmm Vmm, int[] Mme, int Param)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
2018-06-17 21:32:11 -07:00
|
|
|
Interpreter?.Execute(Vmm, Mme, Position, Param);
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-17 21:32:11 -07:00
|
|
|
private int CurrMacroPosition;
|
|
|
|
private int CurrMacroBindIndex;
|
2018-04-08 12:17:35 -07:00
|
|
|
|
|
|
|
private CachedMacro[] Macros;
|
|
|
|
|
2018-06-17 21:32:11 -07:00
|
|
|
private int[] Mme;
|
|
|
|
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
public NvGpuFifo(NvGpu Gpu)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
|
|
|
this.Gpu = Gpu;
|
|
|
|
|
2018-08-14 18:27:05 -07:00
|
|
|
BufferQueue = new ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry[])>();
|
2018-04-08 12:17:35 -07:00
|
|
|
|
|
|
|
SubChannels = new NvGpuEngine[8];
|
|
|
|
|
|
|
|
Macros = new CachedMacro[MacrosCount];
|
2018-06-17 21:32:11 -07:00
|
|
|
|
|
|
|
Mme = new int[MmeWords];
|
2018-07-12 10:03:52 -07:00
|
|
|
|
|
|
|
Event = new AutoResetEvent(false);
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
2018-08-14 18:27:05 -07:00
|
|
|
BufferQueue.Enqueue((Vmm, Buffer));
|
2018-07-12 10:03:52 -07:00
|
|
|
|
|
|
|
Event.Set();
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public void DispatchCalls()
|
|
|
|
{
|
|
|
|
while (Step());
|
|
|
|
}
|
|
|
|
|
2018-08-14 18:27:05 -07:00
|
|
|
private (NvGpuVmm Vmm, NvGpuPBEntry[] Pb) Curr;
|
|
|
|
|
|
|
|
private int CurrPbEntryIndex;
|
|
|
|
|
2018-04-08 12:17:35 -07:00
|
|
|
public bool Step()
|
|
|
|
{
|
2018-08-14 18:27:05 -07:00
|
|
|
while (Curr.Pb == null || Curr.Pb.Length <= CurrPbEntryIndex)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
2018-08-14 18:27:05 -07:00
|
|
|
if (!BufferQueue.TryDequeue(out Curr))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Gpu.Engine3d.ResetCache();
|
2018-04-08 12:17:35 -07:00
|
|
|
|
2018-08-14 18:27:05 -07:00
|
|
|
CurrPbEntryIndex = 0;
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
|
2018-08-14 18:27:05 -07:00
|
|
|
CallMethod(Curr.Vmm, Curr.Pb[CurrPbEntryIndex++]);
|
|
|
|
|
|
|
|
return true;
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
private void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
|
|
|
if (PBEntry.Method < 0x80)
|
|
|
|
{
|
|
|
|
switch ((NvGpuFifoMeth)PBEntry.Method)
|
|
|
|
{
|
|
|
|
case NvGpuFifoMeth.BindChannel:
|
|
|
|
{
|
|
|
|
NvGpuEngine Engine = (NvGpuEngine)PBEntry.Arguments[0];
|
|
|
|
|
|
|
|
SubChannels[PBEntry.SubChannel] = Engine;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NvGpuFifoMeth.SetMacroUploadAddress:
|
|
|
|
{
|
2018-06-17 21:32:11 -07:00
|
|
|
CurrMacroPosition = PBEntry.Arguments[0];
|
2018-04-08 12:17:35 -07:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NvGpuFifoMeth.SendMacroCodeData:
|
|
|
|
{
|
|
|
|
foreach (int Arg in PBEntry.Arguments)
|
|
|
|
{
|
2018-06-17 21:32:11 -07:00
|
|
|
Mme[CurrMacroPosition++] = Arg;
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NvGpuFifoMeth.SetMacroBindingIndex:
|
|
|
|
{
|
|
|
|
CurrMacroBindIndex = PBEntry.Arguments[0];
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NvGpuFifoMeth.BindMacro:
|
|
|
|
{
|
2018-06-17 21:32:11 -07:00
|
|
|
int Position = PBEntry.Arguments[0];
|
2018-04-08 12:17:35 -07:00
|
|
|
|
|
|
|
Macros[CurrMacroBindIndex] = new CachedMacro(this, Gpu.Engine3d, Position);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (SubChannels[PBEntry.SubChannel])
|
|
|
|
{
|
2018-06-13 06:55:01 -07:00
|
|
|
case NvGpuEngine._2d: Call2dMethod (Vmm, PBEntry); break;
|
|
|
|
case NvGpuEngine._3d: Call3dMethod (Vmm, PBEntry); break;
|
|
|
|
case NvGpuEngine.Dma: CallDmaMethod(Vmm, PBEntry); break;
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
private void Call2dMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
|
2018-04-25 19:11:26 -07:00
|
|
|
{
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
Gpu.Engine2d.CallMethod(Vmm, PBEntry);
|
2018-04-25 19:11:26 -07:00
|
|
|
}
|
|
|
|
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
private void Call3dMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
|
2018-04-08 12:17:35 -07:00
|
|
|
{
|
|
|
|
if (PBEntry.Method < 0xe00)
|
|
|
|
{
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 11:53:23 -07:00
|
|
|
Gpu.Engine3d.CallMethod(Vmm, PBEntry);
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int MacroIndex = (PBEntry.Method >> 1) & MacroIndexMask;
|
|
|
|
|
|
|
|
if ((PBEntry.Method & 1) != 0)
|
|
|
|
{
|
|
|
|
foreach (int Arg in PBEntry.Arguments)
|
|
|
|
{
|
|
|
|
Macros[MacroIndex].PushParam(Arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-06-17 21:32:11 -07:00
|
|
|
Macros[MacroIndex].Execute(Vmm, Mme, PBEntry.Arguments[0]);
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-13 06:55:01 -07:00
|
|
|
|
|
|
|
private void CallDmaMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
|
|
|
|
{
|
|
|
|
Gpu.EngineDma.CallMethod(Vmm, PBEntry);
|
|
|
|
}
|
2018-04-08 12:17:35 -07:00
|
|
|
}
|
|
|
|
}
|