private void TriggerRenderOrUpdateBesideTask(int actTaskIndex)
        {
            if (actTaskIndex < _devicesInUse !.Count)
            {
                // Render all targets for the current device
                var actDevice = _devicesInUse[actTaskIndex];
                using (_core.BeginMeasureActivityDuration(_perfDeviceRenderActivityNames[actDevice.DeviceIndex]))
                {
                    for (var loop = 0; loop < _registeredRenderLoops !.Count; loop++)
                    {
                        var actRenderLoop = _registeredRenderLoops[loop];

                        try
                        {
                            if (actRenderLoop.Device == actDevice)
                            {
                                actRenderLoop.Render();
                            }
                        }
                        catch (Exception ex)
                        {
                            // Mark this renderloop as invalid
                            _invalidRenderLoops.Enqueue(actRenderLoop);

                            // Publish exception info
                            GraphicsCore.PublishInternalExceptionInfo(ex, InternalExceptionLocation.EngineMainLoop_Render);
                        }
                    }
                }
            }
Пример #2
0
        /// <summary>
        /// Updates current RenderLoop registrations.
        /// </summary>
        /// <param name="renderingRenderLoops">The list of currently working RenderLoops.</param>
        internal async Task UpdateRenderLoopRegistrationsAsync(ICollection <RenderLoop> renderingRenderLoops)
        {
            // Unload all deregistered RenderLoops
            if (_unregisteredRenderLoops.Count > 0)
            {
                // Handle global and local RenderLoop collections
                List <RenderLoop>?copiedUnregisteredRenderLoops = null;

                lock (_registeredRenderLoopsLock)
                {
                    copiedUnregisteredRenderLoops = new List <RenderLoop>(_unregisteredRenderLoops);
                    _unregisteredRenderLoops.Clear();

                    foreach (var actRenderLoop in copiedUnregisteredRenderLoops)
                    {
                        // RemoveObject this RenderLoop for further rendering inside this pass
                        while (renderingRenderLoops.Contains(actRenderLoop))
                        {
                            renderingRenderLoops.Remove(actRenderLoop);
                        }
                    }
                }

                // Now perform cleaning operations
                foreach (var actRenderLoop in copiedUnregisteredRenderLoops)
                {
                    try
                    {
                        // Perform unloading of UI resources
                        await actRenderLoop.UnloadViewResourcesAsync();

                        // Deregister this view from the scene
                        if (actRenderLoop.Scene != null &&
                            actRenderLoop.ViewInformation != null &&
                            actRenderLoop.Scene.IsViewRegistered(actRenderLoop.ViewInformation))
                        {
                            actRenderLoop.Scene.DeregisterView(actRenderLoop.ViewInformation);
                        }
                    }
                    catch (Exception ex)
                    {
                        // Publish exception info
                        GraphicsCore.PublishInternalExceptionInfo(ex, InternalExceptionLocation.RenderLoop_Unload);
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Prepares rendering (Loads all needed resources).
        /// </summary>
        /// <param name="renderState">Current render state.</param>
        internal void PrepareRendering(RenderState renderState)
        {
            List <SceneObject>?invalidObjects = null;

            // Load all resources
            var sceneObjectArrayLength = this.ObjectsInternal.Count;
            var sceneObjectArray       = this.ObjectsInternal.BackingArray;

            for (var loop = 0; loop < sceneObjectArrayLength; loop++)
            {
                var actObject = sceneObjectArray[loop];
                if (actObject == null)
                {
                    continue;
                }

                try
                {
                    // Load all resources of the object
                    if (!actObject.IsLoaded(renderState.Device))
                    {
                        actObject.LoadResources(renderState.Device, renderState.CurrentResources !);
                    }
                }
                catch (Exception ex)
                {
                    // Publish exception info
                    GraphicsCore.PublishInternalExceptionInfo(
                        ex, InternalExceptionLocation.Loading3DObject);

                    //Build list of invalid objects
                    if (invalidObjects == null)
                    {
                        invalidObjects = new List <SceneObject>();
                    }

                    invalidObjects.Add(actObject);
                }
            }

            //RemoveObject all invalid objects
            if (invalidObjects != null)
            {
                this.HandleInvalidObjects(invalidObjects);
            }
        }
Пример #4
0
        /// <summary>
        /// Handles invalid objects.
        /// </summary>
        /// <param name="invalidObjects">List containing all invalid objects to handle.</param>
        private void HandleInvalidObjects(List <SceneObject> invalidObjects)
        {
            foreach (var actObject in invalidObjects)
            {
                //Unload the object if it is loaded
                try
                {
                    actObject.UnloadResources();
                }
                catch (Exception ex)
                {
                    // Publish exception info
                    GraphicsCore.PublishInternalExceptionInfo(
                        ex, InternalExceptionLocation.UnloadingInvalid3DObject);
                }

                //RemoveObject this object from this layer
                this.RemoveObject(actObject);
            }
        }
Пример #5
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);
        }