Procházet zdrojové kódy

Merge pull request #88589 from RandomShaper/gl_preview_liveunlock

Rework viewport capture in preview generation
Rémi Verschelde před 1 rokem
rodič
revize
63bde2feff

+ 29 - 2
editor/editor_resource_preview.cpp

@@ -95,8 +95,35 @@ void EditorResourcePreviewGenerator::_bind_methods() {
 EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
 }
 
+void EditorResourcePreviewGenerator::DrawRequester::request_and_wait(RID p_viewport) const {
+	if (EditorResourcePreview::get_singleton()->is_threaded()) {
+		Callable request_vp_update_once = callable_mp(RS::get_singleton(), &RS::viewport_set_update_mode).bind(p_viewport, RS::VIEWPORT_UPDATE_ONCE);
+		RS::get_singleton()->connect(SNAME("frame_pre_draw"), request_vp_update_once, Object::CONNECT_ONE_SHOT);
+		RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorResourcePreviewGenerator::DrawRequester *>(this), &EditorResourcePreviewGenerator::DrawRequester::_post_semaphore));
+
+		semaphore.wait();
+	} else {
+		RS::get_singleton()->draw(false);
+	}
+}
+
+void EditorResourcePreviewGenerator::DrawRequester::abort() const {
+	if (EditorResourcePreview::get_singleton()->is_threaded()) {
+		semaphore.post();
+	}
+}
+
+Variant EditorResourcePreviewGenerator::DrawRequester::_post_semaphore() const {
+	semaphore.post();
+	return Variant(); // Needed because of how the callback is used.
+}
+
 EditorResourcePreview *EditorResourcePreview::singleton = nullptr;
 
+bool EditorResourcePreview::is_threaded() const {
+	return RSG::texture_storage->can_create_resources_async();
+}
+
 void EditorResourcePreview::_thread_func(void *ud) {
 	EditorResourcePreview *erp = (EditorResourcePreview *)ud;
 	erp->_thread();
@@ -470,7 +497,7 @@ void EditorResourcePreview::start() {
 		return;
 	}
 
-	if (RSG::texture_storage->can_create_resources_async()) {
+	if (is_threaded()) {
 		ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
 		thread.start(_thread_func, this);
 	} else {
@@ -481,7 +508,7 @@ void EditorResourcePreview::start() {
 }
 
 void EditorResourcePreview::stop() {
-	if (RSG::texture_storage->can_create_resources_async()) {
+	if (is_threaded()) {
 		if (thread.is_started()) {
 			exiting.set();
 			preview_sem.post();

+ 11 - 0
editor/editor_resource_preview.h

@@ -51,6 +51,16 @@ protected:
 	GDVIRTUAL0RC(bool, _generate_small_preview_automatically)
 	GDVIRTUAL0RC(bool, _can_generate_small_preview)
 
+	class DrawRequester : public Object {
+		Semaphore semaphore;
+
+		Variant _post_semaphore() const;
+
+	public:
+		void request_and_wait(RID p_viewport) const;
+		void abort() const;
+	};
+
 public:
 	virtual bool handles(const String &p_type) const;
 	virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const;
@@ -132,6 +142,7 @@ public:
 
 	void start();
 	void stop();
+	bool is_threaded() const;
 
 	EditorResourcePreview();
 	~EditorResourcePreview();

+ 6 - 42
editor/plugins/editor_preview_plugins.cpp

@@ -285,18 +285,8 @@ EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
 
 //////////////////////////////////////////////////////////////////
 
-void EditorMaterialPreviewPlugin::_generate_frame_started() {
-	RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
-
-	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_preview_done));
-}
-
-void EditorMaterialPreviewPlugin::_preview_done() {
-	preview_done.post();
-}
-
 void EditorMaterialPreviewPlugin::abort() {
-	preview_done.post();
+	draw_requester.abort();
 }
 
 bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
@@ -314,9 +304,7 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const Ref<Resource> &p_from
 	if (material->get_shader_mode() == Shader::MODE_SPATIAL) {
 		RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
 
-		RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT);
-
-		preview_done.wait();
+		draw_requester.request_and_wait(viewport);
 
 		Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
 		RS::get_singleton()->mesh_surface_set_material(sphere, 0, RID());
@@ -701,18 +689,8 @@ EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() {
 
 ///////////////////////////////////////////////////////////////////////////
 
-void EditorMeshPreviewPlugin::_generate_frame_started() {
-	RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
-
-	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_preview_done));
-}
-
-void EditorMeshPreviewPlugin::_preview_done() {
-	preview_done.post();
-}
-
 void EditorMeshPreviewPlugin::abort() {
-	preview_done.post();
+	draw_requester.abort();
 }
 
 bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
@@ -743,9 +721,7 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const Ref<Resource> &p_from, co
 	xform.origin.z -= rot_aabb.size.z * 2;
 	RS::get_singleton()->instance_set_transform(mesh_instance, xform);
 
-	RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT);
-
-	preview_done.wait();
+	draw_requester.request_and_wait(viewport);
 
 	Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
 	ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>());
@@ -822,18 +798,8 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
 
 ///////////////////////////////////////////////////////////////////////////
 
-void EditorFontPreviewPlugin::_generate_frame_started() {
-	RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
-
-	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_preview_done));
-}
-
-void EditorFontPreviewPlugin::_preview_done() {
-	preview_done.post();
-}
-
 void EditorFontPreviewPlugin::abort() {
-	preview_done.post();
+	draw_requester.abort();
 }
 
 bool EditorFontPreviewPlugin::handles(const String &p_type) const {
@@ -865,9 +831,7 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
 	const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0;
 	sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
 
-	RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT);
-
-	preview_done.wait();
+	draw_requester.request_and_wait(viewport);
 
 	RS::get_singleton()->canvas_item_clear(canvas_item);
 

+ 3 - 12
editor/plugins/editor_preview_plugins.h

@@ -96,10 +96,7 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
 	RID light_instance2;
 	RID camera;
 	RID camera_attributes;
-	Semaphore preview_done;
-
-	void _generate_frame_started();
-	void _preview_done();
+	DrawRequester draw_requester;
 
 public:
 	virtual bool handles(const String &p_type) const override;
@@ -147,10 +144,7 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
 	RID light_instance2;
 	RID camera;
 	RID camera_attributes;
-	Semaphore preview_done;
-
-	void _generate_frame_started();
-	void _preview_done();
+	DrawRequester draw_requester;
 
 public:
 	virtual bool handles(const String &p_type) const override;
@@ -168,10 +162,7 @@ class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator {
 	RID viewport_texture;
 	RID canvas;
 	RID canvas_item;
-	Semaphore preview_done;
-
-	void _generate_frame_started();
-	void _preview_done();
+	DrawRequester draw_requester;
 
 public:
 	virtual bool handles(const String &p_type) const override;