Example #1
0
        public void SetPassParameters(
            List <RenderLoop> renderingRenderLoops, IReadOnlyList <Scene> scenesToRender,
            IReadOnlyList <EngineDevice> devicesInUse, UpdateState updateState)
        {
            // Update all local members
            _renderingRenderLoops = renderingRenderLoops;
            _scenesToRender       = scenesToRender;
            _devicesInUse         = devicesInUse;
            _updateState          = updateState;

            // Clear temporary needed arrays
            while (_exceptionsDuringUpdate.TryDequeue(out _))
            {
            }
            _additionalContinuationActions.Clear();
            _prepareRenderTasks.Clear();

            // Prepare cached activity names for measuring scene updates
            while (_scenesToRender.Count > _perfSceneUpdateActivityNames.Count)
            {
                _perfSceneUpdateActivityNames.Add(
                    string.Format(SeeingSharpConstants.PERF_GLOBAL_UPDATE_SCENE, _perfSceneUpdateActivityNames.Count));
            }
        }
Example #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Updating3DArgs"/> class.
 /// </summary>
 public Updating3DArgs(UpdateState updateState)
 {
     this.UpdateState = updateState;
 }
Example #3
0
        /// <summary>
        /// Starts the engine's main loop.
        /// </summary>
        /// <param name="cancelToken"></param>
        /// <returns></returns>
        internal Task Start(CancellationToken cancelToken)
        {
            if (_runningTask != null)
            {
                throw new SeeingSharpGraphicsException("Unable to start engine's main loop: Loop has already started!");
            }

            _runningTask = Task.Factory.StartNew(async() =>
            {
                var renderStopWatch = new Stopwatch();
                renderStopWatch.Start();

                var renderingRenderLoops = new List <RenderLoop>(16);
                var scenesToRender       = new List <Scene>(16);
                var camerasToUpdate      = new List <Camera3DBase>(16);
                var devicesInUse         = new List <EngineDevice>(16);
                var inputFrames          = new List <InputFrame>(16);
                var updateState          = new UpdateState(TimeSpan.Zero, null);

                while (!cancelToken.IsCancellationRequested)
                {
                    var exceptionOccurred = false;

                    try
                    {
                        using (_host.BeginMeasureActivityDuration(SeeingSharpConstants.PERF_GLOBAL_PER_FRAME))
                        {
                            // Wait some time before doing anything..
                            var lastRenderMilliseconds = renderStopWatch.GetTrueElapsedMilliseconds();
                            var delayTime = SeeingSharpConstants.MINIMUM_FRAME_TIME_MS - lastRenderMilliseconds;
                            if (delayTime < SeeingSharpConstants.MINIMUM_DELAY_TIME_MS)
                            {
                                delayTime = SeeingSharpConstants.MINIMUM_DELAY_TIME_MS;
                            }

                            using (_host.BeginMeasureActivityDuration(SeeingSharpConstants.PERF_GLOBAL_WAIT_TIME))
                            {
                                SeeingSharpUtil.MaximumDelay(delayTime);
                            }

                            // Get all render loops
                            renderingRenderLoops.Clear();
                            lock (_registeredRenderLoopsLock)
                            {
                                renderingRenderLoops.AddRange(_registeredRenderLoops);
                            }

                            // Queries for devices / scenes in use
                            QueryForScenesAndCameras(renderingRenderLoops, scenesToRender, camerasToUpdate);
                            QueryForDevicesInUse(renderingRenderLoops, devicesInUse);
                            var deviceInUseCount = devicesInUse.Count;

                            // Handle device lost events
                            for (var loop = 0; loop < deviceInUseCount; loop++)
                            {
                                var actDevice = devicesInUse[loop];
                                if (!actDevice.IsLost)
                                {
                                    continue;
                                }

                                actDevice.RecreateAfterDeviceLost();
                            }

                            // Cleanup device resources
                            for (var loop = 0; loop < deviceInUseCount; loop++)
                            {
                                var actDevice = devicesInUse[loop];
                                actDevice.CleanupDeviceResourceCollection();
                            }

                            // Get all input frames
                            _host.InputGatherer !.QueryForCurrentFrames(inputFrames);

                            // Build new UpdateState object
                            var updateTime = renderStopWatch.Elapsed;
                            if (updateTime.TotalMilliseconds > 100.0)
                            {
                                updateTime = TimeSpan.FromMilliseconds(100.0);
                            }

                            updateState.Reset(updateTime, inputFrames);

                            // Restart the stopwatch
                            renderStopWatch.Restart();

                            // First global pass: Update scene and prepare rendering
                            _logicUpdateAndPrepareRendering.SetPassParameters(renderingRenderLoops, scenesToRender, devicesInUse, updateState);
                            await _logicUpdateAndPrepareRendering.ExecutePassAsync()
                            .ConfigureAwait(false);

                            // Update all cameras
                            foreach (var actCamera in camerasToUpdate)
                            {
                                actCamera.AnimationHandler.Update(updateState);
                            }

                            // Queries for devices / scenes in use (may have changed during prepare)
                            QueryForScenesAndCameras(renderingRenderLoops, scenesToRender, camerasToUpdate);
                            QueryForDevicesInUse(renderingRenderLoops, devicesInUse);

                            // Second global pass: Render scene(s) and update beside
                            _logicRenderAndUpdateBeside.SetPassParameters(renderingRenderLoops, scenesToRender, devicesInUse, updateState);
                            _logicRenderAndUpdateBeside.ExecutePass();

                            // Raise generic input event (if registered)
                            _cachedInputEventArgs.NotifyNewPass(inputFrames);
                            try
                            {
                                this.GenericInput?.Raise(this, _cachedInputEventArgs);
                            }
                            catch (Exception ex)
                            {
                                GraphicsCore.PublishInternalExceptionInfo(ex, InternalExceptionLocation.EngineMainLoop_GenericInputEvent);
                            }

                            // Clear unreferenced Scenes finally
                            lock (_scenesForUnloadLock)
                            {
                                foreach (var actScene in _scenesForUnload)
                                {
                                    actScene.UnloadResources();
                                    actScene.Clear(true);
                                }

                                _scenesForUnload.Clear();
                            }

                            // Unload all Direct2D resources which are not needed anymore
                            while (_drawing2DResourcesToUnload.TryDequeue(out var act2DResourceToUnload))
                            {
                                var deviceCount = _host.DeviceCount;
                                for (var loop = 0; loop < deviceCount; loop++)
                                {
                                    act2DResourceToUnload.UnloadResources(_host.Devices[loop]);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        exceptionOccurred = true;

                        // Publish exception info
                        GraphicsCore.PublishInternalExceptionInfo(ex, InternalExceptionLocation.EngineMainLoop_Loop);
                    }

                    // Execute global awaitors
                    var prevCount    = _globalLoopAwaitors.Count;
                    var currentIndex = 0;
                    while (currentIndex < prevCount)
                    {
                        currentIndex++;
                        if (_globalLoopAwaitors.TryDequeue(out var currentAction))
                        {
                            currentAction();
                        }
                    }

                    if (exceptionOccurred)
                    {
                        // Wait some time and try rendering again
                        await Task.Delay(1000);
                    }

                    // Handle suspend / resume
                    var suspendWaiter = _suspendWaiter;
                    if (suspendWaiter != null)
                    {
                        _suspendCallWaiterSource !.TrySetResult(null);

                        // Wait for resuming
                        await suspendWaiter;
                    }

                    // Trigger calculation of performance values
                    _host.PerformanceAnalyzer !.CalculateResults();
                }
            });

            return(_runningTask);
        }