diff --git a/Source/Core/VideoBackends/Vulkan/BoundingBox.h b/Source/Core/VideoBackends/Vulkan/BoundingBox.h index 3bb8606d05..0647c08607 100644 --- a/Source/Core/VideoBackends/Vulkan/BoundingBox.h +++ b/Source/Core/VideoBackends/Vulkan/BoundingBox.h @@ -40,7 +40,7 @@ private: void Readback(StateTracker* state_tracker); VkBuffer m_gpu_buffer = VK_NULL_HANDLE; - VkDeviceMemory m_gpu_memory = nullptr; + VkDeviceMemory m_gpu_memory = VK_NULL_HANDLE; static const size_t NUM_VALUES = 4; static const size_t BUFFER_SIZE = sizeof(u32) * NUM_VALUES; diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp index 537c21c514..202c3f6777 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp @@ -73,7 +73,7 @@ void CommandBufferManager::DestroyCommandPool() if (m_command_pool) { vkDestroyCommandPool(g_vulkan_context->GetDevice(), m_command_pool, nullptr); - m_command_pool = nullptr; + m_command_pool = VK_NULL_HANDLE; } } @@ -141,8 +141,8 @@ void CommandBufferManager::DestroyCommandBuffers() for (FrameResources& resources : m_frame_resources) { - for (const auto& it : resources.cleanup_resources) - it.destroy_callback(device, it.object); + for (auto& it : resources.cleanup_resources) + it(); resources.cleanup_resources.clear(); if (resources.fence != VK_NULL_HANDLE) @@ -385,8 +385,8 @@ void CommandBufferManager::OnCommandBufferExecuted(size_t index) iter.second.second(resources.fence); // Clean up all objects pending destruction on this command buffer - for (const auto& it : resources.cleanup_resources) - it.destroy_callback(g_vulkan_context->GetDevice(), it.object); + for (auto& it : resources.cleanup_resources) + it(); resources.cleanup_resources.clear(); } @@ -446,6 +446,48 @@ void CommandBufferManager::ExecuteCommandBuffer(bool submit_off_thread, bool wai WaitForFence(pending_fence); } +void CommandBufferManager::DeferBufferDestruction(VkBuffer object) +{ + FrameResources& resources = m_frame_resources[m_current_frame]; + resources.cleanup_resources.push_back( + [object]() { vkDestroyBuffer(g_vulkan_context->GetDevice(), object, nullptr); }); +} + +void CommandBufferManager::DeferBufferViewDestruction(VkBufferView object) +{ + FrameResources& resources = m_frame_resources[m_current_frame]; + resources.cleanup_resources.push_back( + [object]() { vkDestroyBufferView(g_vulkan_context->GetDevice(), object, nullptr); }); +} + +void CommandBufferManager::DeferDeviceMemoryDestruction(VkDeviceMemory object) +{ + FrameResources& resources = m_frame_resources[m_current_frame]; + resources.cleanup_resources.push_back( + [object]() { vkFreeMemory(g_vulkan_context->GetDevice(), object, nullptr); }); +} + +void CommandBufferManager::DeferFramebufferDestruction(VkFramebuffer object) +{ + FrameResources& resources = m_frame_resources[m_current_frame]; + resources.cleanup_resources.push_back( + [object]() { vkDestroyFramebuffer(g_vulkan_context->GetDevice(), object, nullptr); }); +} + +void CommandBufferManager::DeferImageDestruction(VkImage object) +{ + FrameResources& resources = m_frame_resources[m_current_frame]; + resources.cleanup_resources.push_back( + [object]() { vkDestroyImage(g_vulkan_context->GetDevice(), object, nullptr); }); +} + +void CommandBufferManager::DeferImageViewDestruction(VkImageView object) +{ + FrameResources& resources = m_frame_resources[m_current_frame]; + resources.cleanup_resources.push_back( + [object]() { vkDestroyImageView(g_vulkan_context->GetDevice(), object, nullptr); }); +} + void CommandBufferManager::AddFencePointCallback( const void* key, const CommandBufferQueuedCallback& queued_callback, const CommandBufferExecutedCallback& executed_callback) diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h index 1b6d3ea665..96b09b1bde 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h @@ -81,12 +81,12 @@ public: // Schedule a vulkan resource for destruction later on. This will occur when the command buffer // is next re-used, and the GPU has finished working with the specified resource. - template - void DeferResourceDestruction(T object) - { - DeferredResourceDestruction wrapper = DeferredResourceDestruction::Wrapper(object); - m_frame_resources[m_current_frame].cleanup_resources.push_back(wrapper); - } + void DeferBufferDestruction(VkBuffer object); + void DeferBufferViewDestruction(VkBufferView object); + void DeferDeviceMemoryDestruction(VkDeviceMemory object); + void DeferFramebufferDestruction(VkFramebuffer object); + void DeferImageDestruction(VkImage object); + void DeferImageViewDestruction(VkImageView object); // Instruct the manager to fire the specified callback when a fence is flagged to be signaled. // This happens when command buffers are executed, and can be tested if signaled, which means @@ -124,7 +124,7 @@ private: bool init_command_buffer_used; bool needs_fence_wait; - std::vector cleanup_resources; + std::vector> cleanup_resources; }; std::array m_frame_resources = {}; diff --git a/Source/Core/VideoBackends/Vulkan/RasterFont.cpp b/Source/Core/VideoBackends/Vulkan/RasterFont.cpp index 72f393bb1e..f67412e243 100644 --- a/Source/Core/VideoBackends/Vulkan/RasterFont.cpp +++ b/Source/Core/VideoBackends/Vulkan/RasterFont.cpp @@ -170,9 +170,9 @@ RasterFont::RasterFont() RasterFont::~RasterFont() { if (m_vertex_shader != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_vertex_shader); + vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_vertex_shader, nullptr); if (m_fragment_shader != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_fragment_shader); + vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_fragment_shader, nullptr); } bool RasterFont::Initialize() @@ -279,8 +279,8 @@ bool RasterFont::CreateTexture() // Free temp buffers after command buffer executes m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - g_command_buffer_mgr->DeferResourceDestruction(temp_buffer); - g_command_buffer_mgr->DeferResourceDestruction(temp_buffer_memory); + g_command_buffer_mgr->DeferBufferDestruction(temp_buffer); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(temp_buffer_memory); return true; } diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index e1c6394b30..c6837ef7f8 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -164,13 +164,13 @@ void Renderer::DestroySemaphores() if (m_image_available_semaphore) { vkDestroySemaphore(g_vulkan_context->GetDevice(), m_image_available_semaphore, nullptr); - m_image_available_semaphore = nullptr; + m_image_available_semaphore = VK_NULL_HANDLE; } if (m_rendering_finished_semaphore) { vkDestroySemaphore(g_vulkan_context->GetDevice(), m_rendering_finished_semaphore, nullptr); - m_rendering_finished_semaphore = nullptr; + m_rendering_finished_semaphore = VK_NULL_HANDLE; } } diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h index 3110a090e5..1b1e175272 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.h +++ b/Source/Core/VideoBackends/Vulkan/Renderer.h @@ -105,8 +105,8 @@ private: FramebufferManager* m_framebuffer_mgr = nullptr; - VkSemaphore m_image_available_semaphore = nullptr; - VkSemaphore m_rendering_finished_semaphore = nullptr; + VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE; + VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE; std::unique_ptr m_swap_chain; std::unique_ptr m_state_tracker; diff --git a/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp b/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp index 052897d9bc..f972492abb 100644 --- a/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp +++ b/Source/Core/VideoBackends/Vulkan/StagingBuffer.cpp @@ -26,8 +26,8 @@ StagingBuffer::~StagingBuffer() if (m_map_pointer) Unmap(); - g_command_buffer_mgr->DeferResourceDestruction(m_memory); - g_command_buffer_mgr->DeferResourceDestruction(m_buffer); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory); + g_command_buffer_mgr->DeferBufferDestruction(m_buffer); } bool StagingBuffer::Map(VkDeviceSize offset, VkDeviceSize size) diff --git a/Source/Core/VideoBackends/Vulkan/StagingTexture2D.cpp b/Source/Core/VideoBackends/Vulkan/StagingTexture2D.cpp index c82d449c49..1f5be7563c 100644 --- a/Source/Core/VideoBackends/Vulkan/StagingTexture2D.cpp +++ b/Source/Core/VideoBackends/Vulkan/StagingTexture2D.cpp @@ -133,8 +133,8 @@ StagingTexture2DLinear::~StagingTexture2DLinear() if (m_map_pointer) Unmap(); - g_command_buffer_mgr->DeferResourceDestruction(m_memory); - g_command_buffer_mgr->DeferResourceDestruction(m_image); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory); + g_command_buffer_mgr->DeferImageDestruction(m_image); } void StagingTexture2DLinear::CopyFromImage(VkCommandBuffer command_buffer, VkImage image, @@ -362,8 +362,8 @@ StagingTexture2DBuffer::~StagingTexture2DBuffer() if (m_map_pointer) Unmap(); - g_command_buffer_mgr->DeferResourceDestruction(m_memory); - g_command_buffer_mgr->DeferResourceDestruction(m_buffer); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory); + g_command_buffer_mgr->DeferBufferDestruction(m_buffer); } void StagingTexture2DBuffer::CopyFromImage(VkCommandBuffer command_buffer, VkImage image, diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp index 4d6f8dea7a..80c13323b0 100644 --- a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp +++ b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp @@ -539,7 +539,7 @@ void StateTracker::EndRenderPass() return; vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer()); - m_current_render_pass = nullptr; + m_current_render_pass = VK_NULL_HANDLE; } void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue clear_values[2]) diff --git a/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp b/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp index 9d7f4d8820..4d90401bcf 100644 --- a/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp @@ -35,9 +35,9 @@ StreamBuffer::~StreamBuffer() vkUnmapMemory(g_vulkan_context->GetDevice(), m_memory); if (m_buffer != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_buffer); + g_command_buffer_mgr->DeferBufferDestruction(m_buffer); if (m_memory != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_memory); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory); } std::unique_ptr StreamBuffer::Create(VkBufferUsageFlags usage, size_t initial_size, @@ -124,9 +124,9 @@ bool StreamBuffer::ResizeBuffer(size_t size) // Destroy the backings for the buffer after the command buffer executes if (m_buffer != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_buffer); + g_command_buffer_mgr->DeferBufferDestruction(m_buffer); if (m_memory != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_memory); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory); // Replace with the new buffer m_buffer = buffer; diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp index f0a35fd526..34ad5c39f2 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp @@ -280,8 +280,8 @@ void SwapChain::DestroyRenderPass() if (!m_render_pass) return; - g_command_buffer_mgr->DeferResourceDestruction(m_render_pass); - m_render_pass = nullptr; + vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr); + m_render_pass = VK_NULL_HANDLE; } bool SwapChain::CreateSwapChain() diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.h b/Source/Core/VideoBackends/Vulkan/SwapChain.h index 3278139d1b..f0ccb81921 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.h +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.h @@ -77,15 +77,15 @@ private: }; void* m_native_handle = nullptr; - VkSurfaceKHR m_surface = nullptr; + VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSurfaceFormatKHR m_surface_format = {}; VkPresentModeKHR m_present_mode = VK_PRESENT_MODE_RANGE_SIZE_KHR; - VkSwapchainKHR m_swap_chain = nullptr; + VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE; std::vector m_swap_chain_images; u32 m_current_swap_chain_image_index = 0; - VkRenderPass m_render_pass = nullptr; + VkRenderPass m_render_pass = VK_NULL_HANDLE; u32 m_width = 0; u32 m_height = 0; diff --git a/Source/Core/VideoBackends/Vulkan/Texture2D.cpp b/Source/Core/VideoBackends/Vulkan/Texture2D.cpp index 470328c47c..9dda089b21 100644 --- a/Source/Core/VideoBackends/Vulkan/Texture2D.cpp +++ b/Source/Core/VideoBackends/Vulkan/Texture2D.cpp @@ -21,13 +21,13 @@ Texture2D::Texture2D(u32 width, u32 height, u32 levels, u32 layers, VkFormat for Texture2D::~Texture2D() { - g_command_buffer_mgr->DeferResourceDestruction(m_view); + g_command_buffer_mgr->DeferImageViewDestruction(m_view); // If we don't have device memory allocated, the image is not owned by us (e.g. swapchain) if (m_device_memory != VK_NULL_HANDLE) { - g_command_buffer_mgr->DeferResourceDestruction(m_image); - g_command_buffer_mgr->DeferResourceDestruction(m_device_memory); + g_command_buffer_mgr->DeferImageDestruction(m_image); + g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_device_memory); } } @@ -134,6 +134,8 @@ std::unique_ptr Texture2D::CreateFromExistingImage(u32 width, u32 hei static_cast(VK_IMAGE_ASPECT_COLOR_BIT), 0, levels, 0, layers}}; + // Memory is managed by the owner of the image. + VkDeviceMemory memory = VK_NULL_HANDLE; VkImageView view = VK_NULL_HANDLE; VkResult res = vkCreateImageView(g_vulkan_context->GetDevice(), &view_info, nullptr, &view); if (res != VK_SUCCESS) @@ -143,7 +145,7 @@ std::unique_ptr Texture2D::CreateFromExistingImage(u32 width, u32 hei } return std::make_unique(width, height, levels, layers, format, samples, view_type, - existing_image, nullptr, view); + existing_image, memory, view); } void Texture2D::OverrideImageLayout(VkImageLayout new_layout) diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp index a866202545..e3b989c34e 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp @@ -316,7 +316,7 @@ TextureCache::TCacheEntry::~TCacheEntry() m_parent->m_state_tracker->UnbindTexture(m_texture->GetView()); if (m_framebuffer != VK_NULL_HANDLE) - g_command_buffer_mgr->DeferResourceDestruction(m_framebuffer); + g_command_buffer_mgr->DeferFramebufferDestruction(m_framebuffer); } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/Vulkan/Util.cpp b/Source/Core/VideoBackends/Vulkan/Util.cpp index 63bc9b94c5..9ef432d779 100644 --- a/Source/Core/VideoBackends/Vulkan/Util.cpp +++ b/Source/Core/VideoBackends/Vulkan/Util.cpp @@ -260,120 +260,6 @@ VkShaderModule CompileAndCreateFragmentShader(const std::string& source_code, bo } // namespace Util -template <> -DeferredResourceDestruction -DeferredResourceDestruction::Wrapper(VkCommandPool object) -{ - DeferredResourceDestruction ret; - ret.object.command_pool = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyCommandPool(device, obj.command_pool, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction -DeferredResourceDestruction::Wrapper(VkDeviceMemory object) -{ - DeferredResourceDestruction ret; - ret.object.device_memory = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkFreeMemory(device, obj.device_memory, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction DeferredResourceDestruction::Wrapper(VkBuffer object) -{ - DeferredResourceDestruction ret; - ret.object.buffer = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyBuffer(device, obj.buffer, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction DeferredResourceDestruction::Wrapper(VkBufferView object) -{ - DeferredResourceDestruction ret; - ret.object.buffer_view = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyBufferView(device, obj.buffer_view, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction DeferredResourceDestruction::Wrapper(VkImage object) -{ - DeferredResourceDestruction ret; - ret.object.image = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyImage(device, obj.image, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction DeferredResourceDestruction::Wrapper(VkImageView object) -{ - DeferredResourceDestruction ret; - ret.object.image_view = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyImageView(device, obj.image_view, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction DeferredResourceDestruction::Wrapper(VkRenderPass object) -{ - DeferredResourceDestruction ret; - ret.object.render_pass = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyRenderPass(device, obj.render_pass, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction -DeferredResourceDestruction::Wrapper(VkFramebuffer object) -{ - DeferredResourceDestruction ret; - ret.object.framebuffer = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyFramebuffer(device, obj.framebuffer, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction -DeferredResourceDestruction::Wrapper(VkShaderModule object) -{ - DeferredResourceDestruction ret; - ret.object.shader_module = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyShaderModule(device, obj.shader_module, nullptr); - }; - return ret; -} - -template <> -DeferredResourceDestruction DeferredResourceDestruction::Wrapper(VkPipeline object) -{ - DeferredResourceDestruction ret; - ret.object.pipeline = object; - ret.destroy_callback = [](VkDevice device, const Object& obj) { - vkDestroyPipeline(device, obj.pipeline, nullptr); - }; - return ret; -} - UtilityShaderDraw::UtilityShaderDraw(VkCommandBuffer command_buffer, VkPipelineLayout pipeline_layout, VkRenderPass render_pass, VkShaderModule vertex_shader, VkShaderModule geometry_shader, diff --git a/Source/Core/VideoBackends/Vulkan/Util.h b/Source/Core/VideoBackends/Vulkan/Util.h index dce0c720c7..e9dec51700 100644 --- a/Source/Core/VideoBackends/Vulkan/Util.h +++ b/Source/Core/VideoBackends/Vulkan/Util.h @@ -66,28 +66,6 @@ VkShaderModule CompileAndCreateFragmentShader(const std::string& source_code, bool prepend_header = true); } -// Helper methods for cleaning up device objects, used by deferred destruction -struct DeferredResourceDestruction -{ - union Object { - VkCommandPool command_pool; - VkDeviceMemory device_memory; - VkBuffer buffer; - VkBufferView buffer_view; - VkImage image; - VkImageView image_view; - VkRenderPass render_pass; - VkFramebuffer framebuffer; - VkShaderModule shader_module; - VkPipeline pipeline; - } object; - - void (*destroy_callback)(VkDevice device, const Object& object); - - template - static DeferredResourceDestruction Wrapper(T object); -}; - // Utility shader vertex format #pragma pack(push, 1) struct UtilityShaderVertex diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index ef2e6e1fb3..7696568ef4 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -526,7 +526,8 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la device_info.pQueueCreateInfos = &queue_info; ExtensionList enabled_extensions; - if (!SelectDeviceExtensions(&enabled_extensions, (surface != nullptr), enable_validation_layer)) + if (!SelectDeviceExtensions(&enabled_extensions, (surface != VK_NULL_HANDLE), + enable_validation_layer)) return false; device_info.enabledLayerCount = 0;