Minor cleanup.

This commit is contained in:
Ottermandias 2024-08-09 01:15:05 +02:00
parent b3d841a8ec
commit a52a43bd86
4 changed files with 38 additions and 55 deletions

View file

@ -11,10 +11,8 @@ public unsafe class HumanSetupScalingHook : FastHook<HumanSetupScalingHook.Deleg
public event EventDelegate? SetupReplacements; public event EventDelegate? SetupReplacements;
public HumanSetupScalingHook(HookManager hooks, CharacterBaseVTables vTables) public HumanSetupScalingHook(HookManager hooks, CharacterBaseVTables vTables)
{ => Task = hooks.CreateHook<Delegate>("Human.SetupScaling", vTables.HumanVTable[58], Detour,
Task = hooks.CreateHook<Delegate>("Human.SetupScaling", vTables.HumanVTable[58], Detour,
!HookOverrides.Instance.PostProcessing.HumanSetupScaling); !HookOverrides.Instance.PostProcessing.HumanSetupScaling);
}
private void Detour(CharacterBase* drawObject, uint slotIndex) private void Detour(CharacterBase* drawObject, uint slotIndex)
{ {
@ -32,6 +30,7 @@ public unsafe class HumanSetupScalingHook : FastHook<HumanSetupScalingHook.Deleg
Monitor.Enter(shpkLock); Monitor.Enter(shpkLock);
releaseLock = true; releaseLock = true;
} }
for (var i = 0; i < numReplacements; ++i) for (var i = 0; i < numReplacements; ++i)
*(nint*)replacements[i].AddressToReplace = replacements[i].ValueToSet; *(nint*)replacements[i].AddressToReplace = replacements[i].ValueToSet;
Task.Result.Original(drawObject, slotIndex); Task.Result.Original(drawObject, slotIndex);

View file

