Fix resource leaks in VoxelGI

This commit is contained in:
Bastiaan Olij 2022-08-09 15:18:03 +10:00
parent 7355dfb502
commit f50f0844e9
3 changed files with 48 additions and 25 deletions

View file

@ -1140,6 +1140,7 @@ void GI::SDFGI::erase() {
RD::get_singleton()->free(lightprobe_data);
RD::get_singleton()->free(lightprobe_history_scroll);
RD::get_singleton()->free(lightprobe_average_scroll);
RD::get_singleton()->free(occlusion_data);
RD::get_singleton()->free(ambient_texture);
@ -2427,18 +2428,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
if (last_probe_data_version != data_version) {
//need to re-create everything
if (texture.is_valid()) {
RD::get_singleton()->free(texture);
RD::get_singleton()->free(write_buffer);
mipmaps.clear();
}
for (int i = 0; i < dynamic_maps.size(); i++) {
RD::get_singleton()->free(dynamic_maps[i].texture);
RD::get_singleton()->free(dynamic_maps[i].depth);
}
dynamic_maps.clear();
free_resources();
Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
@ -3130,6 +3120,37 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
last_probe_version = gi->voxel_gi_get_version(probe);
}
void GI::VoxelGIInstance::free_resources() {
if (texture.is_valid()) {
RD::get_singleton()->free(texture);
RD::get_singleton()->free(write_buffer);
texture = RID();
write_buffer = RID();
mipmaps.clear();
}
for (int i = 0; i < dynamic_maps.size(); i++) {
RD::get_singleton()->free(dynamic_maps[i].texture);
RD::get_singleton()->free(dynamic_maps[i].depth);
// these only exist on the first level...
if (dynamic_maps[i].fb_depth.is_valid()) {
RD::get_singleton()->free(dynamic_maps[i].fb_depth);
}
if (dynamic_maps[i].albedo.is_valid()) {
RD::get_singleton()->free(dynamic_maps[i].albedo);
}
if (dynamic_maps[i].normal.is_valid()) {
RD::get_singleton()->free(dynamic_maps[i].normal);
}
if (dynamic_maps[i].orm.is_valid()) {
RD::get_singleton()->free(dynamic_maps[i].orm);
}
}
dynamic_maps.clear();
}
void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@ -3936,6 +3957,12 @@ RID GI::voxel_gi_instance_create(RID p_base) {
return rid;
}
void GI::voxel_gi_instance_free(RID p_rid) {
GI::VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_rid);
voxel_gi->free_resources();
voxel_gi_instance_owner.free(p_rid);
}
void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
ERR_FAIL_COND(!voxel_gi);

View file

@ -469,6 +469,7 @@ public:
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void free_resources();
};
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
@ -483,6 +484,12 @@ public:
return voxel_gi->texture;
};
bool voxel_gi_instance_owns(RID p_rid) const {
return voxel_gi_instance_owner.owns(p_rid);
}
void voxel_gi_instance_free(RID p_rid);
RS::VoxelGIQuality voxel_gi_quality = RS::VOXEL_GI_QUALITY_LOW;
/* SDFGI */

View file

@ -4086,19 +4086,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
decal_instance_owner.free(p_rid);
} else if (lightmap_instance_owner.owns(p_rid)) {
lightmap_instance_owner.free(p_rid);
} else if (gi.voxel_gi_instance_owner.owns(p_rid)) {
RendererRD::GI::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.get_or_null(p_rid);
if (voxel_gi->texture.is_valid()) {
RD::get_singleton()->free(voxel_gi->texture);
RD::get_singleton()->free(voxel_gi->write_buffer);
}
for (int i = 0; i < voxel_gi->dynamic_maps.size(); i++) {
RD::get_singleton()->free(voxel_gi->dynamic_maps[i].texture);
RD::get_singleton()->free(voxel_gi->dynamic_maps[i].depth);
}
gi.voxel_gi_instance_owner.free(p_rid);
} else if (gi.voxel_gi_instance_owns(p_rid)) {
gi.voxel_gi_instance_free(p_rid);
} else if (sky.sky_owner.owns(p_rid)) {
sky.update_dirty_skys();
sky.free_sky(p_rid);