From f80083491aa228f7f4467ca5d5d1398bb7450e69 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 1 Sep 2025 12:38:57 +0200 Subject: [PATCH] Revert "Vulkan: Remove resource pools" This reverts commit ce0406b97bdf7964716847ed70e86d21f3531203. Reports on blender-coders mentioned that it could fail on startup. --- intern/ghost/intern/GHOST_ContextVK.cc | 7 +--- intern/ghost/intern/GHOST_ContextVK.hh | 9 +++++ source/blender/gpu/vulkan/vk_context.cc | 12 ++++-- source/blender/gpu/vulkan/vk_context.hh | 2 +- source/blender/gpu/vulkan/vk_device.cc | 5 +++ source/blender/gpu/vulkan/vk_device.hh | 40 ++++++++++++++++++- source/blender/gpu/vulkan/vk_resource_pool.hh | 5 +++ 7 files changed, 68 insertions(+), 12 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextVK.cc b/intern/ghost/intern/GHOST_ContextVK.cc index 37db0353177..c8e3dccfbae 100644 --- a/intern/ghost/intern/GHOST_ContextVK.cc +++ b/intern/ghost/intern/GHOST_ContextVK.cc @@ -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 swapchain_images(actual_image_count); vkGetSwapchainImagesKHR(device, swapchain_, &actual_image_count, swapchain_images.data()); diff --git a/intern/ghost/intern/GHOST_ContextVK.hh b/intern/ghost/intern/GHOST_ContextVK.hh index f5fcc30a540..1b0c1afc51c 100644 --- a/intern/ghost/intern/GHOST_ContextVK.hh +++ b/intern/ghost/intern/GHOST_ContextVK.hh @@ -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; diff --git a/source/blender/gpu/vulkan/vk_context.cc b/source/blender/gpu/vulkan/vk_context.cc index 8947f41ef38..adc29516d95 100644 --- a/source/blender/gpu/vulkan/vk_context.cc +++ b/source/blender/gpu/vulkan/vk_context.cc @@ -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( diff --git a/source/blender/gpu/vulkan/vk_context.hh b/source/blender/gpu/vulkan/vk_context.hh index bce610762ce..ed4a61ee1fa 100644 --- a/source/blender/gpu/vulkan/vk_context.hh +++ b/source/blender/gpu/vulkan/vk_context.hh @@ -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() { diff --git a/source/blender/gpu/vulkan/vk_device.cc b/source/blender/gpu/vulkan/vk_device.cc index 4c1f0ebdb12..f8014a04818 100644 --- a/source/blender/gpu/vulkan/vk_device.cc +++ b/source/blender/gpu/vulkan/vk_device.cc @@ -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); diff --git a/source/blender/gpu/vulkan/vk_device.hh b/source/blender/gpu/vulkan/vk_device.hh index 1efe816afa2..29272f31fea 100644 --- a/source/blender/gpu/vulkan/vk_device.hh +++ b/source/blender/gpu/vulkan/vk_device.hh @@ -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 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 { diff --git a/source/blender/gpu/vulkan/vk_resource_pool.hh b/source/blender/gpu/vulkan/vk_resource_pool.hh index 770433d9e0e..3afc189303d 100644 --- a/source/blender/gpu/vulkan/vk_resource_pool.hh +++ b/source/blender/gpu/vulkan/vk_resource_pool.hh @@ -143,4 +143,9 @@ class VKDiscardPool { static VKDiscardPool &discard_pool_get(); }; +class VKResourcePool { + + public: + VKDescriptorSetTracker descriptor_set; +}; } // namespace blender::gpu