From 92e795aa288eddd74773225a0cb96ce9c8215b64 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 10 May 2021 21:33:16 -0700 Subject: [PATCH 1/2] (main) Remove null check from video_driver_set_cached_frame_ptr The only call sites here use NULL as a parameter, and it makes sense to clear it, since the intent is to remove a potentially dangling pointer. --- retroarch.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/retroarch.c b/retroarch.c index b82cc1c540..ae5acfd768 100644 --- a/retroarch.c +++ b/retroarch.c @@ -30810,8 +30810,7 @@ static void video_driver_lock_new(struct rarch_state *p_rarch) void video_driver_set_cached_frame_ptr(const void *data) { struct rarch_state *p_rarch = &rarch_st; - if (data) - p_rarch->frame_cache_data = data; + p_rarch->frame_cache_data = data; } void video_driver_set_stub_frame(void) From c9aaf598bbd8a8267e120b693daf47734c267283 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 10 May 2021 21:18:31 -0700 Subject: [PATCH 2/2] (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) {