Delay IM hook setup to after the game sets up rendering

This seems to (hack)fix some odd behavior around shader caching as reported by various users.
This commit is contained in:
goaaats 2025-04-03 19:15:12 +02:00
parent f812bf8f09
commit 97b01d697b

View file

@ -30,9 +30,12 @@ using Dalamud.Interface.Windowing;
using Dalamud.Interface.Windowing.Persistence; using Dalamud.Interface.Windowing.Persistence;
using Dalamud.IoC.Internal; using Dalamud.IoC.Internal;
using Dalamud.Logging.Internal; using Dalamud.Logging.Internal;
using Dalamud.Plugin.Services;
using Dalamud.Utility; using Dalamud.Utility;
using Dalamud.Utility.Timing; using Dalamud.Utility.Timing;
using FFXIVClientStructs.FFXIV.Client.Graphics.Environment;
using ImGuiNET; using ImGuiNET;
using ImGuiScene; using ImGuiScene;
@ -119,6 +122,7 @@ internal partial class InterfaceManager : IInternalDisposableService
[ServiceManager.ServiceConstructor] [ServiceManager.ServiceConstructor]
private InterfaceManager() private InterfaceManager()
{ {
this.framework.Update += this.FrameworkOnUpdate;
} }
[UnmanagedFunctionPointer(CallingConvention.StdCall)] [UnmanagedFunctionPointer(CallingConvention.StdCall)]
@ -507,13 +511,26 @@ internal partial class InterfaceManager : IInternalDisposableService
{ {
var im = Service<InterfaceManager>.GetNullable(); var im = Service<InterfaceManager>.GetNullable();
if (im?.dalamudAtlas is not { } atlas) if (im?.dalamudAtlas is not { } atlas)
throw new InvalidOperationException($"Tried to access fonts before {nameof(ContinueConstruction)} call."); throw new InvalidOperationException($"Tried to access fonts before {nameof(SetupHooks)} call.");
if (!atlas.HasBuiltAtlas) if (!atlas.HasBuiltAtlas)
atlas.BuildTask.GetAwaiter().GetResult(); atlas.BuildTask.GetAwaiter().GetResult();
return im; return im;
} }
private unsafe void FrameworkOnUpdate(IFramework framework1)
{
// We now delay hooking until Framework is set up and has fired its first update.
// Some graphics drivers seem to consider the game's shader cache as invalid if we hook too early.
// The game loads shader packages on the file thread and then compiles them. It will show the logo once it is done.
// This is a workaround, but it fixes an issue where the game would take a very long time to get to the title screen.
if (EnvManager.Instance() == null)
return;
this.SetupHooks(Service<TargetSigScanner>.Get(), Service<FontAtlasFactory>.Get());
this.framework.Update -= this.FrameworkOnUpdate;
}
/// <summary>Checks if the provided swap chain is the target that Dalamud should draw its interface onto, /// <summary>Checks if the provided swap chain is the target that Dalamud should draw its interface onto,
/// and initializes ImGui for drawing.</summary> /// and initializes ImGui for drawing.</summary>
/// <param name="swapChain">The swap chain to test and initialize ImGui with if conditions are met.</param> /// <param name="swapChain">The swap chain to test and initialize ImGui with if conditions are met.</param>
@ -748,9 +765,7 @@ internal partial class InterfaceManager : IInternalDisposableService
} }
} }
[ServiceManager.CallWhenServicesReady( private unsafe void SetupHooks(
"InterfaceManager accepts event registration and stuff even when the game window is not ready.")]
private unsafe void ContinueConstruction(
TargetSigScanner sigScanner, TargetSigScanner sigScanner,
FontAtlasFactory fontAtlasFactory) FontAtlasFactory fontAtlasFactory)
{ {