(HELP) AssetRegistryState loading for improved scan time
Hi, I am trying to improve the asset registry scan time by loading pre-serialized version of it, but it doesn't work at all so far.
For context, in our project we have pak files that are stored on a remote server. They have to stay there and cannot be copied to a local disk. The paks are already big, and will be even bigger in the future. Because of that, the call to `IAssetRegistry::ScanPathsSynchronous` takes multiple seconds.
The idea is to produce a serialized version of the registry for each pak containing only the assets with the corresponding chunk ID, with hope that it will be faster.
I wrote a commandlet that takes the `DevelopmentAssetRegistry.bin` generated during cooking, and tried to split it. However, the application crashes during deserialization of my "handmade" registries due to an out of bound index. From what I understand, it seems the content of the file is not what is expected.
Here is the splitting code:
bool GeneratePaksAssetRegistries(const FString& BasePath)
{
FAssetRegistryState AssetRegistryState;
if (!FAssetRegistryState::LoadFromDisk(\*(BasePath / "DevelopmentAssetRegistry.bin"), {}, AssetRegistryState))
{
return false;
}
TSet<int32> ChunkIds;
AssetRegistryState.EnumerateAllAssets(\[&ChunkIds\](const FAssetData& AssetData)
{
for (const int32 ChunkId : AssetData.GdtChunkIDs())
{
ChunkIds.Add(ChunkId);
}
});
for (const int32 ChunkId : ChunkIds)
{
FAssetRegistryState ChunkState;
ChunkState.InitializeFromExistingAndPrune(AssetRegistryState, {}, {}, { ChunkId }, {});
const FString Filename = FString::Printf("AssetRegistry\_pakchunk%d-Windows.bin"), ChunkId);
const FString FullPath = BasePath / Filename;
if (FArchive\* Writer = IFileManager::Get().CreateFileWriter(\*FullPath))
{
FAssetRegistrySerializationOptions SerializationOptions{};
SerializationOptions.bSerializeAssetRegistry = true;
SerializationOptions.bSerializeDependencies = true;
SerializationOptions.bSerializePackageData = true;
ChunkState.Save(\*Writer, SerializationOptions);
Writer->Close();
}
else
{
return false;
}
}
return true;
}
And here is the snippet of the loading code:
IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get();
FAssetRegistryState CachedState;
FAssetRegistryState LoadOptions{};
LoadOptions.bLoadDependencies = true;
LoadOptions.bLoadPackageData = true;
if (FAssetRegistryState::LoadFromDisk(\*CachedAsserRegistryPath, LoadOptions, CschedState)) // Crash here
{
AssetRegistry.AppendState(CachedState);
}
I tried the different serialization/deserialization options, but the index is always out of bound.
It may be because because a packaged application cannot read serialized asset registries produced from cooking data. So, I also tried to do the scan the first time the packaged application starts, and then split and serialize the registry so that future launch will be faster. However, all `.bin` files produced with this method have the same size, which is abnormal considering the number of assets in each pak is not the same at all. The post-cook commandlet does not have this issue.
I am completely stuck at the moment. Is it even possible to cache the asset registry for faster launch time of a packaged application?