From f4f496cb48a59aae36e3252baa90396e1bfadd2e Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 28 Sep 2021 19:43:40 -0300 Subject: NVDEC (H264): Use separate contexts per channel and decode frames in DTS order (#2671) * Use separate NVDEC contexts per channel (for FFMPEG) * Remove NVDEC -> VIC frame override hack * Add missing bottom_field_pic_order_in_frame_present_flag * Make FFMPEG logging static * nit: Remove empty lines * New FFMPEG decoding approach -- call h264_decode_frame directly, trim surface cache to reduce memory usage * Fix case * Silence warnings * PR feedback * Per-decoder rather than per-codec ownership of surfaces on the cache --- Ryujinx.Graphics.Nvdec/NvdecDevice.cs | 45 +++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) (limited to 'Ryujinx.Graphics.Nvdec/NvdecDevice.cs') diff --git a/Ryujinx.Graphics.Nvdec/NvdecDevice.cs b/Ryujinx.Graphics.Nvdec/NvdecDevice.cs index 08f802a1..5319429b 100644 --- a/Ryujinx.Graphics.Nvdec/NvdecDevice.cs +++ b/Ryujinx.Graphics.Nvdec/NvdecDevice.cs @@ -2,17 +2,20 @@ using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Nvdec.Image; -using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Threading; namespace Ryujinx.Graphics.Nvdec { - public class NvdecDevice : IDeviceState + public class NvdecDevice : IDeviceStateWithContext { private readonly ResourceManager _rm; private readonly DeviceState _state; - public event Action FrameDecoded; + private long _currentId; + private ConcurrentDictionary _contexts; + private NvdecDecoderContext _currentContext; public NvdecDevice(MemoryManager gmm) { @@ -21,6 +24,33 @@ namespace Ryujinx.Graphics.Nvdec { { nameof(NvdecRegisters.Execute), new RwCallback(Execute, null) } }); + _contexts = new ConcurrentDictionary(); + } + + public long CreateContext() + { + long id = Interlocked.Increment(ref _currentId); + _contexts.TryAdd(id, new NvdecDecoderContext()); + + return id; + } + + public void DestroyContext(long id) + { + if (_contexts.TryRemove(id, out var context)) + { + context.Dispose(); + } + + _rm.Cache.Trim(); + } + + public void BindContext(long id) + { + if (_contexts.TryGetValue(id, out var context)) + { + _currentContext = context; + } } public int Read(int offset) => _state.Read(offset); @@ -36,20 +66,15 @@ namespace Ryujinx.Graphics.Nvdec switch (codecId) { case CodecId.H264: - H264Decoder.Decode(this, _rm, ref _state.State); + H264Decoder.Decode(_currentContext, _rm, ref _state.State); break; case CodecId.Vp9: - Vp9Decoder.Decode(this, _rm, ref _state.State); + Vp9Decoder.Decode(_rm, ref _state.State); break; default: Logger.Error?.Print(LogClass.Nvdec, $"Unsupported codec \"{codecId}\"."); break; } } - - internal void OnFrameDecoded(CodecId codecId, uint lumaOffset, uint chromaOffset) - { - FrameDecoded?.Invoke(new FrameDecodedEventArgs(codecId, lumaOffset, chromaOffset)); - } } } -- cgit v1.2.3