644de99e86
* Implement GPU syncpoints This adds support for GPU syncpoints on the GPU backend & nvservices. Everything that was implemented here is based on my researches, hardware testing of the GM20B and reversing of nvservices (8.1.0). Thanks to @fincs for the informations about some behaviours of the pusher and for the initial informations about syncpoints. * syncpoint: address gdkchan's comments * Add some missing logic to handle SubmitGpfifo correctly * Handle the NV event API correctly * evnt => hostEvent * Finish addressing gdkchan's comments * nvservices: write the output buffer even when an error is returned * dma pusher: Implemnet prefetch barrier lso fix when the commands should be prefetch. * Partially fix prefetch barrier * Add a missing syncpoint check in QueryEvent of NvHostSyncPt * Address Ac_K's comments and fix GetSyncpoint for ChannelResourcePolicy == Channel * fix SyncptWait & SyncptWaitEx cmds logic * Address ripinperi's comments * Address gdkchan's comments * Move user event management to the control channel * Fix mm implementation, nvdec works again * Address ripinperi's comments * Address gdkchan's comments * Implement nvhost-ctrl close accurately + make nvservices dispose channels when stopping the emulator * Fix typo in MultiMediaOperationType
101 lines
No EOL
2.8 KiB
C#
101 lines
No EOL
2.8 KiB
C#
using Ryujinx.Graphics.Gpu;
|
|
using Ryujinx.Graphics.Gpu.Synchronization;
|
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
|
using Ryujinx.HLE.HOS.Services.Nv.Types;
|
|
using System;
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
|
|
{
|
|
class NvHostEvent : IDisposable
|
|
{
|
|
public NvFence Fence;
|
|
public NvHostEventState State;
|
|
public KEvent Event;
|
|
|
|
private uint _eventId;
|
|
private NvHostSyncpt _syncpointManager;
|
|
private SyncpointWaiterHandle _waiterInformation;
|
|
|
|
public NvHostEvent(NvHostSyncpt syncpointManager, uint eventId, Horizon system)
|
|
{
|
|
Fence.Id = 0;
|
|
|
|
State = NvHostEventState.Available;
|
|
|
|
Event = new KEvent(system);
|
|
|
|
_eventId = eventId;
|
|
|
|
_syncpointManager = syncpointManager;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
Fence.Id = NvFence.InvalidSyncPointId;
|
|
Fence.Value = 0;
|
|
State = NvHostEventState.Available;
|
|
}
|
|
|
|
private void Signal()
|
|
{
|
|
NvHostEventState oldState = State;
|
|
|
|
State = NvHostEventState.Signaling;
|
|
|
|
if (oldState == NvHostEventState.Waiting)
|
|
{
|
|
Event.WritableEvent.Signal();
|
|
}
|
|
|
|
State = NvHostEventState.Signaled;
|
|
}
|
|
|
|
private void GpuSignaled()
|
|
{
|
|
Signal();
|
|
}
|
|
|
|
public void Cancel(GpuContext gpuContext)
|
|
{
|
|
if (_waiterInformation != null)
|
|
{
|
|
gpuContext.Synchronization.UnregisterCallback(Fence.Id, _waiterInformation);
|
|
|
|
Signal();
|
|
}
|
|
|
|
Event.WritableEvent.Clear();
|
|
}
|
|
|
|
public void Wait(GpuContext gpuContext, NvFence fence)
|
|
{
|
|
Fence = fence;
|
|
State = NvHostEventState.Waiting;
|
|
|
|
_waiterInformation = gpuContext.Synchronization.RegisterCallbackOnSyncpoint(Fence.Id, Fence.Value, GpuSignaled);
|
|
}
|
|
|
|
public string DumpState(GpuContext gpuContext)
|
|
{
|
|
string res = $"\nNvHostEvent {_eventId}:\n";
|
|
res += $"\tState: {State}\n";
|
|
|
|
if (State == NvHostEventState.Waiting)
|
|
{
|
|
res += "\tFence:\n";
|
|
res += $"\t\tId : {Fence.Id}\n";
|
|
res += $"\t\tThreshold : {Fence.Value}\n";
|
|
res += $"\t\tCurrent Value : {gpuContext.Synchronization.GetSyncpointValue(Fence.Id)}\n";
|
|
res += $"\t\tWaiter Valid : {_waiterInformation != null}\n";
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Event.ReadableEvent.DecrementReferenceCount();
|
|
Event.WritableEvent.DecrementReferenceCount();
|
|
}
|
|
}
|
|
} |