WuhuIslandTesting/Library/PackageCache/com.unity.addressables@1.21.12/Editor/Diagnostics/Profiler/BuildLayoutsManager.cs
2025-01-07 02:06:59 +01:00

195 lines
7.8 KiB
C#

#if ENABLE_ADDRESSABLE_PROFILER && UNITY_2022_2_OR_NEWER
using System.Collections.Generic;
using System.IO;
using Unity.Collections;
using UnityEditor.AddressableAssets.Build.Layout;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.Profiling;
namespace UnityEditor.AddressableAssets.Diagnostics
{
internal class BuildLayoutsManager
{
private class ActiveLayout
{
public Hash128 BuildResultHash;
private readonly Dictionary<int, BuildLayout.Bundle> m_BundleMap = new Dictionary<int, BuildLayout.Bundle>();
private readonly Dictionary<int, Dictionary<int,BuildLayout.ExplicitAsset>> m_BundleAssetsMap = new Dictionary<int, Dictionary<int, BuildLayout.ExplicitAsset>>();
public ActiveLayout(BuildLayout layout)
{
layout.ReadFull();
foreach (BuildLayout.Bundle bundle in BuildLayoutHelpers.EnumerateBundles(layout))
{
int bundleCode = bundle.InternalName.GetHashCode();
m_BundleMap.Add(bundleCode, bundle);
Dictionary<int, BuildLayout.ExplicitAsset> assetMap = new Dictionary<int, BuildLayout.ExplicitAsset>(bundle.AssetCount);
foreach (BuildLayout.ExplicitAsset asset in BuildLayoutHelpers.EnumerateAssets(bundle))
{
int assetCode = asset.InternalId.GetHashCode();
assetMap[assetCode] = asset;
}
m_BundleAssetsMap[bundleCode] = assetMap;
}
}
public BuildLayout.Bundle GetBundle(int bundleCode)
{
if (!m_BundleMap.TryGetValue(bundleCode, out BuildLayout.Bundle value))
return null;
return value;
}
public BuildLayout.ExplicitAsset GetAsset(int bundleCode, int assetCode)
{
if (!m_BundleAssetsMap.TryGetValue(bundleCode, out Dictionary<int, BuildLayout.ExplicitAsset> assetMap))
return null;
if (!assetMap.TryGetValue(assetCode, out BuildLayout.ExplicitAsset value))
return null;
return value;
}
}
private Dictionary<Hash128, BuildLayout> m_BuildLayouts = new Dictionary<Hash128, BuildLayout>();
private readonly List<ActiveLayout> m_ActiveLayouts = new List<ActiveLayout>();
public void LoadReports()
{
m_BuildLayouts.Clear();
m_ActiveLayouts.Clear();
if (Directory.Exists(Addressables.BuildReportPath))
{
foreach (string file in Directory.EnumerateFiles(Addressables.BuildReportPath, "*.json", SearchOption.TopDirectoryOnly))
{
if (!TryLoadLayoutAtPath(file, out BuildLayout layout))
continue;
Hash128 buildHash = Hash128.Parse(layout.BuildResultHash);
if (m_BuildLayouts.TryGetValue(buildHash, out var other))
{
// doesn't really matter, just means multiple with the same results exist, get the latest anyway
int comp = layout.Header.BuildStart.CompareTo(other.Header.BuildStart);
if (comp > 0)
{
m_BuildLayouts[buildHash].Close();
m_BuildLayouts[buildHash] = layout;
}
}
else
m_BuildLayouts.Add(buildHash, layout);
}
}
}
public bool LoadManualReport(string path)
{
if (!TryLoadLayoutAtPath(path, out BuildLayout layout, true))
return false;
// set a save for the build hash
EditorPrefs.SetString("com.unity.addressabes.reportFilePath_" + layout.BuildResultHash, path);
m_BuildLayouts[Hash128.Parse(layout.BuildResultHash)] = layout;
return true;
}
private bool TryLoadLayoutAtPath(string path, out BuildLayout layoutOut, bool logErrors = false)
{
layoutOut = BuildLayout.Open(path);
if (layoutOut == null)
return false;
if (!layoutOut.ReadHeader())
return false;
if (!string.IsNullOrEmpty(layoutOut.Header.BuildError))
return false;
Hash128 hash = Hash128.Parse(layoutOut.BuildResultHash);
if (!hash.isValid)
{
if (logErrors)
Debug.LogError($"Could not load build report at {path}. Missing BuildResultHash");
return false;
}
return true;
}
public HashSet<Hash128> SetActiveReportsAndGetMissingBuildHashes(NativeArray<CatalogFrameData> loadedRuntimeCatalogs)
{
HashSet<ActiveLayout> oldActives = new HashSet<ActiveLayout>(m_ActiveLayouts);
HashSet<Hash128> missingBuildHashes = new HashSet<Hash128>();
for (int i = 0; i < loadedRuntimeCatalogs.Length; ++i)
{
var recordedHash = loadedRuntimeCatalogs[i].BuildResultHash;
var layout = m_ActiveLayouts.Find(activeLayout => activeLayout.BuildResultHash == recordedHash);
if (layout != null)
{
oldActives.Remove(layout);
continue;
}
if (m_BuildLayouts.TryGetValue(recordedHash, out BuildLayout newActiveLayout))
m_ActiveLayouts.Add(new ActiveLayout(newActiveLayout));
else
{
// try get from saved manual path
BuildLayout buildLayout = null;
if (EditorPrefs.HasKey("com.unity.addressabes.reportFilePath_" + recordedHash.ToString()))
{
string path = EditorPrefs.GetString("com.unity.addressabes.reportFilePath_" + recordedHash.ToString());
if (TryLoadLayoutAtPath(path, out buildLayout))
{
m_BuildLayouts[Hash128.Parse(buildLayout.BuildResultHash)] = buildLayout;
m_ActiveLayouts.Add(new ActiveLayout(buildLayout));
}
}
if (buildLayout == null)
missingBuildHashes.Add(recordedHash);
}
}
foreach (ActiveLayout oldActive in oldActives)
m_ActiveLayouts.Remove(oldActive);
if (missingBuildHashes.Count == 0)
return null;
return missingBuildHashes;
}
public BuildLayout.Bundle GetBundle(int bundleCode)
{
BuildLayout.Bundle value;
foreach (ActiveLayout activeLayout in m_ActiveLayouts)
{
value = activeLayout.GetBundle(bundleCode);
if (value != null)
return value;
}
return null;
}
public BuildLayout.ExplicitAsset GetAsset(int bundleCode, int assetCode)
{
BuildLayout.ExplicitAsset value = null;
foreach (ActiveLayout activeLayout in m_ActiveLayouts)
{
value = activeLayout.GetAsset(bundleCode, assetCode);
if (value != null)
{
// this should be fixed in layout gen bug fix
// keeping bundle assignment to handle any previous data
if (value.Bundle == null)
value.Bundle = value.File.Bundle;
return value;
}
}
return null;
}
}
}
#endif