Vulkan: Postpone Resource Destruction
Resources can still be in use inside the vulkan command queue, when they are destroyed. Especially as Vulkan doesn't allow resetting bindings to nothing. This PR will collect the resources that needs to be destroyed inside the VKDevice and actually destroy the resources when on frame end. The resources currently include: * VkBuffer * VkImage * VkImageView * VkFramebuffer * VkRenderPass Pull Request: https://projects.blender.org/blender/blender/pulls/112514
This commit is contained in:
@@ -87,6 +87,11 @@ class VKBackend : public GPUBackend {
|
||||
return device_;
|
||||
}
|
||||
|
||||
VKDevice &device_get()
|
||||
{
|
||||
return device_;
|
||||
}
|
||||
|
||||
static void platform_init(const VKDevice &device);
|
||||
static void capabilities_init(VKDevice &device);
|
||||
|
||||
|
||||
@@ -143,9 +143,8 @@ bool VKBuffer::free()
|
||||
unmap();
|
||||
}
|
||||
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
VmaAllocator allocator = device.mem_allocator_get();
|
||||
vmaDestroyBuffer(allocator, vk_buffer_, allocation_);
|
||||
VKDevice &device = VKBackend::get().device_get();
|
||||
device.discard_buffer(vk_buffer_, allocation_);
|
||||
allocation_ = VK_NULL_HANDLE;
|
||||
vk_buffer_ = VK_NULL_HANDLE;
|
||||
return true;
|
||||
|
||||
@@ -112,7 +112,11 @@ void VKContext::deactivate()
|
||||
|
||||
void VKContext::begin_frame() {}
|
||||
|
||||
void VKContext::end_frame() {}
|
||||
void VKContext::end_frame()
|
||||
{
|
||||
VKDevice &device = VKBackend::get().device_get();
|
||||
device.destroy_discarded_resources();
|
||||
}
|
||||
|
||||
void VKContext::flush()
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ void VKDevice::deinit()
|
||||
|
||||
dummy_buffer_.free();
|
||||
sampler_.free();
|
||||
destroy_discarded_resources();
|
||||
vmaDestroyAllocator(mem_allocator_);
|
||||
mem_allocator_ = VK_NULL_HANDLE;
|
||||
debugging_tools_.deinit(vk_instance_);
|
||||
@@ -248,6 +249,60 @@ const Vector<std::reference_wrapper<VKContext>> &VKDevice::contexts_get() const
|
||||
return contexts_;
|
||||
};
|
||||
|
||||
void VKDevice::discard_image(VkImage vk_image, VmaAllocation vma_allocation)
|
||||
{
|
||||
discarded_images_.append(std::pair(vk_image, vma_allocation));
|
||||
}
|
||||
|
||||
void VKDevice::discard_image_view(VkImageView vk_image_view)
|
||||
{
|
||||
discarded_image_views_.append(vk_image_view);
|
||||
}
|
||||
|
||||
void VKDevice::discard_buffer(VkBuffer vk_buffer, VmaAllocation vma_allocation)
|
||||
{
|
||||
discarded_buffers_.append(std::pair(vk_buffer, vma_allocation));
|
||||
}
|
||||
|
||||
void VKDevice::discard_render_pass(VkRenderPass vk_render_pass)
|
||||
{
|
||||
discarded_render_passes_.append(vk_render_pass);
|
||||
}
|
||||
void VKDevice::discard_frame_buffer(VkFramebuffer vk_frame_buffer)
|
||||
{
|
||||
discarded_frame_buffers_.append(vk_frame_buffer);
|
||||
}
|
||||
|
||||
void VKDevice::destroy_discarded_resources()
|
||||
{
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
|
||||
while (!discarded_image_views_.is_empty()) {
|
||||
VkImageView vk_image_view = discarded_image_views_.pop_last();
|
||||
vkDestroyImageView(vk_device_, vk_image_view, vk_allocation_callbacks);
|
||||
}
|
||||
|
||||
while (!discarded_images_.is_empty()) {
|
||||
std::pair<VkImage, VmaAllocation> image_allocation = discarded_images_.pop_last();
|
||||
vmaDestroyImage(mem_allocator_get(), image_allocation.first, image_allocation.second);
|
||||
}
|
||||
|
||||
while (!discarded_buffers_.is_empty()) {
|
||||
std::pair<VkBuffer, VmaAllocation> buffer_allocation = discarded_buffers_.pop_last();
|
||||
vmaDestroyBuffer(mem_allocator_get(), buffer_allocation.first, buffer_allocation.second);
|
||||
}
|
||||
|
||||
while (!discarded_render_passes_.is_empty()) {
|
||||
VkRenderPass vk_render_pass = discarded_render_passes_.pop_last();
|
||||
vkDestroyRenderPass(vk_device_, vk_render_pass, vk_allocation_callbacks);
|
||||
}
|
||||
|
||||
while (!discarded_frame_buffers_.is_empty()) {
|
||||
VkFramebuffer vk_frame_buffer = discarded_frame_buffers_.pop_last();
|
||||
vkDestroyFramebuffer(vk_device_, vk_frame_buffer, vk_allocation_callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
||||
@@ -73,6 +73,12 @@ class VKDevice : public NonCopyable {
|
||||
/** Buffer to bind to unbound resource locations. */
|
||||
VKBuffer dummy_buffer_;
|
||||
|
||||
Vector<std::pair<VkImage, VmaAllocation>> discarded_images_;
|
||||
Vector<std::pair<VkBuffer, VmaAllocation>> discarded_buffers_;
|
||||
Vector<VkRenderPass> discarded_render_passes_;
|
||||
Vector<VkFramebuffer> discarded_frame_buffers_;
|
||||
Vector<VkImageView> discarded_image_views_;
|
||||
|
||||
public:
|
||||
VkPhysicalDevice physical_device_get() const
|
||||
{
|
||||
@@ -177,6 +183,13 @@ class VKDevice : public NonCopyable {
|
||||
return dummy_buffer_;
|
||||
}
|
||||
|
||||
void discard_image(VkImage vk_image, VmaAllocation vma_allocation);
|
||||
void discard_image_view(VkImageView vk_image_view);
|
||||
void discard_buffer(VkBuffer vk_buffer, VmaAllocation vma_allocation);
|
||||
void discard_render_pass(VkRenderPass vk_render_pass);
|
||||
void discard_frame_buffer(VkFramebuffer vk_framebuffer);
|
||||
void destroy_discarded_resources();
|
||||
|
||||
/** \} */
|
||||
|
||||
private:
|
||||
|
||||
@@ -469,12 +469,11 @@ void VKFrameBuffer::render_pass_free()
|
||||
if (vk_render_pass_ == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
VKDevice &device = VKBackend::get().device_get();
|
||||
if (device.is_initialized()) {
|
||||
vkDestroyRenderPass(device.device_get(), vk_render_pass_, vk_allocation_callbacks);
|
||||
vkDestroyFramebuffer(device.device_get(), vk_framebuffer_, vk_allocation_callbacks);
|
||||
device.discard_render_pass(vk_render_pass_);
|
||||
device.discard_frame_buffer(vk_framebuffer_);
|
||||
}
|
||||
image_views_.clear();
|
||||
vk_render_pass_ = VK_NULL_HANDLE;
|
||||
|
||||
@@ -56,9 +56,9 @@ VKImageView::VKImageView(VKImageView &&other)
|
||||
VKImageView::~VKImageView()
|
||||
{
|
||||
if (vk_image_view_ != VK_NULL_HANDLE) {
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkDestroyImageView(device.device_get(), vk_image_view_, vk_allocation_callbacks);
|
||||
VKDevice &device = VKBackend::get().device_get();
|
||||
device.discard_image_view(vk_image_view_);
|
||||
vk_image_view_ = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,11 @@ namespace blender::gpu {
|
||||
VKTexture::~VKTexture()
|
||||
{
|
||||
if (is_allocated() && !is_texture_view()) {
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vmaDestroyImage(device.mem_allocator_get(), vk_image_, allocation_);
|
||||
VKDevice &device = VKBackend::get().device_get();
|
||||
device.discard_image(vk_image_, allocation_);
|
||||
|
||||
vk_image_ = VK_NULL_HANDLE;
|
||||
allocation_ = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user