Browse Source

Merge pull request #85520 from YuriSizov/rendering-gracefully-leak-canvas-items

Avoid crashes when engine leaks canvas items and friends
Rémi Verschelde 1 năm trước cách đây
mục cha
commit
673102ffd8

+ 24 - 0
servers/rendering/renderer_canvas_cull.cpp

@@ -2165,6 +2165,30 @@ bool RendererCanvasCull::free(RID p_rid) {
 	return true;
 }
 
+template <class T>
+void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) {
+	List<RID> owned;
+	p_owner.get_owned_list(&owned);
+	if (owned.size()) {
+		if (owned.size() == 1) {
+			WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type));
+		} else {
+			WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));
+		}
+		for (const RID &E : owned) {
+			free(E);
+		}
+	}
+}
+
+void RendererCanvasCull::finalize() {
+	_free_rids(canvas_owner, "Canvas");
+	_free_rids(canvas_item_owner, "CanvasItem");
+	_free_rids(canvas_light_owner, "CanvasLight");
+	_free_rids(canvas_light_occluder_owner, "CanvasLightOccluder");
+	_free_rids(canvas_light_occluder_polygon_owner, "CanvasLightOccluderPolygon");
+}
+
 RendererCanvasCull::RendererCanvasCull() {
 	z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
 	z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));

+ 6 - 0
servers/rendering/renderer_canvas_cull.h

@@ -170,6 +170,9 @@ public:
 	RID_Owner<Item, true> canvas_item_owner;
 	RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner;
 
+	template <class T>
+	void _free_rids(T &p_owner, const char *p_type);
+
 	bool disable_scale;
 	bool sdf_used = false;
 	bool snapping_2d_transforms_to_pixel = false;
@@ -329,6 +332,9 @@ public:
 	Rect2 _debug_canvas_item_get_rect(RID p_item);
 
 	bool free(RID p_rid);
+
+	void finalize();
+
 	RendererCanvasCull();
 	~RendererCanvasCull();
 };

+ 2 - 0
servers/rendering/renderer_canvas_render.cpp

@@ -31,6 +31,8 @@
 #include "renderer_canvas_render.h"
 #include "servers/rendering/rendering_server_globals.h"
 
+RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
+
 const Rect2 &RendererCanvasRender::Item::get_rect() const {
 	if (custom_rect || (!rect_dirty && !update_when_visible && skeleton == RID())) {
 		return rect;

+ 0 - 4
servers/rendering/renderer_compositor.cpp

@@ -31,8 +31,6 @@
 #include "renderer_compositor.h"
 
 #include "core/config/project_settings.h"
-#include "core/os/os.h"
-#include "core/string/print_string.h"
 #include "servers/xr_server.h"
 
 RendererCompositor *RendererCompositor::singleton = nullptr;
@@ -57,5 +55,3 @@ RendererCompositor::RendererCompositor() {
 		xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
 	}
 }
-
-RendererCanvasRender *RendererCanvasRender::singleton = nullptr;

+ 1 - 0
servers/rendering/rendering_server_default.cpp

@@ -211,6 +211,7 @@ void RenderingServerDefault::_finish() {
 		free(test_cube);
 	}
 
+	RSG::canvas->finalize();
 	RSG::rasterizer->finalize();
 }