Пример #1
0
        public JobHandle Execute(JobHandle inputHandles)
        {
            var       engines         = _engines;
            JobHandle combinedHandles = inputHandles;

            using (var profiler = new PlatformProfiler(_name))
            {
                for (var index = 0; index < engines.count; index++)
                {
                    ref var engine = ref engines[index];
                    using (profiler.Sample(engine.name))
                    {
                        combinedHandles = engine.Execute(inputHandles);
                    }
                }
            }
Пример #2
0
        public JobHandle Execute(JobHandle combinedHandles, ref Param _param)
        {
            var engines = _engines;

            using (var profiler = new PlatformProfiler(_name))
            {
                for (var index = 0; index < engines.count; index++)
                {
                    var engine = engines[index];
                    using (profiler.Sample(engine.name))
                        combinedHandles = JobHandle.CombineDependencies(combinedHandles, engine.Execute(combinedHandles, ref _param));
                }
            }

            return(combinedHandles);
        }
Пример #3
0
        public JobHandle Execute(JobHandle inputHandles)
        {
            var       sequenceItems   = _instancedSequence.items;
            JobHandle combinedHandles = inputHandles;

            using (var profiler = new PlatformProfiler(_name))
            {
                for (var index = 0; index < sequenceItems.count; index++)
                {
                    var engine = sequenceItems[index];
                    using (profiler.Sample(engine.name))
                        combinedHandles = engine.Execute(combinedHandles);
                }
            }

            return(combinedHandles);
        }
        void PreSubmissionPhase(ref JobHandle jobHandle, PlatformProfiler profiler)
        {
            using (profiler.Sample("Complete All Pending Jobs")) jobHandle.Complete(); //sync-point

            _entityCommandBuffer = new EntityCommandBuffer((Allocator)Common.Allocator.TempJob);

            foreach (var system in _submissionEngines)
            {
                system.entityCommandBuffer =
                    new EntityCommandBufferForSvelto(_entityCommandBuffer, World.EntityManager);
            }

            foreach (var system in _sveltoOnDotsHandleLifeTimeEngines)
            {
                system.entityCommandBuffer =
                    new EntityCommandBufferForSvelto(_entityCommandBuffer, World.EntityManager);
            }
        }
Пример #5
0
        void RemoveGroupAndEntitiesFromDB(int groupID)
        {
            using (var profiler = new PlatformProfiler("Remove Group"))
            {
                var dictionariesOfEntities = _groupEntityDB[groupID];
                foreach (var dictionaryOfEntities in dictionariesOfEntities)
                {
                    var platformProfiler = profiler;
                    dictionaryOfEntities.Value.RemoveEntitiesFromEngines(_entityEngines, ref platformProfiler);
                    var groupedGroupOfEntities = _groupsPerEntity[dictionaryOfEntities.Key];
                    groupedGroupOfEntities.Remove(groupID);
                }

                //careful, in this case I assume you really don't want to use this group anymore
                //so I remove it from the database
                _groupEntityDB.Remove(groupID);
            }
        }
Пример #6
0
        void SubmitEntityComponents()
        {
            using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission"))
            {
                int iterations = 0;
                do
                {
                    SingleSubmission(profiler);
                } while ((_groupedEntityToAdd.currentEntitiesCreatedPerGroup.count > 0 ||
                          _entitiesOperations.Count > 0) && ++iterations < 5);

#if DEBUG && !PROFILE_SVELTO
                if (iterations == 5)
                {
                    throw new ECSException("possible circular submission detected");
                }
#endif
            }
        }
        public void SubmitEntities(JobHandle jobHandle)
        {
            JobHandle RefHelper()
            {
                //execute submission engines and complete jobs because of this I don't need to do _ECBSystem.AddJobHandleForProducer(Dependency);
                using (var profiler = new PlatformProfiler("SveltoUECSEntitiesSubmissionGroup"))
                {
                    for (var index = 0; index < _engines.count; index++)
                    {
                        ref var engine = ref _engines[index];
                        using (profiler.Sample(engine.name))
                        {
                            jobHandle = engine.Execute(jobHandle);
                        }
                    }
                }

                return(jobHandle);
            }
        void PreSubmissionPhase(ref JobHandle jobHandle, PlatformProfiler profiler)
        {
            JobHandle BeforeECBFlushEngines()
            {
                JobHandle jobHandle = default;

                //execute submission engines and complete jobs because of this I don't need to do _ECBSystem.AddJobHandleForProducer(Dependency);

                for (var index = 0; index < _beforeSubmissionEngines.count; index++)
                {
                    ref var engine = ref _beforeSubmissionEngines[index];
                    using (profiler.Sample(engine.name))
                    {
                        jobHandle = JobHandle.CombineDependencies(jobHandle, engine.BeforeSubmissionUpdate(jobHandle));
                    }
                }

                return(jobHandle);
            }
        public void SubmitEntities(JobHandle jobHandle)
        {
            if (_submissionScheduler.paused)
            {
                return;
            }

            using (var profiler = new PlatformProfiler("SveltoUECSEntitiesSubmissionGroup - PreSubmissionPhase"))
            {
                PreSubmissionPhase(ref jobHandle, profiler);

                //Submit Svelto Entities, calls Add/Remove/MoveTo that can be used by the IUECSSubmissionEngines
                using (profiler.Sample("Submit svelto entities"))
                {
                    _submissionScheduler.SubmitEntities();
                }

                AfterSubmissionPhase(profiler);
            }
        }
        /// <summary>
        /// Dispose an EngineRoot once not used anymore, so that all the
        /// engines are notified with the entities removed.
        /// It's a clean up process.
        /// </summary>
        public void Dispose()
        {
            using (var profiler = new PlatformProfiler("Final Dispose"))
            {
                foreach (FasterDictionary <uint, FasterDictionary <RefWrapper <Type>, ITypeSafeDictionary> > .KeyValuePairFast groups in _groupEntityComponentsDB)
                {
                    foreach (FasterDictionary <RefWrapper <Type>, ITypeSafeDictionary> .KeyValuePairFast entityList in groups.Value)
                    {
                        entityList.Value.RemoveEntitiesFromEngines(_reactiveEnginesAddRemove, profiler,
                                                                   new ExclusiveGroupStruct(groups.Key));
                        entityList.Value.Dispose();
                    }
                }

                _groupEntityComponentsDB.Clear();
                _groupsPerEntity.Clear();

                foreach (var engine in _disposableEngines)
                {
                    engine.Dispose();
                }

                _disposableEngines.Clear();
                _enginesSet.Clear();
                _enginesTypeSet.Clear();
                _reactiveEnginesSwap.Clear();
                _reactiveEnginesAddRemove.Clear();

                _entitiesOperations.Clear();
                _transientEntitiesOperations.Clear();
                scheduler.Dispose();
#if DEBUG && !PROFILE_SVELTO
                _idCheckers.Clear();
#endif
                _groupedEntityToAdd = null;

                _entitiesStream.Dispose();
            }

            GC.SuppressFinalize(this);
        }
        ///--------------------------------------------
        ///
        void MoveEntityFromAndToEngines(IEntityBuilder[] entityBuilders, EGID fromEntityGID, EGID?toEntityGID)
        {
            using (var sampler = new PlatformProfiler("Move Entity From Engines"))
            {
                var fromGroup = GetGroup(fromEntityGID.groupID);

                //Check if there is an EntityInfoView linked to this entity, if so it's a DynamicEntityDescriptor!
                if (fromGroup.TryGetValue(new RefWrapper <Type>(EntityBuilderUtilities.ENTITY_STRUCT_INFO_VIEW),
                                          out var entityInfoViewDic) &&
                    (entityInfoViewDic as ITypeSafeDictionary <EntityStructInfoView>).TryGetValue(fromEntityGID.entityID,
                                                                                                  out var entityInfoView))
                {
                    MoveEntityViews(fromEntityGID, toEntityGID, entityInfoView.entitiesToBuild, fromGroup, sampler);
                }
                //otherwise it's a normal static entity descriptor
                else
                {
                    MoveEntityViews(fromEntityGID, toEntityGID, entityBuilders, fromGroup, sampler);
                }
            }
        }
Пример #12
0
        ///--------------------------------------------
        ///
        void MoveEntityFromAndToEngines(IComponentBuilder[] componentBuilders, EGID fromEntityGID, EGID?toEntityGID)
        {
            using (var sampler = new PlatformProfiler("Move Entity From Engines")) {
                var fromGroup = GetGroup(fromEntityGID.groupID);

                //Check if there is an EntityInfo linked to this entity, if so it's a DynamicEntityDescriptor!
                if (fromGroup.TryGetValue(new RefWrapperType(ComponentBuilderUtilities.ENTITY_INFO_COMPONENT)
                                          , out var entityInfoDic) &&
                    (entityInfoDic as ITypeSafeDictionary <EntityInfoComponent>).TryGetValue(
                        fromEntityGID.entityID, out var entityInfo))
                {
                    MoveEntityComponents(fromEntityGID, toEntityGID, entityInfo.componentsToBuild, fromGroup
                                         , sampler);
                }
                //otherwise it's a normal static entity descriptor
                else
                {
                    MoveEntityComponents(fromEntityGID, toEntityGID, componentBuilders, fromGroup, sampler);
                }
            }
        }
        /// <summary>
        /// Dispose an EngineRoot once not used anymore, so that all the
        /// engines are notified with the entities removed.
        /// It's a clean up process.
        /// </summary>
        public void Dispose()
        {
            using (var profiler = new PlatformProfiler("Final Dispose"))
            {
                foreach (var groups in _groupEntityViewsDB)
                {
                    foreach (var entityList in groups.Value)
                    {
                        entityList.Value.RemoveEntitiesFromEngines(_reactiveEnginesAddRemove, profiler,
                                                                   new ExclusiveGroupStruct(groups.Key));
                    }
                }

                _groupEntityViewsDB.Clear();
                _groupsPerEntity.Clear();

                foreach (var engine in _disposableEngines)
                {
                    engine.Dispose();
                }

                _disposableEngines.Clear();
                _enginesSet.Clear();
                _enginesTypeSet.Clear();
                _reactiveEnginesSwap.Clear();
                _reactiveEnginesAddRemove.Clear();

                _entitiesOperations.Clear();
                _transientEntitiesOperations.Clear();
                _scheduler.Dispose();
#if DEBUG && !PROFILER
                _idCheckers.Clear();
#endif
                _groupedEntityToAdd = null;

                _entitiesStream.Dispose();
            }

            GC.SuppressFinalize(this);
        }
Пример #14
0
        IEnumerator SubmitEntityComponents(uint maxNumberOfOperations)
        {
            using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission"))
            {
                int iterations = 0;
                do
                {
                    var submitEntityComponents = SingleSubmission(profiler, maxNumberOfOperations);
                    while (submitEntityComponents.MoveNext() == true)
                    {
                        yield return(null);
                    }
                } while ((_groupedEntityToAdd.currentEntitiesCreatedPerGroup.count > 0 ||
                          _entitiesOperations.count > 0) && ++iterations < 5);

#if DEBUG && !PROFILE_SVELTO
                if (iterations == 5)
                {
                    throw new ECSException("possible circular submission detected");
                }
#endif
            }
        }
        //Right, when you record a command outside of a job using the regular ECB, you don't pass it a sort key.
        //We instead use a constant for the main thread that is actually set to Int32.MaxValue. Where as the commands
        //that are recording from jobs with the ParallelWriter, get a lower value sort key from the job. Because we
        //playback the commands in order based on this sort key, the ParallelWriter commands end up happening before
        //the main thread commands. This is where your error is coming from because the Instantiate command happens at
        //the end because it's sort key is Int32.MaxValue.
        //We don't recommend mixing the main thread and ParallelWriter commands in a single ECB for this reason.
        public void SubmitEntities(JobHandle jobHandle)
        {
            if (_submissionScheduler.paused == true)
            {
                return;
            }

            using (var profiler = new PlatformProfiler("SveltoDOTSEntitiesSubmissionGroup"))
            {
                using (profiler.Sample("PreSubmissionPhase"))
                {
                    PreSubmissionPhase(ref jobHandle, profiler);
                }

                //Submit Svelto Entities, calls Add/Remove/MoveTo that can be used by the IDOTS ECSSubmissionEngines
                _submissionScheduler.SubmitEntities();

                using (profiler.Sample("AfterSubmissionPhase"))
                {
                    AfterSubmissionPhase(profiler);
                }
            }
        }
        public void MoveEntityFromDictionaryAndEngines(EGID fromEntityGid, EGID?toEntityID,
                                                       ITypeSafeDictionary toGroup,
                                                       Dictionary <Type, FasterList <IHandleEntityViewEngineAbstracted> > engines,
                                                       ref PlatformProfiler profiler)
        {
            var valueIndex = GetValueIndex(fromEntityGid.entityID);

            if (engines != null)
            {
                RemoveEntityViewFromEngines(engines, ref _values[valueIndex], ref profiler, toGroup != null);
            }

            if (toGroup != null)
            {
                var     toGroupCasted = toGroup as TypeSafeDictionary <TValue>;
                ref var entity        = ref _values[valueIndex];
                var     previousGroup = fromEntityGid.groupID;

                ///
                /// NOTE I WOULD EVENTUALLY NEED TO REUSE THE REAL ID OF THE REMOVING ELEMENT
                /// SO THAT I CAN DECREASE THE GLOBAL GROUP COUNT
                ///

                //      entity.ID = EGID.UPDATE_REAL_ID_AND_GROUP(entity.ID, toEntityID.groupID, entityCount);
                if (HasEgid)
                {
                    (entity as INeedEGID).ID = toEntityID.Value;
                }

                var index = toGroupCasted.Add(fromEntityGid.entityID, ref entity);

                if (engines != null)
                {
                    AddEntityViewToEngines(engines, ref toGroupCasted._values[index], previousGroup,
                                           ref profiler);
                }
            }
        /// <summary>
        /// Dispose an EngineRoot once not used anymore, so that all the
        /// engines are notified with the entities removed.
        /// It's a clean up process.
        /// </summary>
        public void Dispose()
        {
            var profiler = new PlatformProfiler();

            using (profiler.StartNewSession("Final Dispose"))
            {
                foreach (var groups in _groupEntityDB)
                {
                    foreach (var entityList in groups.Value)
                    {
                        try
                        {
                            entityList.Value.RemoveEntitiesFromEngines(_entityEngines, ref profiler);
                        }
                        catch (Exception e)
                        {
                            Console.LogException(e);
                        }
                    }
                }

                foreach (var engine in _disposableEngines)
                {
                    try
                    {
                        engine.Dispose();
                    }
                    catch (Exception e)
                    {
                        Console.LogException(e);
                    }
                }
            }

            GC.SuppressFinalize(this);
        }
Пример #18
0
        internal ContinuationEnumerator Run <TRunner>(TRunner runner, ref TTask task)
            where TRunner : class, IRunner <LeanSveltoTask <TTask> >
        {
            using (var profiler = new PlatformProfiler("LeanSveltoTask.Run"))
            {
                using (profiler.Sample("create task"))
                    _sveltoTask = new SveltoTaskWrapper <TTask, IRunner <LeanSveltoTask <TTask> > >(ref task, runner);
#if DEBUG && !PROFILE_SVELTO
                DBC.Tasks.Check.Require(IS_TASK_STRUCT == true || task != null,
                                        "A valid enumerator is required to enable a LeanSveltTask ".FastConcat(ToString()));

                DBC.Tasks.Check.Require(runner != null, "SetScheduler function has never been called");
#endif

                using (profiler.Sample("fetch enumerator"))
                    _continuationEnumerator = new ContinuationEnumerator(ContinuationPool.RetrieveFromPool());
                _threadSafeSveltoTaskStates.started = true;

                using (profiler.Sample("StartCoroutine"))
                    runner.StartCoroutine(this);

                return(_continuationEnumerator);
            }
        }
Пример #19
0
        void Dispose(bool disposing)
        {
            _isDisposing = disposing;

            if (disposing == false)
            {
                return;
            }

            using (var profiler = new PlatformProfiler("Final Dispose"))
            {
                //Note: The engines are disposed before the the remove callback to give the chance to behave
                //differently if a remove happens as a consequence of a dispose
                //The pattern is to implement the IDisposable interface and set a flag in the engine. The
                //remove callback will then behave differently according the flag.
                foreach (var engine in _disposableEngines)
                {
                    try
                    {
                        if (engine is IDisposingEngine dengine)
                        {
                            dengine.isDisposing = true;
                        }
                        engine.Dispose();
                    }
                    catch (Exception e)
                    {
                        Console.LogException(e);
                    }
                }

                foreach (var groups in _groupEntityComponentsDB)
                {
                    foreach (var entityList in groups.value)
                    {
                        try
                        {
                            ITypeSafeDictionary typeSafeDictionary = entityList.value;

                            typeSafeDictionary.ExecuteEnginesDisposeCallbacks_Group(_reactiveEnginesDispose, groups.key,
                                                                                    profiler);
                        }
                        catch (Exception e)
                        {
                            Console.LogException(e);
                        }
                    }
                }

                foreach (var groups in _groupEntityComponentsDB)
                {
                    foreach (var entityList in groups.value)
                    {
                        entityList.value.Dispose();
                    }
                }

                foreach (var type in _groupFilters)
                {
                    foreach (var group in type.value)
                    {
                        group.value.Dispose();
                    }
                }

                _groupFilters.Clear();

                DisposeFilters();

#if UNITY_NATIVE
                _nativeAddOperationQueue.Dispose();
                _nativeRemoveOperationQueue.Dispose();
                _nativeSwapOperationQueue.Dispose();
#endif
                _groupEntityComponentsDB.Clear();
                _groupsPerEntity.Clear();

                _disposableEngines.Clear();
                _enginesSet.Clear();
                _enginesTypeSet.Clear();
                _reactiveEnginesSwap.Clear();
                _reactiveEnginesAdd.Clear();
                _reactiveEnginesRemove.Clear();
                _reactiveEnginesDispose.Clear();
                _reactiveEnginesSubmission.Clear();

                _groupedEntityToAdd.Dispose();

                _entityLocator.DisposeEntityReferenceMap();

                _entityStreams.Dispose();
                scheduler.Dispose();
            }
        }
        void SubmitEntityViews()
        {
            using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission"))
            {
                if (_entitiesOperations.Count > 0)
                {
                    using (profiler.Sample("Remove and Swap operations"))
                    {
#if DEBUG && !PROFILER
                        _entitiesOperationsDebug.Clear();
#endif
                        _transientEntitiesOperations.FastClear();
                        _transientEntitiesOperations.AddRange(_entitiesOperations);
                        _entitiesOperations.FastClear();
                        var entitiesOperations = _transientEntitiesOperations.ToArrayFast();
                        for (var i = 0; i < _transientEntitiesOperations.Count; i++)
                        {
                            try
                            {
                                switch (entitiesOperations[i].type)
                                {
                                case EntitySubmitOperationType.Swap:
                                    SwapEntityGroup(entitiesOperations[i].builders,
                                                    entitiesOperations[i].entityDescriptor,
                                                    new EGID(entitiesOperations[i].ID,
                                                             entitiesOperations[i].fromGroupID),
                                                    new EGID(
                                                        entitiesOperations[i].toID,
                                                        entitiesOperations[i].toGroupID));
                                    break;

                                case EntitySubmitOperationType.Remove:
                                    MoveEntity(entitiesOperations[i].builders,
                                               new EGID(entitiesOperations[i].ID,
                                                        entitiesOperations[i].fromGroupID),
                                               entitiesOperations[i].entityDescriptor, new EGID());
                                    break;

                                case EntitySubmitOperationType.RemoveGroup:
                                    RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromGroupID);
                                    break;
                                }
                            }
                            catch (Exception e)
                            {
#if DEBUG && !PROFILER
                                var str = "Crash while executing Entity Operation"
                                          .FastConcat(entitiesOperations[i].type.ToString())
                                          .FastConcat(" id: ")
                                          .FastConcat(entitiesOperations[i].ID)
                                          .FastConcat(" to id: ")
                                          .FastConcat(entitiesOperations[i].toID)
                                          .FastConcat(" from groupid: ")
                                          .FastConcat(entitiesOperations[i].fromGroupID)
                                          .FastConcat(" to groupid: ")
                                          .FastConcat(entitiesOperations[i].toGroupID);
#if RELAXED_ECS
                                Console.LogException(str.FastConcat(" ", entitiesOperations[i].trace), e);
#else
                                throw new ECSException(str.FastConcat(" ").FastConcat(entitiesOperations[i].trace), e);
#endif
#else
                                var str = "Entity Operation is ".FastConcat(entitiesOperations[i].type.ToString())
                                          .FastConcat(" id: ")
                                          .FastConcat(entitiesOperations[i].ID)
                                          .FastConcat(" to id: ")
                                          .FastConcat(entitiesOperations[i].toID)
                                          .FastConcat(" from groupid: ")
                                          .FastConcat(entitiesOperations[i].fromGroupID)
                                          .FastConcat(" to groupid: ")
                                          .FastConcat(entitiesOperations[i].toGroupID);

                                Console.LogException(str, e);
#endif
                            }
                        }
                    }
                }

                if (_groupedEntityToAdd.current.Count > 0)
                {
                    using (profiler.Sample("Add operations"))
                    {
                        //use other as source from now on current will be use to write new entityViews
                        _groupedEntityToAdd.Swap();

                        try
                        {
                            //Note: if N entity of the same type are added on the same frame the Add callback is called N
                            //times on the same frame. if the Add callback builds a new entity, that entity will not
                            //be available in the database until the N callbacks are done solving it could be complicated as
                            //callback and database update must be interleaved.
                            AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd.other, profiler);
                        }
#if !DEBUG
                        catch (Exception e)
                        {
                            Console.LogException(e);
                        }
#endif
                        finally
                        {
                            //other can be cleared now, but let's avoid deleting the dictionary every time
                            _groupedEntityToAdd.ClearOther();
                        }
                    }
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Todo: it would be probably better to split even further the logic between submission and callbacks
        /// Something to do when I will optimize the callbacks
        /// </summary>
        /// <param name="profiler"></param>
        /// <param name="maxNumberOfOperations"></param>
        IEnumerator SingleSubmission(PlatformProfiler profiler, uint maxNumberOfOperations)
        {
#if UNITY_NATIVE
            NativeOperationSubmission(profiler);
#endif
            ClearChecks();

            bool entitiesAreSubmitted = false;
            uint numberOfOperations   = 0;

            if (_entitiesOperations.count > 0)
            {
                using (profiler.Sample("Remove and Swap operations"))
                {
                    _transientEntitiesOperations.FastClear();
                    _entitiesOperations.CopyValuesTo(_transientEntitiesOperations);
                    _entitiesOperations.FastClear();

                    EntitySubmitOperation[] entitiesOperations = _transientEntitiesOperations.ToArrayFast(out var count);
                    for (var i = 0; i < count; i++)
                    {
                        try
                        {
                            switch (entitiesOperations[i].type)
                            {
                            case EntitySubmitOperationType.Swap:
                                MoveEntityFromAndToEngines(entitiesOperations[i].builders,
                                                           entitiesOperations[i].fromID, entitiesOperations[i].toID);
                                break;

                            case EntitySubmitOperationType.Remove:
                                MoveEntityFromAndToEngines(entitiesOperations[i].builders,
                                                           entitiesOperations[i].fromID, null);
                                break;

                            case EntitySubmitOperationType.RemoveGroup:
                                RemoveEntitiesFromGroup(
                                    entitiesOperations[i].fromID.groupID, profiler);
                                break;

                            case EntitySubmitOperationType.SwapGroup:
                                SwapEntitiesBetweenGroups(entitiesOperations[i].fromID.groupID,
                                                          entitiesOperations[i].toID.groupID, profiler);
                                break;
                            }
                        }
                        catch
                        {
                            var str = "Crash while executing Entity Operation "
                                      .FastConcat(entitiesOperations[i].type.ToString());


                            Svelto.Console.LogError(str.FastConcat(" ")
#if DEBUG && !PROFILE_SVELTO
                                                    .FastConcat(entitiesOperations[i].trace.ToString())
#endif
                                                    );

                            throw;
                        }

                        ++numberOfOperations;

                        if ((uint)numberOfOperations >= (uint)maxNumberOfOperations)
                        {
                            yield return(null);

                            numberOfOperations = 0;
                        }
                    }
                }

                entitiesAreSubmitted = true;
            }

            _groupedEntityToAdd.Swap();

            if (_groupedEntityToAdd.otherEntitiesCreatedPerGroup.count > 0)
            {
                using (profiler.Sample("Add operations"))
                {
                    try
                    {
                        using (profiler.Sample("Add entities to database"))
                        {
                            //each group is indexed by entity view type. for each type there is a dictionary indexed by entityID
                            foreach (var groupToSubmit in _groupedEntityToAdd.otherEntitiesCreatedPerGroup)
                            {
                                var groupID = groupToSubmit.Key;
                                var groupDB = GetOrCreateGroup(groupID, profiler);

                                //add the entityComponents in the group
                                foreach (var entityComponentsToSubmit in _groupedEntityToAdd.other[groupID])
                                {
                                    var type = entityComponentsToSubmit.Key;
                                    var targetTypeSafeDictionary = entityComponentsToSubmit.Value;
                                    var wrapper = new RefWrapperType(type);

                                    ITypeSafeDictionary dbDic = GetOrCreateTypeSafeDictionary(groupID, groupDB, wrapper,
                                                                                              targetTypeSafeDictionary);

                                    //Fill the DB with the entity components generate this frame.
                                    dbDic.AddEntitiesFromDictionary(targetTypeSafeDictionary, groupID);
                                }
                            }
                        }

                        //then submit everything in the engines, so that the DB is up to date with all the entity components
                        //created by the entity built
                        using (profiler.Sample("Add entities to engines"))
                        {
                            foreach (var groupToSubmit in _groupedEntityToAdd.otherEntitiesCreatedPerGroup)
                            {
                                var groupID = groupToSubmit.Key;
                                var groupDB = _groupEntityComponentsDB[groupID];
//entityComponentsToSubmit is the array of components found in the groupID per component type.
//if there are N entities to submit, and M components type to add for each entity, this foreach will run NxM times.
                                foreach (var entityComponentsToSubmit in _groupedEntityToAdd.other[groupID])
                                {
                                    var realDic = groupDB[new RefWrapperType(entityComponentsToSubmit.Key)];

                                    entityComponentsToSubmit.Value.ExecuteEnginesAddOrSwapCallbacks(_reactiveEnginesAddRemove, realDic,
                                                                                                    null, new ExclusiveGroupStruct(groupID), in profiler);

                                    numberOfOperations += entityComponentsToSubmit.Value.count;

                                    if (numberOfOperations >= maxNumberOfOperations)
                                    {
                                        yield return(null);

                                        numberOfOperations = 0;
                                    }
                                }
                            }
                        }
                    }
                    finally
                    {
                        using (profiler.Sample("clear double buffering"))
                        {
                            //other can be cleared now, but let's avoid deleting the dictionary every time
                            _groupedEntityToAdd.ClearOther();
                        }
                    }
                }

                entitiesAreSubmitted = true;
            }

            if (entitiesAreSubmitted)
            {
                var enginesCount = _reactiveEnginesSubmission.count;
                for (int i = 0; i < enginesCount; i++)
                {
                    _reactiveEnginesSubmission[i].EntitiesSubmitted();
                }
            }
        }
Пример #22
0
        void SubmitEntityViews()
        {
            using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission"))
            {
                if (_entitiesOperations.Count > 0)
                {
                    using (profiler.Sample("Remove and Swap operations"))
                    {
                        _transientEntitiesOperations.FastClear();
                        var entitySubmitOperations = _entitiesOperations.GetValuesArray(out var count);
                        _transientEntitiesOperations.AddRange(entitySubmitOperations, count);
                        _entitiesOperations.FastClear();

                        var entitiesOperations = _transientEntitiesOperations.ToArrayFast();
                        for (var i = 0; i < _transientEntitiesOperations.Count; i++)
                        {
                            try
                            {
                                switch (entitiesOperations[i].type)
                                {
                                case EntitySubmitOperationType.Swap:
                                    SwapEntityGroup(entitiesOperations[i].builders,
                                                    entitiesOperations[i].entityDescriptor,
                                                    entitiesOperations[i].fromID,
                                                    entitiesOperations[i].toID);
                                    break;

                                case EntitySubmitOperationType.Remove:
                                    MoveEntity(entitiesOperations[i].builders,
                                               entitiesOperations[i].fromID,
                                               entitiesOperations[i].entityDescriptor, null);
                                    break;

                                case EntitySubmitOperationType.RemoveGroup:
                                    if (entitiesOperations[i].entityDescriptor == null)
                                    {
                                        RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromID.groupID);
                                    }
                                    else
                                    {
                                        RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromID.groupID,
                                                                     entitiesOperations[i].entityDescriptor);
                                    }

                                    break;
                                }
                            }
                            catch (Exception e)
                            {
                                var str = "Crash while executing Entity Operation "
                                          .FastConcat(entitiesOperations[i].type.ToString());
#if RELAXED_ECS && !PROFILER
                                Console.LogException(str.FastConcat(" "
#if DEBUG && !PROFILER
                                                                    , entitiesOperations[i].trace
#endif
                                                                    ), e);
#else
                                throw new ECSException(str.FastConcat(" ")
#if DEBUG && !PROFILER
                                                       .FastConcat(entitiesOperations[i].trace)
#endif
                                                       , e);
#endif
                            }
                        }
                    }
                }

                if (_groupedEntityToAdd.currentEntitiesCreatedPerGroup.Count > 0)
                {
                    using (profiler.Sample("Add operations"))
                    {
                        //use other as source from now on current will be use to write new entityViews
                        _groupedEntityToAdd.Swap();

                        try
                        {
                            //Note: if N entity of the same type are added on the same frame the Add callback is called
                            //N times on the same frame. if the Add callback builds a new entity, that entity will not
                            //be available in the database until the N callbacks are done. Solving this could be
                            //complicated as callback and database update must be interleaved.
                            AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd, profiler);
                        }
                        finally
                        {
                            //other can be cleared now, but let's avoid deleting the dictionary every time
                            _groupedEntityToAdd.ClearOther();
                        }
                    }
                }
            }
        }
Пример #23
0
 void FixedUpdate()
 {
     using (var platform = new PlatformProfiler("Physic tasks")) ExecuteRoutines(_physicRoutines, platform);
 }
Пример #24
0
 void LateUpdate()
 {
     using (var platform = new PlatformProfiler("Late tasks")) ExecuteRoutines(_lateRoutines, platform);
 }
Пример #25
0
 public void OnGUI()
 {
     using (var platform = new PlatformProfiler("onGui tasks")) ExecuteRoutines(_onGuiRoutines, platform);
 }
        static void ExecuteRoutines(ThreadSafeFasterList <FasterList <IProcessSveltoTasks> > list, PlatformProfiler profiler)
        {
            var orderedRoutines = list.ToArrayFast(out var orderedCount);

            for (int ii = 0; ii < orderedCount; ii++)
            {
                if (orderedRoutines[ii] == null)
                {
                    continue;
                }

                var routines = orderedRoutines[ii];

                for (int i = 0; i < routines.count; i++)
                {
                    var ret = routines[i].MoveNext(profiler);
                    if (ret == false)
                    {
                        routines.UnorderedRemoveAt(i);
                        i--;
                    }
                }
            }
        }
Пример #27
0
            IEnumerator <bool> Invoke()
            {
                while (true)
                {
                    DBC.ECS.Check.Require(_enginesRoot.IsValid, "ticking an GCed engines root?");

                    var enginesRootTarget           = _enginesRoot.Target;
                    var entitiesSubmissionScheduler = enginesRootTarget.scheduler;

                    if (entitiesSubmissionScheduler.paused == false)
                    {
                        DBC.ECS.Check.Require(entitiesSubmissionScheduler.isRunning == false
                                              , "A submission started while the previous one was still flushing");
                        entitiesSubmissionScheduler.isRunning = true;

                        using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission"))
                        {
                            var iterations       = 0;
                            var hasEverSubmitted = false;
#if UNITY_NATIVE
                            enginesRootTarget.FlushNativeOperations(profiler);
#endif

                            //todo: proper unit test structural changes made as result of add/remove callbacks
                            while (enginesRootTarget.HasMadeNewStructuralChangesInThisIteration() && iterations++ < 5)
                            {
                                hasEverSubmitted = true;

                                while (true)
                                {
                                    _privateSubmitEntities.MoveNext();
                                    if (_privateSubmitEntities.Current == true)
                                    {
                                        using (profiler.Yield())
                                        {
                                            yield return(true);
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
#if UNITY_NATIVE
                                if (enginesRootTarget.HasMadeNewStructuralChangesInThisIteration())
                                {
                                    enginesRootTarget.FlushNativeOperations(profiler);
                                }
#endif
                            }

#if DEBUG && !PROFILE_SVELTO
                            if (iterations == 5)
                            {
                                throw new ECSException("possible circular submission detected");
                            }
#endif
                            if (hasEverSubmitted)
                            {
                                enginesRootTarget.NotifyReactiveEnginesOnSubmission();
                            }
                        }

                        entitiesSubmissionScheduler.isRunning = false;
                        ++entitiesSubmissionScheduler.iteration;
                    }

                    yield return(false);
                }
            }
        void MoveEntityView(EGID entityGID, EGID?toEntityGID, Dictionary <Type, ITypeSafeDictionary> toGroup,
                            ref Dictionary <Type, ITypeSafeDictionary> fromGroup, Type entityViewType, PlatformProfiler profiler)
        {
            if (fromGroup.TryGetValue(entityViewType, out var fromTypeSafeDictionary) == false)
            {
                throw new ECSException("no entities in from group eid: ".FastConcat(entityGID.entityID)
                                       .FastConcat(" group: ").FastConcat(entityGID.groupID));
            }

            ITypeSafeDictionary toEntitiesDictionary = null;

            //in case we want to move to a new group, otherwise is just a remove
            if (toEntityGID != null)
            {
                if (toGroup.TryGetValue(entityViewType, out toEntitiesDictionary) == false)
                {
                    toEntitiesDictionary = fromTypeSafeDictionary.Create();
                    toGroup.Add(entityViewType, toEntitiesDictionary);
                }

                if (_groupsPerEntity.TryGetValue(entityViewType, out var groupedGroup) == false)
                {
                    groupedGroup = _groupsPerEntity[entityViewType] = new FasterDictionary <uint, ITypeSafeDictionary>();
                }

                groupedGroup[toEntityGID.Value.groupID] = toEntitiesDictionary;
            }

            if (fromTypeSafeDictionary.Has(entityGID.entityID) == false)
            {
                throw new EntityNotFoundException(entityGID, entityViewType);
            }

            fromTypeSafeDictionary.MoveEntityFromDictionaryAndEngines(entityGID, toEntityGID,
                                                                      toEntitiesDictionary, _entityEngines,
                                                                      ref profiler);

            if (fromTypeSafeDictionary.Count == 0) //clean up
            {
                _groupsPerEntity[entityViewType].Remove(entityGID.groupID);

                //I don't remove the group if empty on purpose, in case it needs to be reused however I trim it to save
                //memory
                fromTypeSafeDictionary.Trim();
            }
        }
Пример #29
0
        /// <summary>
        /// Dispose an EngineRoot once not used anymore, so that all the
        /// engines are notified with the entities removed.
        /// It's a clean up process.
        /// </summary>
        public void Dispose()
        {
            _isDisposing = true;

            using (var profiler = new PlatformProfiler("Final Dispose"))
            {
                //Note: The engines are disposed before the the remove callback to give the chance to behave
                //differently if a remove happens as a consequence of a dispose
                //The pattern is to implement the IDisposable interface and set a flag in the engine. The
                //remove callback will then behave differently according the flag.
                foreach (var engine in _disposableEngines)
                {
                    try
                    {
                        if (engine is IDisposingEngine dengine)
                        {
                            dengine.isDisposing = true;
                        }
                        engine.Dispose();
                    }
                    catch (Exception e)
                    {
                        Svelto.Console.LogException(e);
                    }
                }

                foreach (var groups in _groupEntityComponentsDB)
                {
                    foreach (var entityList in groups.Value)
                    {
                        try
                        {
                            entityList.Value.ExecuteEnginesRemoveCallbacks(_reactiveEnginesAddRemoveOnDispose, profiler
                                                                           , new ExclusiveGroupStruct(groups.Key));
                        }
                        catch (Exception e)
                        {
                            Svelto.Console.LogException(e);
                        }
                    }
                }

                foreach (var groups in _groupEntityComponentsDB)
                {
                    foreach (var entityList in groups.Value)
                    {
                        entityList.Value.Dispose();
                    }
                }

                foreach (var type in _groupFilters)
                {
                    foreach (var group in type.Value)
                    {
                        group.Value.Dispose();
                    }
                }

                _groupFilters.Clear();

#if UNITY_NATIVE
                _nativeAddOperationQueue.Dispose();
                _nativeRemoveOperationQueue.Dispose();
                _nativeSwapOperationQueue.Dispose();
#endif
                _groupEntityComponentsDB.Clear();
                _groupsPerEntity.Clear();

                _disposableEngines.Clear();
                _enginesSet.Clear();
                _enginesTypeSet.Clear();
                _reactiveEnginesSwap.Clear();
                _reactiveEnginesAddRemove.Clear();
                _reactiveEnginesAddRemoveOnDispose.Clear();
                _reactiveEnginesSubmission.Clear();

                _entitiesOperations.Clear();
                _transientEntitiesOperations.Clear();

                _groupedEntityToAdd.Dispose();
                _entityStreams.Dispose();
                scheduler.Dispose();
            }

            GC.SuppressFinalize(this);
        }
        ///--------------------------------------------
        ///
        void MoveEntity(IEntityBuilder[] entityBuilders, EGID fromEntityGID, Type originalDescriptorType, EGID?toEntityGID)
        {
            var profiler = new PlatformProfiler();

            using (profiler.StartNewSession("Move Entity"))
            {
                //for each entity view generated by the entity descriptor
                if (_groupEntityDB.TryGetValue(fromEntityGID.groupID, out var fromGroup) == false)
                {
                    throw new ECSException("from group not found eid: ".FastConcat(fromEntityGID.entityID)
                                           .FastConcat(" group: ").FastConcat(fromEntityGID.groupID));
                }

                //Check if there is an EntityInfoView linked to this entity, if so it's a DynamicEntityDescriptor!
                bool correctEntityDescriptorFound = true;

                EntityInfoView entityInfoView = default;
                if (fromGroup.TryGetValue(ENTITY_INFO_VIEW_TYPE, out var entityInfoViewDic) &&
                    (entityInfoViewDic as TypeSafeDictionary <EntityInfoView>).TryGetValue(
                        fromEntityGID.entityID, out entityInfoView) && (correctEntityDescriptorFound =
                                                                            entityInfoView.type == originalDescriptorType))
                {
                    var entitiesToMove = entityInfoView.entitiesToBuild;

                    Dictionary <Type, ITypeSafeDictionary> toGroup = null;

                    if (toEntityGID != null)
                    {
                        var toGroupID = toEntityGID.Value.groupID;

                        if (_groupEntityDB.TryGetValue(toGroupID, out toGroup) == false)
                        {
                            toGroup = _groupEntityDB[toGroupID] = new Dictionary <Type, ITypeSafeDictionary>();
                        }
                    }

                    for (int i = 0; i < entitiesToMove.Length; i++)
                    {
                        MoveEntityView(fromEntityGID, toEntityGID, toGroup, ref fromGroup,
                                       entitiesToMove[i].GetEntityType(), profiler);
                    }
                }
                //otherwise it's a normal static entity descriptor
                else
                {
#if DEBUG && !PROFILER
                    if (correctEntityDescriptorFound == false)
                    {
                        throw new ECSException(INVALID_DYNAMIC_DESCRIPTOR_ERROR.FastConcat(" ID ").FastConcat(fromEntityGID.entityID)
                                               .FastConcat(" group ID ").FastConcat(fromEntityGID.groupID).FastConcat(
                                                   " descriptor found: ", entityInfoView.type.Name, " descriptor Excepted ",
                                                   originalDescriptorType.Name));
                    }
#endif

                    Dictionary <Type, ITypeSafeDictionary> toGroup = null;
                    if (toEntityGID != null)
                    {
                        var toGroupID = toEntityGID.Value.groupID;

                        if (_groupEntityDB.TryGetValue(toGroupID, out toGroup) == false)
                        {
                            toGroup = _groupEntityDB[toGroupID] = new Dictionary <Type, ITypeSafeDictionary>();
                        }
                    }

                    for (var i = 0; i < entityBuilders.Length; i++)
                    {
                        MoveEntityView(fromEntityGID, toEntityGID, toGroup, ref fromGroup,
                                       entityBuilders[i].GetEntityType(), profiler);
                    }
                }
            }
        }