aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Host1x
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-09-28 19:43:40 -0300
committerGitHub <noreply@github.com>2021-09-29 00:43:40 +0200
commitf4f496cb48a59aae36e3252baa90396e1bfadd2e (patch)
tree5594d76b3f1b552f1fecdeda37bd2f6667781a56 /Ryujinx.Graphics.Host1x
parent0d23504e30395ba20d1704da464b41f3fe539062 (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.cs61
-rw-r--r--Ryujinx.Graphics.Host1x/ThiDevice.cs53
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);