Optimize I/O of ShPk for ResourceTree generation

This commit is contained in:
Exter-N 2024-08-03 17:46:29 +02:00
parent 5323add662
commit c01aa000fb
2 changed files with 17 additions and 8 deletions

View file

@ -230,7 +230,7 @@ internal unsafe partial record ResolveContext(
node.Children.Add(shpkNode); node.Children.Add(shpkNode);
} }
var shpkFile = Global.WithUiData && shpkNode != null ? Global.TreeBuildCache.ReadShaderPackage(shpkNode.FullPath) : null; var shpkNames = Global.WithUiData && shpkNode != null ? Global.TreeBuildCache.ReadShaderPackageNames(shpkNode.FullPath) : null;
var shpk = Global.WithUiData && shpkNode != null ? (ShaderPackage*)shpkNode.ObjectAddress : null; var shpk = Global.WithUiData && shpkNode != null ? (ShaderPackage*)shpkNode.ObjectAddress : null;
var alreadyProcessedSamplerIds = new HashSet<uint>(); var alreadyProcessedSamplerIds = new HashSet<uint>();
@ -255,7 +255,12 @@ internal unsafe partial record ResolveContext(
alreadyProcessedSamplerIds.Add(samplerId.Value); alreadyProcessedSamplerIds.Add(samplerId.Value);
var samplerCrc = GetSamplerCrcById(shpk, samplerId.Value); var samplerCrc = GetSamplerCrcById(shpk, samplerId.Value);
if (samplerCrc.HasValue) if (samplerCrc.HasValue)
name = shpkFile?.GetSamplerById(samplerCrc.Value)?.Name ?? $"Texture 0x{samplerCrc.Value:X8}"; {
if (shpkNames != null && shpkNames.TryGetValue(samplerCrc.Value, out var samplerName))
name = samplerName.Value;
else
name = $"Texture 0x{samplerCrc.Value:X8}";
}
} }
} }

View file

@ -1,8 +1,11 @@
using System.IO.MemoryMappedFiles;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Files; using Penumbra.GameData.Files;
using Penumbra.GameData.Files.ShaderStructs;
using Penumbra.GameData.Files.Utility;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using Penumbra.String.Classes; using Penumbra.String.Classes;
@ -11,7 +14,7 @@ namespace Penumbra.Interop.ResourceTree;
internal readonly struct TreeBuildCache(ObjectManager objects, IDataManager dataManager, ActorManager actors) internal readonly struct TreeBuildCache(ObjectManager objects, IDataManager dataManager, ActorManager actors)
{ {
private readonly Dictionary<FullPath, ShpkFile?> _shaderPackages = []; private readonly Dictionary<FullPath, IReadOnlyDictionary<uint, Name>?> _shaderPackageNames = [];
public unsafe bool IsLocalPlayerRelated(ICharacter character) public unsafe bool IsLocalPlayerRelated(ICharacter character)
{ {
@ -68,10 +71,10 @@ internal readonly struct TreeBuildCache(ObjectManager objects, IDataManager data
} }
/// <summary> Try to read a shpk file from the given path and cache it on success. </summary> /// <summary> Try to read a shpk file from the given path and cache it on success. </summary>
public ShpkFile? ReadShaderPackage(FullPath path) public IReadOnlyDictionary<uint, Name>? ReadShaderPackageNames(FullPath path)
=> ReadFile(dataManager, path, _shaderPackages, bytes => new ShpkFile(bytes)); => ReadFile(dataManager, path, _shaderPackageNames, bytes => ShpkFile.FastExtractNames(bytes.Span));
private static T? ReadFile<T>(IDataManager dataManager, FullPath path, Dictionary<FullPath, T?> cache, Func<byte[], T> parseFile) private static T? ReadFile<T>(IDataManager dataManager, FullPath path, Dictionary<FullPath, T?> cache, Func<ReadOnlyMemory<byte>, T> parseFile)
where T : class where T : class
{ {
if (path.FullName.Length == 0) if (path.FullName.Length == 0)
@ -86,7 +89,8 @@ internal readonly struct TreeBuildCache(ObjectManager objects, IDataManager data
{ {
if (path.IsRooted) if (path.IsRooted)
{ {
parsed = parseFile(File.ReadAllBytes(pathStr)); using var mmFile = MmioMemoryManager.CreateFromFile(pathStr, access: MemoryMappedFileAccess.Read);
parsed = parseFile(mmFile.Memory);
} }
else else
{ {