From 977ffe200e176f01f1fd956580ec775309478703 Mon Sep 17 00:00:00 2001 From: arkology <43543909+arkology@users.noreply.github.com> Date: Sat, 22 Mar 2025 18:35:23 +0300 Subject: [PATCH] TextureEditors: Compile shader/material only once --- editor/register_editor_types.cpp | 11 +++++++ .../texture/texture_3d_editor_plugin.cpp | 30 +++++++++-------- .../scene/texture/texture_3d_editor_plugin.h | 9 ++--- .../scene/texture/texture_editor_plugin.cpp | 33 +++++++++++-------- editor/scene/texture/texture_editor_plugin.h | 6 +++- .../texture/texture_layered_editor_plugin.cpp | 32 +++++++++++------- .../texture/texture_layered_editor_plugin.h | 7 ++-- 7 files changed, 81 insertions(+), 47 deletions(-) diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp index f3e1aa86980..ac16ca802b3 100644 --- a/editor/register_editor_types.cpp +++ b/editor/register_editor_types.cpp @@ -302,6 +302,13 @@ void register_editor_types() { ei_singleton.editor_only = true; Engine::get_singleton()->add_singleton(ei_singleton); + if (RenderingServer::get_singleton()) { + // RenderingServer needs to exist for this to succeed. + Texture3DEditor::init_shaders(); + TextureLayeredEditor::init_shaders(); + TexturePreview::init_shaders(); + } + // Required as GDExtensions can register docs at init time way before this // class is actually instantiated. EditorHelp::init_gdext_pointers(); @@ -312,6 +319,10 @@ void register_editor_types() { void unregister_editor_types() { OS::get_singleton()->benchmark_begin_measure("Editor", "Unregister Types"); + Texture3DEditor::finish_shaders(); + TextureLayeredEditor::finish_shaders(); + TexturePreview::finish_shaders(); + EditorNode::cleanup(); EditorInterface::free(); diff --git a/editor/scene/texture/texture_3d_editor_plugin.cpp b/editor/scene/texture/texture_3d_editor_plugin.cpp index f42037f2f58..174f643ba78 100644 --- a/editor/scene/texture/texture_3d_editor_plugin.cpp +++ b/editor/scene/texture/texture_3d_editor_plugin.cpp @@ -111,13 +111,13 @@ void Texture3DEditor::_texture_changed() { } void Texture3DEditor::_update_material(bool p_texture_changed) { - material->set_shader_parameter("layer", (layer->get_value() + 0.5) / texture->get_depth()); + texture_material->set_shader_parameter("layer", (layer->get_value() + 0.5) / texture->get_depth()); if (p_texture_changed) { - material->set_shader_parameter("tex", texture->get_rid()); + texture_material->set_shader_parameter("tex", texture->get_rid()); } - material->set_shader_parameter("u_channel_factors", channel_selector->get_selected_channel_factors()); + texture_material->set_shader_parameter("u_channel_factors", channel_selector->get_selected_channel_factors()); } void Texture3DEditor::_draw_outline() { @@ -126,14 +126,6 @@ void Texture3DEditor::_draw_outline() { draw_rect(outline_rect, theme_cache.outline_color, false, outline_width); } -void Texture3DEditor::_make_shaders() { - shader.instantiate(); - shader->set_code(texture_3d_shader); - - material.instantiate(); - material->set_shader(shader); -} - void Texture3DEditor::_texture_rect_update_area() { Size2 size = get_size(); int tex_width = texture->get_width() * size.height / texture->get_height(); @@ -208,6 +200,15 @@ void Texture3DEditor::on_selected_channels_changed() { _update_material(false); } +void Texture3DEditor::init_shaders() { + texture_shader.instantiate(); + texture_shader->set_code(texture_3d_shader); +} + +void Texture3DEditor::finish_shaders() { + texture_shader.unref(); +} + void Texture3DEditor::edit(Ref p_texture) { if (texture.is_valid()) { texture->disconnect_changed(callable_mp(this, &Texture3DEditor::_texture_changed)); @@ -216,12 +217,13 @@ void Texture3DEditor::edit(Ref p_texture) { texture = p_texture; if (texture.is_valid()) { - if (shader.is_null()) { - _make_shaders(); + if (texture_material.is_null()) { + texture_material.instantiate(); + texture_material->set_shader(texture_shader); } texture->connect_changed(callable_mp(this, &Texture3DEditor::_texture_changed)); - texture_rect->set_material(material); + texture_rect->set_material(texture_material); setting = true; layer->set_value(0); diff --git a/editor/scene/texture/texture_3d_editor_plugin.h b/editor/scene/texture/texture_3d_editor_plugin.h index 64fb3b1e09a..36e1cea3b2d 100644 --- a/editor/scene/texture/texture_3d_editor_plugin.h +++ b/editor/scene/texture/texture_3d_editor_plugin.h @@ -49,8 +49,8 @@ class Texture3DEditor : public Control { Label *info = nullptr; Ref texture; - Ref shader; - Ref material; + static inline Ref texture_shader; + Ref texture_material; Control *texture_rect = nullptr; @@ -60,8 +60,6 @@ class Texture3DEditor : public Control { void _draw_outline(); - void _make_shaders(); - void _layer_changed(double) { if (!setting) { _update_material(false); @@ -82,6 +80,9 @@ protected: void _notification(int p_what); public: + static void init_shaders(); + static void finish_shaders(); + void edit(Ref p_texture); Texture3DEditor(); diff --git a/editor/scene/texture/texture_editor_plugin.cpp b/editor/scene/texture/texture_editor_plugin.cpp index 27c73f6f157..d3087b0ed5f 100644 --- a/editor/scene/texture/texture_editor_plugin.cpp +++ b/editor/scene/texture/texture_editor_plugin.cpp @@ -44,11 +44,11 @@ #include "scene/resources/portable_compressed_texture.h" #include "scene/resources/style_box_flat.h" -constexpr const char *texture_2d_shader = R"( +constexpr const char *texture_2d_shader_code = R"( shader_type canvas_item; render_mode blend_mix; -uniform vec4 u_channel_factors = vec4(1.0); +instance uniform vec4 u_channel_factors = vec4(1.0); vec4 filter_preview_colors(vec4 input_color, vec4 factors) { // Filter RGB. @@ -73,6 +73,20 @@ void fragment() { } )"; +void TexturePreview::init_shaders() { + texture_material.instantiate(); + + Ref texture_shader; + texture_shader.instantiate(); + texture_shader->set_code(texture_2d_shader_code); + + texture_material->set_shader(texture_shader); +} + +void TexturePreview::finish_shaders() { + texture_material.unref(); +} + TextureRect *TexturePreview::get_texture_display() { return texture_display; } @@ -212,7 +226,7 @@ void TexturePreview::_update_metadata_label_text() { } void TexturePreview::on_selected_channels_changed() { - material->set_shader_parameter("u_channel_factors", channel_selector->get_selected_channel_factors()); + texture_display->set_instance_shader_parameter("u_channel_factors", channel_selector->get_selected_channel_factors()); } TexturePreview::TexturePreview(Ref p_texture, bool p_show_metadata) { @@ -239,21 +253,12 @@ TexturePreview::TexturePreview(Ref p_texture, bool p_show_metadata) { checkerboard->set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED); centering_container->add_child(checkerboard); - { - Ref shader; - shader.instantiate(); - shader->set_code(texture_2d_shader); - - material.instantiate(); - material->set_shader(shader); - material->set_shader_parameter("u_channel_factors", Vector4(1, 1, 1, 1)); - } - texture_display = memnew(TextureRect); texture_display->set_texture_filter(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); texture_display->set_texture(p_texture); texture_display->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE); - texture_display->set_material(material); + texture_display->set_material(texture_material); + texture_display->set_instance_shader_parameter("u_channel_factors", Vector4(1, 1, 1, 1)); centering_container->add_child(texture_display); // Creating a separate control so it is not affected by the filtering shader. diff --git a/editor/scene/texture/texture_editor_plugin.h b/editor/scene/texture/texture_editor_plugin.h index be043dc5357..d66aa46a70e 100644 --- a/editor/scene/texture/texture_editor_plugin.h +++ b/editor/scene/texture/texture_editor_plugin.h @@ -57,7 +57,8 @@ private: ColorRect *bg_rect = nullptr; TextureRect *checkerboard = nullptr; Label *metadata_label = nullptr; - Ref material; + + static inline Ref texture_material; ColorChannelSelector *channel_selector = nullptr; @@ -71,6 +72,9 @@ protected: void on_selected_channels_changed(); public: + static void init_shaders(); + static void finish_shaders(); + TextureRect *get_texture_display(); TexturePreview(Ref p_texture, bool p_show_metadata); }; diff --git a/editor/scene/texture/texture_layered_editor_plugin.cpp b/editor/scene/texture/texture_layered_editor_plugin.cpp index 98adcc3d6ef..adb42513b9c 100644 --- a/editor/scene/texture/texture_layered_editor_plugin.cpp +++ b/editor/scene/texture/texture_layered_editor_plugin.cpp @@ -302,16 +302,7 @@ void TextureLayeredEditor::_draw_outline() { draw_rect(outline_rect, theme_cache.outline_color, false, outline_width); } -void TextureLayeredEditor::_make_shaders() { - shaders[0].instantiate(); - shaders[0]->set_code(array_2d_shader); - - shaders[1].instantiate(); - shaders[1]->set_code(cubemap_shader); - - shaders[2].instantiate(); - shaders[2]->set_code(cubemap_array_shader); - +void TextureLayeredEditor::_make_materials() { for (int i = 0; i < 3; i++) { materials[i].instantiate(); materials[i]->set_shader(shaders[i]); @@ -343,6 +334,23 @@ void TextureLayeredEditor::_texture_rect_update_area() { texture_rect->set_size(Vector2(tex_width, tex_height)); } +void TextureLayeredEditor::init_shaders() { + shaders[0].instantiate(); + shaders[0]->set_code(array_2d_shader); + + shaders[1].instantiate(); + shaders[1]->set_code(cubemap_shader); + + shaders[2].instantiate(); + shaders[2]->set_code(cubemap_array_shader); +} + +void TextureLayeredEditor::finish_shaders() { + shaders[0].unref(); + shaders[1].unref(); + shaders[2].unref(); +} + void TextureLayeredEditor::edit(Ref p_texture) { if (texture.is_valid()) { texture->disconnect_changed(callable_mp(this, &TextureLayeredEditor::_texture_changed)); @@ -351,8 +359,8 @@ void TextureLayeredEditor::edit(Ref p_texture) { texture = p_texture; if (texture.is_valid()) { - if (shaders[0].is_null()) { - _make_shaders(); + if (materials[0].is_null()) { + _make_materials(); } texture->connect_changed(callable_mp(this, &TextureLayeredEditor::_texture_changed)); diff --git a/editor/scene/texture/texture_layered_editor_plugin.h b/editor/scene/texture/texture_layered_editor_plugin.h index 900c2ab9b03..977bff7ba5f 100644 --- a/editor/scene/texture/texture_layered_editor_plugin.h +++ b/editor/scene/texture/texture_layered_editor_plugin.h @@ -49,7 +49,7 @@ class TextureLayeredEditor : public Control { Label *info = nullptr; Ref texture; - Ref shaders[3]; + static inline Ref shaders[3]; Ref materials[3]; float x_rot = 0; @@ -62,7 +62,7 @@ class TextureLayeredEditor : public Control { void _draw_outline(); - void _make_shaders(); + void _make_materials(); void _update_material(bool p_texture_changed); void _layer_changed(double) { @@ -85,6 +85,9 @@ protected: virtual void gui_input(const Ref &p_event) override; public: + static void init_shaders(); + static void finish_shaders(); + void edit(Ref p_texture); TextureLayeredEditor();