From c9aaf598bbd8a8267e120b693daf47734c267283 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 10 May 2021 21:18:31 -0700 Subject: [PATCH] (video/vulkan) Avoid caching stale mapped GPU texture as frame data At best, this results in junk on screen, at worst we could crash. It's not a perfect fix, there's still a scenario where this breaks: when fast forwarding is enabled, and we swap from vsync-off to vsync-on when pausing/rendering the menu, the swap chain (and textures) gets recreated, and the frame data is completely lost. There isn't much we can do about this without more intrusive changes, such as preserving the textures inbetween swap chain reinits. --- gfx/drivers/vulkan.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 4f9b5720c2..24f803b80b 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -57,6 +57,8 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width, unsigned viewport_height, bool force_full, bool allow_rotate); +static bool vulkan_is_mapped_swapchain_texture_ptr(const vk_t* vk, + const void* ptr); #ifdef HAVE_OVERLAY static void vulkan_overlay_free(vk_t *vk); @@ -682,6 +684,12 @@ static void vulkan_deinit_textures(vk_t *vk) { unsigned i; + /* Avoid memcpying from a destroyed/unmapped texture later on. */ + const void* cached_frame; + video_driver_cached_frame_get(&cached_frame, NULL, NULL, NULL); + if (vulkan_is_mapped_swapchain_texture_ptr(vk, cached_frame)) + video_driver_set_cached_frame_ptr(NULL); + vulkan_deinit_samplers(vk); for (i = 0; i < vk->num_swapchain_images; i++) @@ -2391,6 +2399,18 @@ static bool vulkan_get_current_sw_framebuffer(void *data, return true; } +static bool vulkan_is_mapped_swapchain_texture_ptr(const vk_t* vk, + const void* ptr) +{ + for (unsigned i = 0; i < vk->num_swapchain_images; i++) + { + if (ptr == vk->swapchain[i].texture.mapped) + return true; + } + + return false; +} + static bool vulkan_get_hw_render_interface(void *data, const struct retro_hw_render_interface **iface) {