Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: lods removing from scene cache #1857

Merged
merged 13 commits into from
Aug 26, 2024
6 changes: 6 additions & 0 deletions Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace DCL.LOD.Components
{
public struct MockSceneLODInfo
{
}
}
3 changes: 3 additions & 0 deletions Explorer/Assets/DCL/LOD/Components/MockSceneLODInfo.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Explorer/Assets/DCL/LOD/Components/SceneLODInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public struct SceneLODInfo

public AssetPromise<AssetBundleData, GetAssetBundleIntention> CurrentLODPromise;
public byte CurrentLODLevelPromise;


public void Dispose(World world)
{
Expand Down Expand Up @@ -135,5 +136,9 @@ public bool HasLOD(byte lodForAcquisition)
CurrentLODLevelPromise == lodForAcquisition;
}

public bool IsInitialized()
{
return !string.IsNullOrEmpty(id);
}
}
}
1 change: 1 addition & 0 deletions Explorer/Assets/DCL/LOD/Pools/ILODCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public interface ILODCache
void Release(in string key, LODCacheInfo asset);

void Unload(IPerformanceBudget frameTimeBudgetProvider, int maxUnloadAmount);
void UnloadImmediate();
}
}
9 changes: 9 additions & 0 deletions Explorer/Assets/DCL/LOD/Pools/LODCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
}
22 changes: 15 additions & 7 deletions Explorer/Assets/DCL/LOD/Systems/InitializeSceneLODInfoSystem.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -25,12 +23,19 @@ public partial class InitializeSceneLODInfoSystem : BaseUnityLoopSystem
private readonly IComponentPool<LODGroup> lodGroupsPool;
private readonly Transform lodCacheParent;

private readonly ISceneReadinessReportQueue sceneReadinessReportQueue;
private readonly IScenesCache scenesCache;

public InitializeSceneLODInfoSystem(World world, ILODCache lodCache, int lodLevels, IComponentPool<LODGroup> lodGroupsPool, Transform lodCacheParent) : base(world)

public InitializeSceneLODInfoSystem(World world, ILODCache lodCache, int lodLevels,
IComponentPool<LODGroup> 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;
}

Expand All @@ -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.TryReportSceneLoadedForLOD(sceneLODInfo, sceneDefinitionComponent, sceneReadinessReportQueue,
scenesCache);
}
else
sceneLODInfo.metadata = new LODCacheInfo(InitializeLODGroup(sceneID), lodLevels);
sceneLODInfo.id = sceneID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.TryReportSceneLoadedForLOD(sceneLODInfo, sceneDefinitionComponent, sceneReadinessReportQueue,
scenesCache);
}
}

Expand All @@ -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);
}
}


}
}
5 changes: 3 additions & 2 deletions Explorer/Assets/DCL/LOD/Systems/LODPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder<Arch.Core.World> 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);
Expand All @@ -105,7 +106,7 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder<Arch.Core.World> builder,

public void Dispose()
{
lodCache.Unload(frameCapBudget, 3);
lodCache.UnloadImmediate();
lodGroupPool?.Dispose();
}
}
Expand Down
20 changes: 15 additions & 5 deletions Explorer/Assets/DCL/LOD/Systems/LODUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -68,19 +70,27 @@ public static IReadOnlyList<SceneAssetBundleManifest> LODManifests(IDecentraland
return newSlots.ToArray();
}

public static void CheckSceneReadiness(ISceneReadinessReportQueue sceneReadinessReportQueue, SceneDefinitionComponent sceneDefinitionComponent)
public static void TryReportSceneLoadedForLOD(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 (sceneLODInfo.HasLOD(0) && !sceneDefinitionComponent.IsSDK7)
dalkia marked this conversation as resolved.
Show resolved Hide resolved
ReportSceneLoaded(sceneDefinitionComponent, sceneReadinessReportQueue, scenesCache);
}

public static void ReportSceneLoaded(SceneDefinitionComponent sceneDefinitionComponent,
dalkia marked this conversation as resolved.
Show resolved Hide resolved
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);
}
}
}



}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.ReportSceneLoaded(sceneDefinitionComponent, sceneReadinessReportQueue, scenesCache);

World.Add<MockSceneLODInfo>(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<SceneLODInfo, VisualSceneState, DeleteEntityIntention>(entity);
World.Remove<SceneLODInfo, VisualSceneState, DeleteEntityIntention, MockSceneLODInfo>(entity);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<ISceneReadinessReportQueue>(),
Substitute.For<IScenesCache>());
}

[Test]
Expand Down
6 changes: 4 additions & 2 deletions Explorer/Assets/DCL/Roads/Systems/RoadInstantiatorSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.ReportSceneLoaded(sceneDefinitionComponent, sceneReadinessReportQueue, scenesCache);
}


Expand Down
2 changes: 1 addition & 1 deletion Explorer/Assets/DCL/Roads/Systems/UnloadRoadSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Loading