Example #1
0
        protected override unsafe void OnUpdate()
        {
            {
                var ecb = new EntityCommandBuffer(Allocator.Temp);
                Entities
                .WithAll <SceneData, RequestSceneLoaded>()
                .WithNone <SceneLoadRequest>()
                .ForEach((Entity e) =>
                {
                    if (m_currentRequestTotal >= kMaxRequestsInFlight)
                    {
                        return;
                    }

                    var sceneData = EntityManager.GetComponentData <SceneData>(e);
                    var sceneGuid = sceneData.Scene.SceneGuid;
                    var path      = "Data/" + sceneGuid.Guid.ToString("N");

                    // Fire async reads for scene data
                    SceneLoadRequest request = new SceneLoadRequest();
                    request.SceneOpHandle    = IOService.RequestAsyncRead(path);
                    ecb.AddComponent(e, request);
                    ecb.RemoveComponent <RequestSceneLoaded>(e);

                    sceneData.Status = SceneStatus.Loading;
                    ecb.SetComponent(e, sceneData);

                    m_currentRequestTotal++;
                });
                ecb.Playback(EntityManager);
                ecb.Dispose();
            }

            if (m_PendingRequestsQuery.CalculateLength() > 0)
            {
                var ecb             = new EntityCommandBuffer(Allocator.Temp);
                var pendingRequests = m_PendingRequestsQuery.ToEntityArray(Allocator.Temp);

                Entity           requestEntity = pendingRequests[0];
                SceneData        sceneData     = EntityManager.GetComponentData <SceneData>(requestEntity);
                SceneLoadRequest request       = EntityManager.GetComponentData <SceneLoadRequest>(requestEntity);

                var opStatus = request.SceneOpHandle.GetStatus();

                if (opStatus <= Status.InProgress)
                {
                    ecb.Playback(EntityManager);
                    ecb.Dispose();
                    return;
                }

                if (opStatus == Status.Failure)
                {
                    request.SceneOpHandle.Dispose();
                    ecb.RemoveComponent <SceneLoadRequest>(requestEntity);

                    sceneData.Status = SceneStatus.FailedToLoad;
                    ecb.SetComponent(requestEntity, sceneData);

                    ecb.Playback(EntityManager);
                    ecb.Dispose();
                    m_currentRequestTotal--;
                    return;
                }
                Assert.IsTrue(opStatus == Status.Success);

                request.SceneOpHandle.GetData(out var data, out var sceneDataSize);
                SceneHeader header     = *(SceneHeader *)data;
                int         headerSize = UnsafeUtility.SizeOf <SceneHeader>();
                if (header.Version != SceneHeader.CurrentVersion)
                {
                    throw new Exception($"Scene serialization version mismatch. Reading version '{header.Version}', expected '{SceneHeader.CurrentVersion}'");
                }

                byte *decompressedScene = data + headerSize;
                if (header.Codec != Codec.Codec.None)
                {
                    decompressedScene = (byte *)UnsafeUtility.Malloc(header.DecompressedSize, 16, Allocator.Temp);

                    if (!CodecService.Decompress(header.Codec, data + headerSize, sceneDataSize - headerSize, decompressedScene, header.DecompressedSize))
                    {
                        throw new Exception($"Failed to decompress compressed scene using codec '{header.Codec}'");
                    }
                }

                using (var sceneReader = new MemoryBinaryReader(decompressedScene))
                {
                    var loadingEM   = m_LoadingWorld.EntityManager;
                    var transaction = loadingEM.BeginExclusiveEntityTransaction();
                    if (header.SharedComponentCount > 0)
                    {
                        int numSharedComponentsLoaded = SerializeUtility.DeserializeSharedComponents(loadingEM, sceneReader);

                        // Chunks have now taken over ownership of the shared components (reference counts have been added)
                        // so remove the ref that was added on deserialization
                        for (int i = 0; i < numSharedComponentsLoaded; ++i)
                        {
                            transaction.ManagedComponentStore.RemoveReference(i + 1);
                        }
                        Assert.IsTrue(numSharedComponentsLoaded == header.SharedComponentCount,
                                      $"Number of loaded SharedComponents for '{sceneData.Scene.SceneGuid.Guid}' loaded ({numSharedComponentsLoaded }) does not match what we expect ({header.SharedComponentCount})");
                    }

                    SerializeUtility.DeserializeWorld(transaction, sceneReader, header.SharedComponentCount);
                    loadingEM.EndExclusiveEntityTransaction();
                }

                var scene = sceneData.Scene;
                World.Active.EntityManager.MoveEntitiesFrom(out var movedEntities, m_LoadingWorld.EntityManager);
                foreach (var e in movedEntities)
                {
                    World.Active.EntityManager.AddSharedComponentData(e, scene.SceneGuid);
                    World.Active.EntityManager.AddSharedComponentData(e, scene.SceneInstanceId);
                }

                // Fixup Entity references now that the entities have moved
                EntityManager.World.GetOrCreateSystem <EntityReferenceRemapSystem>().Update();
                EntityManager.World.GetOrCreateSystem <RemoveRemapInformationSystem>().Update();

                if (header.Codec != Codec.Codec.None)
                {
                    UnsafeUtility.Free(decompressedScene, Allocator.Temp);
                }

                sceneData.Status = SceneStatus.Loaded;
                ecb.SetComponent(requestEntity, sceneData);
                ecb.AddSharedComponent(requestEntity, scene.SceneGuid);
                ecb.AddSharedComponent(requestEntity, scene.SceneInstanceId);

                request.SceneOpHandle.Dispose();
                ecb.RemoveComponent <SceneLoadRequest>(requestEntity);

                ecb.Playback(EntityManager);
                ecb.Dispose();

                m_LoadingWorld.EntityManager.PrepareForDeserialize();
                movedEntities.Dispose();
                pendingRequests.Dispose();
                m_currentRequestTotal--;
            }
        }
