Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3: ensure that a texture in _WantDestroy state always turn to _Destroyed. (#8977)

Amend 9809b0b. Strictly speaking this is not necessary anymore but it seems generally sane to promote this.
This commit is contained in:
ocornut
2025-10-01 17:49:22 +02:00
parent ea564a6a5e
commit fc4105c8a8
11 changed files with 80 additions and 83 deletions

View File

@@ -325,18 +325,18 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex) static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData; if (ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return; IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID); backend_tex->pTextureView->Release();
backend_tex->pTexture->Release(); backend_tex->pTexture->Release();
backend_tex->pTextureView->Release(); IM_DELETE(backend_tex);
IM_DELETE(backend_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
} }
void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex) void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex)

View File

@@ -341,18 +341,18 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex) static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData; if (ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return; IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID); backend_tex->pTextureView->Release();
backend_tex->pTextureView->Release(); backend_tex->pTexture->Release();
backend_tex->pTexture->Release(); IM_DELETE(backend_tex);
IM_DELETE(backend_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
} }
void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex) void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex)

View File

@@ -345,21 +345,21 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex) static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData; if (ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return; IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID);
IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID); ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle);
bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle); SafeRelease(backend_tex->pTextureResource);
SafeRelease(backend_tex->pTextureResource); backend_tex->hFontSrvCpuDescHandle.ptr = 0;
backend_tex->hFontSrvCpuDescHandle.ptr = 0; backend_tex->hFontSrvGpuDescHandle.ptr = 0;
backend_tex->hFontSrvGpuDescHandle.ptr = 0; IM_DELETE(backend_tex);
IM_DELETE(backend_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
} }
void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)

View File

@@ -431,14 +431,14 @@ void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
} }
else if (tex->Status == ImTextureStatus_WantDestroy) else if (tex->Status == ImTextureStatus_WantDestroy)
{ {
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID; if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
if (backend_tex == nullptr) {
return; IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex); backend_tex->Release();
backend_tex->Release();
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
} }
} }

View File

@@ -338,16 +338,16 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex) static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
{ {
MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData); if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
if (backend_tex == nullptr) {
return; IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID); backend_tex.metalTexture = nil;
backend_tex.metalTexture = nil;
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
} }
void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex) void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex)

View File

@@ -307,8 +307,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex) static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID(); if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
if (raw_tex != nullptr)
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex); SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)

View File

@@ -267,10 +267,8 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
} }
else if (tex->Status == ImTextureStatus_WantDestroy) else if (tex->Status == ImTextureStatus_WantDestroy)
{ {
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID; if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
if (sdl_texture == nullptr) SDL_DestroyTexture(sdl_texture);
return;
SDL_DestroyTexture(sdl_texture);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);

View File

@@ -283,10 +283,8 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
} }
else if (tex->Status == ImTextureStatus_WantDestroy) else if (tex->Status == ImTextureStatus_WantDestroy)
{ {
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID; if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
if (sdl_texture == nullptr) SDL_DestroyTexture(sdl_texture);
return;
SDL_DestroyTexture(sdl_texture);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);

View File

@@ -663,22 +663,22 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex) static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData; if (ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return; IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID); ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet); vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);
vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator); vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);
vkDestroyImage(v->Device, backend_tex->Image, v->Allocator); vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);
vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator); IM_DELETE(backend_tex);
IM_DELETE(backend_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
} }
void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex) void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)

View File

@@ -533,19 +533,18 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex) static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData; if (ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return; IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID);
wgpuTextureViewRelease(backend_tex->TextureView);
wgpuTextureRelease(backend_tex->Texture);
IM_DELETE(backend_tex);
IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID); // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
wgpuTextureViewRelease(backend_tex->TextureView); tex->SetTexID(ImTextureID_Invalid);
wgpuTextureRelease(backend_tex->Texture); tex->BackendUserData = nullptr;
IM_DELETE(backend_tex); }
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
} }
void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex) void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)

View File

@@ -99,6 +99,9 @@ Other Changes:
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
- Backends: Vulkan: added a way to specify custom shaders by filling init fields - Backends: Vulkan: added a way to specify custom shaders by filling init fields
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
- Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
ensure that a texture in _WantDestroy state always turn to _Destroyed even
if your underlying graphics data was already destroyed.
- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is
not available. (#5924, #5562) not available. (#5924, #5562)
- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]