Example #1
0
        static void ApplyBlobAssetChanges(
            EntityManager entityManager,
            NativeArray <EntityGuid> packedEntityGuids,
            NativeMultiHashMap <int, Entity> packedEntities,
            NativeArray <ComponentType> packedTypes,
            NativeArray <BlobAssetChange> createdBlobAssets,
            NativeArray <byte> createdBlobAssetData,
            NativeArray <ulong> destroyedBlobAssets,
            NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges)
        {
            if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0)
            {
                return;
            }

            var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>();

            var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr();

            for (var i = 0; i < createdBlobAssets.Length; i++)
            {
                if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _))
                {
                    patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash);
                }

                blobAssetDataPtr += createdBlobAssets[i].Length;
            }

            for (var i = 0; i < destroyedBlobAssets.Length; i++)
            {
                patcherBlobAssetSystem.ReleaseBlobAsset(destroyedBlobAssets[i]);
            }

            for (var i = 0; i < blobAssetReferenceChanges.Length; i++)
            {
                var packedComponent = blobAssetReferenceChanges[i].Component;
                var component       = packedTypes[packedComponent.PackedTypeIndex];
                var targetOffset    = blobAssetReferenceChanges[i].Offset;

                BlobAssetReferenceData targetBlobAssetReferenceData;
                if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr))
                {
                    targetBlobAssetReferenceData = new BlobAssetReferenceData {
                        m_Ptr = (byte *)blobAssetPtr.Data
                    };
                }

                if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator))
                {
                    do
                    {
                        if (!entityManager.Exists(entity))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist.");
                        }
                        else if (!entityManager.HasComponent(entity, component))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist.");
                        }
                        else
                        {
                            if (component.IsBuffer)
                            {
                                var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
#if !NET_DOTS
                            else if (component.IsManagedComponent)
                            {
                                var obj     = entityManager.GetManagedComponentDataAsObject(entity, component);
                                var pointer = (byte *)UnsafeUtility.PinGCObjectAndGetAddress(obj, out ulong handle);
                                pointer += TypeManager.ObjectOffset;
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                                UnsafeUtility.ReleaseGCObject(handle);
                            }
#endif
                            else
                            {
                                var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
                        }
                    }while (packedEntities.TryGetNextValue(out entity, ref iterator));
                }
            }

            // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off).
            patcherBlobAssetSystem.ReleaseUnusedBlobAssets();
        }
Example #2
0
 /// <summary>
 /// Construct a BlobAssetReference from the blob data
 /// </summary>
 /// <param name="blobData">The blob data to attach to the returned object</param>
 /// <returns>The created BlobAssetReference</returns>
 internal static BlobAssetReference <T> Create(BlobAssetReferenceData blobData)
 {
     return(new BlobAssetReference <T> {
         m_data = blobData
     });
 }
        static void ApplyBlobAssetChanges(
            EntityManager entityManager,
            NativeArray <EntityGuid> packedEntityGuids,
            NativeMultiHashMap <int, Entity> packedEntities,
            NativeArray <ComponentType> packedTypes,
            NativeArray <BlobAssetChange> createdBlobAssets,
            NativeArray <byte> createdBlobAssetData,
            NativeArray <ulong> destroyedBlobAssets,
            NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges)
        {
            if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0)
            {
                return;
            }

            s_ApplyBlobAssetChangesProfilerMarker.Begin();

            var managedObjectBlobAssetReferencePatches = new NativeMultiHashMap <EntityComponentPair, ManagedObjectBlobAssetReferencePatch>(blobAssetReferenceChanges.Length, Allocator.Temp);

            var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>();

            var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr();

            for (var i = 0; i < createdBlobAssets.Length; i++)
            {
                if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _))
                {
                    patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash);
                }

                blobAssetDataPtr += createdBlobAssets[i].Length;
            }

            for (var i = 0; i < destroyedBlobAssets.Length; i++)
            {
                patcherBlobAssetSystem.ReleaseBlobAsset(entityManager, destroyedBlobAssets[i]);
            }

            for (var i = 0; i < blobAssetReferenceChanges.Length; i++)
            {
                var packedComponent = blobAssetReferenceChanges[i].Component;
                var component       = packedTypes[packedComponent.PackedTypeIndex];
                var targetOffset    = blobAssetReferenceChanges[i].Offset;

                BlobAssetReferenceData targetBlobAssetReferenceData;
                if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr))
                {
                    targetBlobAssetReferenceData = new BlobAssetReferenceData {
                        m_Ptr = (byte *)blobAssetPtr.Data
                    };
                }

                if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator))
                {
                    do
                    {
                        if (!entityManager.Exists(entity))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist.");
                        }
                        else if (!entityManager.HasComponent(entity, component))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist.");
                        }
                        else
                        {
                            if (component.IsBuffer)
                            {
                                var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
                            else if (component.IsManagedComponent || component.IsSharedComponent)
                            {
                                managedObjectBlobAssetReferencePatches.Add(
                                    new EntityComponentPair {
                                    Entity = entity, Component = component
                                },
                                    new ManagedObjectBlobAssetReferencePatch {
                                    Id = targetOffset, Target = blobAssetReferenceChanges[i].Value
                                });
                            }
                            else
                            {
                                var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
                        }
                    }while (packedEntities.TryGetNextValue(out entity, ref iterator));
                }
            }
            s_ApplyBlobAssetChangesProfilerMarker.End();

#if !UNITY_DOTSRUNTIME
            var managedObjectPatcher = new ManagedObjectBlobAssetReferencePatcher(patcherBlobAssetSystem);

            // Apply all managed entity patches
            using (var keys = managedObjectBlobAssetReferencePatches.GetKeyArray(Allocator.Temp))
            {
                keys.Sort();
                var uniqueCount = keys.Unique();

                for (var i = 0; i < uniqueCount; i++)
                {
                    var pair    = keys[i];
                    var patches = managedObjectBlobAssetReferencePatches.GetValuesForKey(pair);

                    if (pair.Component.IsManagedComponent)
                    {
                        var obj = entityManager.GetComponentObject <object>(pair.Entity, pair.Component);
                        managedObjectPatcher.ApplyPatches(ref obj, patches);
                    }
                    else if (pair.Component.IsSharedComponent)
                    {
                        var obj = entityManager.GetSharedComponentData(pair.Entity, pair.Component.TypeIndex);
                        managedObjectPatcher.ApplyPatches(ref obj, patches);
                        entityManager.SetSharedComponentDataBoxedDefaultMustBeNull(pair.Entity, pair.Component.TypeIndex, obj);
                    }

                    patches.Dispose();
                }
            }
#endif

            managedObjectBlobAssetReferencePatches.Dispose();

            // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off).
            patcherBlobAssetSystem.ReleaseUnusedBlobAssets();
        }