public bool Wait(GpuContext gpuContext, NvFence fence) { lock (Lock) { Fence = fence; State = NvHostEventState.Waiting; // NOTE: nvservices code should always wait on the GPU side. // If we do this, we may get an abort or undefined behaviour when the GPU processing thread is blocked for a long period (for example, during shader compilation). // The reason for this is that the NVN code will try to wait until giving up. // This is done by trying to wait and signal multiple times until aborting after you are past the timeout. // As such, if it fails too many time, we enforce a wait on the CPU side indefinitely. // This allows to keep GPU and CPU in sync when we are slow. if (_failingCount == FailingCountMax) { Logger.PrintWarning(LogClass.ServiceNv, "GPU processing thread is too slow, waiting on CPU..."); bool timedOut = Fence.Wait(gpuContext, Timeout.InfiniteTimeSpan); GpuSignaled(); return(timedOut); } else { _waiterInformation = gpuContext.Synchronization.RegisterCallbackOnSyncpoint(Fence.Id, Fence.Value, GpuSignaled); return(true); } } }
public void Cancel(GpuContext gpuContext) { lock (Lock) { NvHostEventState oldState = State; State = NvHostEventState.Cancelling; if (oldState == NvHostEventState.Waiting && _waiterInformation != null) { gpuContext.Synchronization.UnregisterCallback(Fence.Id, _waiterInformation); _waiterInformation = null; if (_previousFailingFence.Id == Fence.Id && _previousFailingFence.Value == Fence.Value) { _failingCount++; } else { _failingCount = 1; _previousFailingFence = Fence; } } State = NvHostEventState.Cancelled; Event.WritableEvent.Clear(); } }
public void Wait(GpuContext gpuContext, NvFence fence) { Fence = fence; State = NvHostEventState.Waiting; _waiterInformation = gpuContext.Synchronization.RegisterCallbackOnSyncpoint(Fence.Id, Fence.Value, GpuSignaled); }
private void GpuSignaled(SyncpointWaiterHandle waiterInformation) { lock (Lock) { // If the signal does not match our current waiter, // then it is from a past fence and we should just ignore it. if (waiterInformation != null && waiterInformation != _waiterInformation) { return; } ResetFailingState(); Signal(); } }