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/Vic | |
| 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/Vic')
| -rw-r--r-- | Ryujinx.Graphics/Vic/StructUnpacker.cs | 69 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Vic/SurfaceOutputConfig.cs | 33 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Vic/SurfacePixelFormat.cs | 8 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Vic/VideoImageComposer.cs | 107 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Vic/VideoImageComposerMeth.cs | 12 |
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 |
