Optimize shared texture creation

Texture::slice_trackers is now a pointer and is allocated on demand only when a shared texture is created.
This makes copying Texture significantly faster.
This commit is contained in:
ze2j 2024-12-20 16:45:15 +01:00
parent 30bb49ec1f
commit 6413a8a94b
2 changed files with 16 additions and 9 deletions

View file

@ -1091,6 +1091,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with
// Create view.
Texture texture = *src_texture;
texture.slice_trackers = nullptr;
texture.shared_fallback = nullptr;
RDD::TextureView tv;
@ -1149,8 +1150,6 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with
ERR_FAIL_COND_V(!texture.driver_id, RID());
texture.slice_trackers.clear();
if (texture.draw_tracker != nullptr) {
texture.draw_tracker->reference_count++;
}
@ -1245,6 +1244,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view,
}
Texture texture = *src_texture;
texture.slice_trackers = nullptr;
texture.shared_fallback = nullptr;
get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height);
@ -5844,9 +5844,12 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id
p_texture->draw_tracker->reference_count++;
} else {
// Slice texture.
HashMap<Rect2i, RDG::ResourceTracker *>::ConstIterator draw_tracker_iterator = owner_texture->slice_trackers.find(p_texture->slice_rect);
if (owner_texture->slice_trackers == nullptr) {
owner_texture->slice_trackers = memnew((HashMap<Rect2i, RDG::ResourceTracker *>));
}
HashMap<Rect2i, RDG::ResourceTracker *>::ConstIterator draw_tracker_iterator = owner_texture->slice_trackers->find(p_texture->slice_rect);
RDG::ResourceTracker *draw_tracker = nullptr;
if (draw_tracker_iterator != owner_texture->slice_trackers.end()) {
if (draw_tracker_iterator != owner_texture->slice_trackers->end()) {
// Reuse the tracker at the matching rectangle.
draw_tracker = draw_tracker_iterator->value;
} else {
@ -5858,10 +5861,9 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id
draw_tracker->texture_subresources = p_texture->barrier_range();
draw_tracker->texture_usage = p_texture->usage_flags;
draw_tracker->texture_slice_or_dirty_rect = p_texture->slice_rect;
owner_texture->slice_trackers[p_texture->slice_rect] = draw_tracker;
(*owner_texture->slice_trackers)[p_texture->slice_rect] = draw_tracker;
}
p_texture->slice_trackers.clear();
p_texture->draw_tracker = draw_tracker;
p_texture->draw_tracker->reference_count++;
}
@ -6020,8 +6022,13 @@ void RenderingDevice::_free_internal(RID p_id) {
if (texture->owner.is_valid() && (texture->slice_type != TEXTURE_SLICE_MAX)) {
// If this was a texture slice, erase the tracker from the map.
Texture *owner_texture = texture_owner.get_or_null(texture->owner);
if (owner_texture != nullptr) {
owner_texture->slice_trackers.erase(texture->slice_rect);
if (owner_texture != nullptr && owner_texture->slice_trackers != nullptr) {
owner_texture->slice_trackers->erase(texture->slice_rect);
if (owner_texture->slice_trackers->is_empty()) {
memdelete(owner_texture->slice_trackers);
owner_texture->slice_trackers = nullptr;
}
}
}
}