Vp9Decoder.cs
1 using Ryujinx.Common; 2 using Ryujinx.Graphics.Device; 3 using Ryujinx.Graphics.Nvdec.Image; 4 using Ryujinx.Graphics.Nvdec.Types.Vp9; 5 using Ryujinx.Graphics.Nvdec.Vp9; 6 using Ryujinx.Graphics.Video; 7 using System; 8 using System.Runtime.CompilerServices; 9 using System.Runtime.InteropServices; 10 using static Ryujinx.Graphics.Nvdec.MemoryExtensions; 11 12 namespace Ryujinx.Graphics.Nvdec 13 { 14 static class Vp9Decoder 15 { 16 private static readonly Decoder _decoder = new(); 17 18 public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state) 19 { 20 PictureInfo pictureInfo = rm.MemoryManager.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset); 21 EntropyProbs entropy = rm.MemoryManager.DeviceRead<EntropyProbs>(state.Vp9SetProbTabBufOffset); 22 23 ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size) 24 { 25 return rm.Cache.Get(_decoder, lumaOffset, chromaOffset, size.Width, size.Height); 26 } 27 28 ISurface lastSurface = Rent(state.SetPictureLumaOffset[0], state.SetPictureChromaOffset[0], pictureInfo.LastFrameSize); 29 ISurface goldenSurface = Rent(state.SetPictureLumaOffset[1], state.SetPictureChromaOffset[1], pictureInfo.GoldenFrameSize); 30 ISurface altSurface = Rent(state.SetPictureLumaOffset[2], state.SetPictureChromaOffset[2], pictureInfo.AltFrameSize); 31 ISurface currentSurface = Rent(state.SetPictureLumaOffset[3], state.SetPictureChromaOffset[3], pictureInfo.CurrentFrameSize); 32 33 Vp9PictureInfo info = pictureInfo.Convert(); 34 35 info.LastReference = lastSurface; 36 info.GoldenReference = goldenSurface; 37 info.AltReference = altSurface; 38 39 entropy.Convert(ref info.Entropy); 40 41 ReadOnlySpan<byte> bitstream = rm.MemoryManager.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize); 42 43 ReadOnlySpan<Vp9MvRef> mvsIn = ReadOnlySpan<Vp9MvRef>.Empty; 44 45 if (info.UsePrevInFindMvRefs) 46 { 47 mvsIn = GetMvsInput(rm.MemoryManager, pictureInfo.CurrentFrameSize, state.Vp9SetColMvReadBufOffset); 48 } 49 50 int miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8); 51 int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 8); 52 53 using var mvsRegion = rm.MemoryManager.GetWritableRegion(ExtendOffset(state.Vp9SetColMvWriteBufOffset), miRows * miCols * 16); 54 55 Span<Vp9MvRef> mvsOut = MemoryMarshal.Cast<byte, Vp9MvRef>(mvsRegion.Memory.Span); 56 57 uint lumaOffset = state.SetPictureLumaOffset[3]; 58 uint chromaOffset = state.SetPictureChromaOffset[3]; 59 60 if (_decoder.Decode(ref info, currentSurface, bitstream, mvsIn, mvsOut)) 61 { 62 SurfaceWriter.Write(rm.MemoryManager, currentSurface, lumaOffset, chromaOffset); 63 } 64 65 WriteBackwardUpdates(rm.MemoryManager, state.Vp9SetCtxCounterBufOffset, ref info.BackwardUpdateCounts); 66 67 rm.Cache.Put(lastSurface); 68 rm.Cache.Put(goldenSurface); 69 rm.Cache.Put(altSurface); 70 rm.Cache.Put(currentSurface); 71 } 72 73 private static ReadOnlySpan<Vp9MvRef> GetMvsInput(DeviceMemoryManager mm, FrameSize size, uint offset) 74 { 75 int miCols = BitUtils.DivRoundUp(size.Width, 8); 76 int miRows = BitUtils.DivRoundUp(size.Height, 8); 77 78 return MemoryMarshal.Cast<byte, Vp9MvRef>(mm.DeviceGetSpan(offset, miRows * miCols * 16)); 79 } 80 81 private static void WriteBackwardUpdates(DeviceMemoryManager mm, uint offset, ref Vp9BackwardUpdates counts) 82 { 83 using var backwardUpdatesRegion = mm.GetWritableRegion(ExtendOffset(offset), Unsafe.SizeOf<BackwardUpdates>()); 84 85 ref var backwardUpdates = ref MemoryMarshal.Cast<byte, BackwardUpdates>(backwardUpdatesRegion.Memory.Span)[0]; 86 87 backwardUpdates = new BackwardUpdates(ref counts); 88 } 89 } 90 }