From 91f0a65fc90ef9550ad1c0d3fc857017a4f844d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Wed, 21 Feb 2024 10:44:21 +0100 Subject: [PATCH] Rework viewport capture in preview generation --- editor/editor_resource_preview.cpp | 31 ++++++++++++++- editor/editor_resource_preview.h | 11 ++++++ editor/plugins/editor_preview_plugins.cpp | 48 +++-------------------- editor/plugins/editor_preview_plugins.h | 15 ++----- 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index bae7887c0226..fc1dda9669d6 100644 --- a/editor/editor_resource_preview.cpp +++ b/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(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(); diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index bc99372bc23a..3cad56f75e88 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -51,6 +51,16 @@ class EditorResourcePreviewGenerator : public RefCounted { 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 generate(const Ref &p_from, const Size2 &p_size, Dictionary &p_metadata) const; @@ -132,6 +142,7 @@ class EditorResourcePreview : public Node { void start(); void stop(); + bool is_threaded() const; EditorResourcePreview(); ~EditorResourcePreview(); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index fbec9ca68f23..e8804fdf1241 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/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(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 EditorMaterialPreviewPlugin::generate(const Ref &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(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT); - - preview_done.wait(); + draw_requester.request_and_wait(viewport); Ref 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(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 EditorMeshPreviewPlugin::generate(const Ref &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(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT); - - preview_done.wait(); + draw_requester.request_and_wait(viewport); Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); ERR_FAIL_COND_V(img.is_null(), Ref()); @@ -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(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 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(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); diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index fa7015f42390..2b3da76a9d0b 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/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;