Fix #114742: Draw: Buffers never shrink #114857

Merged
Miguel Pozo merged 5 commits from pragma37/blender:pull-draw-memory-housekeeping into main 2023-11-20 12:23:22 +01:00
5 changed files with 40 additions and 3 deletions

View File

@ -69,7 +69,7 @@ class Instance {
void begin_sync()
{
resources.material_buf.clear();
resources.material_buf.clear_and_trim();
opaque_ps.sync(scene_state, resources);
transparent_ps.sync(scene_state, resources);

View File

@ -373,6 +373,20 @@ class StorageArrayBuffer : public detail::StorageCommon<T, len, device_only> {
return this->data_[index];
}
/*
* Ensure the allocated size is not much larger than the currently required size,
* using the same heuristic as `get_or_resize`.
*/
void trim_to_next_power_of_2(int64_t required_size)
{
/* Don't go below the size used at creation. */
required_size = std::max(required_size, len);
size_t target_size = power_of_2_max_u(required_size);
if (this->len_ > target_size) {
this->resize(target_size);
}
}
int64_t size() const
{
return this->len_;
@ -414,6 +428,16 @@ class StorageVectorBuffer : public StorageArrayBuffer<T, len, false> {
item_len_ = 0;
}
/**
* Set item count to zero
* and trim the buffer if current size is much larger than the current item count.
*/
void clear_and_trim()
{
this->trim_to_next_power_of_2(item_len_);
clear();
}
/**
* Insert a new element at the end of the vector.
* This might cause a reallocation with the capacity is exceeded.

View File

@ -701,7 +701,7 @@ void DrawMultiBuf::bind(RecordingState &state,
prototype_buf_.push_update();
/* Allocate enough for the expansion pass. */
resource_id_buf_.get_or_resize(resource_id_count_ * (use_custom_ids ? 2 : 1));
/* Two command per group. */
/* Two commands per group (inverted and non-inverted scale). */
command_buf_.get_or_resize(group_count_ * 2);
if (prototype_count_ > 0) {

View File

@ -443,7 +443,10 @@ class DrawCommandBuf {
uint resource_id_count_ = 0;
public:
void clear(){};
void clear()
{
resource_id_buf_.trim_to_next_power_of_2(resource_id_count_);
};
void append_draw(Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
@ -554,6 +557,11 @@ class DrawMultiBuf {
public:
void clear()
{
group_buf_.trim_to_next_power_of_2(group_count_);
/* Two commands per group (inverted and non-inverted scale). */
command_buf_.trim_to_next_power_of_2(group_count_ * 2);
prototype_buf_.trim_to_next_power_of_2(prototype_count_);
resource_id_buf_.trim_to_next_power_of_2(resource_id_count_);
header_id_counter_ = 0;
group_count_ = 0;
prototype_count_ = 0;

View File

@ -32,6 +32,11 @@ void Manager::begin_sync()
bounds_buf.swap();
infos_buf.swap();
matrix_buf.current().trim_to_next_power_of_2(resource_len_);
bounds_buf.current().trim_to_next_power_of_2(resource_len_);
infos_buf.current().trim_to_next_power_of_2(resource_len_);
attributes_buf.trim_to_next_power_of_2(attribute_len_);
/* TODO: This means the reference is kept until further redraw or manager tear-down. Instead,
* they should be released after each draw loop. But for now, mimics old DRW behavior. */
for (GPUTexture *texture : acquired_textures) {