Vp9Decoder.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using Ryujinx.Common;
  2. using Ryujinx.Graphics.Gpu.Memory;
  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. namespace Ryujinx.Graphics.Nvdec
  12. {
  13. static class Vp9Decoder
  14. {
  15. private static Decoder _decoder = new Decoder();
  16. public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state)
  17. {
  18. PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset);
  19. EntropyProbs entropy = rm.Gmm.DeviceRead<EntropyProbs>(state.SetVp9EntropyProbsOffset);
  20. ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size)
  21. {
  22. return rm.Cache.Get(_decoder, lumaOffset, chromaOffset, size.Width, size.Height);
  23. }
  24. ISurface lastSurface = Rent(state.SetSurfaceLumaOffset[0], state.SetSurfaceChromaOffset[0], pictureInfo.LastFrameSize);
  25. ISurface goldenSurface = Rent(state.SetSurfaceLumaOffset[1], state.SetSurfaceChromaOffset[1], pictureInfo.GoldenFrameSize);
  26. ISurface altSurface = Rent(state.SetSurfaceLumaOffset[2], state.SetSurfaceChromaOffset[2], pictureInfo.AltFrameSize);
  27. ISurface currentSurface = Rent(state.SetSurfaceLumaOffset[3], state.SetSurfaceChromaOffset[3], pictureInfo.CurrentFrameSize);
  28. Vp9PictureInfo info = pictureInfo.Convert();
  29. info.LastReference = lastSurface;
  30. info.GoldenReference = goldenSurface;
  31. info.AltReference = altSurface;
  32. entropy.Convert(ref info.Entropy);
  33. ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.BitstreamSize);
  34. ReadOnlySpan<Vp9MvRef> mvsIn = ReadOnlySpan<Vp9MvRef>.Empty;
  35. if (info.UsePrevInFindMvRefs)
  36. {
  37. mvsIn = GetMvsInput(rm.Gmm, pictureInfo.CurrentFrameSize, state.SetVp9LastFrameMvsOffset);
  38. }
  39. int miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8);
  40. int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 8);
  41. using var mvsRegion = rm.Gmm.GetWritableRegion(ExtendOffset(state.SetVp9CurrFrameMvsOffset), miRows * miCols * 16);
  42. Span<Vp9MvRef> mvsOut = MemoryMarshal.Cast<byte, Vp9MvRef>(mvsRegion.Memory.Span);
  43. uint lumaOffset = state.SetSurfaceLumaOffset[3];
  44. uint chromaOffset = state.SetSurfaceChromaOffset[3];
  45. if (_decoder.Decode(ref info, currentSurface, bitstream, mvsIn, mvsOut))
  46. {
  47. SurfaceWriter.Write(rm.Gmm, currentSurface, lumaOffset, chromaOffset);
  48. }
  49. WriteBackwardUpdates(rm.Gmm, state.SetVp9BackwardUpdatesOffset, ref info.BackwardUpdateCounts);
  50. rm.Cache.Put(lastSurface);
  51. rm.Cache.Put(goldenSurface);
  52. rm.Cache.Put(altSurface);
  53. rm.Cache.Put(currentSurface);
  54. }
  55. private static ReadOnlySpan<Vp9MvRef> GetMvsInput(MemoryManager gmm, FrameSize size, uint offset)
  56. {
  57. int miCols = BitUtils.DivRoundUp(size.Width, 8);
  58. int miRows = BitUtils.DivRoundUp(size.Height, 8);
  59. return MemoryMarshal.Cast<byte, Vp9MvRef>(gmm.DeviceGetSpan(offset, miRows * miCols * 16));
  60. }
  61. private static void WriteBackwardUpdates(MemoryManager gmm, uint offset, ref Vp9BackwardUpdates counts)
  62. {
  63. using var backwardUpdatesRegion = gmm.GetWritableRegion(ExtendOffset(offset), Unsafe.SizeOf<BackwardUpdates>());
  64. ref var backwardUpdates = ref MemoryMarshal.Cast<byte, BackwardUpdates>(backwardUpdatesRegion.Memory.Span)[0];
  65. backwardUpdates = new BackwardUpdates(ref counts);
  66. }
  67. }
  68. }