WIP - Adding a RefCount to textures so backend can avoid destroying them on shutdown if atlas is shared.

This commit is contained in:
ocornut 2025-03-07 16:14:11 +01:00 committed by ocornut
parent 46325b4b59
commit 74b711e072
2 changed files with 17 additions and 7 deletions

View file

@ -3992,6 +3992,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
Font = NULL;
FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
IO.Fonts->RefCount++;
Time = 0.0f;
FrameCount = 0;
FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
@ -4279,12 +4280,15 @@ void ImGui::Shutdown()
IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL, "Forgot to shutdown Renderer backend?");
// The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
if (g.IO.Fonts)
ImFontAtlasRemoveDrawListSharedData(g.IO.Fonts, &g.DrawListSharedData);
if (g.IO.Fonts && g.FontAtlasOwnedByContext)
if (ImFontAtlas* atlas = g.IO.Fonts)
{
g.IO.Fonts->Locked = false;
IM_DELETE(g.IO.Fonts);
ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData);
atlas->RefCount--;
if (g.FontAtlasOwnedByContext)
{
atlas->Locked = false;
IM_DELETE(atlas);
}
}
g.IO.Fonts = NULL;
g.DrawListSharedData.TempBuffer.clear();
@ -5349,7 +5353,12 @@ static void ImGui::UpdateTexturesEndFrame()
g.PlatformIO.Textures.resize(0);
g.PlatformIO.Textures.reserve(atlas->TexList.Size);
for (ImTextureData* tex : atlas->TexList)
{
// We provide this information so backends can decide whether to destroy textures.
// This means in practice that if N imgui contexts are created with a shared atlas, we assume all of them have a backend initialized.
tex->RefCount = (unsigned short)atlas->RefCount;
g.PlatformIO.Textures.push_back(tex);
}
}
// Called once a frame. Followed by SetCurrentFont() which sets up the remaining data.

View file

@ -3480,6 +3480,7 @@ struct IMGUI_API ImTextureData
ImTextureRect UpdateRect; // Bounding box encompassing all individual updates.
ImVector<ImTextureRect> Updates; // Array of individual updates.
int UnusedFrames; // In order to facilitate handling Status==WantDestroy in some backend: this is a count successive frames where the texture was not used.
unsigned short RefCount; // Number of contexts using this texture.
bool UseColors; // Tell whether our texture data is known to use colors (rather than just white + alpha).
bool WantDestroyNextFrame; // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
@ -3689,13 +3690,12 @@ struct ImFontAtlas
// Input
ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_)
ImTextureRef TexRef; // User data to refer to the latest texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
ImTextureFormat TexDesiredFormat; // Desired texture format (default to ImTextureFormat_RGBA32 but may be changed to ImTextureFormat_Alpha8).
int TexGlyphPadding; // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false).
void* UserData; // Store your own atlas related user-data (if e.g. you have multiple font atlas).
// [Internal]
ImTextureRef TexRef; // User data to refer to the latest texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
ImTextureData* TexData; // Current texture
ImVector<ImTextureData*> TexList; // Texture list (most often TexList.Size == 1). TexData is always == TexList.back(). DO NOT USE DIRECTLY, USE GetPlatformIO().Textures[] instead!
bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
@ -3716,6 +3716,7 @@ struct ImFontAtlas
const char* FontLoaderName; // Font loader name (for display e.g. in About box) == FontLoader->Name
void* FontLoaderData; // Font backend opaque storage
unsigned int FontBuilderFlags; // [FIXME: Should be called FontLoaderFlags] Shared flags (for all fonts) for font loader. THIS IS BUILD IMPLEMENTATION DEPENDENT (e.g. . Per-font override is also available in ImFontConfig.
int RefCount; // Number of contexts using this atlas
int _PackedSurface; // Number of packed pixels. Used when compacting to heuristically find the ideal texture size.
int _PackedRects; // Number of packed rectangles.
float _PackNodesFactor = 1.0f;