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
This commit is contained in:
parent
0d23504e30
commit
f4f496cb48
18 changed files with 358 additions and 200 deletions
|
@ -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<NvdecRegisters> _state;
|
||||
|
||||
public event Action<FrameDecodedEventArgs> FrameDecoded;
|
||||
private long _currentId;
|
||||
private ConcurrentDictionary<long, NvdecDecoderContext> _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<long, NvdecDecoderContext>();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue