Exemple #1
0
        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);
                }
            }
        }
Exemple #2
0
        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();
            }
        }
Exemple #3
0
        public void Wait(GpuContext gpuContext, NvFence fence)
        {
            Fence = fence;
            State = NvHostEventState.Waiting;

            _waiterInformation = gpuContext.Synchronization.RegisterCallbackOnSyncpoint(Fence.Id, Fence.Value, GpuSignaled);
        }
Exemple #4
0
        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();
            }
        }