@ -19,7 +19,7 @@ public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredServi
Utf8GamePath.FromSpan("chara/xls/boneDeformer/human.pbd"u8, MetaDataComputation.All, out var p) ? p : Utf8GamePath.Empty; Utf8GamePath.FromSpan("chara/xls/boneDeformer/human.pbd"u8, MetaDataComputation.All, out var p) ? p : Utf8GamePath.Empty;
// Approximate name guess. // Approximate name guess.
private delegate void* CharacterBaseCreateDeformerDelegate(CharacterBase* drawObject, uint slotIndex); private delegate void* CharacterBaseCreateDeformerDelegate(CharacterBase* drawObject, uint slotIndex);
private readonly Hook<CharacterBaseCreateDeformerDelegate> _humanCreateDeformerHook; private readonly Hook<CharacterBaseCreateDeformerDelegate> _humanCreateDeformerHook;
@ -32,12 +32,12 @@ public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredServi
public PreBoneDeformerReplacer(CharacterUtility utility, CollectionResolver collectionResolver, ResourceLoader resourceLoader, public PreBoneDeformerReplacer(CharacterUtility utility, CollectionResolver collectionResolver, ResourceLoader resourceLoader,
HookManager hooks, IFramework framework, CharacterBaseVTables vTables, HumanSetupScalingHook humanSetupScalingHook) HookManager hooks, IFramework framework, CharacterBaseVTables vTables, HumanSetupScalingHook humanSetupScalingHook)
{ {
_utility = utility; _utility = utility;
_collectionResolver = collectionResolver; _collectionResolver = collectionResolver;
_resourceLoader = resourceLoader; _resourceLoader = resourceLoader;
_framework = framework; _framework = framework;
_humanSetupScalingHook = humanSetupScalingHook; _humanSetupScalingHook = humanSetupScalingHook;
_humanSetupScalingHook.SetupReplacements += SetupHSSReplacements; _humanSetupScalingHook.SetupReplacements += SetupHssReplacements;
_humanCreateDeformerHook = hooks.CreateHook<CharacterBaseCreateDeformerDelegate>("HumanCreateDeformer", vTables.HumanVTable[101], _humanCreateDeformerHook = hooks.CreateHook<CharacterBaseCreateDeformerDelegate>("HumanCreateDeformer", vTables.HumanVTable[101],
CreateDeformer, !HookOverrides.Instance.PostProcessing.HumanCreateDeformer).Result; CreateDeformer, !HookOverrides.Instance.PostProcessing.HumanCreateDeformer).Result;
} }
@ -45,7 +45,7 @@ public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredServi
public void Dispose() public void Dispose()
{ {
_humanCreateDeformerHook.Dispose(); _humanCreateDeformerHook.Dispose();
_humanSetupScalingHook.SetupReplacements -= SetupHSSReplacements; _humanSetupScalingHook.SetupReplacements -= SetupHssReplacements;
} }
private SafeResourceHandle GetPreBoneDeformerForCharacter(CharacterBase* drawObject) private SafeResourceHandle GetPreBoneDeformerForCharacter(CharacterBase* drawObject)
@ -57,18 +57,19 @@ public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredServi
return cache.CustomResources.Get(ResourceCategory.Chara, ResourceType.Pbd, PreBoneDeformerPath, resolveData); return cache.CustomResources.Get(ResourceCategory.Chara, ResourceType.Pbd, PreBoneDeformerPath, resolveData);
} }
private void SetupHSSReplacements(CharacterBase* drawObject, uint slotIndex, Span<HumanSetupScalingHook.Replacement> replacements, private void SetupHssReplacements(CharacterBase* drawObject, uint slotIndex, Span<HumanSetupScalingHook.Replacement> replacements,
ref int numReplacements, ref IDisposable? pbdDisposable, ref object? shpkLock) ref int numReplacements, ref IDisposable? pbdDisposable, ref object? shpkLock)
{ {
if (!_framework.IsInFrameworkUpdateThread) if (!_framework.IsInFrameworkUpdateThread)
Penumbra.Log.Warning( Penumbra.Log.Warning(
$"{nameof(PreBoneDeformerReplacer)}.{nameof(SetupHSSReplacements)}(0x{(nint)drawObject:X}, {slotIndex}) called out of framework thread"); $"{nameof(PreBoneDeformerReplacer)}.{nameof(SetupHssReplacements)}(0x{(nint)drawObject:X}, {slotIndex}) called out of framework thread");
var preBoneDeformer = GetPreBoneDeformerForCharacter(drawObject); var preBoneDeformer = GetPreBoneDeformerForCharacter(drawObject);
try try
{ {
pbdDisposable = preBoneDeformer; pbdDisposable = preBoneDeformer;
replacements[numReplacements++] = new((nint)(&_utility.Address->HumanPbdResource), (nint)preBoneDeformer.ResourceHandle, replacements[numReplacements++] = new HumanSetupScalingHook.Replacement((nint)(&_utility.Address->HumanPbdResource),
(nint)preBoneDeformer.ResourceHandle,
_utility.DefaultHumanPbdResource); _utility.DefaultHumanPbdResource);
} }
catch catch

View file

@ -8,7 +8,6 @@ using OtterGui.Services;
using Penumbra.Communication; using Penumbra.Communication;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.Interop.Hooks.Resources; using Penumbra.Interop.Hooks.Resources;
using Penumbra.Interop.Services;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Services; using Penumbra.Services;
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility; using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
@ -137,7 +136,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
_hairMaskState = _hairMaskState =
new ModdedShaderPackageState(() => _modelRenderer.HairMaskShaderPackage, () => _modelRenderer.DefaultHairMaskShaderPackage); new ModdedShaderPackageState(() => _modelRenderer.HairMaskShaderPackage, () => _modelRenderer.DefaultHairMaskShaderPackage);
_humanSetupScalingHook.SetupReplacements += SetupHSSReplacements; _humanSetupScalingHook.SetupReplacements += SetupHssReplacements;
_humanOnRenderMaterialHook = hooks.CreateHook<CharacterBaseOnRenderMaterialDelegate>("Human.OnRenderMaterial", vTables.HumanVTable[64], _humanOnRenderMaterialHook = hooks.CreateHook<CharacterBaseOnRenderMaterialDelegate>("Human.OnRenderMaterial", vTables.HumanVTable[64],
OnRenderHumanMaterial, !HookOverrides.Instance.PostProcessing.HumanOnRenderMaterial).Result; OnRenderHumanMaterial, !HookOverrides.Instance.PostProcessing.HumanOnRenderMaterial).Result;
_modelRendererOnRenderMaterialHook = hooks.CreateHook<ModelRendererOnRenderMaterialDelegate>("ModelRenderer.OnRenderMaterial", _modelRendererOnRenderMaterialHook = hooks.CreateHook<ModelRendererOnRenderMaterialDelegate>("ModelRenderer.OnRenderMaterial",
@ -146,7 +145,8 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
_modelRendererUnkFuncHook = hooks.CreateHook<ModelRendererUnkFuncDelegate>("ModelRenderer.UnkFunc", _modelRendererUnkFuncHook = hooks.CreateHook<ModelRendererUnkFuncDelegate>("ModelRenderer.UnkFunc",
Sigs.ModelRendererUnkFunc, ModelRendererUnkFuncDetour, Sigs.ModelRendererUnkFunc, ModelRendererUnkFuncDetour,
!HookOverrides.Instance.PostProcessing.ModelRendererUnkFunc).Result; !HookOverrides.Instance.PostProcessing.ModelRendererUnkFunc).Result;
_prepareColorTableHook = hooks.CreateHook<MaterialResourceHandle.Delegates.PrepareColorTable>("MaterialResourceHandle.PrepareColorTable", _prepareColorTableHook = hooks.CreateHook<MaterialResourceHandle.Delegates.PrepareColorTable>(
"MaterialResourceHandle.PrepareColorTable",
Sigs.PrepareColorSet, PrepareColorTableDetour, Sigs.PrepareColorSet, PrepareColorTableDetour,
!HookOverrides.Instance.PostProcessing.PrepareColorTable).Result; !HookOverrides.Instance.PostProcessing.PrepareColorTable).Result;
@ -160,7 +160,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
_modelRendererUnkFuncHook.Dispose(); _modelRendererUnkFuncHook.Dispose();
_modelRendererOnRenderMaterialHook.Dispose(); _modelRendererOnRenderMaterialHook.Dispose();
_humanOnRenderMaterialHook.Dispose(); _humanOnRenderMaterialHook.Dispose();
_humanSetupScalingHook.SetupReplacements -= SetupHSSReplacements; _humanSetupScalingHook.SetupReplacements -= SetupHssReplacements;
_communicator.MtrlLoaded.Unsubscribe(OnMtrlLoaded); _communicator.MtrlLoaded.Unsubscribe(OnMtrlLoaded);
_resourceHandleDestructor.Unsubscribe(OnResourceHandleDestructor); _resourceHandleDestructor.Unsubscribe(OnResourceHandleDestructor);
@ -188,14 +188,6 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
_characterOcclusionState.GetAndResetSlowPathCallDelta(), _characterOcclusionState.GetAndResetSlowPathCallDelta(),
_hairMaskState.GetAndResetSlowPathCallDelta()); _hairMaskState.GetAndResetSlowPathCallDelta());
private static bool IsMaterialWithShpk(MaterialResourceHandle* mtrlResource, ReadOnlySpan<byte> shpkName)
{
if (mtrlResource == null)
return false;
return shpkName.SequenceEqual(mtrlResource->ShpkNameSpan);
}
private void OnMtrlLoaded(nint mtrlResourceHandle, nint gameObject) private void OnMtrlLoaded(nint mtrlResourceHandle, nint gameObject)
{ {
var mtrl = (MaterialResourceHandle*)mtrlResourceHandle; var mtrl = (MaterialResourceHandle*)mtrlResourceHandle;
@ -203,9 +195,11 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
if (shpk == null) if (shpk == null)
return; return;
var shpkName = mtrl->ShpkNameSpan; var shpkName = mtrl->ShpkNameSpan;
var shpkState = GetStateForHumanSetup(shpkName) ?? GetStateForHumanRender(shpkName) ?? GetStateForModelRendererRender(shpkName) var shpkState = GetStateForHumanSetup(shpkName)
?? GetStateForModelRendererUnk(shpkName) ?? GetStateForColorTable(shpkName); ?? GetStateForHumanRender(shpkName)
?? GetStateForModelRendererRender(shpkName)
?? GetStateForModelRendererUnk(shpkName) ?? GetStateForColorTable(shpkName);
if (shpkState != null && shpk != shpkState.DefaultShaderPackage) if (shpkState != null && shpk != shpkState.DefaultShaderPackage)
shpkState.TryAddMaterial(mtrlResourceHandle); shpkState.TryAddMaterial(mtrlResourceHandle);
@ -228,12 +222,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
=> mtrlResource == null ? null : GetStateForHumanSetup(mtrlResource->ShpkNameSpan); => mtrlResource == null ? null : GetStateForHumanSetup(mtrlResource->ShpkNameSpan);
private ModdedShaderPackageState? GetStateForHumanSetup(ReadOnlySpan<byte> shpkName) private ModdedShaderPackageState? GetStateForHumanSetup(ReadOnlySpan<byte> shpkName)
{ => CharacterStockingsShpkName.SequenceEqual(shpkName) ? _characterStockingsState : null;
if (CharacterStockingsShpkName.SequenceEqual(shpkName))
return _characterStockingsState;
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private uint GetTotalMaterialCountForHumanSetup() private uint GetTotalMaterialCountForHumanSetup()
@ -243,12 +232,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
=> mtrlResource == null ? null : GetStateForHumanRender(mtrlResource->ShpkNameSpan); => mtrlResource == null ? null : GetStateForHumanRender(mtrlResource->ShpkNameSpan);
private ModdedShaderPackageState? GetStateForHumanRender(ReadOnlySpan<byte> shpkName) private ModdedShaderPackageState? GetStateForHumanRender(ReadOnlySpan<byte> shpkName)
{ => SkinShpkName.SequenceEqual(shpkName) ? _skinState : null;
if (SkinShpkName.SequenceEqual(shpkName))
return _skinState;
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private uint GetTotalMaterialCountForHumanRender() private uint GetTotalMaterialCountForHumanRender()
@ -305,18 +289,13 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
+ _characterStockingsState.MaterialCount; + _characterStockingsState.MaterialCount;
private ModdedShaderPackageState? GetStateForColorTable(ReadOnlySpan<byte> shpkName) private ModdedShaderPackageState? GetStateForColorTable(ReadOnlySpan<byte> shpkName)
{ => CharacterLegacyShpkName.SequenceEqual(shpkName) ? _characterLegacyState : null;
if (CharacterLegacyShpkName.SequenceEqual(shpkName))
return _characterLegacyState;
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private uint GetTotalMaterialCountForColorTable() private uint GetTotalMaterialCountForColorTable()
=> _characterLegacyState.MaterialCount; => _characterLegacyState.MaterialCount;
private void SetupHSSReplacements(CharacterBase* drawObject, uint slotIndex, Span<HumanSetupScalingHook.Replacement> replacements, private void SetupHssReplacements(CharacterBase* drawObject, uint slotIndex, Span<HumanSetupScalingHook.Replacement> replacements,
ref int numReplacements, ref IDisposable? pbdDisposable, ref object? shpkLock) ref int numReplacements, ref IDisposable? pbdDisposable, ref object? shpkLock)
{ {
// If we don't have any on-screen instances of modded characterstockings.shpk, we don't need the slow path at all. // If we don't have any on-screen instances of modded characterstockings.shpk, we don't need the slow path at all.
@ -326,6 +305,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
var model = drawObject->Models[slotIndex]; var model = drawObject->Models[slotIndex];
if (model == null) if (model == null)
return; return;
MaterialResourceHandle* mtrlResource = null; MaterialResourceHandle* mtrlResource = null;
ModdedShaderPackageState? shpkState = null; ModdedShaderPackageState? shpkState = null;
foreach (var material in model->MaterialsSpan) foreach (var material in model->MaterialsSpan)
@ -340,6 +320,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
if (shpkState != null) if (shpkState != null)
break; break;
} }
if (shpkState == null || shpkState.MaterialCount == 0) if (shpkState == null || shpkState.MaterialCount == 0)
return; return;
@ -348,7 +329,8 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
// This is less performance-critical than the others, as this is called by the game only on draw object creation and slot update. // This is less performance-critical than the others, as this is called by the game only on draw object creation and slot update.
// There are still thread safety concerns as it might be called in other threads by plugins. // There are still thread safety concerns as it might be called in other threads by plugins.
shpkLock = shpkState; shpkLock = shpkState;
replacements[numReplacements++] = new((nint)shpkState.ShaderPackageReference, (nint)mtrlResource->ShaderPackageResourceHandle, replacements[numReplacements++] = new HumanSetupScalingHook.Replacement((nint)shpkState.ShaderPackageReference,
(nint)mtrlResource->ShaderPackageResourceHandle,
(nint)shpkState.DefaultShaderPackage); (nint)shpkState.DefaultShaderPackage);
} }
@ -439,7 +421,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
// Same performance considerations as OnRenderHumanMaterial. // Same performance considerations as OnRenderHumanMaterial.
lock (shpkState) lock (shpkState)
{ {
var shpkReference = shpkState.ShaderPackageReference; var shpkReference = shpkState.ShaderPackageReference;
try try
{ {
*shpkReference = mtrlResource->ShaderPackageResourceHandle; *shpkReference = mtrlResource->ShaderPackageResourceHandle;
@ -452,7 +434,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
} }
} }
private MaterialResourceHandle* GetMaterialResourceHandle(ModelRendererStructs.UnkPayload* unkPayload) private static MaterialResourceHandle* GetMaterialResourceHandle(ModelRendererStructs.UnkPayload* unkPayload)
{ {
// TODO ClientStructs-ify // TODO ClientStructs-ify
var unkPointer = *(nint*)((nint)unkPayload->ModelResourceHandle + 0xE8) + unkPayload->UnkIndex * 0x24; var unkPointer = *(nint*)((nint)unkPayload->ModelResourceHandle + 0xE8) + unkPayload->UnkIndex * 0x24;
@ -467,13 +449,14 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
if (mtrlResource->ShaderPackageResourceHandle == null) if (mtrlResource->ShaderPackageResourceHandle == null)
{ {
Penumbra.Log.Warning($"ShaderReplacementFixer found a MaterialResourceHandle with no shader package"); Penumbra.Log.Warning("ShaderReplacementFixer found a MaterialResourceHandle with no shader package");
return null; return null;
} }
if (mtrlResource->ShaderPackageResourceHandle->ShaderPackage != unkPayload->ShaderWrapper->ShaderPackage) if (mtrlResource->ShaderPackageResourceHandle->ShaderPackage != unkPayload->ShaderWrapper->ShaderPackage)
{ {
Penumbra.Log.Warning($"ShaderReplacementFixer found a MaterialResourceHandle (0x{(nint)mtrlResource:X}) with an inconsistent shader package (got 0x{(nint)mtrlResource->ShaderPackageResourceHandle->ShaderPackage:X}, expected 0x{(nint)unkPayload->ShaderWrapper->ShaderPackage:X})"); Penumbra.Log.Warning(
$"ShaderReplacementFixer found a MaterialResourceHandle (0x{(nint)mtrlResource:X}) with an inconsistent shader package (got 0x{(nint)mtrlResource->ShaderPackageResourceHandle->ShaderPackage:X}, expected 0x{(nint)unkPayload->ShaderWrapper->ShaderPackage:X})");
return null; return null;
} }

View file

@ -67,7 +67,7 @@ public unsafe class CharacterUtility : IDisposable, IRequiredService
_framework.Update += LoadDefaultResources; _framework.Update += LoadDefaultResources;
} }
/// <summary> We store the default data of the resources so we can always restore them. </summary> /// <summary> We store the default data of the resources, so we can always restore them. </summary>
private void LoadDefaultResources(object _) private void LoadDefaultResources(object _)
{ {
if (Address == null) if (Address == null)