diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2021-09-28 19:43:40 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-09-29 00:43:40 +0200 |
| commit | f4f496cb48a59aae36e3252baa90396e1bfadd2e (patch) | |
| tree | 5594d76b3f1b552f1fecdeda37bd2f6667781a56 /Ryujinx.Graphics.Host1x | |
| parent | 0d23504e30395ba20d1704da464b41f3fe539062 (diff) | |
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
Diffstat (limited to 'Ryujinx.Graphics.Host1x')
| -rw-r--r-- | Ryujinx.Graphics.Host1x/Host1xDevice.cs | 61 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Host1x/ThiDevice.cs | 53 |
2 files changed, 103 insertions, 11 deletions
diff --git a/Ryujinx.Graphics.Host1x/Host1xDevice.cs b/Ryujinx.Graphics.Host1x/Host1xDevice.cs index 7f6cef62..61408fc4 100644 --- a/Ryujinx.Graphics.Host1x/Host1xDevice.cs +++ b/Ryujinx.Graphics.Host1x/Host1xDevice.cs @@ -9,8 +9,20 @@ namespace Ryujinx.Graphics.Host1x { public sealed class Host1xDevice : IDisposable { + private struct Command + { + public int[] Buffer { get; } + public long ContextId { get; } + + public Command(int[] buffer, long contextId) + { + Buffer = buffer; + ContextId = contextId; + } + } + private readonly SyncptIncrManager _syncptIncrMgr; - private readonly AsyncWorkQueue<int[]> _commandQueue; + private readonly AsyncWorkQueue<Command> _commandQueue; private readonly Devices _devices = new Devices(); @@ -26,7 +38,7 @@ namespace Ryujinx.Graphics.Host1x public Host1xDevice(SynchronizationManager syncMgr) { _syncptIncrMgr = new SyncptIncrManager(syncMgr); - _commandQueue = new AsyncWorkQueue<int[]>(Process, "Ryujinx.Host1xProcessor"); + _commandQueue = new AsyncWorkQueue<Command>(Process, "Ryujinx.Host1xProcessor"); Class = new Host1xClass(syncMgr); @@ -39,13 +51,52 @@ namespace Ryujinx.Graphics.Host1x _devices.RegisterDevice(classId, thi); } - public void Submit(ReadOnlySpan<int> commandBuffer) + public long CreateContext() { - _commandQueue.Add(commandBuffer.ToArray()); + if (_devices.GetDevice(ClassId.Nvdec) is IDeviceStateWithContext nvdec) + { + return nvdec.CreateContext(); + } + + return -1; } - private void Process(int[] commandBuffer) + public void DestroyContext(long id) { + if (id == -1) + { + return; + } + + if (_devices.GetDevice(ClassId.Nvdec) is IDeviceStateWithContext nvdec) + { + nvdec.DestroyContext(id); + } + } + + private void SetNvdecContext(long id) + { + if (id == -1) + { + return; + } + + if (_devices.GetDevice(ClassId.Nvdec) is IDeviceStateWithContext nvdec) + { + nvdec.BindContext(id); + } + } + + public void Submit(ReadOnlySpan<int> commandBuffer, long contextId) + { + _commandQueue.Add(new Command(commandBuffer.ToArray(), contextId)); + } + + private void Process(Command command) + { + SetNvdecContext(command.ContextId); + int[] commandBuffer = command.Buffer; + for (int index = 0; index < commandBuffer.Length; index++) { Step(commandBuffer[index]); diff --git a/Ryujinx.Graphics.Host1x/ThiDevice.cs b/Ryujinx.Graphics.Host1x/ThiDevice.cs index 8e3e11b0..114ee26e 100644 --- a/Ryujinx.Graphics.Host1x/ThiDevice.cs +++ b/Ryujinx.Graphics.Host1x/ThiDevice.cs @@ -5,19 +5,24 @@ using System.Collections.Generic; namespace Ryujinx.Graphics.Host1x { - class ThiDevice : IDeviceState, IDisposable + class ThiDevice : IDeviceStateWithContext, IDisposable { private readonly ClassId _classId; private readonly IDeviceState _device; private readonly SyncptIncrManager _syncptIncrMgr; + private long _currentContextId; + private long _previousContextId; + private class CommandAction { + public long ContextId { get; } public int Data { get; } - public CommandAction(int data) + public CommandAction(long contextId, int data) { + ContextId = contextId; Data = data; } } @@ -26,7 +31,7 @@ namespace Ryujinx.Graphics.Host1x { public int Method { get; } - public MethodCallAction(int method, int data) : base(data) + public MethodCallAction(long contextId, int method, int data) : base(contextId, data) { Method = method; } @@ -34,7 +39,7 @@ namespace Ryujinx.Graphics.Host1x private class SyncptIncrAction : CommandAction { - public SyncptIncrAction(uint syncptIncrHandle) : base((int)syncptIncrHandle) + public SyncptIncrAction(long contextId, uint syncptIncrHandle) : base(contextId, (int)syncptIncrHandle) { } } @@ -54,6 +59,31 @@ namespace Ryujinx.Graphics.Host1x { nameof(ThiRegisters.IncrSyncpt), new RwCallback(IncrSyncpt, null) }, { nameof(ThiRegisters.Method1), new RwCallback(Method1, null) } }); + + _previousContextId = -1; + } + + public long CreateContext() + { + if (_device is IDeviceStateWithContext deviceWithContext) + { + return deviceWithContext.CreateContext(); + } + + return -1; + } + + public void DestroyContext(long id) + { + if (_device is IDeviceStateWithContext deviceWithContext) + { + deviceWithContext.DestroyContext(id); + } + } + + public void BindContext(long id) + { + _currentContextId = id; } public int Read(int offset) => _state.Read(offset); @@ -70,17 +100,28 @@ namespace Ryujinx.Graphics.Host1x } else { - _commandQueue.Add(new SyncptIncrAction(_syncptIncrMgr.IncrementWhenDone(_classId, syncpointId))); + _commandQueue.Add(new SyncptIncrAction(_currentContextId, _syncptIncrMgr.IncrementWhenDone(_classId, syncpointId))); } } private void Method1(int data) { - _commandQueue.Add(new MethodCallAction((int)_state.State.Method0 * 4, data)); + _commandQueue.Add(new MethodCallAction(_currentContextId, (int)_state.State.Method0 * 4, data)); } private void Process(CommandAction cmdAction) { + long contextId = cmdAction.ContextId; + if (contextId != _previousContextId) + { + _previousContextId = contextId; + + if (_device is IDeviceStateWithContext deviceWithContext) + { + deviceWithContext.BindContext(contextId); + } + } + if (cmdAction is SyncptIncrAction syncptIncrAction) { _syncptIncrMgr.SignalDone((uint)syncptIncrAction.Data); |
