diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index b618fc194..2a572812c 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -1264,6 +1264,7 @@ void RasterizerCache::UnregisterAll() { } texture_cube_cache.clear(); remove_surfaces.clear(); + runtime.Clear(); } template diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index e86a31455..518ba08fc 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -96,6 +96,11 @@ TextureRuntime::TextureRuntime(Driver& driver) TextureRuntime::~TextureRuntime() = default; +void TextureRuntime::Clear() { + framebuffer_cache.clear(); + texture_recycler.clear(); +} + StagingData TextureRuntime::FindStaging(u32 size, bool upload) { if (!upload) { if (size > download_buffer.size()) { diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.h b/src/video_core/renderer_opengl/gl_texture_runtime.h index ec27d3f9e..5ea726f9c 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.h +++ b/src/video_core/renderer_opengl/gl_texture_runtime.h @@ -97,6 +97,9 @@ public: /// Causes a GPU command flush void Finish() const {} + /// Destroys runtime cached resources + void Clear(); + /// Takes back ownership of the allocation for recycling void Recycle(const HostTextureTag tag, Allocation&& alloc); diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp index 70964a124..327a01f42 100644 --- a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp @@ -32,13 +32,17 @@ RenderpassCache::~RenderpassCache() { } } - for (auto& [key, framebuffer] : framebuffers) { - device.destroyFramebuffer(framebuffer); - } - + ClearFramebuffers(); device.destroyRenderPass(present_renderpass); } +void RenderpassCache::ClearFramebuffers() { + for (auto& [key, framebuffer] : framebuffers) { + instance.GetDevice().destroyFramebuffer(framebuffer); + } + framebuffers.clear(); +} + void RenderpassCache::EnterRenderpass(Surface* const color, Surface* const depth_stencil, vk::Rect2D render_area, bool do_clear, vk::ClearValue clear) { return EnterRenderpass(Framebuffer{color, depth_stencil, render_area}, do_clear, clear); diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.h b/src/video_core/renderer_vulkan/vk_renderpass_cache.h index c15d0fa79..c6b27023a 100644 --- a/src/video_core/renderer_vulkan/vk_renderpass_cache.h +++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.h @@ -49,6 +49,9 @@ public: RenderpassCache(const Instance& instance, Scheduler& scheduler); ~RenderpassCache(); + /// Destroys cached framebuffers + void ClearFramebuffers(); + /// Begins a new renderpass only when no other renderpass is currently active void EnterRenderpass(const Framebuffer& framebuffer, bool do_clear = false, vk::ClearValue clear = {}); diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index 6c162baf5..996975224 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -130,23 +130,7 @@ TextureRuntime::TextureRuntime(const Instance& instance, Scheduler& scheduler, } TextureRuntime::~TextureRuntime() { - VmaAllocator allocator = instance.GetAllocator(); - vk::Device device = instance.GetDevice(); - device.waitIdle(); - - for (const auto& [key, alloc] : texture_recycler) { - vmaDestroyImage(allocator, alloc.image, alloc.allocation); - device.destroyImageView(alloc.image_view); - if (alloc.depth_view) { - device.destroyImageView(alloc.depth_view); - device.destroyImageView(alloc.stencil_view); - } - if (alloc.storage_view) { - device.destroyImageView(alloc.storage_view); - } - } - - texture_recycler.clear(); + Clear(); } StagingData TextureRuntime::FindStaging(u32 size, bool upload) { @@ -164,6 +148,29 @@ void TextureRuntime::Finish() { scheduler.Finish(); } +void TextureRuntime::Clear() { + scheduler.Finish(); + + VmaAllocator allocator = instance.GetAllocator(); + vk::Device device = instance.GetDevice(); + device.waitIdle(); + + renderpass_cache.ClearFramebuffers(); + for (const auto& [key, alloc] : texture_recycler) { + vmaDestroyImage(allocator, alloc.image, alloc.allocation); + device.destroyImageView(alloc.image_view); + if (alloc.depth_view) { + device.destroyImageView(alloc.depth_view); + device.destroyImageView(alloc.stencil_view); + } + if (alloc.storage_view) { + device.destroyImageView(alloc.storage_view); + } + } + + texture_recycler.clear(); +} + Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels, VideoCore::PixelFormat format, VideoCore::TextureType type) { const FormatTraits traits = instance.GetTraits(format); diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h index fd74148a5..cb93f2b84 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.h +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h @@ -92,6 +92,9 @@ public: /// Causes a GPU command flush void Finish(); + /// Destroys runtime cached resources + void Clear(); + /// Takes back ownership of the allocation for recycling void Recycle(const HostTextureTag tag, Allocation&& alloc);