Example #2
0
        protected override unsafe void OnUpdate()
        {
            var ecb = new EntityCommandBuffer(Allocator.TempJob);

            Entities
            .WithAll <SceneData, RequestSceneLoaded>()
            .WithNone <SceneLoadRequest>()
            .ForEach((Entity e) =>
            {
                var sceneData = EntityManager.GetComponentData <SceneData>(e);
                var sceneGuid = sceneData.Scene.SceneGuid;
                var path      = DataRootPath + sceneGuid.Guid.ToString("N");
#if IO_ENABLE_TRACE
                Debug.Log($"SceneStreamingSystem: starting load for {DebugSceneGuid(sceneData)} from {path}");
#endif

                // Fire async reads for scene data
                SceneLoadRequest request = new SceneLoadRequest();
                request.SceneOpHandle    = IOService.RequestAsyncRead(path);
                ecb.AddComponent(e, request);
                ecb.RemoveComponent <RequestSceneLoaded>(e);

                sceneData.Status = SceneStatus.Loading;
                ecb.SetComponent(e, sceneData);
            });
            ecb.Playback(EntityManager);
            ecb.Dispose();

            var pendingRequests = m_PendingRequestsQuery.ToEntityArray(Allocator.TempJob);
            ecb = new EntityCommandBuffer(Allocator.TempJob);
            foreach (var requestEntity in pendingRequests)
            {
                SceneData        sceneData = EntityManager.GetComponentData <SceneData>(requestEntity);
                SceneLoadRequest request   = EntityManager.GetComponentData <SceneLoadRequest>(requestEntity);

                var opStatus = request.SceneOpHandle.GetStatus();

                if (opStatus <= Status.InProgress)
                {
                    continue;
                }

                if (opStatus == Status.Failure)
                {
                    request.SceneOpHandle.Dispose();
                    ecb.RemoveComponent <SceneLoadRequest>(requestEntity);

                    Debug.Log($"SceneStreamingSystem: Failed to load {DebugSceneGuid(sceneData)}");

                    sceneData.Status = SceneStatus.FailedToLoad;
                    ecb.SetComponent(requestEntity, sceneData);
                    continue;
                }
                Assert.IsTrue(opStatus == Status.Success);

                request.SceneOpHandle.GetData(out var data, out var sceneDataSize);
                SceneHeader header     = *(SceneHeader *)data;
                int         headerSize = UnsafeUtility.SizeOf <SceneHeader>();
                if (header.Version != SceneHeader.CurrentVersion)
                {
                    throw new Exception($"Scene serialization version mismatch in {DebugSceneGuid(sceneData)}. Reading version '{header.Version}', expected '{SceneHeader.CurrentVersion}'");
                }

                byte *decompressedScene = data + headerSize;
                if (header.Codec != Codec.Codec.None)
                {
                    decompressedScene = (byte *)UnsafeUtility.Malloc(header.DecompressedSize, 16, Allocator.Temp);

                    if (!CodecService.Decompress(header.Codec, data + headerSize, sceneDataSize - headerSize, decompressedScene, header.DecompressedSize))
                    {
                        throw new Exception($"Failed to decompress compressed scene {DebugSceneGuid(sceneData)} using codec '{header.Codec}'");
                    }
                }

                using (var sceneReader = new MemoryBinaryReader(decompressedScene))
                {
                    var loadingEM   = m_LoadingWorld.EntityManager;
                    var transaction = loadingEM.BeginExclusiveEntityTransaction();
                    SerializeUtility.DeserializeWorld(transaction, sceneReader);
                    loadingEM.EndExclusiveEntityTransaction();
                }

                var scene    = sceneData.Scene;
                var activeEM = EntityManager;
                activeEM.MoveEntitiesFrom(out var movedEntities, m_LoadingWorld.EntityManager);
                foreach (var e in movedEntities)
                {
                    ecb.AddSharedComponent(e, scene.SceneGuid);
                    ecb.AddSharedComponent(e, scene.SceneInstanceId);
                }

                // Fixup Entity references now that the entities have moved
                EntityManager.World.GetExistingSystem <EntityReferenceRemapSystem>().Update();
                EntityManager.World.GetExistingSystem <RemoveRemapInformationSystem>().Update();

                if (header.Codec != Codec.Codec.None)
                {
                    UnsafeUtility.Free(decompressedScene, Allocator.Temp);
                }
#if IO_ENABLE_TRACE
                Debug.Log($"SceneStreamingSystem: Loaded scene {DebugSceneGuid(sceneData)}");
#endif
                sceneData.Status = SceneStatus.Loaded;
                ecb.SetComponent(requestEntity, sceneData);

                request.SceneOpHandle.Dispose();
                ecb.RemoveComponent <SceneLoadRequest>(requestEntity);

                m_LoadingWorld.EntityManager.PrepareForDeserialize();
                movedEntities.Dispose();
            }
            ecb.Playback(EntityManager);
            ecb.Dispose();
            pendingRequests.Dispose();
        }