IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel (#1458)
* IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel * Fix for applet transfer memory + some nits * Keep handles if possible to avoid server handle table exhaustion * Fix IPC ZeroFill bug * am: Correctly implement CreateManagedDisplayLayer and implement CreateManagedDisplaySeparableLayer CreateManagedDisplaySeparableLayer is requires since 10.x+ when appletResourceUserId != 0 * Make it exit properly * Make ServiceNotImplementedException show the full message again * Allow yielding execution to avoid starving other threads * Only wait if active * Merge IVirtualMemoryManager and IAddressSpaceManager * Fix Ro loading data from the wrong process Co-authored-by: Thog <me@thog.eu>
This commit is contained in:
parent
461c24092a
commit
cf6cd71488
115 changed files with 2356 additions and 1088 deletions
|
@ -1,15 +1,15 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
{
|
||||
class BufferQueue
|
||||
static class BufferQueue
|
||||
{
|
||||
public static void CreateBufferQueue(Switch device, KProcess process, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
|
||||
public static BufferQueueCore CreateBufferQueue(Switch device, long pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
|
||||
{
|
||||
BufferQueueCore core = new BufferQueueCore(device, process);
|
||||
BufferQueueCore core = new BufferQueueCore(device, pid);
|
||||
|
||||
producer = new BufferQueueProducer(core);
|
||||
consumer = new BufferQueueConsumer(core);
|
||||
|
||||
return core;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.HLE.HOS.Kernel;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types;
|
||||
using System;
|
||||
|
@ -40,11 +40,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
private KEvent _waitBufferFreeEvent;
|
||||
private KEvent _frameAvailableEvent;
|
||||
|
||||
public KProcess Owner { get; }
|
||||
public long Owner { get; }
|
||||
|
||||
public bool Active { get; private set; }
|
||||
|
||||
public const int BufferHistoryArraySize = 8;
|
||||
|
||||
public BufferQueueCore(Switch device, KProcess process)
|
||||
public BufferQueueCore(Switch device, long pid)
|
||||
{
|
||||
Slots = new BufferSlotArray();
|
||||
IsAbandoned = false;
|
||||
|
@ -70,7 +72,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
_waitBufferFreeEvent = new KEvent(device.System.KernelContext);
|
||||
_frameAvailableEvent = new KEvent(device.System.KernelContext);
|
||||
|
||||
Owner = process;
|
||||
Owner = pid;
|
||||
|
||||
Active = true;
|
||||
|
||||
BufferHistory = new BufferInfo[BufferHistoryArraySize];
|
||||
EnableExternalEvent = true;
|
||||
|
@ -162,6 +166,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
}
|
||||
}
|
||||
|
||||
public void PrepareForExit()
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
Active = false;
|
||||
|
||||
Monitor.PulseAll(Lock);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Find an accurate way to handle a regular condvar here as this will wake up unwanted threads in some edge cases.
|
||||
public void SignalDequeueEvent()
|
||||
{
|
||||
|
@ -170,7 +184,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
|
||||
public void WaitDequeueEvent()
|
||||
{
|
||||
Monitor.Wait(Lock);
|
||||
Monitor.Exit(Lock);
|
||||
|
||||
KernelStatic.YieldUntilCompletion(WaitForLock);
|
||||
|
||||
Monitor.Enter(Lock);
|
||||
}
|
||||
|
||||
public void SignalIsAllocatingEvent()
|
||||
|
@ -180,7 +198,22 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
|
||||
public void WaitIsAllocatingEvent()
|
||||
{
|
||||
Monitor.Wait(Lock);
|
||||
Monitor.Exit(Lock);
|
||||
|
||||
KernelStatic.YieldUntilCompletion(WaitForLock);
|
||||
|
||||
Monitor.Enter(Lock);
|
||||
}
|
||||
|
||||
private void WaitForLock()
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
if (Active)
|
||||
{
|
||||
Monitor.Wait(Lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void FreeBufferLocked(int slot)
|
||||
|
|
|
@ -816,6 +816,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
}
|
||||
|
||||
Core.WaitDequeueEvent();
|
||||
|
||||
if (!Core.Active)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
{
|
||||
abstract class IHOSBinderDriver : IpcService
|
||||
{
|
||||
public IHOSBinderDriver() {}
|
||||
public IHOSBinderDriver() { }
|
||||
|
||||
[Command(0)]
|
||||
// TransactParcel(s32, u32, u32, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0>
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl;
|
||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
||||
using Ryujinx.HLE.HOS.Services.Nv.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
@ -40,7 +37,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
public int ProducerBinderId;
|
||||
public IGraphicBufferProducer Producer;
|
||||
public BufferItemConsumer Consumer;
|
||||
public KProcess Owner;
|
||||
public BufferQueueCore Core;
|
||||
public long Owner;
|
||||
}
|
||||
|
||||
private class TextureCallbackInformation
|
||||
|
@ -84,7 +82,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
}
|
||||
}
|
||||
|
||||
public IGraphicBufferProducer OpenLayer(KProcess process, long layerId)
|
||||
public IGraphicBufferProducer OpenLayer(long pid, long layerId)
|
||||
{
|
||||
bool needCreate;
|
||||
|
||||
|
@ -95,13 +93,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
|
||||
if (needCreate)
|
||||
{
|
||||
CreateLayerFromId(process, layerId);
|
||||
CreateLayerFromId(pid, layerId);
|
||||
}
|
||||
|
||||
return GetProducerByLayerId(layerId);
|
||||
}
|
||||
|
||||
public IGraphicBufferProducer CreateLayer(KProcess process, out long layerId)
|
||||
public IGraphicBufferProducer CreateLayer(long pid, out long layerId)
|
||||
{
|
||||
layerId = 1;
|
||||
|
||||
|
@ -116,25 +114,26 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
}
|
||||
}
|
||||
|
||||
CreateLayerFromId(process, layerId);
|
||||
CreateLayerFromId(pid, layerId);
|
||||
|
||||
return GetProducerByLayerId(layerId);
|
||||
}
|
||||
|
||||
private void CreateLayerFromId(KProcess process, long layerId)
|
||||
private void CreateLayerFromId(long pid, long layerId)
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.SurfaceFlinger, $"Creating layer {layerId}");
|
||||
|
||||
BufferQueue.CreateBufferQueue(_device, process, out BufferQueueProducer producer, out BufferQueueConsumer consumer);
|
||||
BufferQueueCore core = BufferQueue.CreateBufferQueue(_device, pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer);
|
||||
|
||||
_layers.Add(layerId, new Layer
|
||||
{
|
||||
ProducerBinderId = HOSBinderDriverServer.RegisterBinderObject(producer),
|
||||
Producer = producer,
|
||||
Consumer = new BufferItemConsumer(_device, consumer, 0, -1, false, this),
|
||||
Owner = process
|
||||
Core = core,
|
||||
Owner = pid
|
||||
});
|
||||
|
||||
LastId = layerId;
|
||||
|
@ -345,6 +344,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
public void Dispose()
|
||||
{
|
||||
_isRunning = false;
|
||||
|
||||
foreach (Layer layer in _layers.Values)
|
||||
{
|
||||
layer.Core.PrepareForExit();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnFrameAvailable(ref BufferItem item)
|
||||
|
|
|
@ -42,23 +42,23 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>();
|
||||
}
|
||||
|
||||
public void IncrementNvMapHandleRefCount(KProcess process)
|
||||
public void IncrementNvMapHandleRefCount(long pid)
|
||||
{
|
||||
NvMapDeviceFile.IncrementMapRefCount(process, Buffer.NvMapId);
|
||||
NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId);
|
||||
|
||||
for (int i = 0; i < Buffer.Surfaces.Length; i++)
|
||||
{
|
||||
NvMapDeviceFile.IncrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle);
|
||||
NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public void DecrementNvMapHandleRefCount(KProcess process)
|
||||
public void DecrementNvMapHandleRefCount(long pid)
|
||||
{
|
||||
NvMapDeviceFile.DecrementMapRefCount(process, Buffer.NvMapId);
|
||||
NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId);
|
||||
|
||||
for (int i = 0; i < Buffer.Surfaces.Length; i++)
|
||||
{
|
||||
NvMapDeviceFile.DecrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle);
|
||||
NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue