Files
test2/source/blender/gpu/vulkan/vk_resource_pool.cc
Jeroen Bakker ef3ceb3629 Vulkan: Resource Pools
This PR implements #126353; In short: keep discard list as part of swap chain images. This allows
better determination when resources are actually not in use anymore.

## Resource pool

Resource pools keep track of the resources for a swap chain image.

In Blender this is a bit more complicated due to the way GPUContext work. A single thread can have
multiple contexts. Some of them have a swap chain (GHOST Window) other don't (draw manager). The
resource pool should be shared between the contexts running on the same thread.

When opening multiple windows there are also multiple swap chains to consider.

### Discard pile

Resource handles that are deleted and stored in the discard pile. When we are sure that these
resources are not used on the GPU anymore these are destroyed.

### Reusable resources

There are other resources as well like:
- Descriptor sets
- Descriptor pools

## Open issues

There are some limitations that require future PRs to fix including:
- Background rendering
- Handling multiple windows
- Improve CPU/GPU synchronization
- Reuse staging buffers

Pull Request: https://projects.blender.org/blender/blender/pulls/126353
2024-08-19 15:37:48 +02:00

115 lines
3.2 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include "vk_resource_pool.hh"
#include "vk_backend.hh"
#include "vk_memory.hh"
namespace blender::gpu {
void VKResourcePool::init(VKDevice &device)
{
descriptor_pools.init(device);
}
void VKResourcePool::deinit(VKDevice &device)
{
discard_pool.deinit(device);
}
void VKResourcePool::reset()
{
descriptor_pools.reset();
}
void VKDiscardPool::deinit(VKDevice &device)
{
destroy_discarded_resources(device);
}
void VKDiscardPool::move_data(VKDiscardPool &src_pool)
{
std::scoped_lock mutex(mutex_);
std::scoped_lock mutex_src(src_pool.mutex_);
buffers_.extend(src_pool.buffers_);
image_views_.extend(src_pool.image_views_);
images_.extend(src_pool.images_);
shader_modules_.extend(src_pool.shader_modules_);
pipeline_layouts_.extend(src_pool.pipeline_layouts_);
src_pool.buffers_.clear();
src_pool.image_views_.clear();
src_pool.images_.clear();
src_pool.shader_modules_.clear();
src_pool.pipeline_layouts_.clear();
}
void VKDiscardPool::discard_image(VkImage vk_image, VmaAllocation vma_allocation)
{
std::scoped_lock mutex(mutex_);
images_.append(std::pair(vk_image, vma_allocation));
}
void VKDiscardPool::discard_image_view(VkImageView vk_image_view)
{
std::scoped_lock mutex(mutex_);
image_views_.append(vk_image_view);
}
void VKDiscardPool::discard_buffer(VkBuffer vk_buffer, VmaAllocation vma_allocation)
{
std::scoped_lock mutex(mutex_);
buffers_.append(std::pair(vk_buffer, vma_allocation));
}
void VKDiscardPool::discard_shader_module(VkShaderModule vk_shader_module)
{
std::scoped_lock mutex(mutex_);
shader_modules_.append(vk_shader_module);
}
void VKDiscardPool::discard_pipeline_layout(VkPipelineLayout vk_pipeline_layout)
{
std::scoped_lock mutex(mutex_);
pipeline_layouts_.append(vk_pipeline_layout);
}
void VKDiscardPool::destroy_discarded_resources(VKDevice &device)
{
std::scoped_lock mutex(mutex_);
VK_ALLOCATION_CALLBACKS
while (!image_views_.is_empty()) {
VkImageView vk_image_view = image_views_.pop_last();
vkDestroyImageView(device.vk_handle(), vk_image_view, vk_allocation_callbacks);
}
while (!images_.is_empty()) {
std::pair<VkImage, VmaAllocation> image_allocation = images_.pop_last();
device.resources.remove_image(image_allocation.first);
vmaDestroyImage(device.mem_allocator_get(), image_allocation.first, image_allocation.second);
}
while (!buffers_.is_empty()) {
std::pair<VkBuffer, VmaAllocation> buffer_allocation = buffers_.pop_last();
device.resources.remove_buffer(buffer_allocation.first);
vmaDestroyBuffer(
device.mem_allocator_get(), buffer_allocation.first, buffer_allocation.second);
}
while (!pipeline_layouts_.is_empty()) {
VkPipelineLayout vk_pipeline_layout = pipeline_layouts_.pop_last();
vkDestroyPipelineLayout(device.vk_handle(), vk_pipeline_layout, vk_allocation_callbacks);
}
while (!shader_modules_.is_empty()) {
VkShaderModule vk_shader_module = shader_modules_.pop_last();
vkDestroyShaderModule(device.vk_handle(), vk_shader_module, vk_allocation_callbacks);
}
}
} // namespace blender::gpu