internal static BlobAssetsWithDistinctHash GetBlobAssetsWithDistinctHash(
            ManagedComponentStore managedComponentStore,
            NativeArray <ArchetypeChunk> chunks,
            Allocator allocator)
        {
            s_GetBlobAssetsWithDistinctHash.Begin();
            var blobAssetsWithDistinctHash = new BlobAssetsWithDistinctHash(allocator);

            var typeInfoPtr           = TypeManager.GetTypeInfoPointer();
            var blobAssetRefOffsetPtr = TypeManager.GetBlobAssetRefOffsetsPointer();

            var managedObjectBlobs         = new ManagedObjectBlobs();
            var managedObjectBlobAssets    = new NativeList <BlobAssetPtr>(16, Allocator.Temp);
            var managedObjectBlobAssetsMap = new NativeHashMap <BlobAssetPtr, int>(16, Allocator.Temp);

            for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
            {
                var chunk     = chunks[chunkIndex].m_Chunk;
                var archetype = chunk->Archetype;

                // skip this chunk only if we are _certain_ there are no blob asset refs.
                if (!archetype->HasBlobAssetRefs)
                {
                    continue;
                }

                var typesCount  = archetype->TypesCount;
                var entityCount = chunks[chunkIndex].Count;

                for (var unorderedTypeIndexInArchetype = 0; unorderedTypeIndexInArchetype < typesCount; unorderedTypeIndexInArchetype++)
                {
                    var typeIndexInArchetype     = archetype->TypeMemoryOrder[unorderedTypeIndexInArchetype];
                    var componentTypeInArchetype = archetype->Types[typeIndexInArchetype];
                    if (componentTypeInArchetype.IsZeroSized)
                    {
                        continue;
                    }

                    ref var typeInfo = ref typeInfoPtr[componentTypeInArchetype.TypeIndex & TypeManager.ClearFlagsMask];
                    if (!typeInfo.HasBlobAssetRefs)
                    {
                        continue;
                    }

                    var chunkBuffer         = chunk->Buffer;
                    var subArrayOffset      = archetype->Offsets[typeIndexInArchetype];
                    var componentArrayStart = chunkBuffer + subArrayOffset;

                    if (componentTypeInArchetype.IsManagedComponent)
                    {
                        var componentSize = archetype->SizeOfs[typeIndexInArchetype];
                        var end           = componentArrayStart + componentSize * entityCount;

                        for (var componentData = componentArrayStart; componentData < end; componentData += componentSize)
                        {
                            var managedComponentIndex = *(int *)componentData;
                            var managedComponentValue = managedComponentStore.GetManagedComponent(managedComponentIndex);

                            if (null != managedComponentValue)
                            {
                                managedObjectBlobs.GatherBlobAssetReferences(managedComponentValue, managedObjectBlobAssets, managedObjectBlobAssetsMap);
                            }
                        }
                    }
                    else
                    {
                        var blobAssetRefCount = typeInfo.BlobAssetRefOffsetCount;

                        var blobAssetRefOffsets = blobAssetRefOffsetPtr + typeInfo.BlobAssetRefOffsetStartIndex;

                        if (componentTypeInArchetype.IsBuffer)
                        {
                            var header      = (BufferHeader *)componentArrayStart;
                            var strideSize  = archetype->SizeOfs[typeIndexInArchetype];
                            var elementSize = typeInfo.ElementSize;

                            for (var entityIndex = 0; entityIndex < entityCount; entityIndex++)
                            {
                                var bufferStart = BufferHeader.GetElementPointer(header);
                                var bufferEnd   = bufferStart + header->Length * elementSize;

                                for (var componentData = bufferStart; componentData < bufferEnd; componentData += elementSize)
                                {
                                    AddBlobAssetsWithDistinctHash(componentData, blobAssetRefOffsets, blobAssetRefCount, blobAssetsWithDistinctHash);
                                }

                                header = (BufferHeader *)(((byte *)header) + strideSize);
                            }
                        }
                        else
                        {
                            var componentSize = archetype->SizeOfs[typeIndexInArchetype];
                            var end           = componentArrayStart + componentSize * entityCount;

                            for (var componentData = componentArrayStart; componentData < end; componentData += componentSize)
                            {
                                AddBlobAssetsWithDistinctHash(componentData, blobAssetRefOffsets, blobAssetRefCount, blobAssetsWithDistinctHash);
                            }
                        }
                    }
                }
            }
Beispiel #2
0
        internal static BlobAssetsWithDistinctHash GetBlobAssetsWithDistinctHash(
            ManagedComponentStore managedComponentStore,
            NativeArray <ArchetypeChunk> chunks,
            Allocator allocator)
        {
            var blobAssetsWithDistinctHash = new BlobAssetsWithDistinctHash(allocator);

            var typeInfoPtr           = TypeManager.GetTypeInfoPointer();
            var blobAssetRefOffsetPtr = TypeManager.GetBlobAssetRefOffsetsPointer();

            var managedObjectBlobs         = new ManagedObjectBlobs();
            var managedObjectBlobAssets    = new NativeList <BlobAssetPtr>(16, Allocator.Temp);
            var managedObjectBlobAssetsMap = new NativeHashMap <BlobAssetPtr, int>(16, Allocator.Temp);

            for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
            {
                var chunk     = chunks[chunkIndex].m_Chunk;
                var archetype = chunk->Archetype;

                // skip this chunk only if we are _certain_ there are no blob asset refs.
                if (archetype->NumManagedComponents == 0 && archetype->NumSharedComponents == 0 && !archetype->ContainsBlobAssetRefs)
                {
                    continue;
                }

                var typesCount  = archetype->TypesCount;
                var entityCount = chunks[chunkIndex].Count;

                for (var unorderedTypeIndexInArchetype = 0; unorderedTypeIndexInArchetype < typesCount; unorderedTypeIndexInArchetype++)
                {
                    var typeIndexInArchetype = archetype->TypeMemoryOrder[unorderedTypeIndexInArchetype];

                    var componentTypeInArchetype = archetype->Types[typeIndexInArchetype];

                    if (componentTypeInArchetype.IsZeroSized)
                    {
                        continue;
                    }

                    var chunkBuffer         = chunk->Buffer;
                    var subArrayOffset      = archetype->Offsets[typeIndexInArchetype];
                    var componentArrayStart = chunkBuffer + subArrayOffset;

                    if (componentTypeInArchetype.IsManagedComponent)
                    {
                        var componentSize = archetype->SizeOfs[typeIndexInArchetype];
                        var end           = componentArrayStart + componentSize * entityCount;

                        for (var componentData = componentArrayStart; componentData < end; componentData += componentSize)
                        {
                            var managedComponentIndex = *(int *)componentData;
                            var managedComponentValue = managedComponentStore.GetManagedComponent(managedComponentIndex);

                            if (null != managedComponentValue)
                            {
                                managedObjectBlobs.GatherBlobAssetReferences(managedComponentValue, managedObjectBlobAssets, managedObjectBlobAssetsMap);
                            }
                        }
                    }
                    else
                    {
                        var typeInfo          = typeInfoPtr[componentTypeInArchetype.TypeIndex & TypeManager.ClearFlagsMask];
                        var blobAssetRefCount = typeInfo.BlobAssetRefOffsetCount;

                        if (blobAssetRefCount == 0)
                        {
                            continue;
                        }

                        var blobAssetRefOffsets = blobAssetRefOffsetPtr + typeInfo.BlobAssetRefOffsetStartIndex;

                        if (componentTypeInArchetype.IsBuffer)
                        {
                            var header      = (BufferHeader *)componentArrayStart;
                            var strideSize  = archetype->SizeOfs[typeIndexInArchetype];
                            var elementSize = typeInfo.ElementSize;

                            for (var entityIndex = 0; entityIndex < entityCount; entityIndex++)
                            {
                                var bufferStart = BufferHeader.GetElementPointer(header);
                                var bufferEnd   = bufferStart + header->Length * elementSize;

                                for (var componentData = bufferStart; componentData < bufferEnd; componentData += elementSize)
                                {
                                    AddBlobAssetsWithDistinctHash(componentData, blobAssetRefOffsets, blobAssetRefCount, blobAssetsWithDistinctHash);
                                }

                                header = (BufferHeader *)(((byte *)header) + strideSize);
                            }
                        }
                        else
                        {
                            var componentSize = archetype->SizeOfs[typeIndexInArchetype];
                            var end           = componentArrayStart + componentSize * entityCount;

                            for (var componentData = componentArrayStart; componentData < end; componentData += componentSize)
                            {
                                AddBlobAssetsWithDistinctHash(componentData, blobAssetRefOffsets, blobAssetRefCount, blobAssetsWithDistinctHash);
                            }
                        }
                    }
                }
            }

            for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
            {
                var chunk                 = chunks[chunkIndex].m_Chunk;
                var archetype             = chunk->Archetype;
                var sharedComponentValues = chunk->SharedComponentValues;

                for (var i = 0; i < archetype->NumSharedComponents; i++)
                {
                    var sharedComponentIndex = sharedComponentValues[i];

                    if (sharedComponentIndex == 0)
                    {
                        continue;
                    }

                    var sharedComponentValue = managedComponentStore.GetSharedComponentDataNonDefaultBoxed(sharedComponentIndex);
                    managedObjectBlobs.GatherBlobAssetReferences(sharedComponentValue, managedObjectBlobAssets, managedObjectBlobAssetsMap);
                }
            }

            for (var i = 0; i < managedObjectBlobAssets.Length; i++)
            {
                var blobAssetPtr = managedObjectBlobAssets[i];

                void *validationPtr = null;
                try
                {
                    // Try to read ValidationPtr, this might throw if the memory has been unmapped
                    validationPtr = blobAssetPtr.Header->ValidationPtr;
                }
                catch (Exception)
                {
                    // Ignored
                }

                if (validationPtr != blobAssetPtr.Data)
                {
                    continue;
                }

                blobAssetsWithDistinctHash.TryAdd(blobAssetPtr);
            }

            managedObjectBlobAssets.Dispose();
            managedObjectBlobAssetsMap.Dispose();

            new SortBlobAssetPtr
            {
                Array = blobAssetsWithDistinctHash.BlobAssets.AsDeferredJobArray()
            }.Run();

            return(blobAssetsWithDistinctHash);
        }