void AddArchetypeIfMatching(Archetype *archetype, EntityQueryData *query)
        {
            if (!IsMatchingArchetype(archetype, query))
            {
                return;
            }

            var match = (MatchingArchetype *)m_GroupDataChunkAllocator.Allocate(
                MatchingArchetype.GetAllocationSize(query->RequiredComponentsCount), 8);

            match->Archetype = archetype;
            var typeIndexInArchetypeArray = match->IndexInArchetype;

            query->MatchingArchetypes.Add(match);

            for (var component = 0; component < query->RequiredComponentsCount; ++component)
            {
                var typeComponentIndex = -1;
                if (query->RequiredComponents[component].AccessModeType != ComponentType.AccessMode.Exclude)
                {
                    typeComponentIndex = ChunkDataUtility.GetIndexInTypeArray(archetype, query->RequiredComponents[component].TypeIndex);
                    Assert.AreNotEqual(-1, typeComponentIndex);
                }

                typeIndexInArchetypeArray[component] = typeComponentIndex;
            }
        }
        public static bool CompareQuery(EntityQueryDesc[] queryDesc, EntityQueryData *queryData)
        {
            if (queryData->ArchetypeQueryCount != queryDesc.Length)
            {
                return(false);
            }

            for (int i = 0; i != queryDesc.Length; i++)
            {
                if (!CompareQueryArray(queryDesc[i].All, queryData->ArchetypeQuery[i].All, queryData->ArchetypeQuery[i].AllAccessMode, queryData->ArchetypeQuery[i].AllCount))
                {
                    return(false);
                }
                if (!CompareQueryArray(queryDesc[i].None, queryData->ArchetypeQuery[i].None, queryData->ArchetypeQuery[i].NoneAccessMode, queryData->ArchetypeQuery[i].NoneCount))
                {
                    return(false);
                }
                if (!CompareQueryArray(queryDesc[i].Any, queryData->ArchetypeQuery[i].Any, queryData->ArchetypeQuery[i].AnyAccessMode, queryData->ArchetypeQuery[i].AnyCount))
                {
                    return(false);
                }
                if (queryDesc[i].Options != queryData->ArchetypeQuery[i].Options)
                {
                    return(false);
                }
            }

            return(true);
        }
        public EntityQuery CreateEntityQuery(EntityComponentStore *entityComponentStore, ManagedComponentStore managedComponentStore,
                                             ArchetypeQuery *query, int queryCount, ComponentType *component, int componentCount)
        {
            //@TODO: Validate that required types is subset of archetype filters all...

            int hash = (int)math.hash(component, componentCount * sizeof(ComponentType));

            for (var i = 0; i < queryCount; ++i)
            {
                hash = hash * 397 ^ query[i].GetHashCode();
            }
            EntityQueryData *cachedQuery = null;

            if (m_EntityGroupDataCache.TryGetFirstValue(hash, out var entityGroupDataIndex, out var iterator))
            {
                do
                {
                    var possibleMatch = m_EntityGroupDatas.Ptr[entityGroupDataIndex];
                    if (Matches(possibleMatch, query, queryCount, component, componentCount))
                    {
                        cachedQuery = possibleMatch;
                        break;
                    }
                } while (m_EntityGroupDataCache.TryGetNextValue(out entityGroupDataIndex, ref iterator));
            }

            if (cachedQuery == null)
            {
                cachedQuery = (EntityQueryData *)ChunkAllocate <EntityQueryData>();
                cachedQuery->RequiredComponentsCount = componentCount;
                cachedQuery->RequiredComponents      = (ComponentType *)ChunkAllocate <ComponentType>(componentCount, component);
                InitializeReaderWriter(cachedQuery, component, componentCount);
                cachedQuery->ArchetypeQueryCount = queryCount;
                cachedQuery->ArchetypeQuery      = (ArchetypeQuery *)ChunkAllocate <ArchetypeQuery>(queryCount, query);
                for (var i = 0; i < queryCount; ++i)
                {
                    cachedQuery->ArchetypeQuery[i].All            = (int *)ChunkAllocate <int>(cachedQuery->ArchetypeQuery[i].AllCount, query[i].All);
                    cachedQuery->ArchetypeQuery[i].Any            = (int *)ChunkAllocate <int>(cachedQuery->ArchetypeQuery[i].AnyCount, query[i].Any);
                    cachedQuery->ArchetypeQuery[i].None           = (int *)ChunkAllocate <int>(cachedQuery->ArchetypeQuery[i].NoneCount, query[i].None);
                    cachedQuery->ArchetypeQuery[i].AllAccessMode  = (byte *)ChunkAllocate <byte>(cachedQuery->ArchetypeQuery[i].AllCount, query[i].AllAccessMode);
                    cachedQuery->ArchetypeQuery[i].AnyAccessMode  = (byte *)ChunkAllocate <byte>(cachedQuery->ArchetypeQuery[i].AnyCount, query[i].AnyAccessMode);
                    cachedQuery->ArchetypeQuery[i].NoneAccessMode = (byte *)ChunkAllocate <byte>(cachedQuery->ArchetypeQuery[i].NoneCount, query[i].NoneAccessMode);
                }
                cachedQuery->MatchingArchetypes = new UnsafeMatchingArchetypePtrList(entityComponentStore);

                cachedQuery->EntityQueryMask = new EntityQueryMask();

                for (var i = 0; i < entityComponentStore->m_Archetypes.Length; ++i)
                {
                    var archetype = entityComponentStore->m_Archetypes.Ptr[i];
                    AddArchetypeIfMatching(archetype, cachedQuery);
                }

                m_EntityGroupDataCache.Add(hash, m_EntityGroupDatas.Length);
                m_EntityGroupDatas.Add(cachedQuery);
            }

            return(new EntityQuery(cachedQuery, m_JobSafetyManager, entityComponentStore, managedComponentStore));
        }
 internal EntityQuery(EntityQueryData *queryData, ComponentJobSafetyManager *safetyManager, EntityComponentStore *entityComponentStore, ManagedComponentStore managedComponentStore)
 {
     m_QueryData             = queryData;
     m_Filter                = default(EntityQueryFilter);
     m_SafetyManager         = safetyManager;
     m_EntityComponentStore  = entityComponentStore;
     m_ManagedComponentStore = managedComponentStore;
 }
