Ejemplo n.º 1
0
        /// <summary>
        /// Preallocate memory to avoid the impact to resize arrays when many entities are submitted at once
        /// </summary>
        void Preallocate(ExclusiveGroupStruct groupID, uint numberOfEntities, IComponentBuilder[] entityComponentsToBuild)
        {
            void PreallocateEntitiesToAdd()
            {
                _groupedEntityToAdd.Preallocate(groupID, numberOfEntities, entityComponentsToBuild);
            }

            void PreallocateDBGroup()
            {
                var numberOfEntityComponents = entityComponentsToBuild.Length;
                FasterDictionary <RefWrapperType, ITypeSafeDictionary> group = GetOrCreateDBGroup(groupID);

                for (var index = 0; index < numberOfEntityComponents; index++)
                {
                    var entityComponentBuilder = entityComponentsToBuild[index];
                    var entityComponentType    = entityComponentBuilder.GetEntityComponentType();

                    var refWrapper = new RefWrapperType(entityComponentType);
                    var dbList     = group.GetOrCreate(refWrapper, () => entityComponentBuilder.CreateDictionary(numberOfEntities));
                    entityComponentBuilder.Preallocate(dbList, numberOfEntities);

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

                    groupedGroup[groupID] = dbList;
                }
            }

            PreallocateDBGroup();
            PreallocateEntitiesToAdd();
            _entityLocator.PreallocateReferenceMaps(groupID, numberOfEntities);
        }
Ejemplo n.º 2
0
        ///--------------------------------------------
        void Preallocate <T>(ExclusiveGroupStruct groupID, uint size) where T : IEntityDescriptor, new()
        {
            using (var profiler = new PlatformProfiler("Preallocate"))
            {
                var entityComponentsToBuild  = EntityDescriptorTemplate <T> .descriptor.componentsToBuild;
                var numberOfEntityComponents = entityComponentsToBuild.Length;

                FasterDictionary <RefWrapperType, ITypeSafeDictionary> group = GetOrCreateGroup(groupID, profiler);

                for (var index = 0; index < numberOfEntityComponents; index++)
                {
                    var entityComponentBuilder = entityComponentsToBuild[index];
                    var entityComponentType    = entityComponentBuilder.GetEntityComponentType();

                    var refWrapper = new RefWrapperType(entityComponentType);
                    if (group.TryGetValue(refWrapper, out var dbList) == false)
                    {
                        group[refWrapper] = entityComponentBuilder.Preallocate(ref dbList, size);
                    }
                    else
                    {
                        dbList.SetCapacity(size);
                    }

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

                    groupedGroup[groupID] = dbList;
                }
            }
        }
Ejemplo n.º 3
0
            ref FilterGroup CreateOrGetFilterForGroup
                (int filterID, ExclusiveGroupStruct groupID, RefWrapperType refWrapper)
            {
                var fasterDictionary =
                    _filters.GetOrCreate(refWrapper, () => new FasterDictionary <ExclusiveGroupStruct, GroupFilters>());

                GroupFilters filters = fasterDictionary.GetOrCreate(
                    groupID, () => new GroupFilters(new SharedSveltoDictionaryNative <int, FilterGroup>(0), groupID));

                return(ref filters.CreateOrGetFilter(filterID));
            }
Ejemplo n.º 4
0
        public void AddEngine(IEngine engine)
        {
            var type       = engine.GetType();
            var refWrapper = new RefWrapperType(type);

            DBC.ECS.Check.Require(engine != null, "Engine to add is invalid or null");
            DBC.ECS.Check.Require(
                _enginesTypeSet.Contains(refWrapper) == false ||
                type.ContainsCustomAttribute(typeof(AllowMultipleAttribute)) == true
                , "The same engine has been added more than once, if intentional, use [AllowMultiple] class attribute "
                .FastConcat(engine.ToString()));
            try
            {
                if (engine is IReactOnAddAndRemove viewEngine)
                {
                    CheckReactEngineComponents(viewEngine, _reactiveEnginesAddRemove);
                }

                if (engine is IReactOnDispose viewEngineDispose)
                {
                    CheckReactEngineComponents(viewEngineDispose, _reactiveEnginesAddRemoveOnDispose);
                }

                if (engine is IReactOnSwap viewEngineSwap)
                {
                    CheckReactEngineComponents(viewEngineSwap, _reactiveEnginesSwap);
                }

                if (engine is IReactOnSubmission submissionEngine)
                {
                    _reactiveEnginesSubmission.Add(submissionEngine);
                }

                _enginesTypeSet.Add(refWrapper);
                _enginesSet.Add(engine);

                if (engine is IDisposable)
                {
                    _disposableEngines.Add(engine as IDisposable);
                }

                if (engine is IQueryingEntitiesEngine queryableEntityComponentEngine)
                {
                    queryableEntityComponentEngine.entitiesDB = _entitiesDB;
                    queryableEntityComponentEngine.Ready();
                }
            }
            catch (Exception e)
            {
                throw new ECSException("Code crashed while adding engine ".FastConcat(engine.GetType().ToString(), " ")
                                       , e);
            }
        }
Ejemplo n.º 5
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();
                }
            }
        }
Ejemplo n.º 6
0
 internal EntityFilterID(uint filterID, RefWrapperType componentType)
 {
     _filterID      = filterID;
     _componentType = componentType;
     _hashCode      = (int)filterID + (int)filterID ^ componentType.GetHashCode();
 }