Example #1
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);
            }
        }
Example #2
0
        /// <summary>
        /// Adds a resource to the scene
        /// </summary>
        /// <typeparam name="TResourceType">The type of the resource.</typeparam>
        /// <param name="resourceFactory">The factory method which creates the resource object.</param>
        /// <param name="resourceKey">The key for the newly generated resource.</param>
        internal NamedOrGenericKey AddResource <TResourceType>(Func <EngineDevice, TResourceType> resourceFactory, NamedOrGenericKey resourceKey)
            where TResourceType : Resource
        {
            resourceFactory.EnsureNotNull(nameof(resourceFactory));

            this.InitializeResourceDictionaries();

            if (resourceKey == NamedOrGenericKey.Empty)
            {
                resourceKey = GraphicsCore.GetNextGenericResourceKey();
            }

            foreach (var actResourceDict in _registeredResourceDicts)
            {
                actResourceDict.AddResource(resourceKey, resourceFactory(actResourceDict.Device));
            }

            return(resourceKey);
        }
Example #3
0
        /// <summary>
        /// Prevents a default instance of the <see cref="EngineMainLoop"/> class from being created.
        /// </summary>
        internal EngineMainLoop(GraphicsCore graphicsCore)
        {
            _host = graphicsCore;

            _globalLoopAwaitors        = new ConcurrentQueue <Action>();
            _registeredRenderLoops     = new List <RenderLoop>();
            _unregisteredRenderLoops   = new List <RenderLoop>();
            _registeredRenderLoopsLock = new object();

            _drawing2DResourcesToUnload = new ConcurrentQueue <Drawing2DResourceBase>();

            _scenesForUnload     = new List <Scene>();
            _scenesForUnloadLock = new object();

            _cachedInputEventArgs = new GenericInputEventArgs();

            _logicUpdateAndPrepareRendering = new MainLoop_UpdateAndPrepareRendering(graphicsCore, this);
            _logicRenderAndUpdateBeside     = new MainLoop_RenderAndUpdateBeside(_host, this);
        }
Example #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);
            }
        }
            /// <summary>
            /// Loads a bitmap using WIC.
            /// </summary>
            /// <param name="inStream">The stream from which to load the texture file.</param>
            public static WicBitmapSourceInternal LoadBitmapSource(Stream inStream)
            {
                inStream.EnsureNotNull(nameof(inStream));
                inStream.EnsureReadable(nameof(inStream));

                GraphicsCore.EnsureGraphicsSupportLoaded();

                var wicFactory    = GraphicsCore.Current.FactoryWIC;
                var bitmapDecoder = wicFactory !.CreateDecoderFromStream(
                    inStream, DecodeOptions.CacheOnDemand);
                var formatConverter = wicFactory.CreateFormatConverter();

                formatConverter.Initialize(
                    bitmapDecoder.GetFrame(0),
                    DEFAULT_WIC_BITMAP_FORMAT,
                    BitmapDitherType.None,
                    null,
                    0.0,
                    BitmapPaletteType.Custom);

                return(new WicBitmapSourceInternal(bitmapDecoder, formatConverter));
            }
Example #6
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);
        }
        /// <summary>
        /// Adds the given resource to the dictionary.
        /// </summary>
        /// <param name="resource">The resource to add.</param>
        /// <param name="resourceKey">The key of the resource.</param>
        internal TResourceType AddResource <TResourceType>(NamedOrGenericKey resourceKey, TResourceType resource)
            where TResourceType : Resource
        {
            resource.EnsureNotNull(nameof(resource));

            //Perform some checks
            if (resource.Dictionary != null)
            {
                if (resource.Dictionary == this)
                {
                    return(resource);
                }
                if (resource.Dictionary != this)
                {
                    throw new ArgumentException("Given resource belongs to another ResourceDictionary!", nameof(resource));
                }
            }

            //Check given keys
            if (!resource.IsKeyEmpty && !resourceKey.IsEmpty && resource.Key != resourceKey)
            {
                throw new ArgumentException("Unable to override existing key on given resource!");
            }

            //RemoveObject another resource with the same name
            if (!resource.IsKeyEmpty)
            {
                this.RemoveResource(resource.Key);
            }
            if (!resourceKey.IsEmpty)
            {
                this.RemoveResource(resourceKey);
            }

            //Apply a valid key on the given resource object
            if (resource.Key.IsEmpty)
            {
                if (resourceKey.IsEmpty)
                {
                    resource.Key = GraphicsCore.GetNextGenericResourceKey();
                }
                else
                {
                    resource.Key = resourceKey;
                }
            }

            //AddObject the resource
            var newResource = new ResourceInfo(resource);

            _resources[resource.Key] = newResource;

            if (newResource.RenderableResource != null)
            {
                _renderableResources.Add(newResource.RenderableResource);
            }
            if (newResource.UpdatableResource != null)
            {
                _updatableResources.Add(newResource.UpdatableResource);
            }

            //Register this dictionary on the resource
            resource.Dictionary = this;

            return(resource);
        }
Example #8
0
 public Task LoadAsync()
 {
     return(Task.Factory.StartNew(() => GraphicsCore.Load(this)));
 }
Example #9
0
 public void Load()
 {
     GraphicsCore.Load(this);
 }