mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
(Vulkan) Drop the OSD font at init, not at teardown
font_driver_init_osd() only builds a font when video_font_driver is NULL. vulkan_free() is not always reached on a video_driver_reinit(); the old vk_t can be abandoned instead. When that happens the OSD font survives with font->vk pointing at the previous driver instance and VkImage/VkImageView handles belonging to a device that no longer exists, whose handle values the new device promptly recycles. The font draw then samples whatever owns those handles now, so every glyph quad fills solid in the vertex colour with its geometry intact. That also explains why the symptom is insensitive to the atlas contents, the atlas format, the upload path and the choice of font renderer: the real atlas is never sampled. Confirmed by instrumentation comparing font->vk against the vk_t passed to vulkan_font_render_msg(): after the reinit every OSD draw reports a mismatch, while every menu font stays current. Reproduces with MSU-1 content on snes9x, where raising the pipeline to 44.1 kHz issues SET_SYSTEM_AV_INFO and forces reinits mid-session; content that never changes AV info does not. Free the font at the top of vulkan_init() instead. The old device is still alive at that point, so the font releases its own GPU objects cleanly, and the free no longer depends on a teardown path that may not run. vulkan_font_free() additionally tolerates a context that is already gone rather than dereferencing it.
This commit is contained in:
1 parent
4f0a8bc147
commit
b39c7218d3
1 file changed
+34
-9
+34
-9
@@ -2241,13 +2241,17 @@ static void vulkan_font_free(void *data, bool is_threaded)
|
||||
if (font->font_driver && font->font_data)
|
||||
font->font_driver->free(font->font_data);
|
||||
|
||||
vkQueueWaitIdle(font->vk->context->queue);
|
||||
if (font->upload_fence != VK_NULL_HANDLE)
|
||||
vkDestroyFence(font->vk->context->device, font->upload_fence, NULL);
|
||||
vulkan_destroy_texture(
|
||||
font->vk->context->device, &font->texture);
|
||||
vulkan_destroy_texture(
|
||||
font->vk->context->device, &font->texture_optimal);
|
||||
if (font->vk && font->vk->context && font->vk->context->device)
|
||||
{
|
||||
vkQueueWaitIdle(font->vk->context->queue);
|
||||
if (font->upload_fence != VK_NULL_HANDLE)
|
||||
vkDestroyFence(font->vk->context->device,
|
||||
font->upload_fence, NULL);
|
||||
vulkan_destroy_texture(
|
||||
font->vk->context->device, &font->texture);
|
||||
vulkan_destroy_texture(
|
||||
font->vk->context->device, &font->texture_optimal);
|
||||
}
|
||||
|
||||
free(font);
|
||||
}
|
||||
@@ -5213,8 +5217,29 @@ static void *vulkan_init(const video_info_t *video,
|
||||
bool force_fullscreen = false;
|
||||
const gfx_ctx_driver_t *ctx_driver = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
vk_t *vk = (vk_t*)calloc(1, sizeof(*vk));
|
||||
if (!vk)
|
||||
vk_t *vk;
|
||||
|
||||
/* Drop the OSD font before building the new driver instance.
|
||||
*
|
||||
* font_driver_init_osd() only creates a font when video_font_driver
|
||||
* is NULL, and vulkan_free() is not always reached on the reinit
|
||||
* path - the old vk_t can simply be abandoned. When that happens
|
||||
* the font survives with font->vk pointing at the previous
|
||||
* instance and VkImage/VkImageView handles from a device that is
|
||||
* gone, whose handle values the new device then recycles. The font
|
||||
* draw samples whatever now owns them, which is why the glyphs
|
||||
* fill solid at correct geometry and why nothing done to the
|
||||
* atlas, its format, its upload path or the font renderer changes
|
||||
* anything.
|
||||
*
|
||||
* Freeing here rather than in vulkan_free() is deliberate: at this
|
||||
* point the old device is still alive, so the font can release its
|
||||
* own GPU objects. MSU-1 content on snes9x reaches this because
|
||||
* the 44.1 kHz switch issues SET_SYSTEM_AV_INFO and forces reinits
|
||||
* mid-session. */
|
||||
font_driver_free_osd();
|
||||
|
||||
if (!(vk = (vk_t*)calloc(1, sizeof(*vk))))
|
||||
return NULL;
|
||||
ctx_driver = vulkan_get_context(vk, settings);
|
||||
if (!ctx_driver)
|
||||
|
||||
Reference in new issue
Block a user