Resource binding was over-complicated as I didn't understood the state manager and vulkan to make the correct decisions at that time. This refactor will remove a lot of the complexity and improves the performance. **Performance** The performance improvement is noticeable in complex grease pencil scenes. Grease pencil benchmark file picknick: - `NVIDIA Quadro RTX 6000` 17 fps -> 24 fps - `Intel(R) Arc(tm) A750 Graphics (DG2)` 6 -> 21 fps **Bottle-neck** The performance improvements originates from moving the update entry point from state manager to shader interface. The previous implementation (state manager) had to loop over all the bound resources and find in the shader interface where it was located in the descriptor set. Ignoring resources that were not used by the shader. But also making it hard to determine if descriptor sets actually changed. Previous implementation assumed descriptor sets always changed. When descriptor set changed a new descriptor set needed to be allocated. Most drivers this is a fast operation, but on Intel/Mesa this was measurable slow. Using an allocation pool doesn't fit the Vulkan API as you are only able to reuse when the layout matches exactly. Of course doable, but requires another structure to keep track of the actual layouts. **Solution** By using the shader interface as entry point we can: 1. Keep track if there are any changes in the state manager. If not and the layout is the same, the previous shader can be reused. 2. In stead of looping over each bound resource, we loop over bind points. **Future extensions** Bundle all descriptor set uploads just before use. This would be more in line with how 'modern' Vulkan should be implemented. This PR already separates the uploading from the updating and technically allows to upload more than one descriptor set. Instead of looking 1 set back we should measure if we can handle multiple or keep track of the different layouts resources to improve the performance even further. Optional use `VK_KHR_descriptor_buffer` when available. Pull Request: https://projects.blender.org/blender/blender/pulls/128068
66 lines
1.9 KiB
C++
66 lines
1.9 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup gpu
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BLI_vector.hh"
|
|
|
|
#include "vk_descriptor_set.hh"
|
|
|
|
namespace blender::gpu {
|
|
class VKDevice;
|
|
|
|
/**
|
|
* List of VkDescriptorPools.
|
|
*
|
|
* In Vulkan a pool is constructed with a fixed size per resource type. When more resources are
|
|
* needed it a next pool should be created. VKDescriptorPools will keep track of those pools and
|
|
* construct new pools when the previous one is exhausted.
|
|
*
|
|
* At the beginning of a new frame the descriptor pools are reset. This will start allocating
|
|
* again from the first descriptor pool in order to use freed space from previous pools.
|
|
*/
|
|
class VKDescriptorPools {
|
|
/**
|
|
* Pool sizes to use. When one descriptor pool is requested to allocate a descriptor but isn't
|
|
* able to do so, it will fail.
|
|
*
|
|
* Better defaults should be set later on, when we know more about our resource usage.
|
|
*/
|
|
static constexpr uint32_t POOL_SIZE_STORAGE_BUFFER = 1000;
|
|
static constexpr uint32_t POOL_SIZE_DESCRIPTOR_SETS = 1000;
|
|
static constexpr uint32_t POOL_SIZE_STORAGE_IMAGE = 1000;
|
|
static constexpr uint32_t POOL_SIZE_COMBINED_IMAGE_SAMPLER = 1000;
|
|
static constexpr uint32_t POOL_SIZE_UNIFORM_BUFFER = 1000;
|
|
static constexpr uint32_t POOL_SIZE_UNIFORM_TEXEL_BUFFER = 1000;
|
|
|
|
Vector<VkDescriptorPool> pools_;
|
|
int64_t active_pool_index_ = 0;
|
|
|
|
public:
|
|
VKDescriptorPools();
|
|
~VKDescriptorPools();
|
|
|
|
void init(const VKDevice &vk_device);
|
|
|
|
VkDescriptorSet allocate(const VkDescriptorSetLayout descriptor_set_layout);
|
|
|
|
/**
|
|
* Reset the pools to start looking for free space from the first descriptor pool.
|
|
*/
|
|
void reset();
|
|
|
|
private:
|
|
VkDescriptorPool active_pool_get();
|
|
void activate_next_pool();
|
|
void activate_last_pool();
|
|
bool is_last_pool_active();
|
|
void add_new_pool(const VKDevice &device);
|
|
};
|
|
} // namespace blender::gpu
|