diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-12-03 00:38:47 -0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-03 00:38:47 -0200 |
| commit | c86aacde76b5f8e503e2b412385c8491ecc86b3b (patch) | |
| tree | 8e4737422fba15199c1a6ce7c6345996c0e907b5 /Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs | |
| parent | ad00fd02442cf9c0f00c4562635738042b521efa (diff) | |
NVDEC implementation using FFmpeg (#443)
* Initial nvdec implementation using FFmpeg
* Fix swapped channels on the video decoder and the G8R8 texture format
* Fix texture samplers not being set properly (regression)
* Rebased
* Remove unused code introduced on the rebase
* Add support for RGBA8 output format on the video image composer
* Correct spacing
* Some fixes for rebase and other tweaks
* Allow size mismatch on frame copy
* Get rid of GetHostAddress calls on VDec
Diffstat (limited to 'Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs')
| -rw-r--r-- | Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs b/Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs new file mode 100644 index 00000000..f834ade7 --- /dev/null +++ b/Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs @@ -0,0 +1,176 @@ +using Ryujinx.Graphics.Memory; + +namespace Ryujinx.Graphics.Graphics3d +{ + class NvGpuFifo + { + private const int MacrosCount = 0x80; + private const int MacroIndexMask = MacrosCount - 1; + + //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; + + private NvGpu Gpu; + + private NvGpuEngine[] SubChannels; + + private struct CachedMacro + { + public int Position { get; private set; } + + private bool ExecutionPending; + private int Argument; + + private MacroInterpreter Interpreter; + + public CachedMacro(NvGpuFifo PFifo, INvGpuEngine Engine, int Position) + { + this.Position = Position; + + ExecutionPending = false; + Argument = 0; + + Interpreter = new MacroInterpreter(PFifo, Engine); + } + + public void StartExecution(int Argument) + { + this.Argument = Argument; + + ExecutionPending = true; + } + + public void Execute(NvGpuVmm Vmm, int[] Mme) + { + if (ExecutionPending) + { + ExecutionPending = false; + + Interpreter?.Execute(Vmm, Mme, Position, Argument); + } + } + + public void PushArgument(int Argument) + { + Interpreter?.Fifo.Enqueue(Argument); + } + } + + private int CurrMacroPosition; + private int CurrMacroBindIndex; + + private CachedMacro[] Macros; + + private int[] Mme; + + public NvGpuFifo(NvGpu Gpu) + { + this.Gpu = Gpu; + + SubChannels = new NvGpuEngine[8]; + + Macros = new CachedMacro[MacrosCount]; + + Mme = new int[MmeWords]; + } + + public void CallMethod(NvGpuVmm Vmm, GpuMethodCall MethCall) + { + if ((NvGpuFifoMeth)MethCall.Method == NvGpuFifoMeth.BindChannel) + { + NvGpuEngine Engine = (NvGpuEngine)MethCall.Argument; + + SubChannels[MethCall.SubChannel] = Engine; + } + else + { + switch (SubChannels[MethCall.SubChannel]) + { + case NvGpuEngine._2d: Call2dMethod (Vmm, MethCall); break; + case NvGpuEngine._3d: Call3dMethod (Vmm, MethCall); break; + case NvGpuEngine.P2mf: CallP2mfMethod(Vmm, MethCall); break; + case NvGpuEngine.M2mf: CallM2mfMethod(Vmm, MethCall); break; + } + } + } + + private void Call2dMethod(NvGpuVmm Vmm, GpuMethodCall MethCall) + { + Gpu.Engine2d.CallMethod(Vmm, MethCall); + } + + private void Call3dMethod(NvGpuVmm Vmm, GpuMethodCall MethCall) + { + if (MethCall.Method < 0x80) + { + switch ((NvGpuFifoMeth)MethCall.Method) + { + case NvGpuFifoMeth.SetMacroUploadAddress: + { + CurrMacroPosition = MethCall.Argument; + + break; + } + + case NvGpuFifoMeth.SendMacroCodeData: + { + Mme[CurrMacroPosition++] = MethCall.Argument; + + break; + } + + case NvGpuFifoMeth.SetMacroBindingIndex: + { + CurrMacroBindIndex = MethCall.Argument; + + break; + } + + case NvGpuFifoMeth.BindMacro: + { + int Position = MethCall.Argument; + + Macros[CurrMacroBindIndex] = new CachedMacro(this, Gpu.Engine3d, Position); + + break; + } + + default: CallP2mfMethod(Vmm, MethCall); break; + } + } + else if (MethCall.Method < 0xe00) + { + Gpu.Engine3d.CallMethod(Vmm, MethCall); + } + else + { + int MacroIndex = (MethCall.Method >> 1) & MacroIndexMask; + + if ((MethCall.Method & 1) != 0) + { + Macros[MacroIndex].PushArgument(MethCall.Argument); + } + else + { + Macros[MacroIndex].StartExecution(MethCall.Argument); + } + + if (MethCall.IsLastCall) + { + Macros[MacroIndex].Execute(Vmm, Mme); + } + } + } + + private void CallP2mfMethod(NvGpuVmm Vmm, GpuMethodCall MethCall) + { + Gpu.EngineP2mf.CallMethod(Vmm, MethCall); + } + + private void CallM2mfMethod(NvGpuVmm Vmm, GpuMethodCall MethCall) + { + Gpu.EngineM2mf.CallMethod(Vmm, MethCall); + } + } +}
\ No newline at end of file |
