aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-12-03 00:38:47 -0200
committerGitHub <noreply@github.com>2018-12-03 00:38:47 -0200
commitc86aacde76b5f8e503e2b412385c8491ecc86b3b (patch)
tree8e4737422fba15199c1a6ce7c6345996c0e907b5 /Ryujinx.Graphics/Graphics3d/NvGpuFifo.cs
parentad00fd02442cf9c0f00c4562635738042b521efa (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.cs176
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