Beispiel #5
0
 public void EnsureCapacity()
 {
     if (this.count == this.capacity)
     {
         this.capacity = this.capacity * 2;
         this.queries  = MemoryUtility.Realloc(queries, this.capacity);
     }
 }
Beispiel #6
0
        internal static void AppendArchetypesToQueryData(EntityQueryData *queryData, Archetype **archetypes, int count)
        {
            var size = count * sizeof(Archetype *);

            queryData->archetypes = MemoryUtility.ReallocPtrArray <Archetype>(queryData->archetypes, queryData->archetypeCount + count);
            Buffer.MemoryCopy(archetypes, queryData->archetypes + queryData->archetypeCount, size, size);
            queryData->archetypeCount += count;
        }
 public int IndexOf(EntityQueryData *value)
 {
     for (int i = 0; i < Length; ++i)
     {
         if (Ptr[i] == value)
         {
             return(i);
         }
     }
     return(-1);
 }
 public int IndexOf(EntityQueryData *value)
 {
     for (int i = Length - 1; i >= 0; --i)
     {
         if (Ptr[i] == value)
         {
             return(i);
         }
     }
     return(-1);
 }
        void InitializeReaderWriter(EntityQueryData *grp, ComponentType *requiredTypes, int requiredCount)
        {
            Assert.IsTrue(requiredCount > 0);
            Assert.IsTrue(requiredTypes[0] == ComponentType.ReadWrite <Entity>());

            grp->ReaderTypesCount = 0;
            grp->WriterTypesCount = 0;

            for (var i = 1; i != requiredCount; i++)
            {
                // After the first zero sized component the rest are zero sized
                if (requiredTypes[i].IsZeroSized)
                {
                    break;
                }

                switch (requiredTypes[i].AccessModeType)
                {
                case ComponentType.AccessMode.ReadOnly:
                    grp->ReaderTypesCount++;
                    break;

                default:
                    grp->WriterTypesCount++;
                    break;
                }
            }

            grp->ReaderTypes = (int *)m_GroupDataChunkAllocator.Allocate(sizeof(int) * grp->ReaderTypesCount, 4);
            grp->WriterTypes = (int *)m_GroupDataChunkAllocator.Allocate(sizeof(int) * grp->WriterTypesCount, 4);

            var curReader = 0;
            var curWriter = 0;

            for (var i = 1; i != requiredCount; i++)
            {
                if (requiredTypes[i].IsZeroSized)
                {
                    break;
                }

                switch (requiredTypes[i].AccessModeType)
                {
                case ComponentType.AccessMode.ReadOnly:
                    grp->ReaderTypes[curReader++] = requiredTypes[i].TypeIndex;
                    break;

                default:
                    grp->WriterTypes[curWriter++] = requiredTypes[i].TypeIndex;
                    break;
                }
            }
        }
        //@TODO: All this could be much faster by having all ComponentType pre-sorted to perform a single search loop instead two nested for loops...
        static bool IsMatchingArchetype(Archetype *archetype, EntityQueryData *query)
        {
            for (int i = 0; i != query->ArchetypeQueryCount; i++)
            {
                if (IsMatchingArchetype(archetype, query->ArchetypeQuery + i))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #11
0
        public static void GatherEntitiesToArray(EntityQueryData *queryData, ref EntityQueryFilter filter, out EntityQuery.GatherEntitiesResult result)
        {
            if (s_EntityQueryResultBuffer == null)
            {
                s_EntityQueryResultBuffer = (Entity *)UnsafeUtility.Malloc(k_EntityQueryResultBufferSize * sizeof(Entity), 64, Allocator.Persistent);
            }

            var buffer    = s_EntityQueryResultBuffer;
            var curOffset = currentOffsetInResultBuffer;

            // Main method that copies the entities of each chunk of a matching archetype to the buffer
            bool AddArchetype(MatchingArchetype *matchingArchetype, ref EntityQueryFilter queryFilter)
            {
                var archetype = matchingArchetype->Archetype;
                var entityCountInArchetype = archetype->EntityCount;

                if (entityCountInArchetype == 0)
                {
                    return(true);
                }

                var chunkCount = archetype->Chunks.Count;
                var chunks     = archetype->Chunks.p;
                var counts     = archetype->Chunks.GetChunkEntityCountArray();

                for (int i = 0; i < chunkCount; ++i)
                {
                    // Ignore the chunk if the query uses filter and the chunk doesn't comply
                    if (queryFilter.RequiresMatchesFilter && (chunks[i]->MatchesFilter(matchingArchetype, ref queryFilter) == false))
                    {
                        continue;
                    }
                    var entityCountInChunk = counts[i];

                    if ((curOffset + entityCountInChunk) > k_EntityQueryResultBufferSize)
                    {
                        return(false);
                    }

                    UnsafeUtility.MemCpy(buffer + curOffset, chunks[i]->Buffer, entityCountInChunk * sizeof(Entity));
                    curOffset += entityCountInChunk;
                }

                return(true);
            }

            // Parse all the matching archetypes and add the entities that fits the query and its filter
            bool    success            = true;
            ref var matchingArchetypes = ref queryData->MatchingArchetypes;
Beispiel #12
0
        internal void MatchArchetypesToQueryData(EntityQueryData *queryData)
        {
            var count = this.archetypeStore->count;
            var unmatchedArchetypeCount = count - queryData->matchedArchetypeCount;
            var archetypes = this.archetypeStore->archetypes + queryData->matchedArchetypeCount;

            // Update the query data to the current archetype count. This only
            // works because a created archetype cannot be removed.
            queryData->matchedArchetypeCount = count;

            if (unmatchedArchetypeCount == 0)            // Can this be done better?
            {
                return;
            }

            var matchCount = 0;

            if (unmatchedArchetypeCount <= 16)
            {
                var matchingArchetypes = stackalloc Archetype *[unmatchedArchetypeCount];

                for (int i = 0; i < unmatchedArchetypeCount; ++i, ++archetypes)                // This loop can be written shorter and better!
                {
                    if (ArchetypeMatchesQueryFilter(archetypes, queryData))
                    {
                        matchingArchetypes[matchCount++] = archetypes;
                    }
                }

                AppendArchetypesToQueryData(queryData, matchingArchetypes, matchCount);
            }
            else
            {
                var matchingArchetypes = MemoryUtility.MallocPtrArray <Archetype>(unmatchedArchetypeCount);

                for (int i = 0; i < unmatchedArchetypeCount; ++i, ++archetypes)
                {
                    if (ArchetypeMatchesQueryFilter(archetypes, queryData))
                    {
                        matchingArchetypes[matchCount++] = archetypes;
                    }
                }

                AppendArchetypesToQueryData(queryData, matchingArchetypes, matchCount);

                MemoryUtility.Free(matchingArchetypes);
            }
        }
Beispiel #13
0
        internal static bool ArchetypeMatchesQueryFilter(Archetype *archetype, EntityQueryData *query)
        {
            if (query->includeTypesCount > archetype->componentCount)
            {
                return(false);
            }

            var includeTypes = query->componentTypes;

            // TODO: SSE2
            // if sorted save i and j and increment...

            for (int i = 0; i < query->includeTypesCount; ++i)
            {
                for (int j = 0; j < archetype->componentCount; ++j)
                {
                    if (includeTypes[i] == archetype->componentTypes[j])
                    {
                        goto matched;
                    }
                }

                return(false);

matched:
                continue;
            }

            var excludeTypes = query->componentTypes + query->includeTypesCount;

            for (int i = 0; i < query->excludeTypesCount; ++i)
            {
                for (int j = 0; j < archetype->componentCount; ++j)
                {
                    if (excludeTypes[i] == archetype->componentTypes[j])
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #14
0
        internal EntityQuery CreateQueryInternal(Span <int> types, int includeTypesCount, int excludeTypesCount)
        {
            int hashCode = GetQueryTypeHash(types.Slice(0, includeTypesCount), types.Slice(includeTypesCount));

            if (this.queryCache->typeLookup.TryGet(hashCode, out EntityQuery query))
            {
                return(query);
            }

            this.queryCache->EnsureCapacity();

            int index = this.queryCache->count++;

            // InitBlock the struct?
            EntityQueryData *queryData = this.queryCache->queries + index;

            queryData->matchedArchetypeCount = 0;
            queryData->archetypeCount        = 0;
            queryData->includeTypesCount     = includeTypesCount;
            queryData->excludeTypesCount     = excludeTypesCount;
            queryData->componentTypes        = null;
            queryData->archetypes            = MemoryUtility.MallocPtrArray <Archetype>(0); // This is dumb but works, otherwise realloc throws.

            if (types.Length > 0)                                                           // Because Marshal.AllocHGlobal(0) does not return IntPtr.Zero.
            {
                queryData->componentTypes = MemoryUtility.Malloc <int>(types.Length);
                types.CopyTo(new Span <int>(queryData->componentTypes, types.Length));
            }

            MatchArchetypesToQueryData(queryData);             // Lazy?

            query = new EntityQuery(index);

            this.queryCache->typeLookup.Add(hashCode, query);

            return(query);
        }
 bool Matches(EntityQueryData *grp, ArchetypeQuery *archetypeQueries, int archetypeFiltersCount,
              ComponentType *requiredComponents, int requiredComponentsCount)
 {
     if (requiredComponentsCount != grp->RequiredComponentsCount)
     {
         return(false);
     }
     if (archetypeFiltersCount != grp->ArchetypeQueryCount)
     {
         return(false);
     }
     if (requiredComponentsCount > 0 && UnsafeUtility.MemCmp(requiredComponents, grp->RequiredComponents, sizeof(ComponentType) * requiredComponentsCount) != 0)
     {
         return(false);
     }
     for (var i = 0; i < archetypeFiltersCount; ++i)
     {
         if (!archetypeQueries[i].Equals(grp->ArchetypeQuery[i]))
         {
             return(false);
         }
     }
     return(true);
 }
 public bool Contains(EntityQueryData *value)
 {
     return(IndexOf(value) != -1);
 }
 public void Add(EntityQueryData *value)
 {
     this.ListData().Add(value);
 }
 public bool Contains(EntityQueryData *value)
 {
     return(this.ListData().Contains(value));
 }
 public int IndexOf(EntityQueryData *value)
 {
     return(this.ListData().IndexOf(value));
 }
Beispiel #20
0
 public int IndexOf(EntityQueryData *value)
 {
     return(ListData.IndexOf(value));
 }
Beispiel #21
0
 public bool Contains(EntityQueryData *value)
 {
     return(ListData.Contains(value));
 }
 internal unsafe ComponentGroup(EntityQueryData *queryData, ComponentJobSafetyManager *safetyManager, EntityComponentStore *entityComponentStore, ManagedComponentStore managedComponentStore)
 {
     // ctor matching EntityQuery ctor to prevent default parameterless ctor from being created
     throw new NotImplementedException();
 }
 public void AddNoResize(EntityQueryData *value)
 {
     Writer.AddNoResize(value);
 }
Beispiel #24
0
 public void Add(EntityQueryData *value)
 {
     ListData.Add(value);
 }
        public static bool CompareComponents(ComponentType *componentTypes, int componentTypesCount, EntityQueryData *queryData)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            for (var k = 0; k < componentTypesCount; ++k)
            {
                if (componentTypes[k].TypeIndex == TypeManager.GetTypeIndex <Entity>())
                {
                    throw new ArgumentException(
                              "EntityQuery.CompareComponents may not include typeof(Entity), it is implicit");
                }
            }
#endif

            var sortedTypes = stackalloc ComponentType[componentTypesCount];
            for (var i = 0; i < componentTypesCount; ++i)
            {
                SortingUtilities.InsertSorted(sortedTypes, i, componentTypes[i]);
            }

            // EntityQueries are constructed including the Entity ID
            if (componentTypesCount + 1 != queryData->RequiredComponentsCount)
            {
                return(false);
            }

            for (var i = 0; i < componentTypesCount; ++i)
            {
                if (queryData->RequiredComponents[i + 1] != sortedTypes[i])
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #26
0
        public static bool CompareComponents(ComponentType *componentTypes, int componentTypesCount, EntityQueryData *queryData)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            for (var k = 0; k < componentTypesCount; ++k)
            {
                if (componentTypes[k].TypeIndex == TypeManager.GetTypeIndex <Entity>())
                {
                    throw new ArgumentException(
                              "EntityQuery.CompareComponents may not include typeof(Entity), it is implicit");
                }
            }
#endif
            if ((queryData->ArchetypeQueryCount != 1) ||                              // This code path only matches one archetypequery
                (queryData->ArchetypeQuery[0].Options != EntityQueryOptions.Default)) // This code path does not allow query options
            {
                return(false);
            }

            var sortedTypes = stackalloc ComponentType[componentTypesCount];
            for (var i = 0; i < componentTypesCount; ++i)
            {
                SortingUtilities.InsertSorted(sortedTypes, i, componentTypes[i]);
            }

            ConvertComponentListToSortedIntListsNoAlloc(sortedTypes, componentTypesCount, out var componentCompareQuery);

            var includeCount   = componentCompareQuery.includeTypeIndices.Length;
            var excludeCount   = componentCompareQuery.excludeTypeIndices.Length;
            var archetypeQuery = queryData->ArchetypeQuery[0];

            if ((includeCount != archetypeQuery.AllCount) ||
                (excludeCount != archetypeQuery.NoneCount))
            {
                return(false);
            }

            for (int i = 0; i < includeCount; ++i)
            {
                if (componentCompareQuery.includeTypeIndices[i] != archetypeQuery.All[i] ||
                    componentCompareQuery.includeAccessModes[i] != archetypeQuery.AllAccessMode[i])
                {
                    return(false);
                }
            }

            for (int i = 0; i < excludeCount; ++i)
            {
                if (componentCompareQuery.excludeTypeIndices[i] != archetypeQuery.None[i] ||
                    componentCompareQuery.excludeAccessModes[i] != archetypeQuery.NoneAccessMode[i])
                {
                    return(false);
                }
            }

            return(true);
        }