Vulkan: Reduce memory overhead rendergraph

For performance reasons render graphs can keep memory allocated so it
could be reused. This PR optimizes the memory usage inside the
rendergraph to keep it within normal usage.

I didn't detect any performance regression with this change but reduces
the memory when performing final image rendering of heavy scenes.

Partial fix for #137382. the amount of memory still increases with 4mb
per render. It fixes the main difference when using large scenes.

Pull Request: https://projects.blender.org/blender/blender/pulls/137660
This commit is contained in:
Jeroen Bakker
2025-04-17 13:45:47 +02:00
parent 3d1b6f53f3
commit 13d6ba1f62
6 changed files with 67 additions and 24 deletions

View File

@@ -20,13 +20,16 @@ VKRenderGraph::VKRenderGraph(VKResourceStateTracker &resources) : resources_(res
void VKRenderGraph::reset()
{
#if 0
memstats();
#endif
submission_id.next();
links_.clear();
links_.clear_and_shrink();
for (VKRenderGraphNode &node : nodes_) {
node.free_data(storage_);
}
nodes_.clear();
nodes_.clear_and_shrink();
storage_.reset();
debug_.node_group_map.clear();
@@ -35,6 +38,27 @@ void VKRenderGraph::reset()
debug_.groups.clear();
}
void VKRenderGraph::memstats() const
{
std::cout << __func__ << " nodes: (" << nodes_.size() << "/" << nodes_.capacity() << "), "
<< "links: (" << links_.size() << "/" << links_.capacity() << ")\n";
#define PRINT_STORAGE(name) \
std::cout << " " #name " : (" << storage_.name.size() << " / " << storage_.name.capacity() \
<< ")\n "
PRINT_STORAGE(begin_rendering);
PRINT_STORAGE(clear_attachments);
PRINT_STORAGE(blit_image);
PRINT_STORAGE(copy_buffer_to_image);
PRINT_STORAGE(copy_image);
PRINT_STORAGE(copy_image_to_buffer);
PRINT_STORAGE(draw);
PRINT_STORAGE(draw_indexed);
PRINT_STORAGE(draw_indexed_indirect);
PRINT_STORAGE(draw_indirect);
#undef PRINT_STORAGE
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -69,9 +69,9 @@ class VKRenderGraph : public NonCopyable {
using DebugGroupID = int64_t;
/** All links inside the graph indexable via NodeHandle. */
Vector<VKRenderGraphNodeLinks> links_;
Vector<VKRenderGraphNodeLinks, 1024> links_;
/** All nodes inside the graph indexable via NodeHandle. */
Vector<VKRenderGraphNode> nodes_;
Vector<VKRenderGraphNode, 1024> nodes_;
/** Storage for large node datas to improve CPU cache pre-loading. */
VKRenderGraphStorage storage_;
@@ -250,6 +250,8 @@ class VKRenderGraph : public NonCopyable {
*/
void reset();
void memstats() const;
private:
};

View File

@@ -48,29 +48,29 @@ using NodeHandle = uint64_t;
*
*/
struct VKRenderGraphStorage {
Vector<VKBeginRenderingNode::Data> begin_rendering;
Vector<VKClearAttachmentsNode::Data> clear_attachments;
Vector<VKBlitImageNode::Data> blit_image;
Vector<VKCopyBufferToImageNode::Data> copy_buffer_to_image;
Vector<VKCopyImageNode::Data> copy_image;
Vector<VKCopyImageToBufferNode::Data> copy_image_to_buffer;
Vector<VKDrawNode::Data> draw;
Vector<VKDrawIndexedNode::Data> draw_indexed;
Vector<VKDrawIndexedIndirectNode::Data> draw_indexed_indirect;
Vector<VKDrawIndirectNode::Data> draw_indirect;
Vector<VKBeginRenderingNode::Data, 1024> begin_rendering;
Vector<VKClearAttachmentsNode::Data, 1024> clear_attachments;
Vector<VKBlitImageNode::Data, 1024> blit_image;
Vector<VKCopyBufferToImageNode::Data, 1024> copy_buffer_to_image;
Vector<VKCopyImageNode::Data, 1024> copy_image;
Vector<VKCopyImageToBufferNode::Data, 1024> copy_image_to_buffer;
Vector<VKDrawNode::Data, 1024> draw;
Vector<VKDrawIndexedNode::Data, 1024> draw_indexed;
Vector<VKDrawIndexedIndirectNode::Data, 1024> draw_indexed_indirect;
Vector<VKDrawIndirectNode::Data, 1024> draw_indirect;
void reset()
{
begin_rendering.clear();
clear_attachments.clear();
blit_image.clear();
copy_buffer_to_image.clear();
copy_image.clear();
copy_image_to_buffer.clear();
draw.clear();
draw_indexed.clear();
draw_indexed_indirect.clear();
draw_indirect.clear();
begin_rendering.clear_and_shrink();
clear_attachments.clear_and_shrink();
blit_image.clear_and_shrink();
copy_buffer_to_image.clear_and_shrink();
copy_image.clear_and_shrink();
copy_image_to_buffer.clear_and_shrink();
draw.clear_and_shrink();
draw_indexed.clear_and_shrink();
draw_indexed_indirect.clear_and_shrink();
draw_indirect.clear_and_shrink();
}
};

View File

@@ -177,4 +177,14 @@ void VKResourceStateTracker::validate() const
}
#endif
void VKResourceStateTracker::debug_print() const
{
std::ostream &os = std::cout;
os << "VKResourceStateTracker\n";
os << " resources=(" << resources_.size() << "/" << resources_.capacity() << ")\n";
os << " buffers=(" << buffer_resources_.size() << "/" << buffer_resources_.capacity() << ")\n";
os << " images=(" << image_resources_.size() << "/" << image_resources_.capacity() << ")\n";
os << " unused=(" << unused_handles_.size() << "/" << unused_handles_.capacity() << ")\n";
}
} // namespace blender::gpu::render_graph

View File

@@ -260,6 +260,8 @@ class VKResourceStateTracker {
bool use_dynamic_rendering = true;
bool use_dynamic_rendering_local_read = true;
void debug_print() const;
private:
/**
* Get the current stamp of the resource.

View File

@@ -563,6 +563,11 @@ void VKDevice::debug_print()
os << "Discard pool\n";
debug_print(os, orphaned_data);
os << "\n";
for (const std::reference_wrapper<VKContext> &context : contexts_) {
os << " VKContext \n";
debug_print(os, context.get().discard_pool);
}
}
/** \} */