mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
ResourceTree: Use both game path and resource handle as keys for dedup
This commit is contained in:
parent
28a396470b
commit
57f8587a43
1 changed files with 40 additions and 29 deletions
|
|
@ -16,7 +16,7 @@ namespace Penumbra.Interop.ResourceTree;
|
||||||
internal record GlobalResolveContext(IObjectIdentifier Identifier, TreeBuildCache TreeBuildCache,
|
internal record GlobalResolveContext(IObjectIdentifier Identifier, TreeBuildCache TreeBuildCache,
|
||||||
int Skeleton, bool WithUiData)
|
int Skeleton, bool WithUiData)
|
||||||
{
|
{
|
||||||
public readonly Dictionary<nint, ResourceNode> Nodes = new(128);
|
public readonly Dictionary<(Utf8GamePath, nint), ResourceNode> Nodes = new(128);
|
||||||
|
|
||||||
public ResolveContext CreateContext(EquipSlot slot, CharacterArmor equipment)
|
public ResolveContext CreateContext(EquipSlot slot, CharacterArmor equipment)
|
||||||
=> new(this, slot, equipment);
|
=> new(this, slot, equipment);
|
||||||
|
|
@ -30,16 +30,12 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
{
|
{
|
||||||
if (resourceHandle == null)
|
if (resourceHandle == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)resourceHandle, out var cached))
|
|
||||||
return cached;
|
|
||||||
|
|
||||||
if (gamePath.IsEmpty)
|
if (gamePath.IsEmpty)
|
||||||
return null;
|
return null;
|
||||||
if (!Utf8GamePath.FromByteString(ByteString.Join((byte)'/', ShpkPrefix, gamePath), out var path, false))
|
if (!Utf8GamePath.FromByteString(ByteString.Join((byte)'/', ShpkPrefix, gamePath), out var path, false))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return CreateNode(ResourceType.Shpk, (nint)resourceHandle->ShaderPackage, &resourceHandle->ResourceHandle, path);
|
return GetOrCreateNode(ResourceType.Shpk, (nint)resourceHandle->ShaderPackage, &resourceHandle->ResourceHandle, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe ResourceNode? CreateNodeFromTex(TextureResourceHandle* resourceHandle, ByteString gamePath, bool dx11)
|
private unsafe ResourceNode? CreateNodeFromTex(TextureResourceHandle* resourceHandle, ByteString gamePath, bool dx11)
|
||||||
|
|
@ -47,9 +43,6 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (resourceHandle == null)
|
if (resourceHandle == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)resourceHandle, out var cached))
|
|
||||||
return cached;
|
|
||||||
|
|
||||||
if (dx11)
|
if (dx11)
|
||||||
{
|
{
|
||||||
var lastDirectorySeparator = gamePath.LastIndexOf((byte)'/');
|
var lastDirectorySeparator = gamePath.LastIndexOf((byte)'/');
|
||||||
|
|
@ -80,7 +73,19 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (!Utf8GamePath.FromByteString(gamePath, out var path))
|
if (!Utf8GamePath.FromByteString(gamePath, out var path))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return CreateNode(ResourceType.Tex, (nint)resourceHandle->Texture, &resourceHandle->ResourceHandle, path);
|
return GetOrCreateNode(ResourceType.Tex, (nint)resourceHandle->Texture, &resourceHandle->ResourceHandle, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe ResourceNode GetOrCreateNode(ResourceType type, nint objectAddress, ResourceHandle* resourceHandle,
|
||||||
|
Utf8GamePath gamePath)
|
||||||
|
{
|
||||||
|
if (resourceHandle == null)
|
||||||
|
throw new ArgumentNullException(nameof(resourceHandle));
|
||||||
|
|
||||||
|
if (Global.Nodes.TryGetValue((gamePath, (nint)resourceHandle), out var cached))
|
||||||
|
return cached;
|
||||||
|
|
||||||
|
return CreateNode(type, objectAddress, resourceHandle, gamePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe ResourceNode CreateNode(ResourceType type, nint objectAddress, ResourceHandle* resourceHandle,
|
private unsafe ResourceNode CreateNode(ResourceType type, nint objectAddress, ResourceHandle* resourceHandle,
|
||||||
|
|
@ -97,7 +102,7 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
FullPath = fullPath,
|
FullPath = fullPath,
|
||||||
};
|
};
|
||||||
if (autoAdd)
|
if (autoAdd)
|
||||||
Global.Nodes.Add((nint)resourceHandle, node);
|
Global.Nodes.Add((gamePath, (nint)resourceHandle), node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
@ -107,10 +112,9 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (imc == null)
|
if (imc == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)imc, out var cached))
|
var path = Utf8GamePath.Empty; // TODO
|
||||||
return cached;
|
|
||||||
|
|
||||||
return CreateNode(ResourceType.Imc, 0, imc, Utf8GamePath.Empty);
|
return GetOrCreateNode(ResourceType.Imc, 0, imc, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe ResourceNode? CreateNodeFromTex(TextureResourceHandle* tex)
|
public unsafe ResourceNode? CreateNodeFromTex(TextureResourceHandle* tex)
|
||||||
|
|
@ -118,10 +122,9 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (tex == null)
|
if (tex == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)tex, out var cached))
|
var path = Utf8GamePath.Empty; // TODO
|
||||||
return cached;
|
|
||||||
|
|
||||||
return CreateNode(ResourceType.Tex, (nint)tex->Texture, &tex->ResourceHandle, Utf8GamePath.Empty);
|
return GetOrCreateNode(ResourceType.Tex, (nint)tex->Texture, &tex->ResourceHandle, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe ResourceNode? CreateNodeFromRenderModel(Model* mdl)
|
public unsafe ResourceNode? CreateNodeFromRenderModel(Model* mdl)
|
||||||
|
|
@ -129,10 +132,12 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (mdl == null || mdl->ModelResourceHandle == null)
|
if (mdl == null || mdl->ModelResourceHandle == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)mdl->ModelResourceHandle, out var cached))
|
var path = Utf8GamePath.Empty; // TODO
|
||||||
|
|
||||||
|
if (Global.Nodes.TryGetValue((path, (nint)mdl->ModelResourceHandle), out var cached))
|
||||||
return cached;
|
return cached;
|
||||||
|
|
||||||
var node = CreateNode(ResourceType.Mdl, (nint)mdl, &mdl->ModelResourceHandle->ResourceHandle, Utf8GamePath.Empty, false);
|
var node = CreateNode(ResourceType.Mdl, (nint)mdl, &mdl->ModelResourceHandle->ResourceHandle, path, false);
|
||||||
|
|
||||||
for (var i = 0; i < mdl->MaterialCount; i++)
|
for (var i = 0; i < mdl->MaterialCount; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -146,7 +151,7 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Global.Nodes.Add((nint)mdl->ModelResourceHandle, node);
|
Global.Nodes.Add((path, (nint)mdl->ModelResourceHandle), node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
@ -178,11 +183,13 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (mtrl == null || mtrl->MaterialResourceHandle == null)
|
if (mtrl == null || mtrl->MaterialResourceHandle == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
var path = Utf8GamePath.Empty; // TODO
|
||||||
|
|
||||||
var resource = mtrl->MaterialResourceHandle;
|
var resource = mtrl->MaterialResourceHandle;
|
||||||
if (Global.Nodes.TryGetValue((nint)resource, out var cached))
|
if (Global.Nodes.TryGetValue((path, (nint)resource), out var cached))
|
||||||
return cached;
|
return cached;
|
||||||
|
|
||||||
var node = CreateNode(ResourceType.Mtrl, (nint)mtrl, &resource->ResourceHandle, Utf8GamePath.Empty, false);
|
var node = CreateNode(ResourceType.Mtrl, (nint)mtrl, &resource->ResourceHandle, path, false);
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
@ -231,7 +238,7 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
node.Children.Add(texNode);
|
node.Children.Add(texNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Global.Nodes.Add((nint)resource, node);
|
Global.Nodes.Add((path, (nint)resource), node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
@ -241,16 +248,18 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (sklb == null || sklb->SkeletonResourceHandle == null)
|
if (sklb == null || sklb->SkeletonResourceHandle == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)sklb->SkeletonResourceHandle, out var cached))
|
var path = Utf8GamePath.Empty; // TODO
|
||||||
|
|
||||||
|
if (Global.Nodes.TryGetValue((path, (nint)sklb->SkeletonResourceHandle), out var cached))
|
||||||
return cached;
|
return cached;
|
||||||
|
|
||||||
var node = CreateNode(ResourceType.Sklb, (nint)sklb, (ResourceHandle*)sklb->SkeletonResourceHandle, Utf8GamePath.Empty, false);
|
var node = CreateNode(ResourceType.Sklb, (nint)sklb, (ResourceHandle*)sklb->SkeletonResourceHandle, path, false);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
var skpNode = CreateParameterNodeFromPartialSkeleton(sklb);
|
var skpNode = CreateParameterNodeFromPartialSkeleton(sklb);
|
||||||
if (skpNode != null)
|
if (skpNode != null)
|
||||||
node.Children.Add(skpNode);
|
node.Children.Add(skpNode);
|
||||||
Global.Nodes.Add((nint)sklb->SkeletonResourceHandle, node);
|
Global.Nodes.Add((path, (nint)sklb->SkeletonResourceHandle), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
@ -261,15 +270,17 @@ internal record ResolveContext(GlobalResolveContext Global, EquipSlot Slot, Char
|
||||||
if (sklb == null || sklb->SkeletonParameterResourceHandle == null)
|
if (sklb == null || sklb->SkeletonParameterResourceHandle == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (Global.Nodes.TryGetValue((nint)sklb->SkeletonParameterResourceHandle, out var cached))
|
var path = Utf8GamePath.Empty; // TODO
|
||||||
|
|
||||||
|
if (Global.Nodes.TryGetValue((path, (nint)sklb->SkeletonParameterResourceHandle), out var cached))
|
||||||
return cached;
|
return cached;
|
||||||
|
|
||||||
var node = CreateNode(ResourceType.Skp, (nint)sklb, (ResourceHandle*)sklb->SkeletonParameterResourceHandle, Utf8GamePath.Empty, false);
|
var node = CreateNode(ResourceType.Skp, (nint)sklb, (ResourceHandle*)sklb->SkeletonParameterResourceHandle, path, false);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
if (Global.WithUiData)
|
if (Global.WithUiData)
|
||||||
node.FallbackName = "Skeleton Parameters";
|
node.FallbackName = "Skeleton Parameters";
|
||||||
Global.Nodes.Add((nint)sklb->SkeletonParameterResourceHandle, node);
|
Global.Nodes.Add((path, (nint)sklb->SkeletonParameterResourceHandle), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue