Revert "Vulkan: Remove resource pools"

This reverts commit ce0406b97b.
Reports on blender-coders mentioned that it could fail on startup.
This commit is contained in:
Jeroen Bakker
2025-09-01 12:38:57 +02:00
parent 62f5965dee
commit f80083491a
7 changed files with 68 additions and 12 deletions

View File

@@ -603,7 +603,7 @@ GHOST_ContextVK::GHOST_ContextVK(const GHOST_ContextParams &context_params,
hdr_info_(hdr_info),
surface_(VK_NULL_HANDLE),
swapchain_(VK_NULL_HANDLE),
frame_data_(2),
frame_data_(GHOST_FRAMES_IN_FLIGHT),
render_frame_(0),
use_hdr_swapchain_(false)
{
@@ -1160,10 +1160,7 @@ GHOST_TSuccess GHOST_ContextVK::recreateSwapchain(bool use_hdr_swapchain)
/* Some platforms require a minimum amount of render frames that is larger than we expect. When
* that happens we should increase the number of frames in flight. We could also consider
* splitting the frame in flight and image specific data. */
if (actual_image_count > frame_data_.size()) {
CLOG_TRACE(&LOG, "Vulkan: Increasing frame data to %u frames", actual_image_count);
frame_data_.resize(actual_image_count);
}
assert(actual_image_count <= GHOST_FRAMES_IN_FLIGHT);
swapchain_images_.resize(actual_image_count);
std::vector<VkImage> swapchain_images(actual_image_count);
vkGetSwapchainImagesKHR(device, swapchain_, &actual_image_count, swapchain_images.data());

View File

@@ -91,6 +91,15 @@ struct GHOST_Frame {
void destroy(VkDevice vk_device);
};
/**
* The number of frames that GHOST manages.
*
* This must be kept in sync with any frame-aligned resources in the
* Vulkan backend. Notably, VKThreadData::resource_pools_count must
* match this value.
*/
constexpr static uint32_t GHOST_FRAMES_IN_FLIGHT = 5;
class GHOST_ContextVK : public GHOST_Context {
friend class GHOST_XrGraphicsBindingVulkan;
friend class GHOST_XrGraphicsBindingVulkanD3D;

View File

@@ -56,11 +56,15 @@ VKContext::~VKContext()
this->process_frame_timings();
}
void VKContext::sync_backbuffer()
void VKContext::sync_backbuffer(bool cycle_resource_pool)
{
if (ghost_window_) {
GHOST_VulkanSwapChainData swap_chain_data = {};
GHOST_GetVulkanSwapChainFormat((GHOST_WindowHandle)ghost_window_, &swap_chain_data);
VKThreadData &thread_data = thread_data_.value().get();
if (cycle_resource_pool) {
thread_data.resource_pool_next();
}
const bool reset_framebuffer = swap_chain_format_.format !=
swap_chain_data.surface_format.format ||
@@ -128,7 +132,7 @@ void VKContext::activate()
is_active_ = true;
sync_backbuffer();
sync_backbuffer(false);
immActivate();
}
@@ -212,7 +216,7 @@ VKDescriptorPools &VKContext::descriptor_pools_get()
VKDescriptorSetTracker &VKContext::descriptor_set_get()
{
return thread_data_.value().get().descriptor_set;
return thread_data_.value().get().resource_pool_get().descriptor_set;
}
VKStateManager &VKContext::state_manager_get() const
@@ -447,7 +451,7 @@ void VKContext::swap_buffers_pre_handler(const GHOST_VulkanSwapChainData &swap_c
void VKContext::swap_buffers_post_handler()
{
sync_backbuffer();
sync_backbuffer(true);
}
void VKContext::specialization_constants_set(

View File

@@ -137,7 +137,7 @@ class VKContext : public Context, NonCopyable {
VKVertexAttributeObject &vao,
render_graph::VKPipelineData &r_pipeline_data);
void sync_backbuffer();
void sync_backbuffer(bool cycle_resource_pool);
static VKContext *get()
{

View File

@@ -645,6 +645,11 @@ void VKDevice::debug_print()
const bool is_main = pthread_equal(thread_data->thread_id, pthread_self());
os << "ThreadData" << (is_main ? " (main-thread)" : "") << ")\n";
os << " Rendering_depth: " << thread_data->rendering_depth << "\n";
for (int resource_pool_index : IndexRange(thread_data->resource_pools.size())) {
const bool is_active = thread_data->resource_pool_index == resource_pool_index;
os << " Resource Pool (index=" << resource_pool_index << (is_active ? " active" : "")
<< ")\n";
}
}
os << "Discard pool\n";
debug_print(os, orphaned_data);

View File

@@ -106,12 +106,26 @@ struct VKWorkarounds {
* Shared resources between contexts that run in the same thread.
*/
class VKThreadData : public NonCopyable, NonMovable {
/**
* The number of resource pools is aligned to the number of frames
* in flight used by GHOST. Therefore, this constant *must* always
* match GHOST_ContextVK's GHOST_FRAMES_IN_FLIGHT.
*/
static constexpr uint32_t resource_pools_count = 5;
public:
/** Thread ID this instance belongs to. */
pthread_t thread_id;
VKDescriptorPools descriptor_pools;
VKDescriptorSetTracker descriptor_set;
/**
* Index of the active resource pool. Is in sync with the active swap-chain image or cycled when
* rendering.
*
* NOTE: Initialized to `UINT32_MAX` to detect first change.
*/
uint32_t resource_pool_index = UINT32_MAX;
std::array<VKResourcePool, resource_pools_count> resource_pools;
VKDescriptorPools descriptor_pools;
/**
* The current rendering depth.
*
@@ -123,6 +137,28 @@ class VKThreadData : public NonCopyable, NonMovable {
int32_t rendering_depth = 0;
VKThreadData(VKDevice &device, pthread_t thread_id);
/**
* Get the active resource pool.
*/
VKResourcePool &resource_pool_get()
{
if (resource_pool_index >= resource_pools.size()) {
return resource_pools[0];
}
return resource_pools[resource_pool_index];
}
/** Activate the next resource pool. */
void resource_pool_next()
{
if (resource_pool_index == UINT32_MAX) {
resource_pool_index = 1;
}
else {
resource_pool_index = (resource_pool_index + 1) % resource_pools_count;
}
}
};
class VKDevice : public NonCopyable {

View File

@@ -143,4 +143,9 @@ class VKDiscardPool {
static VKDiscardPool &discard_pool_get();
};
class VKResourcePool {
public:
VKDescriptorSetTracker descriptor_set;
};
} // namespace blender::gpu