private static unsafe void PatchBlobAssetsInChunkBeforeSave(Chunk *tempChunk, Chunk *originalChunk, NativeArray <int> blobAssetOffsets, NativeHashMap <BlobAssetRefKey, int> blobAssetRefs) { var archetype = originalChunk->Archetype; var typeCount = archetype->TypesCount; var entityCount = originalChunk->Count; for (var unordered_ti = 0; unordered_ti < typeCount; ++unordered_ti) { var ti = archetype->TypeMemoryOrder[unordered_ti]; var type = archetype->Types[ti]; if (type.IsZeroSized) { continue; } var ct = TypeManager.GetTypeInfo(type.TypeIndex); var blobAssetRefCount = ct.BlobAssetRefOffsetCount; if (blobAssetRefCount == 0) { continue; } var chunkBuffer = tempChunk->Buffer; if (type.IsBuffer) { throw new InvalidOperationException("BlobAssetReferences are not supported inside DynamicBuffer components"); } else if (blobAssetRefCount > 0) { int subArrayOffset = archetype->Offsets[ti]; byte *componentArrayStart = OffsetFromPointer(chunkBuffer, subArrayOffset); int size = archetype->SizeOfs[ti]; byte *end = componentArrayStart + size * entityCount; for (var componentData = componentArrayStart; componentData < end; componentData += size) { for (int i = 0; i < blobAssetRefCount; ++i) { var offset = ct.BlobAssetRefOffsets[i].Offset; var blobAssetRefPtr = (BlobAssetReferenceData *)(componentData + offset); int value = -1; if (blobAssetRefPtr->m_Ptr != null) { var blobAssetPtr = new BlobAssetPtr((*(BlobAssetHeader **)blobAssetRefPtr) - 1); var key = new BlobAssetRefKey { chunk = originalChunk, offsetInBuffer = (int)((byte *)blobAssetRefPtr - chunkBuffer) }; bool found = blobAssetRefs.TryGetValue(key, out value); value = blobAssetOffsets[value]; Assert.IsTrue(found); } blobAssetRefPtr->m_Ptr = (byte *)value; } } } } }
private static unsafe void GatherAllUsedBlobAssets(EntityArchetype[] archetypeArray, out NativeHashMap <BlobAssetRefKey, int> blobAssetRefs, out NativeList <BlobAssetPtr> blobAssets) { var blobAssetMap = new NativeHashMap <BlobAssetPtr, int>(100, Allocator.Temp); blobAssetRefs = new NativeHashMap <BlobAssetRefKey, int>(100, Allocator.Temp); blobAssets = new NativeList <BlobAssetPtr>(100, Allocator.Temp); for (int archetypeIndex = 0; archetypeIndex < archetypeArray.Length; ++archetypeIndex) { var archetype = archetypeArray[archetypeIndex].Archetype; if (!archetype->ContainsBlobAssetRefs) { continue; } var typeCount = archetype->TypesCount; for (var ci = 0; ci < archetype->Chunks.Count; ++ci) { var chunk = archetype->Chunks.p[ci]; var entityCount = chunk->Count; for (var unordered_ti = 0; unordered_ti < typeCount; ++unordered_ti) { var ti = archetype->TypeMemoryOrder[unordered_ti]; var type = archetype->Types[ti]; if (type.IsZeroSized) { continue; } var ct = TypeManager.GetTypeInfo(type.TypeIndex); var blobAssetRefCount = ct.BlobAssetRefOffsetCount; if (blobAssetRefCount == 0) { continue; } var chunkBuffer = chunk->Buffer; if (type.IsBuffer) { } else if (blobAssetRefCount > 0) { int subArrayOffset = archetype->Offsets[ti]; byte *componentArrayStart = OffsetFromPointer(chunkBuffer, subArrayOffset); int size = archetype->SizeOfs[ti]; byte *end = componentArrayStart + size * entityCount; for (var componentData = componentArrayStart; componentData < end; componentData += size) { for (int i = 0; i < blobAssetRefCount; ++i) { var offset = ct.BlobAssetRefOffsets[i].Offset; var blobAssetRefPtr = (BlobAssetReferenceData *)(componentData + offset); if (blobAssetRefPtr->m_Ptr == null) { continue; } var blobAssetPtr = new BlobAssetPtr((*(BlobAssetHeader **)blobAssetRefPtr) - 1); var key = new BlobAssetRefKey { chunk = chunk, offsetInBuffer = (int)((byte *)blobAssetRefPtr - chunkBuffer) }; if (!blobAssetMap.TryGetValue(blobAssetPtr, out var blobAssetIndex)) { blobAssetIndex = blobAssets.Length; blobAssets.Add(blobAssetPtr); blobAssetMap.TryAdd(blobAssetPtr, blobAssetIndex); } blobAssetRefs.TryAdd(key, blobAssetIndex); } } } } } } blobAssetMap.Dispose(); }