mirror of
https://github.com/ocornut/imgui.git
synced 2025-10-05 01:26:28 +00:00
Textures: fixed a crash if a texture marked as _WantDestroy by a backend after it had already been destroyed. (#8977, #8811)
This commit is contained in:
@@ -69,6 +69,9 @@ Other Changes:
|
|||||||
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
|
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
|
||||||
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
|
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
|
||||||
See misc/debuggers/ for details. (#8950) [@mentlerd]
|
See misc/debuggers/ for details. (#8950) [@mentlerd]
|
||||||
|
- Textures: fixed a crash if a texture marked as _WantDestroy by a backend after
|
||||||
|
it had already been destroyed. This would typically happen when calling backend's
|
||||||
|
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
|
||||||
- Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from
|
- Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from
|
||||||
being possible to destroy in any order.
|
being possible to destroy in any order.
|
||||||
- Textures: fixed not updating ImTextureData's RefCount when destroying a context
|
- Textures: fixed not updating ImTextureData's RefCount when destroying a context
|
||||||
|
@@ -2790,21 +2790,29 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
|
|||||||
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
|
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
|
||||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
|
||||||
|
|
||||||
|
// Request destroy
|
||||||
|
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
|
||||||
|
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
|
||||||
|
if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_Destroyed && tex->Status != ImTextureStatus_WantDestroy)
|
||||||
|
{
|
||||||
|
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
|
||||||
|
tex->Status = ImTextureStatus_WantDestroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a texture has never reached the backend, they don't need to know about it.
|
||||||
|
// (note: backends between 1.92.0 and 1.92.4 could set an already destroyed texture to ImTextureStatus_WantDestroy
|
||||||
|
// when invalidating graphics objects twice, which would previously remove it from the list and crash.)
|
||||||
|
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
|
||||||
|
tex->Status = ImTextureStatus_Destroyed;
|
||||||
|
|
||||||
|
// Process texture being destroyed
|
||||||
if (tex->Status == ImTextureStatus_Destroyed)
|
if (tex->Status == ImTextureStatus_Destroyed)
|
||||||
{
|
{
|
||||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
|
||||||
if (tex->WantDestroyNextFrame)
|
if (tex->WantDestroyNextFrame)
|
||||||
remove_from_list = true; // Destroy was scheduled by us
|
remove_from_list = true; // Destroy was scheduled by us
|
||||||
else
|
else
|
||||||
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend (e.g. freed resources mid-run)
|
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend: recreate it (e.g. freed resources mid-run)
|
||||||
}
|
|
||||||
else if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_WantDestroy)
|
|
||||||
{
|
|
||||||
// Request destroy.
|
|
||||||
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
|
|
||||||
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
|
|
||||||
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
|
|
||||||
tex->Status = ImTextureStatus_WantDestroy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
|
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
|
||||||
@@ -2812,13 +2820,10 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
|
|||||||
if (tex->Status == ImTextureStatus_WantDestroy)
|
if (tex->Status == ImTextureStatus_WantDestroy)
|
||||||
tex->UnusedFrames++;
|
tex->UnusedFrames++;
|
||||||
|
|
||||||
// If a texture has never reached the backend, they don't need to know about it.
|
|
||||||
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
|
|
||||||
remove_from_list = true;
|
|
||||||
|
|
||||||
// Destroy and remove
|
// Destroy and remove
|
||||||
if (remove_from_list)
|
if (remove_from_list)
|
||||||
{
|
{
|
||||||
|
IM_ASSERT(atlas->TexData != tex);
|
||||||
tex->DestroyPixels();
|
tex->DestroyPixels();
|
||||||
IM_DELETE(tex);
|
IM_DELETE(tex);
|
||||||
atlas->TexList.erase(atlas->TexList.begin() + tex_n);
|
atlas->TexList.erase(atlas->TexList.begin() + tex_n);
|
||||||
|
Reference in New Issue
Block a user