aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Vic
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/Vic
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/Vic')
-rw-r--r--Ryujinx.Graphics/Vic/StructUnpacker.cs69
-rw-r--r--Ryujinx.Graphics/Vic/SurfaceOutputConfig.cs33
-rw-r--r--Ryujinx.Graphics/Vic/SurfacePixelFormat.cs8
-rw-r--r--Ryujinx.Graphics/Vic/VideoImageComposer.cs107
-rw-r--r--Ryujinx.Graphics/Vic/VideoImageComposerMeth.cs12
5 files changed, 229 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Vic/StructUnpacker.cs b/Ryujinx.Graphics/Vic/StructUnpacker.cs
new file mode 100644
index 00000000..62777aad
--- /dev/null
+++ b/Ryujinx.Graphics/Vic/StructUnpacker.cs
@@ -0,0 +1,69 @@
+using Ryujinx.Graphics.Memory;
+using System;
+
+namespace Ryujinx.Graphics.Vic
+{
+ class StructUnpacker
+ {
+ private NvGpuVmm Vmm;
+
+ private long Position;
+
+ private ulong Buffer;
+ private int BuffPos;
+
+ public StructUnpacker(NvGpuVmm Vmm, long Position)
+ {
+ this.Vmm = Vmm;
+ this.Position = Position;
+
+ BuffPos = 64;
+ }
+
+ public int Read(int Bits)
+ {
+ if ((uint)Bits > 32)
+ {
+ throw new ArgumentOutOfRangeException(nameof(Bits));
+ }
+
+ int Value = 0;
+
+ while (Bits > 0)
+ {
+ RefillBufferIfNeeded();
+
+ int ReadBits = Bits;
+
+ int MaxReadBits = 64 - BuffPos;
+
+ if (ReadBits > MaxReadBits)
+ {
+ ReadBits = MaxReadBits;
+ }
+
+ Value <<= ReadBits;
+
+ Value |= (int)(Buffer >> BuffPos) & (int)(0xffffffff >> (32 - ReadBits));
+
+ BuffPos += ReadBits;
+
+ Bits -= ReadBits;
+ }
+
+ return Value;
+ }
+
+ private void RefillBufferIfNeeded()
+ {
+ if (BuffPos >= 64)
+ {
+ Buffer = Vmm.ReadUInt64(Position);
+
+ Position += 8;
+
+ BuffPos = 0;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Vic/SurfaceOutputConfig.cs b/Ryujinx.Graphics/Vic/SurfaceOutputConfig.cs
new file mode 100644
index 00000000..0a232744
--- /dev/null
+++ b/Ryujinx.Graphics/Vic/SurfaceOutputConfig.cs
@@ -0,0 +1,33 @@
+namespace Ryujinx.Graphics.Vic
+{
+ struct SurfaceOutputConfig
+ {
+ public SurfacePixelFormat PixelFormat;
+
+ public int SurfaceWidth;
+ public int SurfaceHeight;
+ public int GobBlockHeight;
+
+ public long SurfaceLumaAddress;
+ public long SurfaceChromaUAddress;
+ public long SurfaceChromaVAddress;
+
+ public SurfaceOutputConfig(
+ SurfacePixelFormat PixelFormat,
+ int SurfaceWidth,
+ int SurfaceHeight,
+ int GobBlockHeight,
+ long OutputSurfaceLumaAddress,
+ long OutputSurfaceChromaUAddress,
+ long OutputSurfaceChromaVAddress)
+ {
+ this.PixelFormat = PixelFormat;
+ this.SurfaceWidth = SurfaceWidth;
+ this.SurfaceHeight = SurfaceHeight;
+ this.GobBlockHeight = GobBlockHeight;
+ this.SurfaceLumaAddress = OutputSurfaceLumaAddress;
+ this.SurfaceChromaUAddress = OutputSurfaceChromaUAddress;
+ this.SurfaceChromaVAddress = OutputSurfaceChromaVAddress;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Vic/SurfacePixelFormat.cs b/Ryujinx.Graphics/Vic/SurfacePixelFormat.cs
new file mode 100644
index 00000000..ee56ac05
--- /dev/null
+++ b/Ryujinx.Graphics/Vic/SurfacePixelFormat.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Vic
+{
+ enum SurfacePixelFormat
+ {
+ RGBA8 = 0x1f,
+ YUV420P = 0x44
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Vic/VideoImageComposer.cs b/Ryujinx.Graphics/Vic/VideoImageComposer.cs
new file mode 100644
index 00000000..758382fa
--- /dev/null
+++ b/Ryujinx.Graphics/Vic/VideoImageComposer.cs
@@ -0,0 +1,107 @@
+using Ryujinx.Graphics.Memory;
+
+namespace Ryujinx.Graphics.Vic
+{
+ class VideoImageComposer
+ {
+ private NvGpu Gpu;
+
+ private long ConfigStructAddress;
+ private long OutputSurfaceLumaAddress;
+ private long OutputSurfaceChromaUAddress;
+ private long OutputSurfaceChromaVAddress;
+
+ public VideoImageComposer(NvGpu Gpu)
+ {
+ this.Gpu = Gpu;
+ }
+
+ public void Process(NvGpuVmm Vmm, int MethodOffset, int[] Arguments)
+ {
+ VideoImageComposerMeth Method = (VideoImageComposerMeth)MethodOffset;
+
+ switch (Method)
+ {
+ case VideoImageComposerMeth.Execute:
+ Execute(Vmm, Arguments);
+ break;
+
+ case VideoImageComposerMeth.SetConfigStructOffset:
+ SetConfigStructOffset(Vmm, Arguments);
+ break;
+
+ case VideoImageComposerMeth.SetOutputSurfaceLumaOffset:
+ SetOutputSurfaceLumaOffset(Vmm, Arguments);
+ break;
+
+ case VideoImageComposerMeth.SetOutputSurfaceChromaUOffset:
+ SetOutputSurfaceChromaUOffset(Vmm, Arguments);
+ break;
+
+ case VideoImageComposerMeth.SetOutputSurfaceChromaVOffset:
+ SetOutputSurfaceChromaVOffset(Vmm, Arguments);
+ break;
+ }
+ }
+
+ private void Execute(NvGpuVmm Vmm, int[] Arguments)
+ {
+ StructUnpacker Unpacker = new StructUnpacker(Vmm, ConfigStructAddress + 0x20);
+
+ SurfacePixelFormat PixelFormat = (SurfacePixelFormat)Unpacker.Read(7);
+
+ int ChromaLocHoriz = Unpacker.Read(2);
+ int ChromaLocVert = Unpacker.Read(2);
+
+ int BlockLinearKind = Unpacker.Read(4);
+ int BlockLinearHeightLog2 = Unpacker.Read(4);
+
+ int Reserved0 = Unpacker.Read(3);
+ int Reserved1 = Unpacker.Read(10);
+
+ int SurfaceWidthMinus1 = Unpacker.Read(14);
+ int SurfaceHeightMinus1 = Unpacker.Read(14);
+
+ int GobBlockHeight = 1 << BlockLinearHeightLog2;
+
+ int SurfaceWidth = SurfaceWidthMinus1 + 1;
+ int SurfaceHeight = SurfaceHeightMinus1 + 1;
+
+ SurfaceOutputConfig OutputConfig = new SurfaceOutputConfig(
+ PixelFormat,
+ SurfaceWidth,
+ SurfaceHeight,
+ GobBlockHeight,
+ OutputSurfaceLumaAddress,
+ OutputSurfaceChromaUAddress,
+ OutputSurfaceChromaVAddress);
+
+ Gpu.VideoDecoder.CopyPlanes(Vmm, OutputConfig);
+ }
+
+ private void SetConfigStructOffset(NvGpuVmm Vmm, int[] Arguments)
+ {
+ ConfigStructAddress = GetAddress(Arguments);
+ }
+
+ private void SetOutputSurfaceLumaOffset(NvGpuVmm Vmm, int[] Arguments)
+ {
+ OutputSurfaceLumaAddress = GetAddress(Arguments);
+ }
+
+ private void SetOutputSurfaceChromaUOffset(NvGpuVmm Vmm, int[] Arguments)
+ {
+ OutputSurfaceChromaUAddress = GetAddress(Arguments);
+ }
+
+ private void SetOutputSurfaceChromaVOffset(NvGpuVmm Vmm, int[] Arguments)
+ {
+ OutputSurfaceChromaVAddress = GetAddress(Arguments);
+ }
+
+ private static long GetAddress(int[] Arguments)
+ {
+ return (long)(uint)Arguments[0] << 8;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Vic/VideoImageComposerMeth.cs b/Ryujinx.Graphics/Vic/VideoImageComposerMeth.cs
new file mode 100644
index 00000000..b30cabea
--- /dev/null
+++ b/Ryujinx.Graphics/Vic/VideoImageComposerMeth.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.Vic
+{
+ enum VideoImageComposerMeth
+ {
+ Execute = 0xc0,
+ SetControlParams = 0x1c1,
+ SetConfigStructOffset = 0x1c2,
+ SetOutputSurfaceLumaOffset = 0x1c8,
+ SetOutputSurfaceChromaUOffset = 0x1c9,
+ SetOutputSurfaceChromaVOffset = 0x1ca
+ }
+} \ No newline at end of file