feat: defer texturewrap dispose until the end of the frame

This commit is contained in:
goat 2022-12-14 21:57:21 +01:00
parent f9acd82d81
commit f78c5157c8
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
3 changed files with 80 additions and 5 deletions

View file

@ -131,7 +131,7 @@
</PropertyGroup>
<!-- Looks like this is the only way to write a file without a carriage return in msbuild... -->
<Exec Command="echo|set /P =&quot;$(BuildHash)&quot; &gt; $(TempVerFile)" IgnoreExitCode="true"/>
<Exec Command="echo|set /P =&quot;$(BuildHash)&quot; &gt; $(TempVerFile)" IgnoreExitCode="true" />
</Target>
<Target Name="GetGitHashStub" BeforeTargets="WriteGitHash" Condition="'$(BuildHash)'=='' And '$(Configuration)'=='Debug'">
@ -143,7 +143,7 @@
</PropertyGroup>
<!-- Looks like this is the only way to write a file without a carriage return in msbuild... -->
<Exec Command="echo|set /P =&quot;$(BuildHash)&quot; &gt; $(TempVerFile)" IgnoreExitCode="true"/>
<Exec Command="echo|set /P =&quot;$(BuildHash)&quot; &gt; $(TempVerFile)" IgnoreExitCode="true" />
</Target>
<Target Name="WriteGitHash" BeforeTargets="CoreCompile">

View file

@ -0,0 +1,54 @@
using System;
using ImGuiScene;
namespace Dalamud.Interface.Internal;
/// <summary>
/// Safety harness for ImGuiScene textures that will defer destruction until
/// the end of the frame.
/// </summary>
public class DalamudTextureWrap : TextureWrap
{
private readonly TextureWrap wrappedWrap;
/// <summary>
/// Initializes a new instance of the <see cref="DalamudTextureWrap"/> class.
/// </summary>
/// <param name="wrappingWrap">The texture wrap to wrap.</param>
internal DalamudTextureWrap(TextureWrap wrappingWrap)
{
this.wrappedWrap = wrappingWrap;
}
/// <summary>
/// Gets the ImGui handle of the texture.
/// </summary>
public IntPtr ImGuiHandle => this.wrappedWrap.ImGuiHandle;
/// <summary>
/// Gets the width of the texture.
/// </summary>
public int Width => this.wrappedWrap.Width;
/// <summary>
/// Gets the height of the texture.
/// </summary>
public int Height => this.wrappedWrap.Height;
/// <summary>
/// Queue the texture to be disposed once the frame ends.
/// </summary>
public void Dispose()
{
Service<InterfaceManager>.Get().EnqueueDeferredDispose(this);
}
/// <summary>
/// Actually dispose the wrapped texture.
/// </summary>
internal void RealDispose()
{
this.wrappedWrap.Dispose();
}
}

View file

@ -56,6 +56,8 @@ internal class InterfaceManager : IDisposable, IServiceType
private readonly HashSet<SpecialGlyphRequest> glyphRequests = new();
private readonly Dictionary<ImFontPtr, TargetFontModification> loadedFontInfo = new();
private readonly List<DalamudTextureWrap> deferredDisposeTextures = new();
[ServiceManager.ServiceDependency]
private readonly Framework framework = Service<Framework>.Get();
@ -242,7 +244,8 @@ internal class InterfaceManager : IDisposable, IServiceType
try
{
return this.scene?.LoadImage(filePath) ?? null;
var wrap = this.scene?.LoadImage(filePath);
return wrap != null ? new DalamudTextureWrap(wrap) : null;
}
catch (Exception ex)
{
@ -264,7 +267,8 @@ internal class InterfaceManager : IDisposable, IServiceType
try
{
return this.scene?.LoadImage(imageData) ?? null;
var wrap = this.scene?.LoadImage(imageData);
return wrap != null ? new DalamudTextureWrap(wrap) : null;
}
catch (Exception ex)
{
@ -289,7 +293,8 @@ internal class InterfaceManager : IDisposable, IServiceType
try
{
return this.scene?.LoadImageRaw(imageData, width, height, numChannels) ?? null;
var wrap = this.scene?.LoadImageRaw(imageData, width, height, numChannels);
return wrap != null ? new DalamudTextureWrap(wrap) : null;
}
catch (Exception ex)
{
@ -395,6 +400,15 @@ internal class InterfaceManager : IDisposable, IServiceType
return this.NewFontSizeRef(size, ranges);
}
/// <summary>
/// Enqueue a texture to be disposed at the end of the frame.
/// </summary>
/// <param name="wrap">The texture.</param>
public void EnqueueDeferredDispose(DalamudTextureWrap wrap)
{
this.deferredDisposeTextures.Add(wrap);
}
private static void ShowFontError(string path)
{
Util.Fatal($"One or more files required by XIVLauncher were not found.\nPlease restart and report this error if it occurs again.\n\n{path}", "Error");
@ -549,6 +563,13 @@ internal class InterfaceManager : IDisposable, IServiceType
this.RenderImGui();
foreach (var texture in this.deferredDisposeTextures)
{
texture.RealDispose();
}
this.deferredDisposeTextures.Clear();
return this.presentHook.Original(swapChain, syncInterval, presentFlags);
}