diff --git a/Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs b/Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs new file mode 100644 index 0000000000..47692ecd38 --- /dev/null +++ b/Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs @@ -0,0 +1,6 @@ +namespace DCL.LOD.Components +{ + public struct MockSceneLODInfo + { + } +} \ No newline at end of file diff --git a/Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs.meta b/Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs.meta new file mode 100644 index 0000000000..8520a7bbdd --- /dev/null +++ b/Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a80d4ba10f7140f18022a2e40e554863 +timeCreated: 1724413664 \ No newline at end of file diff --git a/Explorer/Assets/DCL/LOD/Components/SceneLODInfo.cs b/Explorer/Assets/DCL/LOD/Components/SceneLODInfo.cs index 31e0e8ba80..2683941bcd 100644 --- a/Explorer/Assets/DCL/LOD/Components/SceneLODInfo.cs +++ b/Explorer/Assets/DCL/LOD/Components/SceneLODInfo.cs @@ -20,6 +20,7 @@ public struct SceneLODInfo public AssetPromise CurrentLODPromise; public byte CurrentLODLevelPromise; + public void Dispose(World world) { @@ -135,5 +136,9 @@ public bool HasLOD(byte lodForAcquisition) CurrentLODLevelPromise == lodForAcquisition; } + public bool IsInitialized() + { + return !string.IsNullOrEmpty(id); + } } } diff --git a/Explorer/Assets/DCL/LOD/Pools/ILODCache.cs b/Explorer/Assets/DCL/LOD/Pools/ILODCache.cs index 007e9c0a35..38c442388e 100644 --- a/Explorer/Assets/DCL/LOD/Pools/ILODCache.cs +++ b/Explorer/Assets/DCL/LOD/Pools/ILODCache.cs @@ -12,5 +12,6 @@ public interface ILODCache void Release(in string key, LODCacheInfo asset); void Unload(IPerformanceBudget frameTimeBudgetProvider, int maxUnloadAmount); + void UnloadImmediate(); } } diff --git a/Explorer/Assets/DCL/LOD/Pools/LODCache.cs b/Explorer/Assets/DCL/LOD/Pools/LODCache.cs index 3e3554ac37..2a87e85dd0 100644 --- a/Explorer/Assets/DCL/LOD/Pools/LODCache.cs +++ b/Explorer/Assets/DCL/LOD/Pools/LODCache.cs @@ -63,5 +63,14 @@ public void Unload(IPerformanceBudget frameTimeBudgetProvider, int maxUnloadAmou asset.Dispose(); } } + + public void UnloadImmediate() + { + while (unloadQueue.TryDequeue(out var key) && lodCache.Remove(key, out var asset)) + { + lodsGroupsPool.Release(asset.LodGroup); + asset.Dispose(); + } + } } } diff --git a/Explorer/Assets/DCL/LOD/Systems/InitializeSceneLODInfoSystem.cs b/Explorer/Assets/DCL/LOD/Systems/InitializeSceneLODInfoSystem.cs index 571c1cad63..5ea05b0634 100644 --- a/Explorer/Assets/DCL/LOD/Systems/InitializeSceneLODInfoSystem.cs +++ b/Explorer/Assets/DCL/LOD/Systems/InitializeSceneLODInfoSystem.cs @@ -1,15 +1,13 @@ -using System.Collections.Generic; -using Arch.Core; +using Arch.Core; using Arch.System; using Arch.SystemGroups; -using Arch.SystemGroups.Metadata; using DCL.Diagnostics; using DCL.LOD.Components; using DCL.Optimization.Pools; using ECS.Abstract; using ECS.LifeCycle.Components; -using ECS.Prioritization.Components; using ECS.SceneLifeCycle; +using ECS.SceneLifeCycle.Reporting; using ECS.SceneLifeCycle.SceneDefinition; using UnityEngine; @@ -25,12 +23,19 @@ public partial class InitializeSceneLODInfoSystem : BaseUnityLoopSystem private readonly IComponentPool lodGroupsPool; private readonly Transform lodCacheParent; + private readonly ISceneReadinessReportQueue sceneReadinessReportQueue; + private readonly IScenesCache scenesCache; - public InitializeSceneLODInfoSystem(World world, ILODCache lodCache, int lodLevels, IComponentPool lodGroupsPool, Transform lodCacheParent) : base(world) + + public InitializeSceneLODInfoSystem(World world, ILODCache lodCache, int lodLevels, + IComponentPool lodGroupsPool, Transform lodCacheParent, + ISceneReadinessReportQueue sceneReadinessReportQueue, IScenesCache scenesCache) : base(world) { this.lodLevels = lodLevels; this.lodGroupsPool = lodGroupsPool; this.lodCacheParent = lodCacheParent; + this.sceneReadinessReportQueue = sceneReadinessReportQueue; + this.scenesCache = scenesCache; this.lodCache = lodCache; } @@ -43,14 +48,17 @@ protected override void Update(float t) [None(typeof(DeleteEntityIntention))] private void InitializeSceneLOD(ref SceneLODInfo sceneLODInfo, SceneDefinitionComponent sceneDefinitionComponent) { - // Means its already initialized - if (!string.IsNullOrEmpty(sceneLODInfo.id)) + if (sceneLODInfo.IsInitialized()) return; string sceneID = sceneDefinitionComponent.Definition.id!; if (lodCache.TryGet(sceneID, out var cacheInfo)) + { sceneLODInfo.metadata = cacheInfo; + LODUtils.TryReportSDK6SceneLoadedForLOD(sceneLODInfo, sceneDefinitionComponent, sceneReadinessReportQueue, + scenesCache); + } else sceneLODInfo.metadata = new LODCacheInfo(InitializeLODGroup(sceneID), lodLevels); sceneLODInfo.id = sceneID; diff --git a/Explorer/Assets/DCL/LOD/Systems/InstantiateSceneLODInfoSystem.cs b/Explorer/Assets/DCL/LOD/Systems/InstantiateSceneLODInfoSystem.cs index ed6581a50f..70e47b35c0 100644 --- a/Explorer/Assets/DCL/LOD/Systems/InstantiateSceneLODInfoSystem.cs +++ b/Explorer/Assets/DCL/LOD/Systems/InstantiateSceneLODInfoSystem.cs @@ -77,15 +77,16 @@ private void ResolveCurrentLODPromise(ref SceneLODInfo sceneLODInfo, ref SceneDe var newLod = new LODAsset(instantiatedLOD, result.Asset, GetTextureSlot(sceneLODInfo.CurrentLODLevelPromise, sceneDefinitionComponent.Definition, instantiatedLOD)); - CheckSceneReadinessAndClean(ref sceneLODInfo, sceneDefinitionComponent); sceneLODInfo.AddSuccessLOD(instantiatedLOD, newLod, defaultFOV, defaultLodBias, realmPartitionSettings.MaxLoadingDistanceInParcels); } else { ReportHub.LogWarning(GetReportCategory(), $"LOD request for {sceneLODInfo.CurrentLODPromise.LoadingIntention.Hash} failed"); - CheckSceneReadinessAndClean(ref sceneLODInfo, sceneDefinitionComponent); sceneLODInfo.AddFailedLOD(); } + + LODUtils.TryReportSDK6SceneLoadedForLOD(sceneLODInfo, sceneDefinitionComponent, sceneReadinessReportQueue, + scenesCache); } } @@ -97,16 +98,5 @@ private void ResolveCurrentLODPromise(ref SceneLODInfo sceneLODInfo, ref SceneDe return slots; } - - private void CheckSceneReadinessAndClean(ref SceneLODInfo sceneLODInfo, SceneDefinitionComponent sceneDefinitionComponent) - { - if (sceneLODInfo.CurrentLODLevelPromise == 0) - { - scenesCache.AddNonRealScene(sceneDefinitionComponent.Parcels); - LODUtils.CheckSceneReadiness(sceneReadinessReportQueue, sceneDefinitionComponent); - } - } - - } } \ No newline at end of file diff --git a/Explorer/Assets/DCL/LOD/Systems/LODPlugin.cs b/Explorer/Assets/DCL/LOD/Systems/LODPlugin.cs index 3e389f9921..4258754757 100644 --- a/Explorer/Assets/DCL/LOD/Systems/LODPlugin.cs +++ b/Explorer/Assets/DCL/LOD/Systems/LODPlugin.cs @@ -91,7 +91,8 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder builder, { CalculateLODBiasSystem.InjectToWorld(ref builder); RecalculateLODDistanceSystem.InjectToWorld(ref builder, partitionSettings); - InitializeSceneLODInfoSystem.InjectToWorld(ref builder, lodCache, lodLevels, lodGroupPool, lodCacheParent); + InitializeSceneLODInfoSystem.InjectToWorld(ref builder, lodCache, lodLevels, lodGroupPool, + lodCacheParent, sceneReadinessReportQueue, scenesCache); UpdateSceneLODInfoSystem.InjectToWorld(ref builder, lodSettingsAsset, scenesCache, sceneReadinessReportQueue, decentralandUrlsSource); InstantiateSceneLODInfoSystem.InjectToWorld(ref builder, frameCapBudget, memoryBudget, scenesCache, sceneReadinessReportQueue, lodTextureArrayContainer, partitionSettings); LODDebugToolsSystem.InjectToWorld(ref builder, debugBuilder, lodSettingsAsset, lodLevels); @@ -105,7 +106,7 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder builder, public void Dispose() { - lodCache.Unload(frameCapBudget, 3); + lodCache.UnloadImmediate(); lodGroupPool?.Dispose(); } } diff --git a/Explorer/Assets/DCL/LOD/Systems/LODUtils.cs b/Explorer/Assets/DCL/LOD/Systems/LODUtils.cs index fc49a511bd..4a036ed10b 100644 --- a/Explorer/Assets/DCL/LOD/Systems/LODUtils.cs +++ b/Explorer/Assets/DCL/LOD/Systems/LODUtils.cs @@ -8,6 +8,8 @@ using SceneRunner.Scene; using System.Collections.Generic; using System.Linq; +using DCL.LOD.Components; +using ECS.SceneLifeCycle; using UnityEngine; using Utility; @@ -68,19 +70,27 @@ public static IReadOnlyList LODManifests(IDecentraland return newSlots.ToArray(); } - public static void CheckSceneReadiness(ISceneReadinessReportQueue sceneReadinessReportQueue, SceneDefinitionComponent sceneDefinitionComponent) + public static void TryReportSDK6SceneLoadedForLOD(SceneLODInfo sceneLODInfo, + SceneDefinitionComponent sceneDefinitionComponent, ISceneReadinessReportQueue sceneReadinessReportQueue, + IScenesCache scenesCache) { + //We have to report ready scenes for LOD_0 which are not SDK7. Only then we can consider this scenes as loaded + if (!sceneDefinitionComponent.IsSDK7 && sceneLODInfo.HasLOD(0)) + ReportSDK6SceneLoaded(sceneDefinitionComponent, sceneReadinessReportQueue, scenesCache); + } + + public static void ReportSDK6SceneLoaded(SceneDefinitionComponent sceneDefinitionComponent, + ISceneReadinessReportQueue sceneReadinessReportQueue, IScenesCache scenesCache) + { + scenesCache.AddNonRealScene(sceneDefinitionComponent.Parcels); if (sceneReadinessReportQueue.TryDequeue(sceneDefinitionComponent.Parcels, out var reports)) { - for (int i = 0; i < reports!.Value.Count; i++) + for (var i = 0; i < reports!.Value.Count; i++) { var report = reports.Value[i]; report.SetProgress(1f); } } } - - - } } diff --git a/Explorer/Assets/DCL/LOD/Systems/UpdateSceneLODInfoMockSystem.cs b/Explorer/Assets/DCL/LOD/Systems/UpdateSceneLODInfoMockSystem.cs index 5843b9d77b..e9c7fed24b 100644 --- a/Explorer/Assets/DCL/LOD/Systems/UpdateSceneLODInfoMockSystem.cs +++ b/Explorer/Assets/DCL/LOD/Systems/UpdateSceneLODInfoMockSystem.cs @@ -35,20 +35,22 @@ protected override void Update(float t) [Query] [All(typeof(SceneLODInfo), typeof(PartitionComponent))] - [None(typeof(DeleteEntityIntention))] - private void UpdateLODLevel(ref SceneLODInfo sceneLODInfo, SceneDefinitionComponent sceneDefinitionComponent) + [None(typeof(DeleteEntityIntention), typeof(MockSceneLODInfo))] + private void UpdateLODLevel(in Entity entity, SceneDefinitionComponent sceneDefinitionComponent) { //If LODs are not enabled, we can consider the scene as ready, //and check scene readiness so not to block the loading screen - scenesCache.AddNonRealScene(sceneDefinitionComponent.Parcels); - LODUtils.CheckSceneReadiness(sceneReadinessReportQueue, sceneDefinitionComponent); + if (!sceneDefinitionComponent.IsSDK7) + LODUtils.ReportSDK6SceneLoaded(sceneDefinitionComponent, sceneReadinessReportQueue, scenesCache); + + World.Add(entity); } [Query] - [All(typeof(DeleteEntityIntention))] - private void UnloadLOD(in Entity entity, ref SceneLODInfo sceneLODInfo, ref SceneDefinitionComponent sceneDefinitionComponent) + [All(typeof(DeleteEntityIntention), typeof(SceneLODInfo), typeof(SceneDefinitionComponent))] + private void UnloadLOD(in Entity entity) { - World.Remove(entity); + World.Remove(entity); } } } diff --git a/Explorer/Assets/DCL/LOD/Tests/EditMode/InitializeSceneLODInfoShould.cs b/Explorer/Assets/DCL/LOD/Tests/EditMode/InitializeSceneLODInfoShould.cs index f8b5cb8833..d1dbab6904 100644 --- a/Explorer/Assets/DCL/LOD/Tests/EditMode/InitializeSceneLODInfoShould.cs +++ b/Explorer/Assets/DCL/LOD/Tests/EditMode/InitializeSceneLODInfoShould.cs @@ -3,6 +3,8 @@ using DCL.LOD.Systems; using DCL.Optimization.Pools; using ECS.Prioritization.Components; +using ECS.SceneLifeCycle; +using ECS.SceneLifeCycle.Reporting; using ECS.SceneLifeCycle.SceneDefinition; using ECS.TestSuite; using NSubstitute; @@ -55,7 +57,9 @@ public void SetUp() }; sceneDefinitionComponent = new SceneDefinitionComponent(sceneEntityDefinition, new IpfsPath()); partitionComponent = new PartitionComponent(); - system = new InitializeSceneLODInfoSystem(world, lodCache, LOD_LEVELS, lodGroupPool, new GameObject().transform); + system = new InitializeSceneLODInfoSystem(world, lodCache, LOD_LEVELS, lodGroupPool, + new GameObject().transform, Substitute.For(), + Substitute.For()); } [Test] diff --git a/Explorer/Assets/DCL/Roads/Systems/RoadInstantiatorSystem.cs b/Explorer/Assets/DCL/Roads/Systems/RoadInstantiatorSystem.cs index 37fc2183a8..94505803f0 100644 --- a/Explorer/Assets/DCL/Roads/Systems/RoadInstantiatorSystem.cs +++ b/Explorer/Assets/DCL/Roads/Systems/RoadInstantiatorSystem.cs @@ -78,8 +78,10 @@ private void InstantiateRoad(ref RoadInfo roadInfo, ref SceneDefinitionComponent $"Road with coords for {sceneDefinitionComponent.Definition.metadata.scene.DecodedBase} do not have a description"); } roadInfo.IsDirty = false; - scenesCache.AddNonRealScene(sceneDefinitionComponent.Parcels); - LODUtils.CheckSceneReadiness(sceneReadinessReportQueue, sceneDefinitionComponent); + + + //In case this is a road teleport destination, we need to release the loading screen + LODUtils.ReportSDK6SceneLoaded(sceneDefinitionComponent, sceneReadinessReportQueue, scenesCache); } diff --git a/Explorer/Assets/DCL/Roads/Systems/UnloadRoadSystem.cs b/Explorer/Assets/DCL/Roads/Systems/UnloadRoadSystem.cs index ca1595c1de..5506ee014e 100644 --- a/Explorer/Assets/DCL/Roads/Systems/UnloadRoadSystem.cs +++ b/Explorer/Assets/DCL/Roads/Systems/UnloadRoadSystem.cs @@ -35,7 +35,7 @@ protected override void Update(float t) [Query] [All(typeof(DeleteEntityIntention), typeof(VisualSceneState))] - private void UnloadRoad(Entity entity, ref RoadInfo roadInfo, ref SceneDefinitionComponent sceneDefinitionComponent) + private void UnloadRoad(ref RoadInfo roadInfo, ref SceneDefinitionComponent sceneDefinitionComponent) { roadInfo.Dispose(roadAssetPool); scenesCache.RemoveNonRealScene(sceneDefinitionComponent.Parcels); diff --git a/Explorer/Assets/Scripts/ECS/SceneLifeCycle/SceneFacade/SceneLODInfoExtensions.cs b/Explorer/Assets/Scripts/ECS/SceneLifeCycle/SceneFacade/SceneLODInfoExtensions.cs index c5b0ab4be5..0f0b759199 100644 --- a/Explorer/Assets/Scripts/ECS/SceneLifeCycle/SceneFacade/SceneLODInfoExtensions.cs +++ b/Explorer/Assets/Scripts/ECS/SceneLifeCycle/SceneFacade/SceneLODInfoExtensions.cs @@ -15,11 +15,12 @@ public static void DisposeSceneLODAndRemoveFromCache(this SceneLODInfo sceneLODI World world) { //Only try to release SceneLODInfo that has been initialized - if (!string.IsNullOrEmpty(sceneLODInfo.id)) + if (sceneLODInfo.IsInitialized()) + { lodCache.Release(sceneLODInfo.id, sceneLODInfo.metadata); - - sceneLODInfo.Dispose(world); - scenesCache.RemoveNonRealScene(parcels); + sceneLODInfo.Dispose(world); + scenesCache.RemoveNonRealScene(parcels); + } } } }