diff options
Diffstat (limited to 'servers')
133 files changed, 13462 insertions, 10708 deletions
diff --git a/servers/SCsub b/servers/SCsub index 2cd4741d56..66a1b9b26f 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -13,6 +13,7 @@ SConscript("rendering/SCsub") SConscript("audio/SCsub") SConscript("text/SCsub") SConscript("debugger/SCsub") +SConscript("extensions/SCsub") lib = env.add_library("servers", env.servers_sources) diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 1ba0afd8a1..635e4601c7 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -54,7 +54,7 @@ Error AudioDriverDummy::init() { }; void AudioDriverDummy::thread_func(void *p_udata) { - AudioDriverDummy *ad = (AudioDriverDummy *)p_udata; + AudioDriverDummy *ad = static_cast<AudioDriverDummy *>(p_udata); uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000; diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 6324e2f5d3..68b523e086 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -40,7 +40,7 @@ class AudioDriverDummy : public AudioDriver { Thread thread; Mutex mutex; - int32_t *samples_in; + int32_t *samples_in = nullptr; static void thread_func(void *p_udata); diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h index 9e55662d0a..1ec1abd4d5 100644 --- a/servers/audio/audio_filter_sw.h +++ b/servers/audio/audio_filter_sw.h @@ -57,7 +57,7 @@ public: class Processor { // simple filter processor - AudioFilterSW *filter; + AudioFilterSW *filter = nullptr; Coeffs coeffs; float ha1, ha2, hb1, hb2; //history Coeffs incr_coeffs; diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h index 3fbe684c3e..81ac6332e2 100644 --- a/servers/audio/audio_rb_resampler.h +++ b/servers/audio/audio_rb_resampler.h @@ -55,8 +55,8 @@ struct AudioRBResampler { MIX_FRAC_MASK = MIX_FRAC_LEN - 1, }; - float *read_buf; - float *rb; + float *read_buf = nullptr; + float *rb = nullptr; template <int C> uint32_t _resample(AudioFrame *p_dest, int p_todo, int32_t p_increment); diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp index a5866bb380..d68522e5b9 100644 --- a/servers/audio/effects/audio_effect_record.cpp +++ b/servers/audio/effects/audio_effect_record.cpp @@ -30,6 +30,11 @@ #include "audio_effect_record.h" +#ifdef TOOLS_ENABLED +// FIXME: This file shouldn't depend on editor stuff. +#include "editor/import/resource_importer_wav.h" +#endif + void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { if (!is_recording) { for (int i = 0; i < p_frame_count; i++) { @@ -57,7 +62,7 @@ void AudioEffectRecordInstance::_update_buffer() { } void AudioEffectRecordInstance::_update(void *userdata) { - AudioEffectRecordInstance *ins = (AudioEffectRecordInstance *)userdata; + AudioEffectRecordInstance *ins = static_cast<AudioEffectRecordInstance *>(userdata); ins->_update_buffer(); } @@ -250,8 +255,12 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { Vector<uint8_t> bleft; Vector<uint8_t> bright; +#ifdef TOOLS_ENABLED ResourceImporterWAV::_compress_ima_adpcm(left, bleft); ResourceImporterWAV::_compress_ima_adpcm(right, bright); +#else + ERR_PRINT("AudioEffectRecord cannot do IMA ADPCM compression at runtime."); +#endif int dl = bleft.size(); dst_data.resize(dl * 2); diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h index 18b5d4d83c..305484d1cb 100644 --- a/servers/audio/effects/audio_effect_record.h +++ b/servers/audio/effects/audio_effect_record.h @@ -35,7 +35,6 @@ #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/os/thread.h" -#include "editor/import/resource_importer_wav.h" #include "scene/resources/audio_stream_sample.h" #include "servers/audio/audio_effect.h" #include "servers/audio_server.h" diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h index 8b8b7b47a0..1f93d1cf9f 100644 --- a/servers/audio/effects/audio_effect_stereo_enhance.h +++ b/servers/audio/effects/audio_effect_stereo_enhance.h @@ -44,7 +44,7 @@ class AudioEffectStereoEnhanceInstance : public AudioEffectInstance { MAX_DELAY_MS = 50 }; - float *delay_ringbuff; + float *delay_ringbuff = nullptr; unsigned int ringbuff_pos; unsigned int ringbuff_mask; diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h index 51288262b3..2ce4b95fcf 100644 --- a/servers/audio/effects/audio_stream_generator.h +++ b/servers/audio/effects/audio_stream_generator.h @@ -65,7 +65,7 @@ class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled { int skips; bool active; float mixed; - AudioStreamGenerator *generator; + AudioStreamGenerator *generator = nullptr; protected: virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override; diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h index ff59ab8d82..de25e8c52b 100644 --- a/servers/audio/effects/reverb.h +++ b/servers/audio/effects/reverb.h @@ -75,7 +75,7 @@ private: Comb comb[MAX_COMBS]; AllPass allpass[MAX_ALLPASS]; - float *input_buffer; + float *input_buffer = nullptr; float *echo_buffer = nullptr; int echo_buffer_size; int echo_buffer_pos; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 9d83e5cacc..777bebcf60 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1343,6 +1343,7 @@ void AudioServer::init_channels_and_buffers() { for (int j = 0; j < channel_count; j++) { buses.write[i]->channels.write[j].buffer.resize(buffer_size); } + _update_bus_effects(i); } } diff --git a/servers/audio_server.h b/servers/audio_server.h index 0c150427f2..5563d60e4a 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -284,7 +284,7 @@ private: struct CallbackItem { AudioCallback callback; - void *userdata; + void *userdata = nullptr; }; SafeList<CallbackItem *> update_callback_list; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 819c151087..67bfc75426 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -44,22 +44,52 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa int DisplayServer::server_create_count = 1; -void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) { +void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); } -void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) { +void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); } -void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu) { +void DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); } -void DisplayServer::global_menu_add_separator(const String &p_menu_root) { +void DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { + WARN_PRINT("Global menus not supported by this display server."); +} + +int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const { + WARN_PRINT("Global menus not supported by this display server."); + return -1; +} + +int DisplayServer::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const { + WARN_PRINT("Global menus not supported by this display server."); + return -1; +} + void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) { WARN_PRINT("Global menus not supported by this display server."); } @@ -74,26 +104,61 @@ bool DisplayServer::global_menu_is_item_checkable(const String &p_menu_root, int return false; } -Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, int p_idx) { +bool DisplayServer::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return false; +} + +Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const { WARN_PRINT("Global menus not supported by this display server."); return Callable(); } -Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) { +Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const { WARN_PRINT("Global menus not supported by this display server."); return Variant(); } -String DisplayServer::global_menu_get_item_text(const String &p_menu_root, int p_idx) { +String DisplayServer::global_menu_get_item_text(const String &p_menu_root, int p_idx) const { WARN_PRINT("Global menus not supported by this display server."); return String(); } -String DisplayServer::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) { +String DisplayServer::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const { WARN_PRINT("Global menus not supported by this display server."); return String(); } +Key DisplayServer::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return Key::NONE; +} + +bool DisplayServer::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return false; +} + +String DisplayServer::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return String(); +} + +int DisplayServer::global_menu_get_item_state(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return -1; +} + +int DisplayServer::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return -1; +} + +Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return Ref<Texture2D>(); +} + void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { WARN_PRINT("Global menus not supported by this display server."); } @@ -102,6 +167,10 @@ void DisplayServer::global_menu_set_item_checkable(const String &p_menu_root, in WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { + WARN_PRINT("Global menus not supported by this display server."); +} + void DisplayServer::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) { WARN_PRINT("Global menus not supported by this display server."); } @@ -114,6 +183,30 @@ void DisplayServer::global_menu_set_item_submenu(const String &p_menu_root, int WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) { + WARN_PRINT("Global menus not supported by this display server."); +} + int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const { WARN_PRINT("Global menus not supported by this display server."); return 0; @@ -135,7 +228,7 @@ DisplayServer::MouseMode DisplayServer::mouse_get_mode() const { return MOUSE_MODE_VISIBLE; } -void DisplayServer::mouse_warp_to_position(const Point2i &p_to) { +void DisplayServer::warp_mouse(const Point2i &p_position) { WARN_PRINT("Mouse warping is not supported by this display server."); } @@ -341,24 +434,46 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature); ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name); - ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag"), &DisplayServer::global_menu_add_item, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag"), &DisplayServer::global_menu_add_check_item, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu"), &DisplayServer::global_menu_add_submenu_item); - ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root"), &DisplayServer::global_menu_add_separator); + ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_icon_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_icon_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_radio_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_radio_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_icon_radio_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_radio_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_multistate_item", "menu_root", "labe", "max_states", "default_state", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu", "index"), &DisplayServer::global_menu_add_submenu_item, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root", "index"), &DisplayServer::global_menu_add_separator, DEFVAL(-1)); + + ClassDB::bind_method(D_METHOD("global_menu_get_item_index_from_text", "menu_root", "text"), &DisplayServer::global_menu_get_item_index_from_text); + ClassDB::bind_method(D_METHOD("global_menu_get_item_index_from_tag", "menu_root", "tag"), &DisplayServer::global_menu_get_item_index_from_tag); ClassDB::bind_method(D_METHOD("global_menu_is_item_checked", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checked); ClassDB::bind_method(D_METHOD("global_menu_is_item_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checkable); + ClassDB::bind_method(D_METHOD("global_menu_is_item_radio_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_radio_checkable); ClassDB::bind_method(D_METHOD("global_menu_get_item_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_callback); ClassDB::bind_method(D_METHOD("global_menu_get_item_tag", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tag); ClassDB::bind_method(D_METHOD("global_menu_get_item_text", "menu_root", "idx"), &DisplayServer::global_menu_get_item_text); ClassDB::bind_method(D_METHOD("global_menu_get_item_submenu", "menu_root", "idx"), &DisplayServer::global_menu_get_item_submenu); + ClassDB::bind_method(D_METHOD("global_menu_get_item_accelerator", "menu_root", "idx"), &DisplayServer::global_menu_get_item_accelerator); + ClassDB::bind_method(D_METHOD("global_menu_is_item_disabled", "menu_root", "idx"), &DisplayServer::global_menu_is_item_disabled); + ClassDB::bind_method(D_METHOD("global_menu_get_item_tooltip", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tooltip); + ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state); + ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states); + ClassDB::bind_method(D_METHOD("global_menu_get_item_icon", "menu_root", "idx"), &DisplayServer::global_menu_get_item_icon); ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked); ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable); + ClassDB::bind_method(D_METHOD("global_menu_set_item_radio_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_radio_checkable); ClassDB::bind_method(D_METHOD("global_menu_set_item_callback", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_callback); ClassDB::bind_method(D_METHOD("global_menu_set_item_tag", "menu_root", "idx", "tag"), &DisplayServer::global_menu_set_item_tag); ClassDB::bind_method(D_METHOD("global_menu_set_item_text", "menu_root", "idx", "text"), &DisplayServer::global_menu_set_item_text); ClassDB::bind_method(D_METHOD("global_menu_set_item_submenu", "menu_root", "idx", "submenu"), &DisplayServer::global_menu_set_item_submenu); + ClassDB::bind_method(D_METHOD("global_menu_set_item_accelerator", "menu_root", "idx", "keycode"), &DisplayServer::global_menu_set_item_accelerator); + ClassDB::bind_method(D_METHOD("global_menu_set_item_disabled", "menu_root", "idx", "disabled"), &DisplayServer::global_menu_set_item_disabled); + ClassDB::bind_method(D_METHOD("global_menu_set_item_tooltip", "menu_root", "idx", "tooltip"), &DisplayServer::global_menu_set_item_tooltip); + ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state); + ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states); + ClassDB::bind_method(D_METHOD("global_menu_set_item_icon", "menu_root", "idx", "icon"), &DisplayServer::global_menu_set_item_icon); ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item); ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear); @@ -366,7 +481,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode); ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode); - ClassDB::bind_method(D_METHOD("mouse_warp_to_position", "position"), &DisplayServer::mouse_warp_to_position); + ClassDB::bind_method(D_METHOD("warp_mouse", "position"), &DisplayServer::warp_mouse); ClassDB::bind_method(D_METHOD("mouse_get_position"), &DisplayServer::mouse_get_position); ClassDB::bind_method(D_METHOD("mouse_get_button_state"), &DisplayServer::mouse_get_button_state); @@ -614,7 +729,7 @@ Input::MouseMode DisplayServer::_input_get_mouse_mode() { } void DisplayServer::_input_warp(const Vector2 &p_to_pos) { - singleton->mouse_warp_to_position(p_to_pos); + singleton->warp_mouse(p_to_pos); } Input::CursorShape DisplayServer::_input_get_current_cursor_shape() { diff --git a/servers/display_server.h b/servers/display_server.h index 67dbab0924..4961b07ba3 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -126,24 +126,46 @@ public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; - virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()); - virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()); - virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu); - virtual void global_menu_add_separator(const String &p_menu_root); + virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); + virtual void global_menu_add_separator(const String &p_menu_root, int p_index = -1); + + virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const; + virtual int global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const; virtual bool global_menu_is_item_checked(const String &p_menu_root, int p_idx) const; virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const; - virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx); - virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx); - virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx); - virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx); + virtual bool global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const; + virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx) const; + virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx) const; + virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx) const; + virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const; + virtual Key global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const; + virtual bool global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const; + virtual String global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const; + virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const; + virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const; + virtual Ref<Texture2D> global_menu_get_item_icon(const String &p_menu_root, int p_idx) const; virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked); virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); + virtual void global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable); virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback); virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag); virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text); virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu); + virtual void global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode); + virtual void global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled); + virtual void global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip); + virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state); + virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states); + virtual void global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon); virtual int global_menu_get_item_count(const String &p_menu_root) const; @@ -161,7 +183,7 @@ public: virtual void mouse_set_mode(MouseMode p_mode); virtual MouseMode mouse_get_mode() const; - virtual void mouse_warp_to_position(const Point2i &p_to); + virtual void warp_mouse(const Point2i &p_position); virtual Point2i mouse_get_position() const; virtual MouseButton mouse_get_button_state() const; diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index f74a8fad23..3853ff4fdc 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -33,7 +33,7 @@ #include "servers/display_server.h" -#include "servers/rendering/rasterizer_dummy.h" +#include "servers/rendering/dummy/rasterizer_dummy.h" class DisplayServerHeadless : public DisplayServer { private: diff --git a/servers/extensions/SCsub b/servers/extensions/SCsub new file mode 100644 index 0000000000..ba73353f2a --- /dev/null +++ b/servers/extensions/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_object = env.Clone() + +env_object.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp new file mode 100644 index 0000000000..b2a9273538 --- /dev/null +++ b/servers/extensions/physics_server_3d_extension.cpp @@ -0,0 +1,322 @@ +/*************************************************************************/ +/* physics_server_3d_extension.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_3d_extension.h" + +bool PhysicsDirectSpaceState3DExtension::is_body_excluded_from_query(const RID &p_body) const { + return exclude && exclude->has(p_body); +} + +thread_local const Set<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr; + +void PhysicsDirectSpaceState3DExtension::_bind_methods() { + GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "hit_back_faces", "result"); + GDVIRTUAL_BIND(_intersect_point, "position", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results"); + GDVIRTUAL_BIND(_intersect_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "result_count", "max_results"); + GDVIRTUAL_BIND(_cast_motion, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "closest_safe", "closest_unsafe", "info"); + GDVIRTUAL_BIND(_collide_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results", "result_count"); + GDVIRTUAL_BIND(_rest_info, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "rest_info"); + GDVIRTUAL_BIND(_get_closest_point_to_object_volume, "object", "point"); +} + +PhysicsDirectSpaceState3DExtension::PhysicsDirectSpaceState3DExtension() { +} + +void PhysicsDirectBodyState3DExtension::_bind_methods() { + GDVIRTUAL_BIND(_get_total_gravity); + GDVIRTUAL_BIND(_get_total_linear_damp); + GDVIRTUAL_BIND(_get_total_angular_damp); + + GDVIRTUAL_BIND(_get_center_of_mass); + GDVIRTUAL_BIND(_get_center_of_mass_local); + GDVIRTUAL_BIND(_get_principal_inertia_axes); + + GDVIRTUAL_BIND(_get_inverse_mass); + GDVIRTUAL_BIND(_get_inverse_inertia); + + GDVIRTUAL_BIND(_set_linear_velocity, "velocity"); + GDVIRTUAL_BIND(_get_linear_velocity); + + GDVIRTUAL_BIND(_set_angular_velocity, "velocity"); + GDVIRTUAL_BIND(_get_angular_velocity); + + GDVIRTUAL_BIND(_set_transform, "transform"); + GDVIRTUAL_BIND(_get_transform); + + GDVIRTUAL_BIND(_get_velocity_at_local_position, "local_position"); + + GDVIRTUAL_BIND(_apply_central_impulse, "impulse"); + GDVIRTUAL_BIND(_apply_impulse, "impulse", "position"); + GDVIRTUAL_BIND(_apply_torque_impulse, "impulse"); + + GDVIRTUAL_BIND(_apply_central_force, "force"); + GDVIRTUAL_BIND(_apply_force, "force", "position"); + GDVIRTUAL_BIND(_apply_torque, "torque"); + + GDVIRTUAL_BIND(_add_constant_central_force, "force"); + GDVIRTUAL_BIND(_add_constant_force, "force", "position"); + GDVIRTUAL_BIND(_add_constant_torque, "torque"); + + GDVIRTUAL_BIND(_set_constant_force, "force"); + GDVIRTUAL_BIND(_get_constant_force); + + GDVIRTUAL_BIND(_set_constant_torque, "torque"); + GDVIRTUAL_BIND(_get_constant_torque); + + GDVIRTUAL_BIND(_set_sleep_state, "enabled"); + GDVIRTUAL_BIND(_is_sleeping); + + GDVIRTUAL_BIND(_get_contact_count); + + GDVIRTUAL_BIND(_get_contact_local_position, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_local_normal, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_impulse, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_local_shape, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_position, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_id, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_object, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_shape, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_velocity_at_position, "contact_idx"); + GDVIRTUAL_BIND(_get_step); + GDVIRTUAL_BIND(_integrate_forces); + GDVIRTUAL_BIND(_get_space_state); +} + +PhysicsDirectBodyState3DExtension::PhysicsDirectBodyState3DExtension() { +} + +thread_local const Set<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr; +thread_local const Set<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr; + +bool PhysicsServer3DExtension::body_test_motion_is_excluding_body(RID p_body) const { + return exclude_bodies && exclude_bodies->has(p_body); +} + +bool PhysicsServer3DExtension::body_test_motion_is_excluding_object(ObjectID p_object) const { + return exclude_objects && exclude_objects->has(p_object); +} + +void PhysicsServer3DExtension::_bind_methods() { + GDVIRTUAL_BIND(_world_boundary_shape_create); + GDVIRTUAL_BIND(_separation_ray_shape_create); + GDVIRTUAL_BIND(_sphere_shape_create); + GDVIRTUAL_BIND(_box_shape_create); + GDVIRTUAL_BIND(_capsule_shape_create); + GDVIRTUAL_BIND(_cylinder_shape_create); + GDVIRTUAL_BIND(_convex_polygon_shape_create); + GDVIRTUAL_BIND(_concave_polygon_shape_create); + GDVIRTUAL_BIND(_heightmap_shape_create); + GDVIRTUAL_BIND(_custom_shape_create); + + GDVIRTUAL_BIND(_shape_set_data, "shape", "data"); + + GDVIRTUAL_BIND(_shape_get_type, "shape"); + GDVIRTUAL_BIND(_shape_get_data, "shape"); + + GDVIRTUAL_BIND(_space_create); + GDVIRTUAL_BIND(_space_set_active, "space", "active"); + GDVIRTUAL_BIND(_space_is_active, "space"); + GDVIRTUAL_BIND(_space_set_param, "space", "param", "value"); + GDVIRTUAL_BIND(_space_get_param, "space", "param"); + GDVIRTUAL_BIND(_space_get_direct_state, "space"); + + GDVIRTUAL_BIND(_area_create); + GDVIRTUAL_BIND(_area_set_space, "area", "space"); + GDVIRTUAL_BIND(_area_get_space, "area"); + + GDVIRTUAL_BIND(_area_add_shape, "area", "shape", "transform", "disabled"); + GDVIRTUAL_BIND(_area_set_shape, "area", "shape_idx", "shape"); + GDVIRTUAL_BIND(_area_set_shape_transform, "area", "shape_idx", "transform"); + GDVIRTUAL_BIND(_area_set_shape_disabled, "area", "shape_idx", "disabled"); + + GDVIRTUAL_BIND(_area_get_shape_count, "area"); + GDVIRTUAL_BIND(_area_get_shape, "area", "shape_idx"); + GDVIRTUAL_BIND(_area_get_shape_transform, "area", "shape_idx"); + + GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx"); + GDVIRTUAL_BIND(_area_clear_shapes, "area"); + + GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer"); + GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask"); + + GDVIRTUAL_BIND(_area_set_param, "area", "param", "value"); + GDVIRTUAL_BIND(_area_set_transform, "area", "transform"); + + GDVIRTUAL_BIND(_area_get_param, "area", "param"); + GDVIRTUAL_BIND(_area_get_transform, "area"); + + GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id"); + GDVIRTUAL_BIND(_area_get_object_instance_id, "area"); + + GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback"); + GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback"); + GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable"); + + GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable"); + + GDVIRTUAL_BIND(_body_create); + + GDVIRTUAL_BIND(_body_set_space, "body", "space"); + GDVIRTUAL_BIND(_body_get_space, "body"); + + GDVIRTUAL_BIND(_body_set_mode, "body", "mode"); + GDVIRTUAL_BIND(_body_get_mode, "body"); + + GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer"); + GDVIRTUAL_BIND(_body_get_collision_layer, "body"); + + GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask"); + GDVIRTUAL_BIND(_body_get_collision_mask, "body"); + + GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled"); + GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape"); + GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform"); + GDVIRTUAL_BIND(_body_set_shape_disabled, "body", "shape_idx", "disabled"); + + GDVIRTUAL_BIND(_body_get_shape_count, "body"); + GDVIRTUAL_BIND(_body_get_shape, "body", "shape_idx"); + GDVIRTUAL_BIND(_body_get_shape_transform, "body", "shape_idx"); + + GDVIRTUAL_BIND(_body_remove_shape, "body", "shape_idx"); + GDVIRTUAL_BIND(_body_clear_shapes, "body"); + + GDVIRTUAL_BIND(_body_attach_object_instance_id, "body", "id"); + GDVIRTUAL_BIND(_body_get_object_instance_id, "body"); + + GDVIRTUAL_BIND(_body_set_enable_continuous_collision_detection, "body", "enable"); + GDVIRTUAL_BIND(_body_is_continuous_collision_detection_enabled, "body"); + + GDVIRTUAL_BIND(_body_set_param, "body", "param", "value"); + GDVIRTUAL_BIND(_body_get_param, "body", "param"); + + GDVIRTUAL_BIND(_body_reset_mass_properties, "body"); + + GDVIRTUAL_BIND(_body_set_state, "body", "state", "value"); + GDVIRTUAL_BIND(_body_get_state, "body", "state"); + + GDVIRTUAL_BIND(_body_apply_central_impulse, "body", "impulse"); + GDVIRTUAL_BIND(_body_apply_impulse, "body", "impulse", "position"); + GDVIRTUAL_BIND(_body_apply_torque_impulse, "body", "impulse"); + + GDVIRTUAL_BIND(_body_apply_central_force, "body", "force"); + GDVIRTUAL_BIND(_body_apply_force, "body", "force", "position"); + GDVIRTUAL_BIND(_body_apply_torque, "body", "torque"); + + GDVIRTUAL_BIND(_body_add_constant_central_force, "body", "force"); + GDVIRTUAL_BIND(_body_add_constant_force, "body", "force", "position"); + GDVIRTUAL_BIND(_body_add_constant_torque, "body", "torque"); + + GDVIRTUAL_BIND(_body_set_constant_force, "body", "force"); + GDVIRTUAL_BIND(_body_get_constant_force, "body"); + + GDVIRTUAL_BIND(_body_set_constant_torque, "body", "torque"); + GDVIRTUAL_BIND(_body_get_constant_torque, "body"); + + GDVIRTUAL_BIND(_body_set_axis_velocity, "body", "axis_velocity"); + + GDVIRTUAL_BIND(_body_set_axis_lock, "body", "axis", "lock"); + GDVIRTUAL_BIND(_body_is_axis_locked, "body", "axis"); + + GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body"); + GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body"); + + GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount"); + GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body"); + + GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable"); + GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body"); + + GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata"); + + GDVIRTUAL_BIND(_body_set_ray_pickable, "body", "enable"); + + GDVIRTUAL_BIND(_body_test_motion, "body", "from", "motion", "margin", "max_collisions", "collide_separation_ray", "result"); + + GDVIRTUAL_BIND(_body_get_direct_state, "body"); + + GDVIRTUAL_BIND(_soft_body_get_bounds, "body"); + + GDVIRTUAL_BIND(_joint_create); + GDVIRTUAL_BIND(_joint_clear, "joint"); + + GDVIRTUAL_BIND(_joint_make_pin, "joint", "body_A", "local_A", "body_B", "local_B"); + GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_pin_joint_set_local_a, "joint", "local_A"); + GDVIRTUAL_BIND(_pin_joint_get_local_a, "joint"); + + GDVIRTUAL_BIND(_pin_joint_set_local_b, "joint", "local_B"); + GDVIRTUAL_BIND(_pin_joint_get_local_b, "joint"); + + GDVIRTUAL_BIND(_joint_make_hinge, "joint", "body_A", "hinge_A", "body_B", "hinge_B"); + + GDVIRTUAL_BIND(_hinge_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_hinge_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_hinge_joint_set_flag, "joint", "flag", "enabled"); + GDVIRTUAL_BIND(_hinge_joint_get_flag, "joint", "flag"); + + GDVIRTUAL_BIND(_joint_make_slider, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); + + GDVIRTUAL_BIND(_slider_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_slider_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_joint_make_cone_twist, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); + + GDVIRTUAL_BIND(_cone_twist_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_cone_twist_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_joint_get_type, "joint"); + + GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority"); + GDVIRTUAL_BIND(_joint_get_solver_priority, "joint"); + + GDVIRTUAL_BIND(_joint_make_generic_6dof, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); + + GDVIRTUAL_BIND(_generic_6dof_joint_set_param, "joint", "axis", "param", "value"); + GDVIRTUAL_BIND(_generic_6dof_joint_get_param, "joint", "axis", "param"); + + GDVIRTUAL_BIND(_generic_6dof_joint_set_flag, "joint", "axis", "flag", "enable"); + GDVIRTUAL_BIND(_generic_6dof_joint_get_flag, "joint", "axis", "flag"); + + GDVIRTUAL_BIND(_free_rid, "rid"); + + GDVIRTUAL_BIND(_set_active, "active"); + + GDVIRTUAL_BIND(_get_process_info, "process_info"); +} + +PhysicsServer3DExtension::PhysicsServer3DExtension() { +} + +PhysicsServer3DExtension::~PhysicsServer3DExtension() { +} diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h new file mode 100644 index 0000000000..ce6bed41c9 --- /dev/null +++ b/servers/extensions/physics_server_3d_extension.h @@ -0,0 +1,548 @@ +/*************************************************************************/ +/* physics_server_3d_extension.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_SERVER_3D_EXTENSION_H +#define PHYSICS_SERVER_3D_EXTENSION_H + +#include "core/extension/ext_wrappers.gen.inc" +#include "core/object/script_language.h" +#include "core/variant/native_ptr.h" +#include "core/variant/type_info.h" +#include "core/variant/typed_array.h" +#include "servers/physics_server_3d.h" + +class PhysicsDirectBodyState3DExtension : public PhysicsDirectBodyState3D { + GDCLASS(PhysicsDirectBodyState3DExtension, PhysicsDirectBodyState3D); + +protected: + static void _bind_methods(); + +public: + // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. + + EXBIND0RC(Vector3, get_total_gravity) + EXBIND0RC(real_t, get_total_angular_damp) + EXBIND0RC(real_t, get_total_linear_damp) + + EXBIND0RC(Vector3, get_center_of_mass) + EXBIND0RC(Vector3, get_center_of_mass_local) + EXBIND0RC(Basis, get_principal_inertia_axes) + EXBIND0RC(real_t, get_inverse_mass) + EXBIND0RC(Vector3, get_inverse_inertia) + EXBIND0RC(Basis, get_inverse_inertia_tensor) + + EXBIND1(set_linear_velocity, const Vector3 &) + EXBIND0RC(Vector3, get_linear_velocity) + + EXBIND1(set_angular_velocity, const Vector3 &) + EXBIND0RC(Vector3, get_angular_velocity) + + EXBIND1(set_transform, const Transform3D &) + EXBIND0RC(Transform3D, get_transform) + + EXBIND1RC(Vector3, get_velocity_at_local_position, const Vector3 &) + + EXBIND1(apply_central_impulse, const Vector3 &) + EXBIND2(apply_impulse, const Vector3 &, const Vector3 &) + EXBIND1(apply_torque_impulse, const Vector3 &) + + EXBIND1(apply_central_force, const Vector3 &) + EXBIND2(apply_force, const Vector3 &, const Vector3 &) + EXBIND1(apply_torque, const Vector3 &) + + EXBIND1(add_constant_central_force, const Vector3 &) + EXBIND2(add_constant_force, const Vector3 &, const Vector3 &) + EXBIND1(add_constant_torque, const Vector3 &) + + EXBIND1(set_constant_force, const Vector3 &) + EXBIND0RC(Vector3, get_constant_force) + + EXBIND1(set_constant_torque, const Vector3 &) + EXBIND0RC(Vector3, get_constant_torque) + + EXBIND1(set_sleep_state, bool) + EXBIND0RC(bool, is_sleeping) + + EXBIND0RC(int, get_contact_count) + + EXBIND1RC(Vector3, get_contact_local_position, int) + EXBIND1RC(Vector3, get_contact_local_normal, int) + EXBIND1RC(real_t, get_contact_impulse, int) + EXBIND1RC(int, get_contact_local_shape, int) + EXBIND1RC(RID, get_contact_collider, int) + EXBIND1RC(Vector3, get_contact_collider_position, int) + EXBIND1RC(ObjectID, get_contact_collider_id, int) + EXBIND1RC(Object *, get_contact_collider_object, int) + EXBIND1RC(int, get_contact_collider_shape, int) + EXBIND1RC(Vector3, get_contact_collider_velocity_at_position, int) + + EXBIND0RC(real_t, get_step) + + EXBIND0(integrate_forces) + EXBIND0R(PhysicsDirectSpaceState3D *, get_space_state) + + PhysicsDirectBodyState3DExtension(); +}; + +typedef PhysicsDirectSpaceState3D::RayResult PhysicsServer3DExtensionRayResult; +typedef PhysicsDirectSpaceState3D::ShapeResult PhysicsServer3DExtensionShapeResult; +typedef PhysicsDirectSpaceState3D::ShapeRestInfo PhysicsServer3DExtensionShapeRestInfo; + +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionRayResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeRestInfo) + +class PhysicsDirectSpaceState3DExtension : public PhysicsDirectSpaceState3D { + GDCLASS(PhysicsDirectSpaceState3DExtension, PhysicsDirectSpaceState3D); + + thread_local static const Set<RID> *exclude; + +protected: + static void _bind_methods(); + bool is_body_excluded_from_query(const RID &p_body) const; + + GDVIRTUAL8R(bool, _intersect_ray, const Vector3 &, const Vector3 &, uint32_t, bool, bool, bool, bool, GDNativePtr<PhysicsServer3DExtensionRayResult>) + GDVIRTUAL6R(int, _intersect_point, const Vector3 &, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int) + GDVIRTUAL9R(int, _intersect_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int) + GDVIRTUAL10R(bool, _cast_motion, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>) + GDVIRTUAL10R(bool, _collide_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector3>, int, GDNativePtr<int>) + GDVIRTUAL8R(bool, _rest_info, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>) + GDVIRTUAL2RC(Vector3, _get_closest_point_to_object_volume, RID, const Vector3 &) + +public: + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_intersect_ray, p_parameters.from, p_parameters.to, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, p_parameters.hit_from_inside, p_parameters.hit_back_faces, &r_result, ret); + exclude = nullptr; + return ret; + } + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { + exclude = &p_parameters.exclude; + int ret = false; + GDVIRTUAL_REQUIRED_CALL(_intersect_point, p_parameters.position, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret); + exclude = nullptr; + return ret; + } + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { + exclude = &p_parameters.exclude; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_intersect_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret); + exclude = nullptr; + return ret; + } + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_cast_motion, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, &p_closest_safe, &p_closest_unsafe, r_info, ret); + exclude = nullptr; + return ret; + } + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_collide_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, &r_result_count, ret); + exclude = nullptr; + return ret; + } + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_rest_info, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_info, ret); + exclude = nullptr; + return ret; + } + + virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override { + Vector3 ret; + GDVIRTUAL_REQUIRED_CALL(_get_closest_point_to_object_volume, p_object, p_point, ret); + return ret; + } + + PhysicsDirectSpaceState3DExtension(); +}; + +typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision; +typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult; + +struct PhysicsServer3DExtensionStateCallback { + void *instance = nullptr; + void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state); +}; + +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionCollision) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionStateCallback) + +class PhysicsServer3DExtension : public PhysicsServer3D { + GDCLASS(PhysicsServer3DExtension, PhysicsServer3D); + +protected: + static void _bind_methods(); + +public: + // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. + + EXBIND0R(RID, world_boundary_shape_create) + EXBIND0R(RID, separation_ray_shape_create) + EXBIND0R(RID, sphere_shape_create) + EXBIND0R(RID, box_shape_create) + EXBIND0R(RID, capsule_shape_create) + EXBIND0R(RID, cylinder_shape_create) + EXBIND0R(RID, convex_polygon_shape_create) + EXBIND0R(RID, concave_polygon_shape_create) + EXBIND0R(RID, heightmap_shape_create) + EXBIND0R(RID, custom_shape_create) + + EXBIND2(shape_set_data, RID, const Variant &) + EXBIND2(shape_set_custom_solver_bias, RID, real_t) + + EXBIND2(shape_set_margin, RID, real_t) + EXBIND1RC(real_t, shape_get_margin, RID) + + EXBIND1RC(ShapeType, shape_get_type, RID) + EXBIND1RC(Variant, shape_get_data, RID) + EXBIND1RC(real_t, shape_get_custom_solver_bias, RID) + + /* SPACE API */ + + EXBIND0R(RID, space_create) + EXBIND2(space_set_active, RID, bool) + EXBIND1RC(bool, space_is_active, RID) + + EXBIND3(space_set_param, RID, SpaceParameter, real_t) + EXBIND2RC(real_t, space_get_param, RID, SpaceParameter) + + EXBIND1R(PhysicsDirectSpaceState3D *, space_get_direct_state, RID) + + EXBIND2(space_set_debug_contacts, RID, int) + EXBIND1RC(Vector<Vector3>, space_get_contacts, RID) + EXBIND1RC(int, space_get_contact_count, RID) + + /* AREA API */ + + //EXBIND0RID(area); + EXBIND0R(RID, area_create) + + EXBIND2(area_set_space, RID, RID) + EXBIND1RC(RID, area_get_space, RID) + + EXBIND4(area_add_shape, RID, RID, const Transform3D &, bool) + EXBIND3(area_set_shape, RID, int, RID) + EXBIND3(area_set_shape_transform, RID, int, const Transform3D &) + EXBIND3(area_set_shape_disabled, RID, int, bool) + + EXBIND1RC(int, area_get_shape_count, RID) + EXBIND2RC(RID, area_get_shape, RID, int) + EXBIND2RC(Transform3D, area_get_shape_transform, RID, int) + EXBIND2(area_remove_shape, RID, int) + EXBIND1(area_clear_shapes, RID) + + EXBIND2(area_attach_object_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, area_get_object_instance_id, RID) + + EXBIND3(area_set_param, RID, AreaParameter, const Variant &) + EXBIND2(area_set_transform, RID, const Transform3D &) + + EXBIND2RC(Variant, area_get_param, RID, AreaParameter) + EXBIND1RC(Transform3D, area_get_transform, RID) + + EXBIND2(area_set_collision_mask, RID, uint32_t) + EXBIND2(area_set_collision_layer, RID, uint32_t) + + EXBIND2(area_set_monitorable, RID, bool) + EXBIND2(area_set_ray_pickable, RID, bool) + + EXBIND2(area_set_monitor_callback, RID, const Callable &) + EXBIND2(area_set_area_monitor_callback, RID, const Callable &) + + /* BODY API */ + + //EXBIND2RID(body,BodyMode,bool); + EXBIND0R(RID, body_create) + + EXBIND2(body_set_space, RID, RID) + EXBIND1RC(RID, body_get_space, RID) + + EXBIND2(body_set_mode, RID, BodyMode) + EXBIND1RC(BodyMode, body_get_mode, RID) + + EXBIND4(body_add_shape, RID, RID, const Transform3D &, bool) + EXBIND3(body_set_shape, RID, int, RID) + EXBIND3(body_set_shape_transform, RID, int, const Transform3D &) + + EXBIND1RC(int, body_get_shape_count, RID) + EXBIND2RC(Transform3D, body_get_shape_transform, RID, int) + EXBIND2RC(RID, body_get_shape, RID, int) + + EXBIND3(body_set_shape_disabled, RID, int, bool) + + EXBIND2(body_remove_shape, RID, int) + EXBIND1(body_clear_shapes, RID) + + EXBIND2(body_attach_object_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, body_get_object_instance_id, RID) + + EXBIND2(body_set_enable_continuous_collision_detection, RID, bool) + EXBIND1RC(bool, body_is_continuous_collision_detection_enabled, RID) + + EXBIND2(body_set_collision_layer, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_collision_layer, RID) + + EXBIND2(body_set_collision_mask, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_collision_mask, RID) + + EXBIND2(body_set_user_flags, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_user_flags, RID) + + EXBIND3(body_set_param, RID, BodyParameter, const Variant &) + EXBIND2RC(Variant, body_get_param, RID, BodyParameter) + + EXBIND1(body_reset_mass_properties, RID) + + EXBIND3(body_set_state, RID, BodyState, const Variant &) + EXBIND2RC(Variant, body_get_state, RID, BodyState) + + EXBIND2(body_apply_torque_impulse, RID, const Vector3 &) + EXBIND2(body_apply_central_impulse, RID, const Vector3 &) + EXBIND3(body_apply_impulse, RID, const Vector3 &, const Vector3 &) + + EXBIND2(body_apply_central_force, RID, const Vector3 &) + EXBIND3(body_apply_force, RID, const Vector3 &, const Vector3 &) + EXBIND2(body_apply_torque, RID, const Vector3 &) + + EXBIND2(body_add_constant_central_force, RID, const Vector3 &) + EXBIND3(body_add_constant_force, RID, const Vector3 &, const Vector3 &) + EXBIND2(body_add_constant_torque, RID, const Vector3 &) + + EXBIND2(body_set_constant_force, RID, const Vector3 &) + EXBIND1RC(Vector3, body_get_constant_force, RID) + + EXBIND2(body_set_constant_torque, RID, const Vector3 &) + EXBIND1RC(Vector3, body_get_constant_torque, RID) + + EXBIND2(body_set_axis_velocity, RID, const Vector3 &) + + EXBIND3(body_set_axis_lock, RID, BodyAxis, bool) + EXBIND2RC(bool, body_is_axis_locked, RID, BodyAxis) + + EXBIND2(body_add_collision_exception, RID, RID) + EXBIND2(body_remove_collision_exception, RID, RID) + + GDVIRTUAL1RC(TypedArray<RID>, _body_get_collision_exceptions, RID) + + void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override { + TypedArray<RID> ret; + GDVIRTUAL_REQUIRED_CALL(_body_get_collision_exceptions, p_body, ret); + for (int i = 0; i < ret.size(); i++) { + p_exceptions->push_back(ret[i]); + } + } + + EXBIND2(body_set_max_contacts_reported, RID, int) + EXBIND1RC(int, body_get_max_contacts_reported, RID) + + EXBIND2(body_set_contacts_reported_depth_threshold, RID, real_t) + EXBIND1RC(real_t, body_get_contacts_reported_depth_threshold, RID) + + EXBIND2(body_set_omit_force_integration, RID, bool) + EXBIND1RC(bool, body_is_omitting_force_integration, RID) + + GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer3DExtensionStateCallback>) + void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override { + PhysicsServer3DExtensionStateCallback callback; + callback.callback = p_callback; + callback.instance = p_instance; + GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback); + } + EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &) + + EXBIND2(body_set_ray_pickable, RID, bool) + + GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDNativePtr<PhysicsServer3DExtensionMotionResult>) + + thread_local static const Set<RID> *exclude_bodies; + thread_local static const Set<ObjectID> *exclude_objects; + + bool body_test_motion_is_excluding_body(RID p_body) const; + bool body_test_motion_is_excluding_object(ObjectID p_object) const; + + bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { + bool ret = false; + exclude_bodies = &p_parameters.exclude_bodies; + exclude_objects = &p_parameters.exclude_objects; + GDVIRTUAL_REQUIRED_CALL(_body_test_motion, p_body, p_parameters.from, p_parameters.motion, p_parameters.margin, p_parameters.max_collisions, p_parameters.collide_separation_ray, r_result, ret); + exclude_bodies = nullptr; + exclude_objects = nullptr; + return ret; + } + + EXBIND1R(PhysicsDirectBodyState3D *, body_get_direct_state, RID) + + /* SOFT BODY API */ + + EXBIND0R(RID, soft_body_create) + + EXBIND2(soft_body_update_rendering_server, RID, PhysicsServer3DRenderingServerHandler *) + + EXBIND2(soft_body_set_space, RID, RID) + EXBIND1RC(RID, soft_body_get_space, RID) + + EXBIND2(soft_body_set_ray_pickable, RID, bool) + + EXBIND2(soft_body_set_collision_layer, RID, uint32_t) + EXBIND1RC(uint32_t, soft_body_get_collision_layer, RID) + + EXBIND2(soft_body_set_collision_mask, RID, uint32_t) + EXBIND1RC(uint32_t, soft_body_get_collision_mask, RID) + + EXBIND2(soft_body_add_collision_exception, RID, RID) + EXBIND2(soft_body_remove_collision_exception, RID, RID) + + GDVIRTUAL1RC(TypedArray<RID>, _soft_body_get_collision_exceptions, RID) + + void soft_body_get_collision_exceptions(RID p_soft_body, List<RID> *p_exceptions) override { + TypedArray<RID> ret; + GDVIRTUAL_REQUIRED_CALL(_soft_body_get_collision_exceptions, p_soft_body, ret); + for (int i = 0; i < ret.size(); i++) { + p_exceptions->push_back(ret[i]); + } + } + + EXBIND3(soft_body_set_state, RID, BodyState, const Variant &) + EXBIND2RC(Variant, soft_body_get_state, RID, BodyState) + + EXBIND2(soft_body_set_transform, RID, const Transform3D &) + + EXBIND2(soft_body_set_simulation_precision, RID, int) + EXBIND1RC(int, soft_body_get_simulation_precision, RID) + + EXBIND2(soft_body_set_total_mass, RID, real_t) + EXBIND1RC(real_t, soft_body_get_total_mass, RID) + + EXBIND2(soft_body_set_linear_stiffness, RID, real_t) + EXBIND1RC(real_t, soft_body_get_linear_stiffness, RID) + + EXBIND2(soft_body_set_pressure_coefficient, RID, real_t) + EXBIND1RC(real_t, soft_body_get_pressure_coefficient, RID) + + EXBIND2(soft_body_set_damping_coefficient, RID, real_t) + EXBIND1RC(real_t, soft_body_get_damping_coefficient, RID) + + EXBIND2(soft_body_set_drag_coefficient, RID, real_t) + EXBIND1RC(real_t, soft_body_get_drag_coefficient, RID) + + EXBIND2(soft_body_set_mesh, RID, RID) + + EXBIND1RC(AABB, soft_body_get_bounds, RID) + + EXBIND3(soft_body_move_point, RID, int, const Vector3 &) + EXBIND2RC(Vector3, soft_body_get_point_global_position, RID, int) + + EXBIND1(soft_body_remove_all_pinned_points, RID) + EXBIND3(soft_body_pin_point, RID, int, bool) + EXBIND2RC(bool, soft_body_is_point_pinned, RID, int) + + /* JOINT API */ + + EXBIND0R(RID, joint_create) + + EXBIND1(joint_clear, RID) + + EXBIND5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &) + + EXBIND3(pin_joint_set_param, RID, PinJointParam, real_t) + EXBIND2RC(real_t, pin_joint_get_param, RID, PinJointParam) + + EXBIND2(pin_joint_set_local_a, RID, const Vector3 &) + EXBIND1RC(Vector3, pin_joint_get_local_a, RID) + + EXBIND2(pin_joint_set_local_b, RID, const Vector3 &) + EXBIND1RC(Vector3, pin_joint_get_local_b, RID) + + EXBIND5(joint_make_hinge, RID, RID, const Transform3D &, RID, const Transform3D &) + EXBIND7(joint_make_hinge_simple, RID, RID, const Vector3 &, const Vector3 &, RID, const Vector3 &, const Vector3 &) + + EXBIND3(hinge_joint_set_param, RID, HingeJointParam, real_t) + EXBIND2RC(real_t, hinge_joint_get_param, RID, HingeJointParam) + + EXBIND3(hinge_joint_set_flag, RID, HingeJointFlag, bool) + EXBIND2RC(bool, hinge_joint_get_flag, RID, HingeJointFlag) + + EXBIND5(joint_make_slider, RID, RID, const Transform3D &, RID, const Transform3D &) + + EXBIND3(slider_joint_set_param, RID, SliderJointParam, real_t) + EXBIND2RC(real_t, slider_joint_get_param, RID, SliderJointParam) + + EXBIND5(joint_make_cone_twist, RID, RID, const Transform3D &, RID, const Transform3D &) + + EXBIND3(cone_twist_joint_set_param, RID, ConeTwistJointParam, real_t) + EXBIND2RC(real_t, cone_twist_joint_get_param, RID, ConeTwistJointParam) + + EXBIND5(joint_make_generic_6dof, RID, RID, const Transform3D &, RID, const Transform3D &) + + EXBIND4(generic_6dof_joint_set_param, RID, Vector3::Axis, G6DOFJointAxisParam, real_t) + EXBIND3RC(real_t, generic_6dof_joint_get_param, RID, Vector3::Axis, G6DOFJointAxisParam) + + EXBIND4(generic_6dof_joint_set_flag, RID, Vector3::Axis, G6DOFJointAxisFlag, bool) + EXBIND3RC(bool, generic_6dof_joint_get_flag, RID, Vector3::Axis, G6DOFJointAxisFlag) + + EXBIND1RC(JointType, joint_get_type, RID) + + EXBIND2(joint_set_solver_priority, RID, int) + EXBIND1RC(int, joint_get_solver_priority, RID) + + EXBIND2(joint_disable_collisions_between_bodies, RID, bool) + EXBIND1RC(bool, joint_is_disabled_collisions_between_bodies, RID) + + /* MISC */ + + GDVIRTUAL1(_free_rid, RID) + virtual void free(RID p_rid) override { + GDVIRTUAL_REQUIRED_CALL(_free_rid, p_rid); + } + + EXBIND1(set_active, bool) + + EXBIND0(init) + EXBIND1(step, real_t) + EXBIND0(sync) + EXBIND0(end_sync) + EXBIND0(flush_queries) + EXBIND0(finish) + + EXBIND0RC(bool, is_flushing_queries) + EXBIND1R(int, get_process_info, ProcessInfo) + + PhysicsServer3DExtension(); + ~PhysicsServer3DExtension(); +}; + +#endif // PHYSICSSERVER3DEXTENSION_H diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index 6e8078909b..dadd9747b1 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -96,7 +96,7 @@ class GodotArea2D : public GodotCollisionObject2D { Set<GodotConstraint2D *> constraints; - virtual void _shapes_changed(); + virtual void _shapes_changed() override; void _queue_monitor_update(); void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode); @@ -151,7 +151,7 @@ public: void set_transform(const Transform2D &p_transform); - void set_space(GodotSpace2D *p_space); + void set_space(GodotSpace2D *p_space) override; void call_queries(); diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 1335a19126..4b87a69d5c 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -103,7 +103,7 @@ class GodotBody2D : public GodotCollisionObject2D { bool can_sleep = true; bool first_time_kinematic = false; void _mass_properties_changed(); - virtual void _shapes_changed(); + virtual void _shapes_changed() override; Transform2D new_transform; List<Pair<GodotConstraint2D *, int>> constraint_list; @@ -302,7 +302,7 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; } _FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } - void set_space(GodotSpace2D *p_space); + void set_space(GodotSpace2D *p_space) override; void update_mass_properties(); void reset_mass_properties(); diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp index 2bf1e5a1d4..6e76697a1b 100644 --- a/servers/physics_2d/godot_body_pair_2d.cpp +++ b/servers/physics_2d/godot_body_pair_2d.cpp @@ -39,7 +39,7 @@ #define MAX_BIAS_ROTATION (Math_PI / 8) void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) { - GodotBodyPair2D *self = (GodotBodyPair2D *)p_self; + GodotBodyPair2D *self = static_cast<GodotBodyPair2D *>(p_self); self->_contact_added_callback(p_point_A, p_point_B); } diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp index 06f035a506..c545fec113 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp @@ -39,31 +39,37 @@ GodotBroadPhase2D::ID GodotBroadPhase2DBVH::create(GodotCollisionObject2D *p_obj } void GodotBroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) { + ERR_FAIL_COND(!p_id); bvh.move(p_id - 1, p_aabb); } void GodotBroadPhase2DBVH::set_static(ID p_id, bool p_static) { + ERR_FAIL_COND(!p_id); uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC; uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); bvh.set_tree(p_id - 1, tree_id, tree_collision_mask, false); } void GodotBroadPhase2DBVH::remove(ID p_id) { + ERR_FAIL_COND(!p_id); bvh.erase(p_id - 1); } GodotCollisionObject2D *GodotBroadPhase2DBVH::get_object(ID p_id) const { + ERR_FAIL_COND_V(!p_id, nullptr); GodotCollisionObject2D *it = bvh.get(p_id - 1); ERR_FAIL_COND_V(!it, nullptr); return it; } bool GodotBroadPhase2DBVH::is_static(ID p_id) const { + ERR_FAIL_COND_V(!p_id, false); uint32_t tree_id = bvh.get_tree_id(p_id - 1); return tree_id == 0; } int GodotBroadPhase2DBVH::get_subindex(ID p_id) const { + ERR_FAIL_COND_V(!p_id, 0); return bvh.get_subindex(p_id - 1); } @@ -76,7 +82,7 @@ int GodotBroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D } void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B) { - GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self); + GodotBroadPhase2DBVH *bpo = static_cast<GodotBroadPhase2DBVH *>(self); if (!bpo->pair_callback) { return nullptr; } @@ -85,7 +91,7 @@ void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollis } void GodotBroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B, void *pairdata) { - GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self); + GodotBroadPhase2DBVH *bpo = static_cast<GodotBroadPhase2DBVH *>(self); if (!bpo->unpair_callback) { return; } diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h index b11ad0e75e..512111f948 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.h +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h @@ -77,22 +77,22 @@ class GodotBroadPhase2DBVH : public GodotBroadPhase2D { public: // 0 is an invalid ID - virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false); - virtual void move(ID p_id, const Rect2 &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); + virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) override; + virtual void move(ID p_id, const Rect2 &p_aabb) override; + virtual void set_static(ID p_id, bool p_static) override; + virtual void remove(ID p_id) override; - virtual GodotCollisionObject2D *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; + virtual GodotCollisionObject2D *get_object(ID p_id) const override; + virtual bool is_static(ID p_id) const override; + virtual int get_subindex(ID p_id) const override; - virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) override; + virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) override; - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) override; + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) override; - virtual void update(); + virtual void update() override; static GodotBroadPhase2D *_create(); GodotBroadPhase2DBVH(); diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h index 19d6e91561..1a683a7b0f 100644 --- a/servers/physics_2d/godot_collision_object_2d.h +++ b/servers/physics_2d/godot_collision_object_2d.h @@ -104,7 +104,7 @@ public: _FORCE_INLINE_ void set_canvas_instance_id(const ObjectID &p_canvas_instance_id) { canvas_instance_id = p_canvas_instance_id; } _FORCE_INLINE_ ObjectID get_canvas_instance_id() const { return canvas_instance_id; } - void _shape_changed(); + void _shape_changed() override; _FORCE_INLINE_ Type get_type() const { return type; } void add_shape(GodotShape2D *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); @@ -166,7 +166,7 @@ public: } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } - void remove_shape(GodotShape2D *p_shape); + void remove_shape(GodotShape2D *p_shape) override; void remove_shape(int p_index); virtual void set_space(GodotSpace2D *p_space) = 0; diff --git a/servers/physics_2d/godot_collision_solver_2d.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp index 263d6d939f..383c6a915c 100644 --- a/servers/physics_2d/godot_collision_solver_2d.cpp +++ b/servers/physics_2d/godot_collision_solver_2d.cpp @@ -150,7 +150,7 @@ struct _ConcaveCollisionInfo2D { }; bool GodotCollisionSolver2D::concave_callback(void *p_userdata, GodotShape2D *p_convex) { - _ConcaveCollisionInfo2D &cinfo = *(_ConcaveCollisionInfo2D *)(p_userdata); + _ConcaveCollisionInfo2D &cinfo = *(static_cast<_ConcaveCollisionInfo2D *>(p_userdata)); cinfo.aabb_tests++; bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, cinfo.motion_A, p_convex, *cinfo.transform_B, cinfo.motion_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, cinfo.sep_axis, cinfo.margin_A, cinfo.margin_B); diff --git a/servers/physics_2d/godot_joints_2d.cpp b/servers/physics_2d/godot_joints_2d.cpp index 0876184d8c..0c21b08ea9 100644 --- a/servers/physics_2d/godot_joints_2d.cpp +++ b/servers/physics_2d/godot_joints_2d.cpp @@ -118,22 +118,26 @@ bool GodotPinJoint2D::setup(real_t p_step) { K1[0].y = 0.0f; K1[1].y = A->get_inv_mass() + B_inv_mass; + Vector2 r1 = rA - A->get_center_of_mass(); + Transform2D K2; - K2[0].x = A->get_inv_inertia() * rA.y * rA.y; - K2[1].x = -A->get_inv_inertia() * rA.x * rA.y; - K2[0].y = -A->get_inv_inertia() * rA.x * rA.y; - K2[1].y = A->get_inv_inertia() * rA.x * rA.x; + K2[0].x = A->get_inv_inertia() * r1.y * r1.y; + K2[1].x = -A->get_inv_inertia() * r1.x * r1.y; + K2[0].y = -A->get_inv_inertia() * r1.x * r1.y; + K2[1].y = A->get_inv_inertia() * r1.x * r1.x; Transform2D K; K[0] = K1[0] + K2[0]; K[1] = K1[1] + K2[1]; if (B) { + Vector2 r2 = rB - B->get_center_of_mass(); + Transform2D K3; - K3[0].x = B->get_inv_inertia() * rB.y * rB.y; - K3[1].x = -B->get_inv_inertia() * rB.x * rB.y; - K3[0].y = -B->get_inv_inertia() * rB.x * rB.y; - K3[1].y = B->get_inv_inertia() * rB.x * rB.x; + K3[0].x = B->get_inv_inertia() * r2.y * r2.y; + K3[1].x = -B->get_inv_inertia() * r2.x * r2.y; + K3[0].y = -B->get_inv_inertia() * r2.x * r2.y; + K3[1].y = B->get_inv_inertia() * r2.x * r2.x; K[0] += K3[0]; K[1] += K3[1]; diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index a9b499c6b5..650a95c914 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -144,7 +144,7 @@ real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const { } void GodotPhysicsServer2D::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { - CollCbkData *cbk = (CollCbkData *)p_userdata; + CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata); if (cbk->max == 0) { return; @@ -1212,7 +1212,7 @@ void GodotPhysicsServer2D::free(RID p_rid) { GodotSpace2D *space = space_owner.get_or_null(p_rid); while (space->get_objects().size()) { - GodotCollisionObject2D *co = (GodotCollisionObject2D *)space->get_objects().front()->get(); + GodotCollisionObject2D *co = static_cast<GodotCollisionObject2D *>(space->get_objects().front()->get()); co->set_space(nullptr); } @@ -1251,7 +1251,7 @@ void GodotPhysicsServer2D::step(real_t p_step) { active_objects = 0; collision_pairs = 0; for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { - stepper->step((GodotSpace2D *)E->get(), p_step); + stepper->step(const_cast<GodotSpace2D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); collision_pairs += E->get()->get_collision_pairs(); @@ -1272,7 +1272,7 @@ void GodotPhysicsServer2D::flush_queries() { uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { - GodotSpace2D *space = (GodotSpace2D *)E->get(); + GodotSpace2D *space = const_cast<GodotSpace2D *>(E->get()); space->call_queries(); } diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp index b5dbb8a2dd..6c020f9e72 100644 --- a/servers/physics_2d/godot_shape_2d.cpp +++ b/servers/physics_2d/godot_shape_2d.cpp @@ -37,7 +37,7 @@ void GodotShape2D::configure(const Rect2 &p_aabb) { aabb = p_aabb; configured = true; for (const KeyValue<GodotShapeOwner2D *, int> &E : owners) { - GodotShapeOwner2D *co = (GodotShapeOwner2D *)E.key; + GodotShapeOwner2D *co = const_cast<GodotShapeOwner2D *>(E.key); co->_shape_changed(); } } diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 04b8d3c741..63e3af1395 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -158,7 +158,7 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame if (p_parameters.hit_from_inside) { // Hit shape at starting point. min_d = 0; - res_point = local_from; + res_point = begin; res_normal = Vector2(); res_shape = shape_idx; res_obj = col_obj; @@ -403,7 +403,7 @@ struct _RestCallbackData2D { }; static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { - _RestCallbackData2D *rd = (_RestCallbackData2D *)p_userdata; + _RestCallbackData2D *rd = static_cast<_RestCallbackData2D *>(p_userdata); Vector2 contact_rel = p_point_B - p_point_A; real_t len = contact_rel.length(); @@ -1005,7 +1005,7 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A SWAP(type_A, type_B); } - GodotSpace2D *self = (GodotSpace2D *)p_self; + GodotSpace2D *self = static_cast<GodotSpace2D *>(p_self); self->collision_pairs++; if (type_A == GodotCollisionObject2D::TYPE_AREA) { @@ -1021,7 +1021,7 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A } } else { - GodotBodyPair2D *b = memnew(GodotBodyPair2D((GodotBody2D *)A, p_subindex_A, (GodotBody2D *)B, p_subindex_B)); + GodotBodyPair2D *b = memnew(GodotBodyPair2D(static_cast<GodotBody2D *>(A), p_subindex_A, static_cast<GodotBody2D *>(B), p_subindex_B)); return b; } diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 866c415440..fd72038be3 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -47,7 +47,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D } for (const Pair<GodotConstraint2D *, int> &E : p_body->get_constraint_list()) { - GodotConstraint2D *constraint = (GodotConstraint2D *)E.first; + GodotConstraint2D *constraint = const_cast<GodotConstraint2D *>(E.first); if (constraint->get_island_step() == _step) { continue; // Already processed. } diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index ce64fc802a..d15f8ec0a6 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -102,7 +102,7 @@ class GodotArea3D : public GodotCollisionObject3D { Set<GodotConstraint3D *> constraints; - virtual void _shapes_changed(); + virtual void _shapes_changed() override; void _queue_monitor_update(); void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode); @@ -172,7 +172,7 @@ public: void set_transform(const Transform3D &p_transform); - void set_space(GodotSpace3D *p_space); + void set_space(GodotSpace3D *p_space) override; void call_queries(); diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h index c416477204..64b43a3b51 100644 --- a/servers/physics_3d/godot_area_pair_3d.h +++ b/servers/physics_3d/godot_area_pair_3d.h @@ -37,8 +37,8 @@ #include "godot_soft_body_3d.h" class GodotAreaPair3D : public GodotConstraint3D { - GodotBody3D *body; - GodotArea3D *area; + GodotBody3D *body = nullptr; + GodotArea3D *area = nullptr; int body_shape; int area_shape; bool colliding = false; @@ -55,8 +55,8 @@ public: }; class GodotArea2Pair3D : public GodotConstraint3D { - GodotArea3D *area_a; - GodotArea3D *area_b; + GodotArea3D *area_a = nullptr; + GodotArea3D *area_b = nullptr; int shape_a; int shape_b; bool colliding_a = false; @@ -76,8 +76,8 @@ public: }; class GodotAreaSoftBodyPair3D : public GodotConstraint3D { - GodotSoftBody3D *soft_body; - GodotArea3D *area; + GodotSoftBody3D *soft_body = nullptr; + GodotArea3D *area = nullptr; int soft_body_shape; int area_shape; bool colliding = false; diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 1906e8aab1..c0c847d920 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -109,7 +109,7 @@ class GodotBody3D : public GodotCollisionObject3D { bool first_time_kinematic = false; void _mass_properties_changed(); - virtual void _shapes_changed(); + virtual void _shapes_changed() override; Transform3D new_transform; Map<GodotConstraint3D *, int> constraint_map; @@ -301,7 +301,7 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; } _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; } - void set_space(GodotSpace3D *p_space); + void set_space(GodotSpace3D *p_space) override; void update_mass_properties(); void reset_mass_properties(); diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index 89d5d59161..eebbe0196d 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -39,7 +39,7 @@ #define MAX_BIAS_ROTATION (Math_PI / 8) void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - GodotBodyPair3D *pair = (GodotBodyPair3D *)p_userdata; + GodotBodyPair3D *pair = static_cast<GodotBodyPair3D *>(p_userdata); pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } @@ -562,7 +562,7 @@ GodotBodyPair3D::~GodotBodyPair3D() { } void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - GodotBodySoftBodyPair3D *pair = (GodotBodySoftBodyPair3D *)p_userdata; + GodotBodySoftBodyPair3D *pair = static_cast<GodotBodySoftBodyPair3D *>(p_userdata); pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp index ecdf74fd41..435c1e8aec 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp @@ -40,31 +40,37 @@ GodotBroadPhase3DBVH::ID GodotBroadPhase3DBVH::create(GodotCollisionObject3D *p_ } void GodotBroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) { + ERR_FAIL_COND(!p_id); bvh.move(p_id - 1, p_aabb); } void GodotBroadPhase3DBVH::set_static(ID p_id, bool p_static) { + ERR_FAIL_COND(!p_id); uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC; uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); bvh.set_tree(p_id - 1, tree_id, tree_collision_mask, false); } void GodotBroadPhase3DBVH::remove(ID p_id) { + ERR_FAIL_COND(!p_id); bvh.erase(p_id - 1); } GodotCollisionObject3D *GodotBroadPhase3DBVH::get_object(ID p_id) const { + ERR_FAIL_COND_V(!p_id, nullptr); GodotCollisionObject3D *it = bvh.get(p_id - 1); ERR_FAIL_COND_V(!it, nullptr); return it; } bool GodotBroadPhase3DBVH::is_static(ID p_id) const { + ERR_FAIL_COND_V(!p_id, false); uint32_t tree_id = bvh.get_tree_id(p_id - 1); return tree_id == 0; } int GodotBroadPhase3DBVH::get_subindex(ID p_id) const { + ERR_FAIL_COND_V(!p_id, 0); return bvh.get_subindex(p_id - 1); } @@ -81,7 +87,7 @@ int GodotBroadPhase3DBVH::cull_aabb(const AABB &p_aabb, GodotCollisionObject3D * } void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B) { - GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self); + GodotBroadPhase3DBVH *bpo = static_cast<GodotBroadPhase3DBVH *>(self); if (!bpo->pair_callback) { return nullptr; } @@ -90,7 +96,7 @@ void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollis } void GodotBroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B, void *pairdata) { - GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self); + GodotBroadPhase3DBVH *bpo = static_cast<GodotBroadPhase3DBVH *>(self); if (!bpo->unpair_callback) { return; } diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h index 7660030195..ae5a18d955 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.h +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h @@ -75,23 +75,23 @@ class GodotBroadPhase3DBVH : public GodotBroadPhase3D { public: // 0 is an invalid ID - virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false); - virtual void move(ID p_id, const AABB &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); + virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) override; + virtual void move(ID p_id, const AABB &p_aabb) override; + virtual void set_static(ID p_id, bool p_static) override; + virtual void remove(ID p_id) override; - virtual GodotCollisionObject3D *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; + virtual GodotCollisionObject3D *get_object(ID p_id) const override; + virtual bool is_static(ID p_id) const override; + virtual int get_subindex(ID p_id) const override; - virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override; + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override; + virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override; - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) override; + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) override; - virtual void update(); + virtual void update() override; static GodotBroadPhase3D *_create(); GodotBroadPhase3DBVH(); diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h index 515b945564..0f09f21962 100644 --- a/servers/physics_3d/godot_collision_object_3d.h +++ b/servers/physics_3d/godot_collision_object_3d.h @@ -112,7 +112,7 @@ public: _FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; } _FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; } - void _shape_changed(); + void _shape_changed() override; _FORCE_INLINE_ Type get_type() const { return type; } void add_shape(GodotShape3D *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false); @@ -173,7 +173,7 @@ public: return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; } - void remove_shape(GodotShape3D *p_shape); + void remove_shape(GodotShape3D *p_shape) override; void remove_shape(int p_index); virtual void set_space(GodotSpace3D *p_space) = 0; diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index 81e1a88366..0adfabef78 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -141,7 +141,7 @@ struct _SoftBodyContactCollisionInfo { }; void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - _SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata); + _SoftBodyContactCollisionInfo &cinfo = *(static_cast<_SoftBodyContactCollisionInfo *>(p_userdata)); ++cinfo.contact_count; @@ -170,7 +170,7 @@ struct _SoftBodyQueryInfo { }; bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) { - _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); + _SoftBodyQueryInfo &query_cinfo = *(static_cast<_SoftBodyQueryInfo *>(p_userdata)); Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index); @@ -189,7 +189,7 @@ bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, voi } bool GodotCollisionSolver3D::soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex) { - _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); + _SoftBodyQueryInfo &query_cinfo = *(static_cast<_SoftBodyQueryInfo *>(p_userdata)); query_cinfo.shape_A = p_convex; @@ -292,7 +292,7 @@ struct _ConcaveCollisionInfo { }; bool GodotCollisionSolver3D::concave_callback(void *p_userdata, GodotShape3D *p_convex) { - _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); + _ConcaveCollisionInfo &cinfo = *(static_cast<_ConcaveCollisionInfo *>(p_userdata)); cinfo.aabb_tests++; bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, nullptr, cinfo.margin_A, cinfo.margin_B); @@ -422,7 +422,7 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T } bool GodotCollisionSolver3D::concave_distance_callback(void *p_userdata, GodotShape3D *p_convex) { - _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); + _ConcaveCollisionInfo &cinfo = *(static_cast<_ConcaveCollisionInfo *>(p_userdata)); cinfo.aabb_tests++; Vector3 close_A, close_B; diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index a1912dc660..e5107be74b 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -920,7 +920,7 @@ RID GodotPhysicsServer3D::soft_body_create() { return rid; } -void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) { +void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) { GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); ERR_FAIL_COND(!soft_body); @@ -1355,7 +1355,7 @@ int GodotPhysicsServer3D::joint_get_solver_priority(RID p_joint) const { return joint->get_priority(); } -void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { +void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) { GodotJoint3D *joint = joint_owner.get_or_null(p_joint); ERR_FAIL_COND(!joint); @@ -1570,7 +1570,7 @@ void GodotPhysicsServer3D::free(RID p_rid) { GodotSpace3D *space = space_owner.get_or_null(p_rid); while (space->get_objects().size()) { - GodotCollisionObject3D *co = (GodotCollisionObject3D *)space->get_objects().front()->get(); + GodotCollisionObject3D *co = static_cast<GodotCollisionObject3D *>(space->get_objects().front()->get()); co->set_space(nullptr); } @@ -1612,7 +1612,7 @@ void GodotPhysicsServer3D::step(real_t p_step) { active_objects = 0; collision_pairs = 0; for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { - stepper->step((GodotSpace3D *)E->get(), p_step); + stepper->step(const_cast<GodotSpace3D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); collision_pairs += E->get()->get_collision_pairs(); @@ -1636,7 +1636,7 @@ void GodotPhysicsServer3D::flush_queries() { uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { - GodotSpace3D *space = (GodotSpace3D *)E->get(); + GodotSpace3D *space = const_cast<GodotSpace3D *>(E->get()); space->call_queries(); } @@ -1709,7 +1709,7 @@ void GodotPhysicsServer3D::_update_shapes() { } void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - CollCbkData *cbk = (CollCbkData *)p_userdata; + CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata); if (cbk->max == 0) { return; diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index b903f4808c..d2078a912c 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -74,7 +74,7 @@ public: struct CollCbkData { int max; int amount; - Vector3 *ptr; + Vector3 *ptr = nullptr; }; static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); @@ -253,7 +253,7 @@ public: virtual RID soft_body_create() override; - virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override; + virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) override; virtual void soft_body_set_space(RID p_body, RID p_space) override; virtual RID soft_body_get_space(RID p_body) const override; @@ -353,7 +353,7 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority) override; virtual int joint_get_solver_priority(RID p_joint) const override; - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) override; + virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) override; virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const override; /* MISC */ diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 7762c4829e..21595c9612 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -62,7 +62,7 @@ void GodotShape3D::configure(const AABB &p_aabb) { aabb = p_aabb; configured = true; for (const KeyValue<GodotShapeOwner3D *, int> &E : owners) { - GodotShapeOwner3D *co = (GodotShapeOwner3D *)E.key; + GodotShapeOwner3D *co = const_cast<GodotShapeOwner3D *>(E.key); co->_shape_changed(); } } diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index 095050b7f3..be4b41292d 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -147,7 +147,7 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) { } } -void GodotSoftBody3D::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) { +void GodotSoftBody3D::update_rendering_server(PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) { if (soft_mesh.is_null()) { return; } @@ -1272,7 +1272,7 @@ struct _SoftBodyIntersectSegmentInfo { real_t hit_dist_sq = INFINITY; static bool process_hit(uint32_t p_face_index, void *p_userdata) { - _SoftBodyIntersectSegmentInfo &query_info = *(_SoftBodyIntersectSegmentInfo *)(p_userdata); + _SoftBodyIntersectSegmentInfo &query_info = *(static_cast<_SoftBodyIntersectSegmentInfo *>(p_userdata)); Vector3 points[3]; query_info.soft_body->get_face_points(p_face_index, points[0], points[1], points[2]); diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index 5028e81dd8..96f63e5819 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -153,11 +153,11 @@ public: } } - virtual void set_space(GodotSpace3D *p_space); + virtual void set_space(GodotSpace3D *p_space) override; void set_mesh(RID p_mesh); - void update_rendering_server(RenderingServerHandler *p_rendering_server_handler); + void update_rendering_server(PhysicsServer3DRenderingServerHandler *p_rendering_server_handler); Vector3 get_vertex_position(int p_index) const; void set_vertex_position(int p_index, const Vector3 &p_position); @@ -204,8 +204,8 @@ public: void predict_motion(real_t p_delta); void solve_constraints(real_t p_delta); - _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return ((Node *)p_node)->index; } - _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return ((Face *)p_face)->index; } + _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return static_cast<Node *>(p_node)->index; } + _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return static_cast<Face *>(p_face)->index; } // Return true to stop the query. // p_index is the node index for AABB query, face index for Ray query. @@ -215,7 +215,7 @@ public: void query_ray(const Vector3 &p_from, const Vector3 &p_to, QueryResultCallback p_result_callback, void *p_userdata); protected: - virtual void _shapes_changed(); + virtual void _shapes_changed() override; private: void update_normals_and_centroids(); diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index e28b6da0d9..0b84520c39 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -153,7 +153,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame if (p_parameters.hit_from_inside) { // Hit shape at starting point. min_d = 0; - res_point = local_from; + res_point = begin; res_normal = Vector3(); res_shape = shape_idx; res_obj = col_obj; @@ -445,7 +445,7 @@ struct _RestCallbackData { }; static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - _RestCallbackData *rd = (_RestCallbackData *)p_userdata; + _RestCallbackData *rd = static_cast<_RestCallbackData *>(p_userdata); Vector3 contact_rel = p_point_B - p_point_A; real_t len = contact_rel.length(); @@ -1017,7 +1017,7 @@ void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A SWAP(type_A, type_B); } - GodotSpace3D *self = (GodotSpace3D *)p_self; + GodotSpace3D *self = static_cast<GodotSpace3D *>(p_self); self->collision_pairs++; @@ -1038,10 +1038,10 @@ void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A } } else if (type_A == GodotCollisionObject3D::TYPE_BODY) { if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) { - GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotSoftBody3D *)B)); + GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D(static_cast<GodotBody3D *>(A), p_subindex_A, static_cast<GodotSoftBody3D *>(B))); return soft_pair; } else { - GodotBodyPair3D *b = memnew(GodotBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotBody3D *)B, p_subindex_B)); + GodotBodyPair3D *b = memnew(GodotBodyPair3D(static_cast<GodotBody3D *>(A), p_subindex_A, static_cast<GodotBody3D *>(B), p_subindex_B)); return b; } } else { @@ -1056,9 +1056,9 @@ void GodotSpace3D::_broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_ return; } - GodotSpace3D *self = (GodotSpace3D *)p_self; + GodotSpace3D *self = static_cast<GodotSpace3D *>(p_self); self->collision_pairs--; - GodotConstraint3D *c = (GodotConstraint3D *)p_data; + GodotConstraint3D *c = static_cast<GodotConstraint3D *>(p_data); memdelete(c); } diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h index ac54c8bf69..6308ede9a9 100644 --- a/servers/physics_3d/godot_space_3d.h +++ b/servers/physics_3d/godot_space_3d.h @@ -47,7 +47,7 @@ class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D { GDCLASS(GodotPhysicsDirectSpaceState3D, PhysicsDirectSpaceState3D); public: - GodotSpace3D *space; + GodotSpace3D *space = nullptr; virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override; diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 63635b224b..204adae450 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -49,7 +49,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D } for (const KeyValue<GodotConstraint3D *, int> &E : p_body->get_constraint_map()) { - GodotConstraint3D *constraint = (GodotConstraint3D *)E.key; + GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E.key); if (constraint->get_island_step() == _step) { continue; // Already processed. } @@ -88,7 +88,7 @@ void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, Local p_soft_body->set_island_step(_step); for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { - GodotConstraint3D *constraint = (GodotConstraint3D *)E->get(); + GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E->get()); if (constraint->get_island_step() == _step) { continue; // Already processed. } diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index fc119e49e9..17c94978d1 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -33,6 +33,22 @@ #include "core/config/project_settings.h" #include "core/string/print_string.h" +void PhysicsServer3DRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { + GDVIRTUAL_REQUIRED_CALL(_set_vertex, p_vertex_id, p_vector3); +} +void PhysicsServer3DRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { + GDVIRTUAL_REQUIRED_CALL(_set_normal, p_vertex_id, p_vector3); +} +void PhysicsServer3DRenderingServerHandler::set_aabb(const AABB &p_aabb) { + GDVIRTUAL_REQUIRED_CALL(_set_aabb, p_aabb); +} + +void PhysicsServer3DRenderingServerHandler::_bind_methods() { + GDVIRTUAL_BIND(_set_vertex, "vertex_id", "vertices"); + GDVIRTUAL_BIND(_set_normal, "vertex_id", "normals"); + GDVIRTUAL_BIND(_set_aabb, "aabb"); +} + PhysicsServer3D *PhysicsServer3D::singleton = nullptr; void PhysicsDirectBodyState3D::integrate_forces() { diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index f830c95b58..4811f7a039 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -33,6 +33,9 @@ #include "core/io/resource.h" #include "core/object/class_db.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/script_language.h" +#include "core/variant/native_ptr.h" class PhysicsDirectSpaceState3D; @@ -202,13 +205,21 @@ public: PhysicsDirectSpaceState3D(); }; -class RenderingServerHandler { +class PhysicsServer3DRenderingServerHandler : public Object { + GDCLASS(PhysicsServer3DRenderingServerHandler, Object) +protected: + GDVIRTUAL2(_set_vertex, int, GDNativeConstPtr<void>) + GDVIRTUAL2(_set_normal, int, GDNativeConstPtr<void>) + GDVIRTUAL1(_set_aabb, const AABB &) + + static void _bind_methods(); + public: - virtual void set_vertex(int p_vertex_id, const void *p_vector3) = 0; - virtual void set_normal(int p_vertex_id, const void *p_vector3) = 0; - virtual void set_aabb(const AABB &p_aabb) = 0; + virtual void set_vertex(int p_vertex_id, const void *p_vector3); + virtual void set_normal(int p_vertex_id, const void *p_vector3); + virtual void set_aabb(const AABB &p_aabb); - virtual ~RenderingServerHandler() {} + virtual ~PhysicsServer3DRenderingServerHandler() {} }; class PhysicsTestMotionParameters3D; @@ -552,7 +563,7 @@ public: virtual RID soft_body_create() = 0; - virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) = 0; + virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) = 0; virtual void soft_body_set_space(RID p_body, RID p_space) = 0; virtual RID soft_body_get_space(RID p_body) const = 0; @@ -624,7 +635,7 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0; virtual int joint_get_solver_priority(RID p_joint) const = 0; - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; + virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) = 0; virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0; diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index ecaef886e1..e44f82672d 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -269,7 +269,7 @@ public: FUNCRID(soft_body) - FUNC2(soft_body_update_rendering_server, RID, class RenderingServerHandler *) + FUNC2(soft_body_update_rendering_server, RID, PhysicsServer3DRenderingServerHandler *) FUNC2(soft_body_set_space, RID, RID) FUNC1RC(RID, soft_body_get_space, RID) @@ -369,7 +369,7 @@ public: FUNC2(joint_set_solver_priority, RID, int); FUNC1RC(int, joint_get_solver_priority, RID); - FUNC2(joint_disable_collisions_between_bodies, RID, const bool); + FUNC2(joint_disable_collisions_between_bodies, RID, bool); FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID); /* MISC */ diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 6848620b48..9843492316 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -70,7 +70,9 @@ #include "rendering/rendering_device.h" #include "rendering/rendering_device_binds.h" #include "rendering_server.h" +#include "servers/extensions/physics_server_3d_extension.h" #include "servers/rendering/shader_types.h" +#include "text/text_server_dummy.h" #include "text/text_server_extension.h" #include "text_server.h" #include "xr/xr_interface.h" @@ -112,6 +114,10 @@ void preregister_server_types() { GDREGISTER_CLASS(TextServerManager); GDREGISTER_ABSTRACT_CLASS(TextServer); GDREGISTER_CLASS(TextServerExtension); + GDREGISTER_CLASS(TextServerDummy); + + GDREGISTER_NATIVE_STRUCT(Glyph, "int start = -1;int end = -1;uint8_t count = 0;uint8_t repeat = 1;uint16_t flags = 0;float x_off = 0.f;float y_off = 0.f;float advance = 0.f;RID font_rid;int font_size = 0;int32_t index = 0"); + GDREGISTER_NATIVE_STRUCT(CaretInfo, "Rect2 leading_caret;Rect2 trailing_caret;TextServer::Direction leading_direction;TextServer::Direction trailing_direction"); Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager")); } @@ -125,6 +131,18 @@ void register_server_types() { GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D); GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D); + GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension); + GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension); + GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3DExtension) + GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DRenderingServerHandler) + + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionRayResult, "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state)"); + GDREGISTER_ABSTRACT_CLASS(NavigationServer2D); GDREGISTER_ABSTRACT_CLASS(NavigationServer3D); GDREGISTER_CLASS(XRServer); diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub index 0939b68482..06d1d28b08 100644 --- a/servers/rendering/SCsub +++ b/servers/rendering/SCsub @@ -5,3 +5,4 @@ Import("env") env.add_source_files(env.servers_sources, "*.cpp") SConscript("renderer_rd/SCsub") +SConscript("storage/SCsub") diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h new file mode 100644 index 0000000000..194b5b5cfe --- /dev/null +++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h @@ -0,0 +1,63 @@ +/*************************************************************************/ +/* rasterizer_canvas_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_CANVAS_DUMMY_H +#define RASTERIZER_CANVAS_DUMMY_H + +#include "servers/rendering/renderer_canvas_render.h" + +class RasterizerCanvasDummy : public RendererCanvasRender { +public: + PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; } + void free_polygon(PolygonID p_polygon) override {} + + void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {} + void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {} + + RID light_create() override { return RID(); } + void light_set_texture(RID p_rid, RID p_texture) override {} + void light_set_use_shadow(RID p_rid, bool p_enable) override {} + void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {} + void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {} + + void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {} + RID occluder_polygon_create() override { return RID(); } + void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {} + void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {} + void set_shadow_texture_size(int p_size) override {} + + bool free(RID p_rid) override { return true; } + void update() override {} + + RasterizerCanvasDummy() {} + ~RasterizerCanvasDummy() {} +}; + +#endif // !RASTERIZER_CANVAS_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h new file mode 100644 index 0000000000..f7bd7d0d18 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -0,0 +1,108 @@ +/*************************************************************************/ +/* rasterizer_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_DUMMY_H +#define RASTERIZER_DUMMY_H + +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "scene/resources/mesh.h" +#include "servers/rendering/dummy/rasterizer_canvas_dummy.h" +#include "servers/rendering/dummy/rasterizer_scene_dummy.h" +#include "servers/rendering/dummy/rasterizer_storage_dummy.h" +#include "servers/rendering/dummy/storage/canvas_texture_storage.h" +#include "servers/rendering/dummy/storage/decal_atlas_storage.h" +#include "servers/rendering/dummy/storage/material_storage.h" +#include "servers/rendering/dummy/storage/mesh_storage.h" +#include "servers/rendering/dummy/storage/texture_storage.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering_server.h" + +class RasterizerDummy : public RendererCompositor { +private: + uint64_t frame = 1; + double delta = 0; + +protected: + RasterizerCanvasDummy canvas; + RendererDummy::CanvasTextureStorage canvas_texture_storage; + RendererDummy::MaterialStorage material_storage; + RendererDummy::MeshStorage mesh_storage; + RendererDummy::TextureStorage texture_storage; + RendererDummy::DecalAtlasStorage decal_atlas_storage; + RasterizerStorageDummy storage; + RasterizerSceneDummy scene; + +public: + RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; }; + RendererMaterialStorage *get_material_storage() override { return &material_storage; }; + RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; }; + RendererTextureStorage *get_texture_storage() override { return &texture_storage; }; + RendererDecalAtlasStorage *get_decal_atlas_storage() override { return &decal_atlas_storage; }; + RendererStorage *get_storage() override { return &storage; } + RendererCanvasRender *get_canvas() override { return &canvas; } + RendererSceneRender *get_scene() override { return &scene; } + + void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {} + + void initialize() override {} + void begin_frame(double frame_step) override { + frame++; + delta = frame_step; + } + + void prepare_for_blitting_render_targets() override {} + void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} + + void end_frame(bool p_swap_buffers) override { + if (p_swap_buffers) { + DisplayServer::get_singleton()->swap_buffers(); + } + } + + void finalize() override {} + + static RendererCompositor *_create_current() { + return memnew(RasterizerDummy); + } + + static void make_current() { + _create_func = _create_current; + } + + bool is_low_end() const override { return true; } + uint64_t get_frame_number() const override { return frame; } + double get_frame_delta_time() const override { return delta; } + + RasterizerDummy() {} + ~RasterizerDummy() {} +}; + +#endif // RASTERIZER_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h new file mode 100644 index 0000000000..3855222554 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -0,0 +1,217 @@ +/*************************************************************************/ +/* rasterizer_scene_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_SCENE_DUMMY_H +#define RASTERIZER_SCENE_DUMMY_H + +#include "servers/rendering/renderer_scene_render.h" + +class RasterizerSceneDummy : public RendererSceneRender { +public: + GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } + void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} + void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} + void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} + void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} + void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} + void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} + void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} + void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} + void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} + void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} + void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} + void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} + + uint32_t geometry_instance_get_pair_mask() override { return 0; } + void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} + void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} + void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} + void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} + void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} + + void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} + + /* SHADOW ATLAS API */ + + RID shadow_atlas_create() override { return RID(); } + void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} + void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} + bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } + + void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} + int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } + void set_directional_shadow_count(int p_count) override {} + + /* SDFGI UPDATE */ + + void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} + int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } + AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } + uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } + + /* SKY API */ + + RID sky_allocate() override { return RID(); } + void sky_initialize(RID p_rid) override {} + void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {} + void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {} + void sky_set_material(RID p_sky, RID p_material) override {} + Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } + + /* ENVIRONMENT API */ + + RID environment_allocate() override { return RID(); } + void environment_initialize(RID p_rid) override {} + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} + void environment_set_sky(RID p_env, RID p_sky) override {} + void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} + void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} + void environment_set_bg_color(RID p_env, const Color &p_color) override {} + void environment_set_bg_energy(RID p_env, float p_energy) override {} + void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} + + void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} + void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} + void environment_glow_set_use_high_quality(bool p_enable) override {} + + void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} + void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} + void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} + void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} + + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} + + void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} + void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} + void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} + + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} + + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} + + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} + void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} + void environment_set_volumetric_fog_filter_active(bool p_enable) override {} + + Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } + + bool is_environment(RID p_env) const override { return false; } + RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } + int environment_get_canvas_max_layer(RID p_env) const override { return 0; } + + RID camera_effects_allocate() override { return RID(); } + void camera_effects_initialize(RID p_rid) override {} + void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} + void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {} + + void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} + void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} + + void shadows_quality_set(RS::ShadowQuality p_quality) override {} + void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} + + RID light_instance_create(RID p_light) override { return RID(); } + void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} + void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} + void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} + void light_instance_mark_visible(RID p_light_instance) override {} + + RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } + void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} + void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} + RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } + Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } + + RID reflection_atlas_create() override { return RID(); } + int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } + void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} + + RID reflection_probe_instance_create(RID p_probe) override { return RID(); } + void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} + void reflection_probe_release_atlas_index(RID p_instance) override {} + bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } + bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } + bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } + bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } + + RID decal_instance_create(RID p_decal) override { return RID(); } + void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} + + RID lightmap_instance_create(RID p_lightmap) override { return RID(); } + void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} + + RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } + void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} + bool voxel_gi_needs_update(RID p_probe) const override { return false; } + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} + + void voxel_gi_set_quality(RS::VoxelGIQuality) override {} + + void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} + void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} + + void set_scene_pass(uint64_t p_pass) override {} + void set_time(double p_time, double p_step) override {} + void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} + + RID render_buffers_create() override { return RID(); } + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} + void gi_set_use_half_resolution(bool p_enable) override {} + + void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} + bool screen_space_roughness_limiter_is_active() const override { return false; } + + void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} + void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} + + TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } + + bool free(RID p_rid) override { return false; } + void update() override {} + void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} + + virtual void decals_set_filter(RS::DecalFilter p_filter) override {} + virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {} + + RasterizerSceneDummy() {} + ~RasterizerSceneDummy() {} +}; + +#endif // !RASTERIZER_SCENE_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h new file mode 100644 index 0000000000..ea69d2f9a6 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_storage_dummy.h @@ -0,0 +1,330 @@ +/*************************************************************************/ +/* rasterizer_storage_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_STORAGE_DUMMY_H +#define RASTERIZER_STORAGE_DUMMY_H + +#include "servers/rendering/renderer_storage.h" +#include "storage/texture_storage.h" + +class RasterizerStorageDummy : public RendererStorage { +public: + /* Light API */ + + RID directional_light_allocate() override { return RID(); } + void directional_light_initialize(RID p_rid) override {} + RID omni_light_allocate() override { return RID(); } + void omni_light_initialize(RID p_rid) override {} + RID spot_light_allocate() override { return RID(); } + void spot_light_initialize(RID p_rid) override {} + RID reflection_probe_allocate() override { return RID(); } + void reflection_probe_initialize(RID p_rid) override {} + + void light_set_color(RID p_light, const Color &p_color) override {} + void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {} + void light_set_shadow(RID p_light, bool p_enabled) override {} + void light_set_projector(RID p_light, RID p_texture) override {} + void light_set_negative(RID p_light, bool p_enable) override {} + void light_set_cull_mask(RID p_light, uint32_t p_mask) override {} + void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {} + void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {} + void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {} + void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {} + + void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {} + + void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {} + void light_directional_set_blend_splits(RID p_light, bool p_enable) override {} + bool light_directional_get_blend_splits(RID p_light) const override { return false; } + void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override {} + RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; } + + RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; } + RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; } + + bool light_has_shadow(RID p_light) const override { return false; } + bool light_has_projector(RID p_light) const override { return false; } + + RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; } + AABB light_get_aabb(RID p_light) const override { return AABB(); } + float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; } + Color light_get_color(RID p_light) override { return Color(); } + RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; } + uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; } + uint64_t light_get_version(RID p_light) const override { return 0; } + + /* PROBE API */ + + void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {} + void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {} + void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {} + void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {} + void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {} + void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {} + void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {} + void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {} + void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {} + void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {} + void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {} + void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {} + void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {} + void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {} + float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; } + + AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); } + RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; } + uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; } + Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); } + Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); } + float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; } + bool reflection_probe_renders_shadows(RID p_probe) const override { return false; } + + void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {} + + /* VOXEL GI API */ + + RID voxel_gi_allocate() override { return RID(); } + void voxel_gi_initialize(RID p_rid) override {} + void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {} + + AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); } + Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); } + Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); } + Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); } + Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); } + + Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); } + Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); } + + void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; } + + void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; } + + void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; } + + void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; } + + void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; } + + void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {} + bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; } + + void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {} + bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; } + + void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {} + float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; } + + uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; } + + /* LIGHTMAP CAPTURE */ + RID lightmap_allocate() override { return RID(); } + void lightmap_initialize(RID p_rid) override {} + void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {} + void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {} + void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {} + void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {} + PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); } + PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); } + PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); } + PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); } + AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); } + void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {} + bool lightmap_is_interior(RID p_lightmap) const override { return false; } + void lightmap_set_probe_capture_update_speed(float p_speed) override {} + float lightmap_get_probe_capture_update_speed() const override { return 0; } + + /* OCCLUDER */ + + void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {} + + /* PARTICLES */ + + RID particles_allocate() override { return RID(); } + void particles_initialize(RID p_rid) override {} + void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {} + void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {} + void particles_set_emitting(RID p_particles, bool p_emitting) override {} + void particles_set_amount(RID p_particles, int p_amount) override {} + void particles_set_lifetime(RID p_particles, double p_lifetime) override {} + void particles_set_one_shot(RID p_particles, bool p_one_shot) override {} + void particles_set_pre_process_time(RID p_particles, double p_time) override {} + void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {} + void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {} + void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {} + void particles_set_speed_scale(RID p_particles, double p_scale) override {} + void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {} + void particles_set_process_material(RID p_particles, RID p_material) override {} + RID particles_get_process_material(RID p_particles) const override { return RID(); } + void particles_set_fixed_fps(RID p_particles, int p_fps) override {} + void particles_set_interpolate(RID p_particles, bool p_enable) override {} + void particles_set_fractional_delta(RID p_particles, bool p_enable) override {} + void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {} + void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {} + void particles_set_collision_base_size(RID p_particles, real_t p_size) override {} + + void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {} + + void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {} + void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {} + + void particles_restart(RID p_particles) override {} + + void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {} + + void particles_set_draw_passes(RID p_particles, int p_count) override {} + void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {} + + void particles_request_process(RID p_particles) override {} + AABB particles_get_current_aabb(RID p_particles) override { return AABB(); } + AABB particles_get_aabb(RID p_particles) const override { return AABB(); } + + void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {} + + bool particles_get_emitting(RID p_particles) override { return false; } + int particles_get_draw_passes(RID p_particles) const override { return 0; } + RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); } + + void particles_add_collision(RID p_particles, RID p_instance) override {} + void particles_remove_collision(RID p_particles, RID p_instance) override {} + + void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {} + + void update_particles() override {} + + /* PARTICLES COLLISION */ + + RID particles_collision_allocate() override { return RID(); } + void particles_collision_initialize(RID p_rid) override {} + void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {} + void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {} + void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {} + void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {} + void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {} + void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {} + void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {} + void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {} + void particles_collision_height_field_update(RID p_particles_collision) override {} + void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {} + AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); } + bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; } + RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); } + + RID particles_collision_instance_create(RID p_collision) override { return RID(); } + void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {} + void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {} + + bool particles_is_inactive(RID p_particles) const override { return false; } + + /* FOG VOLUMES */ + + RID fog_volume_allocate() override { return RID(); } + void fog_volume_initialize(RID p_rid) override {} + + void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {} + void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {} + void fog_volume_set_material(RID p_fog_volume, RID p_material) override {} + AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); } + RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; } + + /* VISIBILITY NOTIFIER */ + virtual RID visibility_notifier_allocate() override { return RID(); } + virtual void visibility_notifier_initialize(RID p_notifier) override {} + virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {} + virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {} + + virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); } + virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {} + + /* RENDER TARGET */ + + RID render_target_create() override { return RID(); } + void render_target_set_position(RID p_render_target, int p_x, int p_y) override {} + void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {} + RID render_target_get_texture(RID p_render_target) override { return RID(); } + void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {} + void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {} + bool render_target_was_used(RID p_render_target) override { return false; } + void render_target_set_as_unused(RID p_render_target) override {} + + void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {} + bool render_target_is_clear_requested(RID p_render_target) override { return false; } + Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); } + void render_target_disable_clear_request(RID p_render_target) override {} + void render_target_do_clear_request(RID p_render_target) override {} + + void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {} + Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); } + void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {} + + RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; } + bool free(RID p_rid) override { + if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid); + return true; + } + return false; + } + + virtual void update_memory_info() override {} + virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; } + + bool has_os_feature(const String &p_feature) const override { + return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2"; + } + + void update_dirty_resources() override {} + + void set_debug_generate_wireframes(bool p_generate) override {} + + String get_video_adapter_name() const override { return String(); } + String get_video_adapter_vendor() const override { return String(); } + RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; } + + static RendererStorage *base_singleton; + + void capture_timestamps_begin() override {} + void capture_timestamp(const String &p_name) override {} + uint32_t get_captured_timestamps_count() const override { return 0; } + uint64_t get_captured_timestamps_frame() const override { return 0; } + uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; } + uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; } + String get_captured_timestamp_name(uint32_t p_index) const override { return String(); } + + RasterizerStorageDummy() {} + ~RasterizerStorageDummy() {} +}; + +#endif // !RASTERIZER_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/canvas_texture_storage.h b/servers/rendering/dummy/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..daa3ac5e42 --- /dev/null +++ b/servers/rendering/dummy/storage/canvas_texture_storage.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_DUMMY_H +#define CANVAS_TEXTURE_STORAGE_DUMMY_H + +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace RendererDummy { + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +public: + virtual RID canvas_texture_allocate() override { return RID(); }; + virtual void canvas_texture_initialize(RID p_rid) override{}; + virtual void canvas_texture_free(RID p_rid) override{}; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{}; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{}; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{}; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{}; +}; + +} // namespace RendererDummy + +#endif // !CANVAS_TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/decal_atlas_storage.h b/servers/rendering/dummy/storage/decal_atlas_storage.h new file mode 100644 index 0000000000..04ddfaca6d --- /dev/null +++ b/servers/rendering/dummy/storage/decal_atlas_storage.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* decal_atlas_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DECAL_ATLAS_STORAGE_DUMMY_H +#define DECAL_ATLAS_STORAGE_DUMMY_H + +#include "servers/rendering/storage/decal_atlas_storage.h" + +namespace RendererDummy { + +class DecalAtlasStorage : public RendererDecalAtlasStorage { +public: + virtual RID decal_allocate() override { return RID(); } + virtual void decal_initialize(RID p_rid) override {} + virtual void decal_free(RID p_rid) override{}; + + virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {} + virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {} + virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {} + virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {} + virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override {} + virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {} + virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {} + virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override {} + virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {} + + virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); } + + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} +}; + +} // namespace RendererDummy + +#endif // !DECAL_ATLAS_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h new file mode 100644 index 0000000000..8890be8ea9 --- /dev/null +++ b/servers/rendering/dummy/storage/material_storage.h @@ -0,0 +1,95 @@ +/*************************************************************************/ +/* material_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MATERIAL_STORAGE_DUMMY_H +#define MATERIAL_STORAGE_DUMMY_H + +#include "servers/rendering/storage/material_storage.h" + +namespace RendererDummy { + +class MaterialStorage : public RendererMaterialStorage { +public: + /* GLOBAL VARIABLE API */ + + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {} + virtual void global_variable_remove(const StringName &p_name) override {} + virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); } + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {} + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {} + virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); } + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } + + virtual void global_variables_load_settings(bool p_load_textures = true) override {} + virtual void global_variables_clear() override {} + + virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; } + virtual void global_variables_instance_free(RID p_instance) override {} + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} + + /* SHADER API */ + + virtual RID shader_allocate() override { return RID(); } + virtual void shader_initialize(RID p_rid) override {} + virtual void shader_free(RID p_rid) override{}; + + virtual void shader_set_code(RID p_shader, const String &p_code) override {} + virtual String shader_get_code(RID p_shader) const override { return ""; } + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } + virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; + + /* MATERIAL API */ + virtual RID material_allocate() override { return RID(); } + virtual void material_initialize(RID p_rid) override {} + virtual void material_free(RID p_rid) override{}; + + virtual void material_set_render_priority(RID p_material, int priority) override {} + virtual void material_set_shader(RID p_shader_material, RID p_shader) override {} + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {} + virtual Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); } + + virtual void material_set_next_pass(RID p_material, RID p_next_material) override {} + + virtual bool material_is_animated(RID p_material) override { return false; } + virtual bool material_casts_shadows(RID p_material) override { return false; } + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} + virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {} +}; + +} // namespace RendererDummy + +#endif // !MATERIAL_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h new file mode 100644 index 0000000000..dfbd265bba --- /dev/null +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* mesh_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_STORAGE_DUMMY_H +#define MESH_STORAGE_DUMMY_H + +#include "servers/rendering/storage/mesh_storage.h" + +namespace RendererDummy { + +class MeshStorage : public RendererMeshStorage { +public: + /* MESH API */ + + virtual RID mesh_allocate() override { return RID(); } + virtual void mesh_initialize(RID p_rid) override {} + virtual void mesh_free(RID p_rid) override {} + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {} + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; } + + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {} + + virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {} + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; } + + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); } + virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; } + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} + virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); } + virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {} + virtual void mesh_clear(RID p_mesh) override {} + + /* MESH INSTANCE */ + + virtual RID mesh_instance_create(RID p_base) override { return RID(); } + virtual void mesh_instance_free(RID p_rid) override {} + + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {} + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {} + virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {} + virtual void update_mesh_instances() override {} + + /* MULTIMESH API */ + + virtual RID multimesh_allocate() override { return RID(); } + virtual void multimesh_initialize(RID p_rid) override {} + virtual void multimesh_free(RID p_rid) override {} + + virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {} + virtual int multimesh_get_instance_count(RID p_multimesh) const override { return 0; } + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {} + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {} + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {} + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {} + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {} + + virtual RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); } + virtual AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); } + + virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); } + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); } + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); } + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); } + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {} + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); } + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {} + virtual int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; } + + /* SKELETON API */ + + virtual RID skeleton_allocate() override { return RID(); } + virtual void skeleton_initialize(RID p_rid) override {} + virtual void skeleton_free(RID p_rid) override {} + virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {} + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {} + virtual int skeleton_get_bone_count(RID p_skeleton) const override { return 0; } + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {} + virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); } + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {} + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); } + + virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {} +}; + +} // namespace RendererDummy + +#endif // !MESH_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h new file mode 100644 index 0000000000..d40a1842a4 --- /dev/null +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -0,0 +1,116 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_DUMMY_H +#define TEXTURE_STORAGE_DUMMY_H + +#include "servers/rendering/rendering_server_globals.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace RendererDummy { + +class TextureStorage : public RendererTextureStorage { +private: + struct DummyTexture { + Ref<Image> image; + }; + mutable RID_PtrOwner<DummyTexture> texture_owner; + +public: + static TextureStorage *get_singleton() { + // Here we cheat until we can retire RasterizerStorageDummy::free() + + return (TextureStorage *)RSG::texture_storage; + }; + + virtual bool can_create_resources_async() const override { return false; } + + DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + + virtual RID texture_allocate() override { + DummyTexture *texture = memnew(DummyTexture); + ERR_FAIL_COND_V(!texture, RID()); + return texture_owner.make_rid(texture); + }; + + virtual void texture_free(RID p_rid) override { + // delete the texture + DummyTexture *texture = texture_owner.get_or_null(p_rid); + texture_owner.free(p_rid); + memdelete(texture); + }; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { + DummyTexture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!t); + t->image = p_image->duplicate(); + }; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override{}; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{}; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override{}; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override{}; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override{}; + virtual void texture_3d_placeholder_initialize(RID p_texture) override{}; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override { + DummyTexture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!t, Ref<Image>()); + return t->image; + }; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override{}; + + virtual void texture_set_path(RID p_texture, const String &p_path) override{}; + virtual String texture_get_path(RID p_texture) const override { return String(); }; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{}; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override{}; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override{}; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; +}; + +} // namespace RendererDummy + +#endif // !TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h deleted file mode 100644 index 8f82356d11..0000000000 --- a/servers/rendering/rasterizer_dummy.h +++ /dev/null @@ -1,801 +0,0 @@ -/*************************************************************************/ -/* rasterizer_dummy.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_DUMMY_H -#define RASTERIZER_DUMMY_H - -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "scene/resources/mesh.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_scene_render.h" -#include "servers/rendering_server.h" - -class RasterizerSceneDummy : public RendererSceneRender { -public: - GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } - void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} - void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} - void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} - void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} - void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} - void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} - void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} - void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} - void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} - void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} - void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} - void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} - - uint32_t geometry_instance_get_pair_mask() override { return 0; } - void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} - void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} - void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} - void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} - - void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} - - /* SHADOW ATLAS API */ - - RID shadow_atlas_create() override { return RID(); } - void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} - void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} - bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } - - void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} - int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } - void set_directional_shadow_count(int p_count) override {} - - /* SDFGI UPDATE */ - - void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} - int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } - AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } - uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } - - /* SKY API */ - - RID sky_allocate() override { return RID(); } - void sky_initialize(RID p_rid) override {} - void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {} - void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {} - void sky_set_material(RID p_sky, RID p_material) override {} - Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - - /* ENVIRONMENT API */ - - RID environment_allocate() override { return RID(); } - void environment_initialize(RID p_rid) override {} - void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} - void environment_set_sky(RID p_env, RID p_sky) override {} - void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} - void environment_set_bg_color(RID p_env, const Color &p_color) override {} - void environment_set_bg_energy(RID p_env, float p_energy) override {} - void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} - void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} - - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} - void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} - void environment_glow_set_use_high_quality(bool p_enable) override {} - - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} - void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} - void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} - void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - - void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} - - void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} - void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} - void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} - - void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} - - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} - void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} - void environment_set_volumetric_fog_filter_active(bool p_enable) override {} - - Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - - bool is_environment(RID p_env) const override { return false; } - RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } - int environment_get_canvas_max_layer(RID p_env) const override { return 0; } - - RID camera_effects_allocate() override { return RID(); } - void camera_effects_initialize(RID p_rid) override {} - void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} - void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {} - - void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} - void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} - - void shadows_quality_set(RS::ShadowQuality p_quality) override {} - void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} - - RID light_instance_create(RID p_light) override { return RID(); } - void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} - void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} - void light_instance_mark_visible(RID p_light_instance) override {} - - RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } - void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} - void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} - RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } - Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } - - RID reflection_atlas_create() override { return RID(); } - int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } - void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} - - RID reflection_probe_instance_create(RID p_probe) override { return RID(); } - void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} - void reflection_probe_release_atlas_index(RID p_instance) override {} - bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } - bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } - bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } - bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } - - RID decal_instance_create(RID p_decal) override { return RID(); } - void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} - - RID lightmap_instance_create(RID p_lightmap) override { return RID(); } - void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} - - RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } - void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} - bool voxel_gi_needs_update(RID p_probe) const override { return false; } - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} - - void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} - void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} - - void set_scene_pass(uint64_t p_pass) override {} - void set_time(double p_time, double p_step) override {} - void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} - - RID render_buffers_create() override { return RID(); } - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} - void gi_set_use_half_resolution(bool p_enable) override {} - - void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} - bool screen_space_roughness_limiter_is_active() const override { return false; } - - void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} - void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} - - TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } - - bool free(RID p_rid) override { return false; } - void update() override {} - void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} - - virtual void decals_set_filter(RS::DecalFilter p_filter) override {} - virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {} - - RasterizerSceneDummy() {} - ~RasterizerSceneDummy() {} -}; - -class RasterizerStorageDummy : public RendererStorage { -public: - bool can_create_resources_async() const override { return false; } - - /* TEXTURE API */ - struct DummyTexture { - Ref<Image> image; - }; - mutable RID_PtrOwner<DummyTexture> texture_owner; - - RID texture_allocate() override { - DummyTexture *texture = memnew(DummyTexture); - ERR_FAIL_COND_V(!texture, RID()); - return texture_owner.make_rid(texture); - } - void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { - DummyTexture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!t); - t->image = p_image->duplicate(); - } - - void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {} - void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {} - void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {} - void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {} - void texture_proxy_initialize(RID p_texture, RID p_base) override {} - void texture_proxy_update(RID p_proxy, RID p_base) override {} - - void texture_2d_placeholder_initialize(RID p_texture) override {} - void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {} - void texture_3d_placeholder_initialize(RID p_texture) override {} - - Ref<Image> texture_2d_get(RID p_texture) const override { - DummyTexture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!t, Ref<Image>()); - return t->image; - } - - Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } - Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - - void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); } - void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} - - void texture_set_path(RID p_texture, const String &p_path) override {} - String texture_get_path(RID p_texture) const override { return String(); } - - void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {} - void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {} - void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {} - - void texture_debug_usage(List<RS::TextureInfo> *r_info) override {} - void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {} - Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); } - - void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - - /* CANVAS TEXTURE API */ - - RID canvas_texture_allocate() override { return RID(); } - void canvas_texture_initialize(RID p_rid) override {} - void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {} - void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {} - - void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {} - void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {} - - /* SHADER API */ - - RID shader_allocate() override { return RID(); } - void shader_initialize(RID p_rid) override {} - void shader_set_code(RID p_shader, const String &p_code) override {} - String shader_get_code(RID p_shader) const override { return ""; } - void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} - - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } - Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } - - RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; - - /* COMMON MATERIAL API */ - - RID material_allocate() override { return RID(); } - void material_initialize(RID p_rid) override {} - void material_set_render_priority(RID p_material, int priority) override {} - void material_set_shader(RID p_shader_material, RID p_shader) override {} - - void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {} - Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); } - - void material_set_next_pass(RID p_material, RID p_next_material) override {} - - bool material_is_animated(RID p_material) override { return false; } - bool material_casts_shadows(RID p_material) override { return false; } - void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} - void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {} - - /* MESH API */ - - RID mesh_allocate() override { return RID(); } - void mesh_initialize(RID p_rid) override {} - void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {} - bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; } - RID mesh_instance_create(RID p_base) override { return RID(); } - void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {} - void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {} - void mesh_instance_check_for_update(RID p_mesh_instance) override {} - void update_mesh_instances() override {} - void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {} - float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; } - - void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {} - - int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } - - void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {} - RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; } - - void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} - void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} - void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} - - void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} - RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } - - RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); } - int mesh_get_surface_count(RID p_mesh) const override { return 0; } - - void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} - AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } - - AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); } - void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {} - void mesh_clear(RID p_mesh) override {} - - /* MULTIMESH API */ - - RID multimesh_allocate() override { return RID(); } - void multimesh_initialize(RID p_rid) override {} - void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {} - int multimesh_get_instance_count(RID p_multimesh) const override { return 0; } - - void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {} - void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {} - void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {} - void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {} - void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {} - - RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); } - AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); } - - Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); } - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); } - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); } - Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); } - void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {} - Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); } - - void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {} - int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; } - - /* SKELETON API */ - - RID skeleton_allocate() override { return RID(); } - void skeleton_initialize(RID p_rid) override {} - void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {} - void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {} - int skeleton_get_bone_count(RID p_skeleton) const override { return 0; } - void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {} - Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); } - void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {} - Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); } - - /* Light API */ - - RID directional_light_allocate() override { return RID(); } - void directional_light_initialize(RID p_rid) override {} - RID omni_light_allocate() override { return RID(); } - void omni_light_initialize(RID p_rid) override {} - RID spot_light_allocate() override { return RID(); } - void spot_light_initialize(RID p_rid) override {} - RID reflection_probe_allocate() override { return RID(); } - void reflection_probe_initialize(RID p_rid) override {} - - void light_set_color(RID p_light, const Color &p_color) override {} - void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {} - void light_set_shadow(RID p_light, bool p_enabled) override {} - void light_set_projector(RID p_light, RID p_texture) override {} - void light_set_negative(RID p_light, bool p_enable) override {} - void light_set_cull_mask(RID p_light, uint32_t p_mask) override {} - void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {} - void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {} - void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {} - void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {} - - void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {} - - void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {} - void light_directional_set_blend_splits(RID p_light, bool p_enable) override {} - bool light_directional_get_blend_splits(RID p_light) const override { return false; } - void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {} - bool light_directional_is_sky_only(RID p_light) const override { return false; } - - RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; } - RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; } - - bool light_has_shadow(RID p_light) const override { return false; } - bool light_has_projector(RID p_light) const override { return false; } - - RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; } - AABB light_get_aabb(RID p_light) const override { return AABB(); } - float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; } - Color light_get_color(RID p_light) override { return Color(); } - RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; } - uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; } - uint64_t light_get_version(RID p_light) const override { return 0; } - - /* PROBE API */ - - void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {} - void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {} - void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {} - void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {} - void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {} - void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {} - void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {} - void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {} - void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {} - void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {} - void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {} - void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {} - void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {} - - AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); } - RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; } - uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; } - Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); } - Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); } - float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; } - bool reflection_probe_renders_shadows(RID p_probe) const override { return false; } - - void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {} - void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {} - - /* DECAL API */ - - RID decal_allocate() override { return RID(); } - void decal_initialize(RID p_rid) override {} - void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {} - void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {} - void decal_set_emission_energy(RID p_decal, float p_energy) override {} - void decal_set_albedo_mix(RID p_decal, float p_mix) override {} - void decal_set_modulate(RID p_decal, const Color &p_modulate) override {} - void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {} - void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {} - void decal_set_fade(RID p_decal, float p_above, float p_below) override {} - void decal_set_normal_fade(RID p_decal, float p_fade) override {} - - AABB decal_get_aabb(RID p_decal) const override { return AABB(); } - - /* VOXEL GI API */ - - RID voxel_gi_allocate() override { return RID(); } - void voxel_gi_initialize(RID p_rid) override {} - void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {} - - AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); } - Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); } - Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); } - Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); } - Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); } - - Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); } - Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); } - - void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {} - float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; } - - void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {} - float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; } - - void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {} - float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; } - - void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {} - float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; } - - void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {} - float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; } - - void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {} - bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; } - - void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {} - bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; } - - void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {} - float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; } - - uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; } - - /* LIGHTMAP CAPTURE */ - RID lightmap_allocate() override { return RID(); } - void lightmap_initialize(RID p_rid) override {} - void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {} - void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {} - void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {} - void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {} - PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); } - PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); } - PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); } - PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); } - AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); } - void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {} - bool lightmap_is_interior(RID p_lightmap) const override { return false; } - void lightmap_set_probe_capture_update_speed(float p_speed) override {} - float lightmap_get_probe_capture_update_speed() const override { return 0; } - - /* OCCLUDER */ - - void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {} - - /* PARTICLES */ - - RID particles_allocate() override { return RID(); } - void particles_initialize(RID p_rid) override {} - void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {} - void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {} - void particles_set_emitting(RID p_particles, bool p_emitting) override {} - void particles_set_amount(RID p_particles, int p_amount) override {} - void particles_set_lifetime(RID p_particles, double p_lifetime) override {} - void particles_set_one_shot(RID p_particles, bool p_one_shot) override {} - void particles_set_pre_process_time(RID p_particles, double p_time) override {} - void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {} - void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {} - void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {} - void particles_set_speed_scale(RID p_particles, double p_scale) override {} - void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {} - void particles_set_process_material(RID p_particles, RID p_material) override {} - RID particles_get_process_material(RID p_particles) const override { return RID(); } - void particles_set_fixed_fps(RID p_particles, int p_fps) override {} - void particles_set_interpolate(RID p_particles, bool p_enable) override {} - void particles_set_fractional_delta(RID p_particles, bool p_enable) override {} - void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {} - void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {} - void particles_set_collision_base_size(RID p_particles, real_t p_size) override {} - - void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {} - - void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {} - void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {} - - void particles_restart(RID p_particles) override {} - - void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {} - - void particles_set_draw_passes(RID p_particles, int p_count) override {} - void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {} - - void particles_request_process(RID p_particles) override {} - AABB particles_get_current_aabb(RID p_particles) override { return AABB(); } - AABB particles_get_aabb(RID p_particles) const override { return AABB(); } - - void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {} - - bool particles_get_emitting(RID p_particles) override { return false; } - int particles_get_draw_passes(RID p_particles) const override { return 0; } - RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); } - - void particles_add_collision(RID p_particles, RID p_instance) override {} - void particles_remove_collision(RID p_particles, RID p_instance) override {} - - void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {} - - void update_particles() override {} - - /* PARTICLES COLLISION */ - - RID particles_collision_allocate() override { return RID(); } - void particles_collision_initialize(RID p_rid) override {} - void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {} - void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {} - void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {} - void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {} - void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {} - void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {} - void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {} - void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {} - void particles_collision_height_field_update(RID p_particles_collision) override {} - void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {} - AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); } - bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; } - RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); } - - RID particles_collision_instance_create(RID p_collision) override { return RID(); } - void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {} - void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {} - - /* FOG VOLUMES */ - - RID fog_volume_allocate() override { return RID(); } - void fog_volume_initialize(RID p_rid) override {} - - void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {} - void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {} - void fog_volume_set_material(RID p_fog_volume, RID p_material) override {} - AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); } - RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; } - - /* VISIBILITY NOTIFIER */ - virtual RID visibility_notifier_allocate() override { return RID(); } - virtual void visibility_notifier_initialize(RID p_notifier) override {} - virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {} - virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {} - - virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); } - virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {} - - /* GLOBAL VARIABLES */ - - void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {} - void global_variable_remove(const StringName &p_name) override {} - Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); } - - void global_variable_set(const StringName &p_name, const Variant &p_value) override {} - void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {} - Variant global_variable_get(const StringName &p_name) const override { return Variant(); } - RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } - - void global_variables_load_settings(bool p_load_textures = true) override {} - void global_variables_clear() override {} - - int32_t global_variables_instance_allocate(RID p_instance) override { return 0; } - void global_variables_instance_free(RID p_instance) override {} - void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} - - bool particles_is_inactive(RID p_particles) const override { return false; } - - /* RENDER TARGET */ - - RID render_target_create() override { return RID(); } - void render_target_set_position(RID p_render_target, int p_x, int p_y) override {} - void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {} - RID render_target_get_texture(RID p_render_target) override { return RID(); } - void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {} - void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {} - bool render_target_was_used(RID p_render_target) override { return false; } - void render_target_set_as_unused(RID p_render_target) override {} - - void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {} - bool render_target_is_clear_requested(RID p_render_target) override { return false; } - Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); } - void render_target_disable_clear_request(RID p_render_target) override {} - void render_target_do_clear_request(RID p_render_target) override {} - - void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {} - Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); } - void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {} - - RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; } - bool free(RID p_rid) override { - if (texture_owner.owns(p_rid)) { - // delete the texture - DummyTexture *texture = texture_owner.get_or_null(p_rid); - texture_owner.free(p_rid); - memdelete(texture); - return true; - } - return false; - } - - virtual void update_memory_info() override {} - virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; } - - bool has_os_feature(const String &p_feature) const override { - return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2"; - } - - void update_dirty_resources() override {} - - void set_debug_generate_wireframes(bool p_generate) override {} - - String get_video_adapter_name() const override { return String(); } - String get_video_adapter_vendor() const override { return String(); } - RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; } - - static RendererStorage *base_singleton; - - void capture_timestamps_begin() override {} - void capture_timestamp(const String &p_name) override {} - uint32_t get_captured_timestamps_count() const override { return 0; } - uint64_t get_captured_timestamps_frame() const override { return 0; } - uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; } - uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; } - String get_captured_timestamp_name(uint32_t p_index) const override { return String(); } - - RasterizerStorageDummy() {} - ~RasterizerStorageDummy() {} -}; - -class RasterizerCanvasDummy : public RendererCanvasRender { -public: - PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; } - void free_polygon(PolygonID p_polygon) override {} - - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {} - void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {} - - RID light_create() override { return RID(); } - void light_set_texture(RID p_rid, RID p_texture) override {} - void light_set_use_shadow(RID p_rid, bool p_enable) override {} - void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {} - void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {} - - void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {} - RID occluder_polygon_create() override { return RID(); } - void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {} - void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {} - void set_shadow_texture_size(int p_size) override {} - - bool free(RID p_rid) override { return true; } - void update() override {} - - RasterizerCanvasDummy() {} - ~RasterizerCanvasDummy() {} -}; - -class RasterizerDummy : public RendererCompositor { -private: - uint64_t frame = 1; - double delta = 0; - -protected: - RasterizerCanvasDummy canvas; - RasterizerStorageDummy storage; - RasterizerSceneDummy scene; - -public: - RendererStorage *get_storage() override { return &storage; } - RendererCanvasRender *get_canvas() override { return &canvas; } - RendererSceneRender *get_scene() override { return &scene; } - - void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {} - - void initialize() override {} - void begin_frame(double frame_step) override { - frame++; - delta = frame_step; - } - - void prepare_for_blitting_render_targets() override {} - void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} - - void end_frame(bool p_swap_buffers) override { - if (p_swap_buffers) { - DisplayServer::get_singleton()->swap_buffers(); - } - } - - void finalize() override {} - - static RendererCompositor *_create_current() { - return memnew(RasterizerDummy); - } - - static void make_current() { - _create_func = _create_current; - } - - bool is_low_end() const override { return true; } - uint64_t get_frame_number() const override { return frame; } - double get_frame_delta_time() const override { return delta; } - - RasterizerDummy() {} - ~RasterizerDummy() {} -}; - -#endif // RASTERIZER_DUMMY_H diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index a96f873088..f38d800aa7 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -34,6 +34,7 @@ #include "renderer_viewport.h" #include "rendering_server_default.h" #include "rendering_server_globals.h" +#include "servers/rendering/storage/canvas_texture_storage.h" static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; @@ -996,8 +997,8 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con ERR_FAIL_COND(!m); m->mesh = p_mesh; if (canvas_item->skeleton.is_valid()) { - m->mesh_instance = RSG::storage->mesh_instance_create(p_mesh); - RSG::storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton); + m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh); + RSG::mesh_storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton); } m->texture = p_texture; @@ -1092,12 +1093,12 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c); if (canvas_item->skeleton.is_valid()) { if (cm->mesh_instance.is_null()) { - cm->mesh_instance = RSG::storage->mesh_instance_create(cm->mesh); + cm->mesh_instance = RSG::mesh_storage->mesh_instance_create(cm->mesh); } - RSG::storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton); + RSG::mesh_storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton); } else { if (cm->mesh_instance.is_valid()) { - RSG::storage->free(cm->mesh_instance); + RSG::mesh_storage->mesh_instance_free(cm->mesh_instance); cm->mesh_instance = RID(); } } @@ -1530,26 +1531,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) { } RID RendererCanvasCull::canvas_texture_allocate() { - return RSG::storage->canvas_texture_allocate(); + return RSG::canvas_texture_storage->canvas_texture_allocate(); } void RendererCanvasCull::canvas_texture_initialize(RID p_rid) { - RSG::storage->canvas_texture_initialize(p_rid); + RSG::canvas_texture_storage->canvas_texture_initialize(p_rid); } void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - RSG::storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); + RSG::canvas_texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); } void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) { - RSG::storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); + RSG::canvas_texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); } void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - RSG::storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); + RSG::canvas_texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); } void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - RSG::storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); + RSG::canvas_texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); } void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { @@ -1663,6 +1664,11 @@ bool RendererCanvasCull::free(RID p_rid) { } */ + if (canvas_item->canvas_group != nullptr) { + memdelete(canvas_item->canvas_group); + canvas_item->canvas_group = nullptr; + } + canvas_item_owner.free(p_rid); } else if (canvas_light_owner.owns(p_rid)) { diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index fc53ce2327..94bae30ae0 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -124,7 +124,7 @@ public: Set<RID> viewports; struct ChildItem { Point2 mirror; - Item *item; + Item *item = nullptr; bool operator<(const ChildItem &p_item) const { return item->index < p_item.item->index; } diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 1840925f78..46ca3b0da8 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -31,6 +31,7 @@ #ifndef RENDERINGSERVERCANVASRENDER_H #define RENDERINGSERVERCANVASRENDER_H +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_storage.h" class RendererCanvasRender { @@ -82,10 +83,10 @@ public: Transform2D light_shader_xform; //Vector2 light_shader_pos; - Light *shadows_next_ptr; - Light *filter_next_ptr; - Light *next_ptr; - Light *directional_next_ptr; + Light *shadows_next_ptr = nullptr; + Light *filter_next_ptr = nullptr; + Light *next_ptr = nullptr; + Light *directional_next_ptr = nullptr; RID light_internal; uint64_t version; @@ -167,7 +168,7 @@ public: MAX_SIZE = 4096 }; uint32_t usage; - uint8_t *memory; + uint8_t *memory = nullptr; }; struct Command { @@ -184,7 +185,7 @@ public: TYPE_ANIMATION_SLICE, }; - Command *next; + Command *next = nullptr; Type type; virtual ~Command() {} }; @@ -304,8 +305,8 @@ public: }; struct ViewportRender { - RenderingServer *owner; - void *udata; + RenderingServer *owner = nullptr; + void *udata = nullptr; Rect2 rect; }; @@ -333,22 +334,22 @@ public: RID material; RID skeleton; - Item *next; + Item *next = nullptr; struct CopyBackBuffer { Rect2 rect; Rect2 screen_rect; bool full; }; - CopyBackBuffer *copy_back_buffer; + CopyBackBuffer *copy_back_buffer = nullptr; Color final_modulate; Transform2D final_transform; Rect2 final_clip_rect; - Item *final_clip_owner; - Item *material_owner; - Item *canvas_group_owner; - ViewportRender *vp_render; + Item *final_clip_owner = nullptr; + Item *material_owner = nullptr; + Item *canvas_group_owner = nullptr; + ViewportRender *vp_render = nullptr; bool distance_field; bool light_masked; @@ -403,14 +404,14 @@ public: } break; case Item::Command::TYPE_MESH: { const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c); - AABB aabb = RendererStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); + AABB aabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(mesh->mesh, RID()); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); } break; case Item::Command::TYPE_MULTIMESH: { const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c); - AABB aabb = RendererStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh); + AABB aabb = RendererRD::MeshStorage::get_singleton()->multimesh_get_aabb(multimesh->multimesh); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); @@ -452,14 +453,14 @@ public: return rect; } - Command *commands; - Command *last_command; + Command *commands = nullptr; + Command *last_command = nullptr; Vector<CommandBlock> blocks; uint32_t current_block; template <class T> T *alloc_command() { - T *command; + T *command = nullptr; if (commands == nullptr) { // As the most common use case of canvas items is to // use only one command, the first is done with it's @@ -589,7 +590,7 @@ public: bool sdf_collision; RS::CanvasOccluderPolygonCullMode cull_cache; - LightOccluderInstance *next; + LightOccluderInstance *next = nullptr; LightOccluderInstance() { enabled = true; diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index e58fd7bebc..74eff4bb40 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -34,6 +34,11 @@ #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_storage.h" +#include "servers/rendering/storage/canvas_texture_storage.h" +#include "servers/rendering/storage/decal_atlas_storage.h" +#include "servers/rendering/storage/material_storage.h" +#include "servers/rendering/storage/mesh_storage.h" +#include "servers/rendering/storage/texture_storage.h" #include "servers/rendering_server.h" class RendererSceneRender; @@ -70,6 +75,11 @@ protected: public: static RendererCompositor *create(); + virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0; + virtual RendererMaterialStorage *get_material_storage() = 0; + virtual RendererMeshStorage *get_mesh_storage() = 0; + virtual RendererTextureStorage *get_texture_storage() = 0; + virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0; virtual RendererStorage *get_storage() = 0; virtual RendererCanvasRender *get_canvas() = 0; virtual RendererSceneRender *get_scene() = 0; diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 64e613ab91..d3ad381965 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -7,3 +7,4 @@ env.add_source_files(env.servers_sources, "*.cpp") SConscript("forward_clustered/SCsub") SConscript("forward_mobile/SCsub") SConscript("shaders/SCsub") +SConscript("storage_rd/SCsub") diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 24108b3a59..0b36fe3964 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -269,7 +269,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size); cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size); - render_elements = (RenderElementData *)memalloc(sizeof(RenderElementData *) * render_element_max); + render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData *) * render_element_max)); render_element_count = 0; element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 6b500260ef..e24d020a14 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -30,6 +30,8 @@ #include "render_forward_clustered.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" @@ -58,14 +60,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() if (msaa == RS::VIEWPORT_MSAA_DISABLED) { { Vector<RID> fb; - fb.push_back(color); - fb.push_back(specular); - fb.push_back(depth); - - color_specular_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector<RID> fb; fb.push_back(specular); specular_only_fb = RD::get_singleton()->framebuffer_create(fb); @@ -78,14 +72,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() { Vector<RID> fb; - fb.push_back(color_msaa); - fb.push_back(specular_msaa); - fb.push_back(depth_msaa); - - color_specular_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector<RID> fb; fb.push_back(specular_msaa); specular_only_fb = RD::get_singleton()->framebuffer_create(fb); @@ -164,11 +150,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { color = RID(); depth = RID(); - color_specular_fb = RID(); - specular_only_fb = RID(); - color_fb = RID(); depth_fb = RID(); + color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations + if (normal_roughness_buffer.is_valid()) { RD::get_singleton()->free(normal_roughness_buffer); if (normal_roughness_buffer_msaa.is_valid()) { @@ -187,12 +172,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) { clear(); - ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support"); - msaa = p_msaa; width = p_width; height = p_height; + view_count = p_view_count; color = p_color_buffer; depth = p_depth_buffer; @@ -203,20 +187,25 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c fb.push_back(p_color_buffer); fb.push_back(depth); - color_fb = RD::get_singleton()->framebuffer_create(fb); + color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } { Vector<RID> fb; fb.push_back(depth); - depth_fb = RD::get_singleton()->framebuffer_create(fb); + depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } } else { RD::TextureFormat tf; + if (view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + } tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = p_width; tf.height = p_height; - tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = view_count; // create a layer for every view tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { @@ -241,17 +230,42 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c fb.push_back(color_msaa); fb.push_back(depth_msaa); - color_fb = RD::get_singleton()->framebuffer_create(fb); + color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } { Vector<RID> fb; fb.push_back(depth_msaa); - depth_fb = RD::get_singleton()->framebuffer_create(fb); + depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } } } +RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) { + if (color_framebuffers.has(p_color_pass_flags)) { + return color_framebuffers[p_color_pass_flags]; + } + + bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED; + + Vector<RID> fb; + fb.push_back(use_msaa ? color_msaa : color); + + if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) { + ensure_specular(); + fb.push_back(use_msaa ? specular_msaa : specular); + } else { + fb.push_back(RID()); + } + + fb.push_back(use_msaa ? depth_msaa : depth); + + int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1; + RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count); + color_framebuffers[p_color_pass_flags] = framebuffer; + return framebuffer; +} + void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) { if (rb->normal_roughness_buffer.is_valid()) { return; @@ -301,8 +315,9 @@ bool RenderForwardClustered::free(RID p_rid) { /// RENDERING /// -template <RenderForwardClustered::PassMode p_pass_mode> +template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags> void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -335,7 +350,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; - if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { + if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass } @@ -398,10 +413,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p RID xforms_uniform_set = surf->owner->transforms_uniform_set; SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. - + uint32_t pipeline_color_pass_flags = 0; uint32_t pipeline_specialization = 0; - if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) { + if (p_pass_mode == PASS_MODE_COLOR) { if (element_info.uses_softshadow) { pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS; } @@ -417,52 +432,60 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p switch (p_pass_mode) { case PASS_MODE_COLOR: { if (element_info.uses_lightmap) { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS; - } else { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS; - } - } break; - case PASS_MODE_COLOR_TRANSPARENT: { - if (element_info.uses_lightmap) { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS; + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_LIGHTMAP; } else { if (element_info.uses_forward_gi) { pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI; } - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS; } - } break; - case PASS_MODE_COLOR_SPECULAR: { - if (element_info.uses_lightmap) { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR; - } else { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR; + + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR; + } + + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT; } + + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MULTIVIEW; + } + + pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS; } break; case PASS_MODE_SHADOW: case PASS_MODE_DEPTH: { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS; } break; case PASS_MODE_SHADOW_DP: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for depth/roughness pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for voxel GI pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI; } break; case PASS_MODE_DEPTH_MATERIAL: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL; } break; case PASS_MODE_SDF: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for SDF pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF; } break; } PipelineCacheRD *pipeline = nullptr; - pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version]; + if constexpr (p_pass_mode == PASS_MODE_COLOR) { + pipeline = &shader->color_pipelines[cull_variant][primitive][pipeline_color_pass_flags]; + } else { + pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version]; + } RD::VertexFormatID vertex_format = -1; RID vertex_array_rd; @@ -470,12 +493,12 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p //skeleton and blend shape if (surf->owner->mesh_instance.is_valid()) { - storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } else { - storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } - index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); if (prev_vertex_array_rd != vertex_array_rd) { RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); @@ -533,14 +556,23 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis //use template for faster performance (pass mode comparisons are inlined) switch (p_params->pass_mode) { +#define VALID_FLAG_COMBINATION(f) \ + case f: { \ + _render_list_template<PASS_MODE_COLOR, f>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); \ + } break; + case PASS_MODE_COLOR: { - _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); - } break; - case PASS_MODE_COLOR_SPECULAR: { - _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); - } break; - case PASS_MODE_COLOR_TRANSPARENT: { - _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + switch (p_params->color_pass_flags) { + VALID_FLAG_COMBINATION(0); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW); + default: { + ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags)); + } + } + } break; case PASS_MODE_SHADOW: { _render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); @@ -602,8 +634,14 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat //store camera into ubo RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); + + for (uint32_t v = 0; v < p_render_data->view_count; v++) { + projection = correction * p_render_data->view_projection[v]; + RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); + RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); + } scene_state.ubo.z_far = p_render_data->z_far; scene_state.ubo.z_near = p_render_data->z_near; @@ -646,7 +684,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.fog_enabled = false; if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); + RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } @@ -927,6 +965,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit return (p_indices - subtractor[p_primitive]) / divisor[p_primitive]; } void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -1063,7 +1103,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con // LOD - if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { //lod Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); @@ -1087,7 +1127,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } uint32_t indices; - surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1099,13 +1139,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } else { surf->sort.lod_index = 0; if (p_render_data->render_info) { - uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface); + uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); to_draw = _indices_to_primitives(surf->primitive, to_draw); to_draw *= inst->instance_count; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } } } @@ -1200,11 +1240,9 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps } void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { - ERR_FAIL_COND_MSG(p_render_data->view_count != 1, "Multiview is currently not supported in the clustered renderer. Please use the mobile renderer for VR."); - RenderBufferDataForwardClustered *render_buffer = nullptr; if (p_render_data->render_buffers.is_valid()) { - render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); + render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); } RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; @@ -1223,12 +1261,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co scene_state.ubo.opaque_prepass_threshold = 0.99f; Size2i screen_size; - RID opaque_framebuffer; - RID opaque_specular_framebuffer; + RID color_framebuffer; + RID color_only_framebuffer; RID depth_framebuffer; - RID alpha_framebuffer; PassMode depth_pass_mode = PASS_MODE_DEPTH; + uint32_t color_pass_flags = 0; Vector<Color> depth_pass_clear; bool using_separate_specular = false; bool using_ssr = false; @@ -1241,15 +1279,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co screen_size.x = render_buffer->width; screen_size.y = render_buffer->height; - opaque_framebuffer = render_buffer->color_fb; - if (p_render_data->voxel_gi_instances->size() > 0) { using_voxelgi = true; } - if (!p_render_data->environment.is_valid() && using_voxelgi) { + if (p_render_data->view_count > 1) { + depth_pass_mode = PASS_MODE_DEPTH; + } else if (!p_render_data->environment.is_valid() && using_voxelgi) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; - } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { if (environment_is_sdfgi_enabled(p_render_data->environment)) { depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi @@ -1257,14 +1294,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } else { depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } - if (environment_is_ssr_enabled(p_render_data->environment)) { - render_buffer->ensure_specular(); using_separate_specular = true; using_ssr = true; - opaque_specular_framebuffer = render_buffer->color_specular_fb; + color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; } - } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } @@ -1289,15 +1323,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co }; } - alpha_framebuffer = opaque_framebuffer; + if (p_render_data->view_count > 1) { + color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW; + } + + color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags); + color_only_framebuffer = render_buffer->color_only_fb; } else if (p_render_data->reflection_probe.is_valid()) { uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; - opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + color_only_framebuffer = color_framebuffer; depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - alpha_framebuffer = opaque_framebuffer; if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors @@ -1327,11 +1366,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; - if (using_sss) { + if (using_sss && !using_separate_specular) { using_separate_specular = true; - render_buffer->ensure_specular(); - using_separate_specular = true; - opaque_specular_framebuffer = render_buffer->color_specular_fb; + color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; + color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags); } RID radiance_texture; bool draw_sky = false; @@ -1353,7 +1391,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.b *= bg_energy; if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } } break; case RS::ENV_BG_COLOR: { @@ -1363,7 +1401,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.b *= bg_energy; if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } } break; case RS::ENV_BG_SKY: { @@ -1434,7 +1472,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID()); bool finish_depth = using_ssao || using_sdfgi || using_voxelgi; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); @@ -1480,20 +1518,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); - //regular forward for now Vector<Color> c; - if (using_separate_specular) { + { Color cc = clear_color.to_linear(); - cc.a = 0; //subsurf scatter must be 0 + if (using_separate_specular) { + cc.a = 0; //subsurf scatter must be 0 + } c.push_back(cc); - c.push_back(Color(0, 0, 0, 0)); - } else { - c.push_back(clear_color.to_linear()); + + if (render_buffer) { + c.push_back(Color(0, 0, 0, 0)); + } } - RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold); - _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); if (will_continue_color && using_separate_specular) { // close the specular framebuffer, as it's no longer used RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); @@ -1511,10 +1550,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co CameraMatrix dc; dc.set_depth_correction(true); CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { - gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); + gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); } RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); @@ -1528,9 +1567,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co CameraMatrix dc; dc.set_depth_correction(true); CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug SDFGI"); - _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm); + _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm); RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); } @@ -1538,14 +1577,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); - CameraMatrix projection = p_render_data->cam_projection; + RD::get_singleton()->draw_command_begin_label("Draw Sky"); + if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; correction.set_depth_correction(true); - projection = correction * p_render_data->cam_projection; + CameraMatrix projection = correction * p_render_data->cam_projection; + sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time); + } else { + sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); } - RD::get_singleton()->draw_command_begin_label("Draw Sky"); - sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time); RD::get_singleton()->draw_command_end_label(); } @@ -1571,12 +1612,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_ssr) { RENDER_TIMESTAMP("Screen-Space Reflections"); RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections"); - _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); + _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); + storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); } } @@ -1599,7 +1640,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); { - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold); + uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~COLOR_PASS_FLAG_SEPARATE_SPECULAR; + RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); } @@ -1649,6 +1692,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page RenderDataRD render_data; render_data.cam_projection = p_projection; render_data.cam_transform = p_transform; + render_data.view_projection[0] = p_projection; render_data.z_far = p_zfar; render_data.z_near = 0.0; render_data.cluster_size = 1; @@ -1720,7 +1764,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); + RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); } @@ -1738,6 +1782,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RenderDataRD render_data; render_data.cam_projection = p_cam_projection; render_data.cam_transform = p_cam_transform; + render_data.view_projection[0] = p_cam_projection; render_data.z_near = 0.0; render_data.z_far = p_cam_projection.get_z_far(); render_data.cluster_size = 1; @@ -1762,7 +1807,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con { //regular forward for now - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set); _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); } RD::get_singleton()->draw_command_end_label(); @@ -1776,6 +1821,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RenderDataRD render_data; render_data.cam_projection = p_cam_projection; render_data.cam_transform = p_cam_transform; + render_data.view_projection[0] = p_cam_projection; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; @@ -1798,7 +1844,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RENDER_TIMESTAMP("Render 3D Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set); //regular forward for now Vector<Color> clear = { Color(0, 0, 0, 0), @@ -1844,7 +1890,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p RENDER_TIMESTAMP("Render 3D Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, true); //regular forward for now Vector<Color> clear = { Color(0, 0, 0, 0), @@ -1898,7 +1944,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i _update_render_base_uniform_set(); - RenderBufferDataForwardClustered *render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForwardClustered *render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); ERR_FAIL_COND(!render_buffer); PassMode pass_mode = PASS_MODE_SDF; @@ -1964,7 +2010,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i E = sdfgi_framebuffer_size_cache.insert(fb_size, fb); } - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false); _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); } @@ -2121,7 +2167,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID decal_atlas = storage->decal_atlas_get_texture(); + RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture(); u.append_id(decal_atlas); uniforms.push_back(u); } @@ -2129,7 +2175,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID decal_atlas = storage->decal_atlas_get_texture_srgb(); + RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb(); u.append_id(decal_atlas); uniforms.push_back(u); } @@ -2145,7 +2191,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -2162,9 +2208,11 @@ void RenderForwardClustered::_update_render_base_uniform_set() { } RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RenderBufferDataForwardClustered *rb = nullptr; if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); + rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); } //default render buffer and scene state uniform set @@ -2194,7 +2242,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -2211,7 +2259,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -2225,7 +2273,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } u.append_id(texture); uniforms.push_back(u); @@ -2237,7 +2285,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -2246,12 +2294,12 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { u.append_id(default_tex); @@ -2264,7 +2312,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]); @@ -2294,7 +2342,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2303,7 +2351,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2313,7 +2361,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); u.append_id(texture); uniforms.push_back(u); } @@ -2323,7 +2371,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); - RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2333,7 +2381,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); - RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2343,7 +2391,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 14; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); - RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2355,7 +2403,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers); } else { - t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } u.append_id(t); uniforms.push_back(u); @@ -2367,7 +2415,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -2386,10 +2434,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers); if (vfog.is_null()) { - vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } } else { - vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(vfog); uniforms.push_back(u); @@ -2399,7 +2447,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID(); - RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2409,6 +2457,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); Vector<RD::Uniform> uniforms; { @@ -2427,7 +2476,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te } { // No radiance texture. - RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2437,7 +2486,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No reflection atlas. - RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2450,7 +2499,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2460,7 +2509,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2471,7 +2520,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { u.append_id(default_tex); } @@ -2485,7 +2534,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { u.append_id(default_tex); } @@ -2537,7 +2586,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te } RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { - RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); return rb->normal_roughness_buffer; } @@ -2565,8 +2614,10 @@ void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_g } void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); + bool has_base_alpha = (p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha; bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; bool has_alpha = has_base_alpha || has_blend_alpha; @@ -2611,14 +2662,14 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet SceneShaderForwardClustered::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); - RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh); + RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); if (shadow_mesh.is_valid()) { - surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface); + surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface); } } else { @@ -2631,8 +2682,8 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet sdcache->shader = p_material->shader_data; sdcache->material_uniform_set = p_material->uniform_set; - sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface); - sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface); + sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); + sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { @@ -2668,23 +2719,25 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) { SceneShaderForwardClustered::MaterialData *material = p_material; + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh); while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); } - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh); } } void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RID m_src; m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; @@ -2692,7 +2745,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw SceneShaderForwardClustered::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2700,10 +2753,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw if (material) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2714,10 +2767,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); @@ -2726,6 +2779,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw } void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); if (ginstance->data->dirty_dependencies) { @@ -2739,7 +2793,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome uint32_t surface_count; RID mesh = ginstance->data->base; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { //if no materials, no surfaces. const RID *inst_materials = ginstance->data->surface_materials.ptr(); @@ -2756,19 +2810,19 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome } break; case RS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(ginstance->data->base); + RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base); if (mesh.is_valid()) { const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t j = 0; j < surface_count; j++) { _geometry_instance_add_surface(ginstance, j, materials[j], mesh); } } - ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base); } } break; @@ -2793,7 +2847,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t k = 0; k < surface_count; k++) { _geometry_instance_add_surface(ginstance, k, materials[k], mesh); @@ -2817,17 +2871,17 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; - if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { + if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; } - if (storage->multimesh_uses_colors(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; } - if (storage->multimesh_uses_custom_data(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; } - ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; @@ -2844,10 +2898,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { - if (storage->skeleton_is_valid(ginstance->data->skeleton)) { - ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { + ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); if (ginstance->data->dirty_dependencies) { - storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); + mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); } } } @@ -2887,7 +2941,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { - ginstance->instance_count = static_cast<RenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); } } break; default: { diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index dd5c719352..37366d3e14 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -103,16 +103,18 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID depth_fb; RID depth_normal_roughness_fb; RID depth_normal_roughness_voxelgi_fb; - RID color_fb; - RID color_specular_fb; + RID color_only_fb; RID specular_only_fb; int width, height; + Map<uint32_t, RID> color_framebuffers; + uint32_t view_count; RID render_sdfgi_uniform_set; void ensure_specular(); void ensure_voxelgi(); void clear(); virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count); + RID get_color_pass_fb(uint32_t p_color_pass_flags); ~RenderBufferDataForwardClustered(); }; @@ -134,8 +136,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { enum PassMode { PASS_MODE_COLOR, - PASS_MODE_COLOR_SPECULAR, - PASS_MODE_COLOR_TRANSPARENT, PASS_MODE_SHADOW, PASS_MODE_SHADOW_DP, PASS_MODE_DEPTH, @@ -145,6 +145,12 @@ class RenderForwardClustered : public RendererSceneRenderRD { PASS_MODE_SDF, }; + enum ColorPassFlags { + COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, + COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, + COLOR_PASS_FLAG_MULTIVIEW = 1 << 2 + }; + struct GeometryInstanceSurfaceDataCache; struct RenderElementInfo; @@ -154,7 +160,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { int element_count = 0; bool reverse_cull = false; PassMode pass_mode = PASS_MODE_COLOR; + uint32_t color_pass_flags = 0; bool no_gi = false; + uint32_t view_count = 1; RID render_pass_uniform_set; bool force_wireframe = false; Vector2 uv_offset; @@ -166,13 +174,15 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t barrier = RD::BARRIER_MASK_ALL; bool use_directional_soft_shadow = false; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; reverse_cull = p_reverse_cull; pass_mode = p_pass_mode; + color_pass_flags = p_color_pass_flags; no_gi = p_no_gi; + view_count = p_view_count; render_pass_uniform_set = p_render_pass_uniform_set; force_wireframe = p_force_wireframe; uv_offset = p_uv_offset; @@ -216,8 +226,11 @@ class RenderForwardClustered : public RendererSceneRenderRD { struct UBO { float projection_matrix[16]; float inv_projection_matrix[16]; - float camera_matrix[16]; - float inv_camera_matrix[16]; + float inv_view_matrix[16]; + float view_matrix[16]; + + float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; float viewport_size[2]; float screen_pixel_size[2]; @@ -319,7 +332,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 }; LocalVector<InstanceData> instance_data[RENDER_LIST_MAX]; - LightmapCaptureData *lightmap_captures; + LightmapCaptureData *lightmap_captures = nullptr; uint32_t max_lightmap_captures; RID lightmap_capture_buffer; @@ -368,7 +381,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t lod_index : 8; }; - template <PassMode p_pass_mode> + template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0> _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index b4def4e11c..2acce8bab7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -32,6 +32,8 @@ #include "core/config/project_settings.h" #include "core/math/math_defs.h" #include "render_forward_clustered.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" using namespace RendererSceneRenderImplementation; @@ -57,6 +59,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { uses_point_size = false; uses_alpha = false; + uses_alpha_clip = false; uses_blend_alpha = false; uses_depth_pre_pass = false; uses_discard = false; @@ -107,6 +110,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { actions.render_mode_flags["particle_trails"] = &uses_particle_trails; actions.usage_flag_pointers["ALPHA"] = &uses_alpha; + actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; @@ -149,7 +153,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element * el = gen_code.code.front(); + Map<String, String>::Element *el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -230,10 +234,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } } - RD::PipelineColorBlendState blend_state_blend; - blend_state_blend.attachments.push_back(blend_attachment); - RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); + // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular + RD::PipelineColorBlendState blend_state_color_blend; + blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment() }; + RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(2); RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1); RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2); @@ -276,12 +280,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, + SHADER_VERSION_DEPTH_PASS_MULTIVIEW, SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, }; shader_version = shader_version_table[k]; @@ -297,38 +297,62 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; RD::PipelineMultisampleState multisample_state; - if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS) { - if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { - multisample_state.enable_alpha_to_coverage = true; - } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { - multisample_state.enable_alpha_to_coverage = true; - multisample_state.enable_alpha_to_one = true; + if (k == PIPELINE_VERSION_COLOR_PASS) { + for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) { + if (!shader_singleton->valid_color_pass_pipelines.has(l)) { + continue; + } + + int shader_flags = 0; + if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) { + if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { + multisample_state.enable_alpha_to_coverage = true; + } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { + multisample_state.enable_alpha_to_coverage = true; + multisample_state.enable_alpha_to_one = true; + } + + blend_state = blend_state_color_blend; + + if (depth_draw == DEPTH_DRAW_OPAQUE) { + depth_stencil.enable_depth_write = false; //alpha does not draw depth + } + } else { + blend_state = blend_state_color_opaque; + + if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) { + shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR; + } + } + + if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) { + shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP; + } + + if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) { + shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW; + } + + int variant = shader_version + shader_flags; + RID shader_variant = shader_singleton->shader.version_get_shader(version, variant); + color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); } - - blend_state = blend_state_blend; - - if (depth_draw == DEPTH_DRAW_OPAQUE) { - depth_stencil.enable_depth_write = false; //alpha does not draw depth - } - } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS) { - blend_state = blend_state_opaque; - } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP) { - //none, leave empty - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { - blend_state = blend_state_depth_normal_roughness; - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { - blend_state = blend_state_depth_normal_roughness_giprobe; - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) { - blend_state = RD::PipelineColorBlendState(); //no color targets for SDF } else { - //specular write - blend_state = blend_state_opaque_specular; - } + if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) { + //none, leave empty + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { + blend_state = blend_state_depth_normal_roughness; + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { + blend_state = blend_state_depth_normal_roughness_giprobe; + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) { + blend_state = RD::PipelineColorBlendState(); //no color targets for SDF + } - RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version); - pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); + RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version); + pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); + } } } } @@ -375,13 +399,13 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> } } -void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -436,7 +460,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { +RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -460,7 +484,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -475,17 +499,20 @@ SceneShaderForwardClustered::SceneShaderForwardClustered() { } SceneShaderForwardClustered::~SceneShaderForwardClustered() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RD::get_singleton()->free(default_vec4_xform_buffer); RD::get_singleton()->free(shadow_sampler); - storage->free(overdraw_material_shader); - storage->free(default_shader); + material_storage->shader_free(overdraw_material_shader); + material_storage->shader_free(default_shader); - storage->free(overdraw_material); - storage->free(default_material); + material_storage->material_free(overdraw_material); + material_storage->material_free(default_material); } void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); storage = p_storage; { @@ -496,27 +523,51 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF - shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR - shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR + shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW + + Vector<String> color_pass_flags = { + "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR + "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP + "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW + }; + + for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) { + String version = ""; + for (int j = 0; (1 << j) < SHADER_COLOR_PASS_FLAG_COUNT; j += 1) { + if ((1 << j) & i) { + version += color_pass_flags[j]; + } + } + shader_versions.push_back(version); + } shader.initialize(shader_versions, p_defines); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false); + // TODO Add a way to enable/disable color pass flags + } } - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); + valid_color_pass_pipelines.insert(0); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler ShaderCompiler::DefaultIdentifierActions actions; - actions.renames["WORLD_MATRIX"] = "world_matrix"; - actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; - actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; - actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; + actions.renames["MODEL_MATRIX"] = "model_matrix"; + actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix"; + actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix"; + actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix"; actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; + actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; @@ -587,8 +638,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["CUSTOM3"] = "custom3_attrib"; actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - // not implemented but need these just in case code is in the shaders - actions.renames["VIEW_INDEX"] = "0"; + actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; @@ -597,7 +647,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["LIGHT_COLOR"] = "light_color"; actions.renames["LIGHT"] = "light"; actions.renames["ATTENUATION"] = "attenuation"; - actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation"; actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions.renames["SPECULAR_LIGHT"] = "specular_light"; @@ -692,9 +741,9 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin { //default material and shader - default_shader = storage->shader_allocate(); - storage->shader_initialize(default_shader); - storage->shader_set_code(default_shader, R"( + default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(default_shader); + material_storage->shader_set_code(default_shader, R"( // Default 3D material shader (clustered). shader_type spatial; @@ -709,11 +758,11 @@ void fragment() { METALLIC = 0.2; } )"); - default_material = storage->material_allocate(); - storage->material_initialize(default_material); - storage->material_set_shader(default_material, default_shader); + default_material = material_storage->material_allocate(); + material_storage->material_initialize(default_material); + material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); @@ -722,10 +771,10 @@ void fragment() { } { - overdraw_material_shader = storage->shader_allocate(); - storage->shader_initialize(overdraw_material_shader); + overdraw_material_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(overdraw_material_shader); // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. - storage->shader_set_code(overdraw_material_shader, R"( + material_storage->shader_set_code(overdraw_material_shader, R"( // 3D editor Overdraw debug draw mode shader (clustered). shader_type spatial; @@ -737,11 +786,11 @@ void fragment() { ALPHA = 0.1; } )"); - overdraw_material = storage->material_allocate(); - storage->material_initialize(overdraw_material); - storage->material_set_shader(overdraw_material, overdraw_material_shader); + overdraw_material = material_storage->material_allocate(); + material_storage->material_initialize(overdraw_material); + material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 33049fad9c..1b7709bedb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -42,7 +42,7 @@ private: static SceneShaderForwardClustered *singleton; public: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; enum ShaderVersion { SHADER_VERSION_DEPTH_PASS, @@ -51,13 +51,18 @@ public: SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, + SHADER_VERSION_DEPTH_PASS_MULTIVIEW, SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, SHADER_VERSION_MAX }; + enum ShaderColorPassFlags { + SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0, + SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1, + SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2, + SHADER_COLOR_PASS_FLAG_COUNT = 1 << 3 + }; + enum PipelineVersion { PIPELINE_VERSION_DEPTH_PASS, PIPELINE_VERSION_DEPTH_PASS_DP, @@ -65,15 +70,19 @@ public: PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL, PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, - PIPELINE_VERSION_OPAQUE_PASS, - PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR, - PIPELINE_VERSION_TRANSPARENT_PASS, - PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS, - PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR, - PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS, + PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW, + PIPELINE_VERSION_COLOR_PASS, PIPELINE_VERSION_MAX }; + enum PipelineColorPassFlags { + PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, + PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, + PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2, + PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3, + PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 4, + }; + enum ShaderSpecializations { SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0, SHADER_SPECIALIZATION_PROJECTOR = 1 << 1, @@ -81,7 +90,7 @@ public: SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3, }; - struct ShaderData : public RendererStorageRD::ShaderData { + struct ShaderData : public RendererRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -125,6 +134,7 @@ public: RID version; uint32_t vertex_input_mask; PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX]; + PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT]; String path; @@ -168,7 +178,7 @@ public: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -183,13 +193,13 @@ public: SelfList<ShaderData>::List shader_list; - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { + RendererRD::ShaderData *_create_shader_func(); + static RendererRD::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererStorageRD::MaterialData { - ShaderData *shader_data; + struct MaterialData : public RendererRD::MaterialData { + ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; uint32_t index = 0; @@ -201,8 +211,8 @@ public: virtual ~MaterialData(); }; - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } @@ -228,6 +238,7 @@ public: ShaderData *overdraw_material_shader_ptr = nullptr; Vector<RD::PipelineSpecializationConstant> default_specialization_constants; + Set<uint32_t> valid_color_pass_pipelines; SceneShaderForwardClustered(); ~SceneShaderForwardClustered(); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 957b490664..156d535447 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -30,6 +30,8 @@ #include "render_forward_mobile.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" @@ -289,12 +291,14 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() { } RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + //there should always be enough uniform buffers for render passes, otherwise bugs ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID()); RenderBufferDataForwardMobile *rb = nullptr; if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); + rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); } // default render buffer and scene state uniform set @@ -315,7 +319,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -332,7 +336,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -346,7 +350,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } u.append_id(texture); uniforms.push_back(u); @@ -358,7 +362,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -369,12 +373,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { u.append_id(default_tex); @@ -390,7 +394,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.resize(MAX_VOXEL_GI_INSTANCESS); - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (i < (int)p_voxel_gi_instances.size()) { RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]); @@ -421,7 +425,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -430,7 +434,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -473,7 +477,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RenderBufferDataForwardMobile *render_buffer = nullptr; if (p_render_data->render_buffers.is_valid()) { - render_buffer = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); + render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); } RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); @@ -592,7 +596,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } */ } break; @@ -604,7 +608,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } */ } break; @@ -1275,7 +1279,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID decal_atlas = storage->decal_atlas_get_texture(); + RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture(); u.append_id(decal_atlas); uniforms.push_back(u); } @@ -1283,7 +1287,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID decal_atlas = storage->decal_atlas_get_texture_srgb(); + RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb(); u.append_id(decal_atlas); uniforms.push_back(u); } @@ -1299,7 +1303,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -1322,6 +1326,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit } void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -1411,7 +1417,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const // LOD - if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { //lod Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); @@ -1435,7 +1441,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } uint32_t indices; - surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1447,13 +1453,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } else { surf->lod_index = 0; if (p_render_data->render_info) { - uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface); + uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); to_draw = _indices_to_primitives(surf->primitive, to_draw); to_draw *= inst->instance_count; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } } } @@ -1520,8 +1526,8 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, //store camera into ubo RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); for (uint32_t v = 0; v < p_render_data->view_count; v++) { projection = correction * p_render_data->view_projection[v]; @@ -1563,7 +1569,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.fog_enabled = false; if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardMobile *render_buffers = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); + RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } @@ -1811,6 +1817,8 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF template <RenderForwardMobile::PassMode p_pass_mode> void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -1953,12 +1961,12 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr //skeleton and blend shape if (surf->owner->mesh_instance.is_valid()) { - storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } else { - storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } - index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); if (prev_vertex_array_rd != vertex_array_rd) { RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); @@ -2277,8 +2285,10 @@ void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geom } void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); + bool has_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; bool has_alpha = has_base_alpha || has_blend_alpha; @@ -2323,14 +2333,14 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI SceneShaderForwardMobile::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); - RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh); + RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); if (shadow_mesh.is_valid()) { - surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface); + surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface); } } else { @@ -2343,8 +2353,8 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI sdcache->shader = p_material->shader_data; sdcache->material_uniform_set = p_material->uniform_set; - sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface); - sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface); + sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); + sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { @@ -2378,23 +2388,25 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) { SceneShaderForwardMobile::MaterialData *material = p_material; + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh); while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); } - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh); } } void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RID m_src; m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; @@ -2402,7 +2414,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward SceneShaderForwardMobile::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2410,10 +2422,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward if (material) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2424,10 +2436,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); @@ -2436,6 +2448,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward } void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); if (ginstance->data->dirty_dependencies) { @@ -2449,7 +2462,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry uint32_t surface_count; RID mesh = ginstance->data->base; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { //if no materials, no surfaces. const RID *inst_materials = ginstance->data->surface_materials.ptr(); @@ -2466,19 +2479,19 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry } break; case RS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(ginstance->data->base); + RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base); if (mesh.is_valid()) { const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t j = 0; j < surface_count; j++) { _geometry_instance_add_surface(ginstance, j, materials[j], mesh); } } - ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base); } } break; @@ -2503,7 +2516,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t k = 0; k < surface_count; k++) { _geometry_instance_add_surface(ginstance, k, materials[k], mesh); @@ -2526,17 +2539,17 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; - if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { + if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; } - if (storage->multimesh_uses_colors(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; } - if (storage->multimesh_uses_custom_data(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; } - ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; @@ -2556,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { - if (storage->skeleton_is_valid(ginstance->data->skeleton)) { - ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { + ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); if (ginstance->data->dirty_dependencies) { - storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); + mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); } } } @@ -2592,7 +2605,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage: case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { - ginstance->instance_count = static_cast<RenderForwardMobile *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); } } break; default: { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 8274dc3b0c..0ddfe89eea 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -254,8 +254,8 @@ protected: struct UBO { float projection_matrix[16]; float inv_projection_matrix[16]; - float camera_matrix[16]; - float inv_camera_matrix[16]; + float inv_view_matrix[16]; + float view_matrix[16]; float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; @@ -328,7 +328,7 @@ protected: uint32_t max_lightmaps; RID lightmap_buffer; - LightmapCaptureData *lightmap_captures; + LightmapCaptureData *lightmap_captures = nullptr; uint32_t max_lightmap_captures; RID lightmap_capture_buffer; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 4dc56e8970..60badbdfee 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "render_forward_mobile.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" using namespace RendererSceneRenderImplementation; @@ -60,6 +61,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { uses_point_size = false; uses_alpha = false; + uses_alpha_clip = false; uses_blend_alpha = false; uses_depth_pre_pass = false; uses_discard = false; @@ -109,6 +111,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { actions.render_mode_flags["particle_trails"] = &uses_particle_trails; actions.usage_flag_pointers["ALPHA"] = &uses_alpha; + actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; // actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; @@ -293,7 +296,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { blend_state = blend_state_blend; - if (depth_draw == DEPTH_DRAW_OPAQUE) { + if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) { depth_stencil.enable_depth_write = false; //alpha does not draw depth } } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) { @@ -364,13 +367,13 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_ } } -void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -425,7 +428,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() { +RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -449,7 +452,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -467,6 +470,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() { void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) { storage = p_storage; + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); /* SCENE SHADER */ @@ -492,17 +496,17 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p } } - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler ShaderCompiler::DefaultIdentifierActions actions; - actions.renames["WORLD_MATRIX"] = "world_matrix"; - actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; - actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; - actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; + actions.renames["MODEL_MATRIX"] = "model_matrix"; + actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix"; + actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix"; + actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix"; actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; @@ -584,7 +588,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.renames["LIGHT_COLOR"] = "light_color"; actions.renames["LIGHT"] = "light"; actions.renames["ATTENUATION"] = "attenuation"; - actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation"; actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions.renames["SPECULAR_LIGHT"] = "specular_light"; @@ -676,9 +679,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p { //default material and shader - default_shader = storage->shader_allocate(); - storage->shader_initialize(default_shader); - storage->shader_set_code(default_shader, R"( + default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(default_shader); + material_storage->shader_set_code(default_shader, R"( // Default 3D material shader (mobile). shader_type spatial; @@ -693,11 +696,11 @@ void fragment() { METALLIC = 0.2; } )"); - default_material = storage->material_allocate(); - storage->material_initialize(default_material); - storage->material_set_shader(default_material, default_shader); + default_material = material_storage->material_allocate(); + material_storage->material_initialize(default_material); + material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_material_shader_ptr = md->shader_data; @@ -705,10 +708,10 @@ void fragment() { } { - overdraw_material_shader = storage->shader_allocate(); - storage->shader_initialize(overdraw_material_shader); + overdraw_material_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(overdraw_material_shader); // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. - storage->shader_set_code(overdraw_material_shader, R"( + material_storage->shader_set_code(overdraw_material_shader, R"( // 3D editor Overdraw debug draw mode shader (mobile). shader_type spatial; @@ -720,11 +723,11 @@ void fragment() { ALPHA = 0.1; } )"); - overdraw_material = storage->material_allocate(); - storage->material_initialize(overdraw_material); - storage->material_set_shader(overdraw_material, overdraw_material_shader); + overdraw_material = material_storage->material_allocate(); + material_storage->material_initialize(overdraw_material); + material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } @@ -764,12 +767,14 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector } SceneShaderForwardMobile::~SceneShaderForwardMobile() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RD::get_singleton()->free(default_vec4_xform_buffer); RD::get_singleton()->free(shadow_sampler); - storage->free(overdraw_material_shader); - storage->free(default_shader); + material_storage->shader_free(overdraw_material_shader); + material_storage->shader_free(default_shader); - storage->free(overdraw_material); - storage->free(default_material); + material_storage->material_free(overdraw_material); + material_storage->material_free(default_material); } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 92db15e3b0..b89fe908d3 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -40,7 +40,7 @@ namespace RendererSceneRenderImplementation { class SceneShaderForwardMobile { private: static SceneShaderForwardMobile *singleton; - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; public: enum ShaderVersion { @@ -57,7 +57,7 @@ public: SHADER_VERSION_MAX }; - struct ShaderData : public RendererStorageRD::ShaderData { + struct ShaderData : public RendererRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -143,7 +143,7 @@ public: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -157,13 +157,13 @@ public: virtual ~ShaderData(); }; - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { + RendererRD::ShaderData *_create_shader_func(); + static RendererRD::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererStorageRD::MaterialData { - ShaderData *shader_data; + struct MaterialData : public RendererRD::MaterialData { + ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; uint32_t index = 0; @@ -177,8 +177,8 @@ public: SelfList<ShaderData>::List shader_list; - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp index e812a48d3d..9151c53823 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp @@ -58,7 +58,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass, specialization_constants); ERR_FAIL_COND_V(pipeline.is_null(), RID()); - versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); + versions = static_cast<Version *>(memrealloc(versions, sizeof(Version) * (version_count + 1))); versions[version_count].framebuffer_id = p_framebuffer_format_id; versions[version_count].vertex_id = p_vertex_format_id; versions[version_count].wireframe = wireframe; diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h index 8d82480b38..1e80381d88 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.h +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h @@ -57,7 +57,7 @@ class PipelineCacheRD { RID pipeline; }; - Version *versions; + Version *versions = nullptr; uint32_t version_count; RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index e6fc50afbf..5b5a39c215 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -35,6 +35,10 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { @@ -105,6 +109,8 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve // This dramatically reduces the amount of pipeline objects // that need to be created for these formats. + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + uint32_t vertex_count = p_points.size(); uint32_t stride = 2; //vertices always repeat if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { @@ -187,7 +193,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[1] = vd; - buffers.write[1] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_COLOR); + buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR); } //uvs @@ -215,7 +221,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[2] = vd; - buffers.write[2] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_TEX_UV); + buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV); } //bones @@ -248,7 +254,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[3] = vd; - buffers.write[3] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES); + buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES); } //weights @@ -281,7 +287,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[4] = vd; - buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_WEIGHTS); + buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS); } //check that everything is as it should be @@ -358,7 +364,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI bool use_normal; bool use_specular; - bool success = storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); + bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); //something odd happened if (!success) { _bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size); @@ -395,6 +401,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { //create an empty push constant + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RS::CanvasItemTextureFilter current_filter = default_filter; RS::CanvasItemTextureRepeat current_repeat = default_repeat; @@ -749,26 +756,26 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } else if (c->type == Item::Command::TYPE_MULTIMESH) { const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c); RID multimesh = mm->multimesh; - mesh = storage->multimesh_get_mesh(multimesh); + mesh = mesh_storage->multimesh_get_mesh(multimesh); texture = mm->texture; - if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { + if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { break; } - instance_count = storage->multimesh_get_instances_to_draw(multimesh); + instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh); if (instance_count == 0) { break; } - RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + RID uniform_set = mesh_storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); push_constant.flags |= 1; //multimesh, trails disabled - if (storage->multimesh_uses_colors(multimesh)) { + if (mesh_storage->multimesh_uses_colors(multimesh)) { push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; } - if (storage->multimesh_uses_custom_data(multimesh)) { + if (mesh_storage->multimesh_uses_custom_data(multimesh)) { push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; } } else if (c->type == Item::Command::TYPE_PARTICLES) { @@ -833,7 +840,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend _bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); - uint32_t surf_count = storage->mesh_get_surface_count(mesh); + uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh); static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; push_constant.modulation[0] = base_color.r * modulate.r; @@ -848,9 +855,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } for (uint32_t j = 0; j < surf_count; j++) { - void *surface = storage->mesh_get_surface(mesh, j); + void *surface = mesh_storage->mesh_get_surface(mesh, j); - RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface); + RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface); ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX); uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask(); @@ -859,15 +866,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID; if (mesh_instance.is_valid()) { - storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format); } else { - storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format); } RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - RID index_array = storage->mesh_surface_get_index_array(surface, 0); + RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0); if (index_array.is_valid()) { RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array); @@ -947,7 +954,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 3; - u.append_id(storage->decal_atlas_get_texture()); + u.append_id(RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture()); uniforms.push_back(u); } @@ -977,7 +984,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } else { screen = storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } u.append_id(screen); @@ -1020,7 +1027,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 9; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -1035,6 +1042,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); Item *current_clip = nullptr; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; @@ -1099,9 +1107,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co } if (material != prev_material) { - MaterialData *material_data = nullptr; + CanvasMaterialData *material_data = nullptr; if (material.is_valid()) { - material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D); + material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); } if (material_data) { @@ -1128,6 +1136,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co } void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + r_sdf_used = false; int item_count = 0; @@ -1253,7 +1264,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p } if (clight->texture.is_valid()) { - Rect2 atlas_rect = storage->decal_atlas_get_texture_rect(clight->texture); + Rect2 atlas_rect = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_rect(clight->texture); state.light_uniforms[index].atlas_rect[0] = atlas_rect.position.x; state.light_uniforms[index].atlas_rect[1] = atlas_rect.position.y; state.light_uniforms[index].atlas_rect[2] = atlas_rect.size.width; @@ -1363,7 +1374,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; if (material.is_valid()) { - MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D); + CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); if (md && md->shader_data->valid) { if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { @@ -1388,7 +1399,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c); if (cm->mesh_instance.is_valid()) { - storage->mesh_instance_check_for_update(cm->mesh_instance); + mesh_storage->mesh_instance_check_for_update(cm->mesh_instance); update_skeletons = true; } } @@ -1400,7 +1411,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (canvas_group_owner == nullptr) { //Canvas group begins here, render until before this item if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); @@ -1423,7 +1434,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (ci == canvas_group_owner) { if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } @@ -1440,7 +1451,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (backbuffer_copy) { //render anything pending, including clearing if no items if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); @@ -1456,7 +1467,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } @@ -1479,18 +1490,20 @@ RID RendererCanvasRenderRD::light_create() { } void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) { + RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton(); + CanvasLight *cl = canvas_light_owner.get_or_null(p_rid); ERR_FAIL_COND(!cl); if (cl->texture == p_texture) { return; } if (cl->texture.is_valid()) { - storage->texture_remove_from_decal_atlas(cl->texture); + decal_atlas_storage->texture_remove_from_decal_atlas(cl->texture); } cl->texture = p_texture; if (cl->texture.is_valid()) { - storage->texture_add_to_decal_atlas(cl->texture); + decal_atlas_storage->texture_add_to_decal_atlas(cl->texture); } } @@ -1935,7 +1948,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS:: oc->cull_mode = p_mode; } -void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { +void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -1973,7 +1986,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); @@ -2117,7 +2130,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { valid = true; } -void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -2134,7 +2147,7 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN } } -void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -2155,13 +2168,13 @@ void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_pa } } -void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -2170,7 +2183,7 @@ void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererSt } } -bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const { +bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -2178,15 +2191,15 @@ bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_pa return uniforms[p_param].texture_order >= 0; } -bool RendererCanvasRenderRD::ShaderData::is_animated() const { +bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const { return false; } -bool RendererCanvasRenderRD::ShaderData::casts_shadows() const { +bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const { return false; } -Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererCanvasRenderRD::CanvasShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -2195,19 +2208,19 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa return Variant(); } -RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const { - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const { + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version); } -RendererCanvasRenderRD::ShaderData::ShaderData() { +RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() { valid = false; uses_screen_texture = false; uses_sdf = false; } -RendererCanvasRenderRD::ShaderData::~ShaderData() { - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() { + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); ERR_FAIL_COND(!canvas_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -2215,23 +2228,23 @@ RendererCanvasRenderRD::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { - ShaderData *shader_data = memnew(ShaderData); +RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { + CanvasShaderData *shader_data = memnew(CanvasShaderData); return shader_data; } -bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } -RendererCanvasRenderRD::MaterialData::~MaterialData() { +RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) { - MaterialData *material_data = memnew(MaterialData); +RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) { + CanvasMaterialData *material_data = memnew(CanvasMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; @@ -2245,6 +2258,8 @@ void RendererCanvasRenderRD::update() { } RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { + RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); storage = p_storage; { //create default samplers @@ -2257,7 +2272,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { String global_defines; - uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); + uint64_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); if (uniform_max_size < 65536) { //Yes, you guessed right, ARM again state.max_lights_per_render = 64; @@ -2359,7 +2374,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { actions.renames["UV"] = "uv"; actions.renames["POINT_SIZE"] = "gl_PointSize"; - actions.renames["WORLD_MATRIX"] = "world_matrix"; + actions.renames["MODEL_MATRIX"] = "model_matrix"; actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform"; actions.renames["SCREEN_MATRIX"] = "canvas_data.screen_transform"; actions.renames["TIME"] = "canvas_data.time"; @@ -2568,29 +2583,29 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.append_id(storage->get_default_rd_storage_buffer()); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); uniforms.push_back(u); } state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); } - default_canvas_texture = storage->canvas_texture_allocate(); - storage->canvas_texture_initialize(default_canvas_texture); + default_canvas_texture = canvas_texture_storage->canvas_texture_allocate(); + canvas_texture_storage->canvas_texture_initialize(default_canvas_texture); state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); //create functions for shader and material - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs); state.time = 0; { - default_canvas_group_shader = storage->shader_allocate(); - storage->shader_initialize(default_canvas_group_shader); + default_canvas_group_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(default_canvas_group_shader); - storage->shader_set_code(default_canvas_group_shader, R"( + material_storage->shader_set_code(default_canvas_group_shader, R"( // Default CanvasGroup shader. shader_type canvas_item; @@ -2605,10 +2620,10 @@ void fragment() { COLOR *= c; } )"); - default_canvas_group_material = storage->material_allocate(); - storage->material_initialize(default_canvas_group_material); + default_canvas_group_material = material_storage->material_allocate(); + material_storage->material_initialize(default_canvas_group_material); - storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); + material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); } static_assert(sizeof(PushConstant) == 128); @@ -2656,10 +2671,11 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) { } RendererCanvasRenderRD::~RendererCanvasRenderRD() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); //canvas state - storage->free(default_canvas_group_material); - storage->free(default_canvas_group_shader); + material_storage->material_free(default_canvas_group_material); + material_storage->shader_free(default_canvas_group_shader); { if (state.canvas_state_buffer.is_valid()) { @@ -2696,6 +2712,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { } RD::get_singleton()->free(state.shadow_texture); - storage->free(default_canvas_texture); + RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture); //pipelines don't need freeing, they are all gone after shaders are gone } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 84f64b6fda..6448e1a664 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -41,7 +41,7 @@ #include "servers/rendering/shader_compiler.h" class RendererCanvasRenderRD : public RendererCanvasRender { - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; enum { BASE_UNIFORM_SET = 0, @@ -151,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { ShaderCompiler compiler; } shader; - struct ShaderData : public RendererStorageRD::ShaderData { + struct CanvasShaderData : public RendererRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -182,7 +182,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -190,28 +190,28 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; - ShaderData(); - virtual ~ShaderData(); + CanvasShaderData(); + virtual ~CanvasShaderData(); }; - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { + RendererRD::ShaderData *_create_shader_func(); + static RendererRD::ShaderData *_create_shader_funcs() { return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererStorageRD::MaterialData { - ShaderData *shader_data; + struct CanvasMaterialData : public RendererRD::MaterialData { + CanvasShaderData *shader_data = nullptr; RID uniform_set; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~MaterialData(); + virtual ~CanvasMaterialData(); }; - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { - return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); + RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader); + static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader)); } /**************************/ @@ -361,7 +361,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t pad2; }; - LightUniform *light_uniforms; + LightUniform *light_uniforms = nullptr; RID lights_uniform_buffer; RID canvas_state_buffer; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index e8978e7dca..5b7c63b508 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -46,7 +46,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID for (int i = 0; i < p_amount; i++) { RID texture = storage->render_target_get_texture(p_render_targets[i].render_target); ERR_CONTINUE(texture.is_null()); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); ERR_CONTINUE(rd_texture.is_null()); // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in. @@ -155,6 +155,11 @@ void RendererCompositorRD::finalize() { memdelete(scene); memdelete(canvas); memdelete(storage); + memdelete(decal_atlas_storage); + memdelete(mesh_storage); + memdelete(material_storage); + memdelete(texture_storage); + memdelete(canvas_texture_storage); //only need to erase these, the rest are erased by cascade blit.shader.version_free(blit.shader_version); @@ -165,9 +170,9 @@ void RendererCompositorRD::finalize() { void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { RD::get_singleton()->prepare_screen_for_drawing(); - RID texture = storage->texture_allocate(); - storage->texture_2d_initialize(texture, p_image); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID texture = texture_storage->texture_allocate(); + texture_storage->texture_2d_initialize(texture, p_image); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); RID uset; { @@ -235,7 +240,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->swap_buffers(); - storage->free(texture); + texture_storage->texture_free(texture); } RendererCompositorRD *RendererCompositorRD::singleton = nullptr; @@ -283,11 +288,16 @@ RendererCompositorRD::RendererCompositorRD() { singleton = this; time = 0; + canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage); + texture_storage = memnew(RendererRD::TextureStorage); + decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage); + material_storage = memnew(RendererRD::MaterialStorage); + mesh_storage = memnew(RendererRD::MeshStorage); storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end"); - uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); if (back_end || textures_per_stage < 48) { scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage)); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index e526b95677..542cff0159 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -39,14 +39,24 @@ #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" class RendererCompositorRD : public RendererCompositor { protected: - UniformSetCacheRD *uniform_set_cache; - RendererCanvasRenderRD *canvas; - RendererStorageRD *storage; - RendererSceneRenderRD *scene; + UniformSetCacheRD *uniform_set_cache = nullptr; + RendererCanvasRenderRD *canvas = nullptr; + RendererRD::CanvasTextureStorage *canvas_texture_storage; + RendererRD::MaterialStorage *material_storage; + RendererRD::MeshStorage *mesh_storage; + RendererRD::TextureStorage *texture_storage; + RendererRD::DecalAtlasStorage *decal_atlas_storage; + RendererStorageRD *storage = nullptr; + RendererSceneRenderRD *scene = nullptr; enum BlitMode { BLIT_MODE_NORMAL, @@ -88,6 +98,11 @@ protected: static uint64_t frame; public: + RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; } + RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; } + RendererMaterialStorage *get_material_storage() { return material_storage; }; + RendererMeshStorage *get_mesh_storage() { return mesh_storage; }; + RendererTextureStorage *get_texture_storage() { return texture_storage; }; RendererStorage *get_storage() { return storage; } RendererCanvasRender *get_canvas() { return canvas; } RendererSceneRender *get_scene() { return scene; } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 8f0e1d36db..75202d5abb 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -40,6 +40,7 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF // SDFGI void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_gi->storage; gi = p_gi; num_cascades = p_env->sdfgi_cascades; @@ -377,7 +378,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -620,7 +621,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -633,7 +634,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -646,7 +647,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -659,7 +660,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1108,6 +1109,8 @@ void RendererSceneGIRD::SDFGI::update_cascades() { } void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -1118,7 +1121,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1131,7 +1134,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1144,7 +1147,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1157,7 +1160,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1455,7 +1458,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j)); ERR_CONTINUE(!li); - if (storage->light_directional_is_sky_only(li->light)) { + if (storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { continue; } @@ -2385,7 +2388,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RID light = p_scene_render->light_instance_get_base_light(light_instance); l.type = storage->light_get_type(light); - if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_is_sky_only(light)) { + if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { light_count--; continue; } @@ -2453,7 +2456,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c passes = 1; //only re-blitting is necessary } int wg_size = 64; - int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X); + int64_t wg_limit_x = (int64_t)RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X); for (int pass = 0; pass < passes; pass++) { if (p_update_light_instances) { @@ -2476,9 +2479,9 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c push_constant.cell_offset = mipmaps[i].cell_offset; push_constant.cell_count = mipmaps[i].cell_count; - int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1; + int64_t wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1; while (wg_todo) { - int wg_count = MIN(wg_todo, wg_limit_x); + int64_t wg_count = MIN(wg_todo, wg_limit_x); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); wg_todo -= wg_count; @@ -2497,9 +2500,9 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c push_constant.cell_offset = mipmaps[i].cell_offset; push_constant.cell_count = mipmaps[i].cell_count; - int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1; + int64_t wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1; while (wg_todo) { - int wg_count = MIN(wg_todo, wg_limit_x); + int64_t wg_count = MIN(wg_todo, wg_limit_x); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); wg_todo -= wg_count; @@ -2807,6 +2810,8 @@ RendererSceneGIRD::~RendererSceneGIRD() { } void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + storage = p_storage; /* GI */ @@ -2924,7 +2929,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); uniforms.push_back(u); } { @@ -3023,6 +3028,8 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme } void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + r_voxel_gi_instances_used = 0; // feels a little dirty to use our container this way but.... @@ -3085,7 +3092,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } if (texture == RID()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } if (texture != rb->gi.voxel_gi_textures[i]) { @@ -3121,6 +3128,8 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RD::get_singleton()->draw_command_begin_label("GI Render"); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); @@ -3186,7 +3195,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3199,7 +3208,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3212,7 +3221,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3225,7 +3234,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3237,7 +3246,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi) { u.append_id(rb->sdfgi->occlusion_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3279,7 +3288,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi) { u.append_id(rb->sdfgi->lightprobe_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3301,7 +3310,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(buffer); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index f2d1a17099..ed60bc4362 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -45,6 +45,7 @@ #include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -54,7 +55,7 @@ class RendererSceneRenderRD; class RendererSceneGIRD { private: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; /* VOXEL_GI INSTANCE */ @@ -330,8 +331,8 @@ public: struct VoxelGIInstance { // access to our containers - RendererStorageRD *storage; - RendererSceneGIRD *gi; + RendererStorageRD *storage = nullptr; + RendererSceneGIRD *gi = nullptr; RID probe; RID texture; @@ -454,8 +455,8 @@ public: }; // access to our containers - RendererStorageRD *storage; - RendererSceneGIRD *gi; + RendererStorageRD *storage = nullptr; + RendererSceneGIRD *gi = nullptr; // used for rendering (voxelization) RID render_albedo; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 14207c6620..ac7ac692ce 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -33,6 +33,9 @@ #include "core/config/project_settings.h" #include "core/os/os.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" void get_vogel_disk(float *r_kernel, int p_sample_count) { @@ -2358,6 +2361,7 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR } void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); @@ -2490,7 +2494,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure_texture = rb->luminance.current; tonemap.auto_exposure_grey = env->auto_exp_scale; } else { - tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } if (can_use_effects && env && env->glow_enabled) { @@ -2506,15 +2510,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_texture = rb->blur[1].texture; if (env->glow_map.is_valid()) { tonemap.glow_map_strength = env->glow_map_strength; - tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map); + tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map); } else { tonemap.glow_map_strength = 0.0f; - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } else { - tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -2536,7 +2540,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && env) { tonemap.use_bcs = env->adjustments_enabled; @@ -2546,7 +2550,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (env->adjustments_enabled && env->color_correction.is_valid()) { tonemap.use_color_correction = true; tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); } } @@ -2570,6 +2574,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RD::get_singleton()->draw_command_begin_label("Post Process Subpass"); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); @@ -2606,14 +2611,14 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr } tonemap.use_glow = false; - tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_auto_exposure = false; - tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && env) { tonemap.use_bcs = env->adjustments_enabled; @@ -2623,7 +2628,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr if (env->adjustments_enabled && env->color_correction.is_valid()) { tonemap.use_color_correction = true; tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); } } @@ -2646,6 +2651,7 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_ } void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); EffectsRD *effects = storage->get_effects(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); @@ -2656,7 +2662,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); if (shadow_atlas_texture.is_null()) { - shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); } Size2 rtsize = storage->render_target_get_size(rb->render_target); @@ -2674,7 +2680,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) { - RID decal_atlas = storage->decal_atlas_get_texture(); + RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture(); if (decal_atlas.is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); @@ -2716,7 +2722,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); + effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); } } } @@ -3262,6 +3268,8 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti } void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) { + RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton(); + Transform3D inverse_transform = p_camera_transform.affine_inverse(); r_directional_light_count = 0; @@ -3286,7 +3294,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const RS::LightType type = storage->light_get_type(base); switch (type) { case RS::LIGHT_DIRECTIONAL: { - if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) { + if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { continue; } @@ -3545,7 +3553,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const RID projector = storage->light_get_projector(base); if (projector.is_valid()) { - Rect2 rect = storage->decal_atlas_get_texture_rect(projector); + Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(projector); if (type == RS::LIGHT_SPOT) { light_data.projector_rect[0] = rect.position.x; @@ -3661,6 +3669,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const } void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) { + RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton(); + Transform3D uv_xform; uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0)); uv_xform.origin = Vector3(-1.0, 0.0, -1.0); @@ -3684,9 +3694,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; - if (storage->decal_is_distance_fade_enabled(decal)) { - float fade_begin = storage->decal_get_distance_fade_begin(decal); - float fade_length = storage->decal_get_distance_fade_length(decal); + if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) { + float fade_begin = decal_atlas_storage->decal_get_distance_fade_begin(decal); + float fade_length = decal_atlas_storage->decal_get_distance_fade_length(decal); if (distance > fade_begin) { if (distance > fade_begin + fade_length) { @@ -3714,15 +3724,15 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const _map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i); } - di->cull_mask = storage->decal_get_cull_mask(decal); + di->cull_mask = decal_atlas_storage->decal_get_cull_mask(decal); Transform3D xform = di->transform; float fade = 1.0; - if (storage->decal_is_distance_fade_enabled(decal)) { + if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) { real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; - float fade_begin = storage->decal_get_distance_fade_begin(decal); - float fade_length = storage->decal_get_distance_fade_length(decal); + float fade_begin = decal_atlas_storage->decal_get_distance_fade_begin(decal); + float fade_length = decal_atlas_storage->decal_get_distance_fade_length(decal); if (distance > fade_begin) { fade = 1.0 - (distance - fade_begin) / fade_length; @@ -3731,7 +3741,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Cluster::DecalData &dd = cluster.decals[i]; - Vector3 decal_extents = storage->decal_get_extents(decal); + Vector3 decal_extents = decal_atlas_storage->decal_get_extents(decal); Transform3D scale_xform; scale_xform.basis.scale(decal_extents); @@ -3744,12 +3754,12 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const dd.normal[0] = normal.x; dd.normal[1] = normal.y; dd.normal[2] = normal.z; - dd.normal_fade = storage->decal_get_normal_fade(decal); + dd.normal_fade = decal_atlas_storage->decal_get_normal_fade(decal); - RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO); - RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION); + RID albedo_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO); + RID emission_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION); if (albedo_tex.is_valid()) { - Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex); + Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(albedo_tex); dd.albedo_rect[0] = rect.position.x; dd.albedo_rect[1] = rect.position.y; dd.albedo_rect[2] = rect.size.x; @@ -3764,10 +3774,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const dd.albedo_rect[3] = 0; } - RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL); + RID normal_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL); if (normal_tex.is_valid()) { - Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex); + Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(normal_tex); dd.normal_rect[0] = rect.position.x; dd.normal_rect[1] = rect.position.y; dd.normal_rect[2] = rect.size.x; @@ -3782,9 +3792,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const dd.normal_rect[3] = 0; } - RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM); + RID orm_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM); if (orm_tex.is_valid()) { - Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex); + Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(orm_tex); dd.orm_rect[0] = rect.position.x; dd.orm_rect[1] = rect.position.y; dd.orm_rect[2] = rect.size.x; @@ -3797,7 +3807,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const } if (emission_tex.is_valid()) { - Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex); + Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(emission_tex); dd.emission_rect[0] = rect.position.x; dd.emission_rect[1] = rect.position.y; dd.emission_rect[2] = rect.size.x; @@ -3809,16 +3819,16 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const dd.emission_rect[3] = 0; } - Color modulate = storage->decal_get_modulate(decal); + Color modulate = decal_atlas_storage->decal_get_modulate(decal); dd.modulate[0] = modulate.r; dd.modulate[1] = modulate.g; dd.modulate[2] = modulate.b; dd.modulate[3] = modulate.a * fade; - dd.emission_energy = storage->decal_get_emission_energy(decal) * fade; - dd.albedo_mix = storage->decal_get_albedo_mix(decal); - dd.mask = storage->decal_get_cull_mask(decal); - dd.upper_fade = storage->decal_get_upper_fade(decal); - dd.lower_fade = storage->decal_get_lower_fade(decal); + dd.emission_energy = decal_atlas_storage->decal_get_emission_energy(decal) * fade; + dd.albedo_mix = decal_atlas_storage->decal_get_albedo_mix(decal); + dd.mask = decal_atlas_storage->decal_get_cull_mask(decal); + dd.upper_fade = decal_atlas_storage->decal_get_upper_fade(decal); + dd.lower_fade = decal_atlas_storage->decal_get_lower_fade(decal); if (current_cluster_builder != nullptr) { current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents); @@ -3855,7 +3865,7 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed."); @@ -3915,13 +3925,13 @@ void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_ } } -void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E->get()); p.info.name = E->key(); //supply name p.index = E->get().instance_index; @@ -3956,7 +3966,7 @@ Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const String } RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version); } @@ -3966,7 +3976,7 @@ RendererSceneRenderRD::FogShaderData::FogShaderData() { } RendererSceneRenderRD::FogShaderData::~FogShaderData() { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -3978,7 +3988,7 @@ RendererSceneRenderRD::FogShaderData::~FogShaderData() { // Fog material bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -3989,23 +3999,23 @@ RendererSceneRenderRD::FogMaterialData::~FogMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() { +RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() { FogShaderData *shader_data = memnew(FogShaderData); return shader_data; } -RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() { +RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() { return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func(); }; -RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); }; @@ -4063,6 +4073,9 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto } void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -4263,7 +4276,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e FogMaterialData *material = nullptr; if (fog_material.is_valid()) { - material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -4271,7 +4284,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (!material) { fog_material = volumetric_fog.default_material; - material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); } ERR_FAIL_COND(!material); @@ -4364,7 +4377,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.binding = 1; ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } else { u.append_id(shadow_atlas->depth); } @@ -4380,7 +4393,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (directional_shadow.depth.is_valid()) { u.append_id(directional_shadow.depth); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -4545,7 +4558,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 19; - RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID(); u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); uniforms.push_back(u); @@ -5488,7 +5501,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto GeometryInstance *gi = geometry_instance_create(p_base); - uint32_t sc = RSG::storage->mesh_get_surface_count(p_base); + uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base); Vector<RID> materials; materials.resize(sc); @@ -5605,6 +5618,8 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { } void RendererSceneRenderRD::init() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + max_cluster_elements = get_max_elements(); directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size"); @@ -5661,8 +5676,8 @@ void RendererSceneRenderRD::init() { volumetric_fog_modes.push_back(""); volumetric_fog.shader.initialize(volumetric_fog_modes); - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); } @@ -5701,9 +5716,9 @@ void RendererSceneRenderRD::init() { { // default material and shader for fog shader - volumetric_fog.default_shader = storage->shader_allocate(); - storage->shader_initialize(volumetric_fog.default_shader); - storage->shader_set_code(volumetric_fog.default_shader, R"( + volumetric_fog.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(volumetric_fog.default_shader); + material_storage->shader_set_code(volumetric_fog.default_shader, R"( // Default fog shader. shader_type fog; @@ -5713,11 +5728,11 @@ void fog() { ALBEDO = vec3(1.0); } )"); - volumetric_fog.default_material = storage->material_allocate(); - storage->material_initialize(volumetric_fog.default_material); - storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); + volumetric_fog.default_material = material_storage->material_allocate(); + material_storage->material_initialize(volumetric_fog.default_material); + material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); - FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG); + FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -5747,7 +5762,7 @@ void fog() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -5816,6 +5831,8 @@ void fog() { } RendererSceneRenderRD::~RendererSceneRenderRD() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { RD::get_singleton()->free(E.value.cubemap); } @@ -5832,20 +5849,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); RD::get_singleton()->free(volumetric_fog.volume_ubo); RD::get_singleton()->free(volumetric_fog.params_ubo); - storage->free(volumetric_fog.default_shader); - storage->free(volumetric_fog.default_material); - } - - RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY); - sky.sky_shader.shader.version_free(md->shader_data->version); - RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer); - RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer); - memdelete_arr(sky.sky_scene_state.directional_lights); - memdelete_arr(sky.sky_scene_state.last_frame_directional_lights); - storage->free(sky.sky_shader.default_shader); - storage->free(sky.sky_shader.default_material); - storage->free(sky.sky_scene_state.fog_shader); - storage->free(sky.sky_scene_state.fog_material); + material_storage->shader_free(volumetric_fog.default_shader); + material_storage->material_free(volumetric_fog.default_material); + } + memdelete_arr(directional_penumbra_shadow_kernel); memdelete_arr(directional_soft_shadow_kernel); memdelete_arr(penumbra_shadow_kernel); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 4a86ced322..b2c8daffb1 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -92,7 +92,7 @@ class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneGIRD; protected: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; double time; double time_step = 0; @@ -314,10 +314,10 @@ private: float shadows_quality_radius = 1.0; float directional_shadow_quality_radius = 1.0; - float *directional_penumbra_shadow_kernel; - float *directional_soft_shadow_kernel; - float *penumbra_shadow_kernel; - float *soft_shadow_kernel; + float *directional_penumbra_shadow_kernel = nullptr; + float *directional_soft_shadow_kernel = nullptr; + float *penumbra_shadow_kernel = nullptr; + float *soft_shadow_kernel = nullptr; int directional_penumbra_shadow_samples = 0; int directional_soft_shadow_samples = 0; int penumbra_shadow_samples = 0; @@ -705,27 +705,27 @@ private: template <class T> struct InstanceSort { float depth; - T *instance; + T *instance = nullptr; bool operator<(const InstanceSort &p_sort) const { return depth < p_sort.depth; } }; - ReflectionData *reflections; + ReflectionData *reflections = nullptr; InstanceSort<ReflectionProbeInstance> *reflection_sort; uint32_t max_reflections; RID reflection_buffer; uint32_t max_reflection_probes_per_instance; uint32_t reflection_count = 0; - DecalData *decals; + DecalData *decals = nullptr; InstanceSort<DecalInstance> *decal_sort; uint32_t max_decals; RID decal_buffer; uint32_t decal_count; - LightData *omni_lights; - LightData *spot_lights; + LightData *omni_lights = nullptr; + LightData *spot_lights = nullptr; InstanceSort<LightInstance> *omni_light_sort; InstanceSort<LightInstance> *spot_light_sort; @@ -735,7 +735,7 @@ private: uint32_t omni_light_count = 0; uint32_t spot_light_count = 0; - DirectionalLightData *directional_lights; + DirectionalLightData *directional_lights = nullptr; uint32_t max_directional_lights; RID directional_light_buffer; @@ -907,7 +907,7 @@ private: void _volumetric_fog_erase(RenderBuffers *rb); void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); - struct FogShaderData : public RendererStorageRD::ShaderData { + struct FogShaderData : public RendererRD::ShaderData { bool valid; RID version; @@ -927,7 +927,7 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; @@ -937,8 +937,8 @@ private: virtual ~FogShaderData(); }; - struct FogMaterialData : public RendererStorageRD::MaterialData { - FogShaderData *shader_data; + struct FogMaterialData : public RendererRD::MaterialData { + FogShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -948,11 +948,11 @@ private: virtual ~FogMaterialData(); }; - RendererStorageRD::ShaderData *_create_fog_shader_func(); - static RendererStorageRD::ShaderData *_create_fog_shader_funcs(); + RendererRD::ShaderData *_create_fog_shader_func(); + static RendererRD::ShaderData *_create_fog_shader_funcs(); - RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader); + RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); + static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); RID shadow_sampler; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 45fc37bd02..061aa8b4aa 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -33,6 +33,8 @@ #include "core/math/math_defs.h" #include "renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" //////////////////////////////////////////////////////////////////////////////// @@ -89,7 +91,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; // !BAS! Contemplate making `SkyShader sky` accessible from this struct or even part of this struct. - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); Error err = scene_singleton->sky.sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); @@ -176,13 +178,13 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par } } -void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -217,7 +219,7 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam } RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version); } @@ -227,7 +229,7 @@ RendererSceneSkyRD::SkyShaderData::SkyShaderData() { } RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -239,7 +241,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { // Sky material bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -621,6 +623,8 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) { } RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { return texture_uniform_sets[p_version]; } @@ -632,7 +636,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.append_id(radiance); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -648,9 +652,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -667,9 +671,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -764,24 +768,24 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, //////////////////////////////////////////////////////////////////////////////// // RendererSceneSkyRD -RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() { +RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { +RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); }; -RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; @@ -793,6 +797,8 @@ RendererSceneSkyRD::RendererSceneSkyRD() { } void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); storage = p_storage; { @@ -829,8 +835,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { } // register our shader funds - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -892,10 +898,10 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { { // default material and shader for sky shader - sky_shader.default_shader = storage->shader_allocate(); - storage->shader_initialize(sky_shader.default_shader); + sky_shader.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(sky_shader.default_shader); - storage->shader_set_code(sky_shader.default_shader, R"( + material_storage->shader_set_code(sky_shader.default_shader, R"( // Default sky shader. shader_type sky; @@ -905,12 +911,12 @@ void sky() { } )"); - sky_shader.default_material = storage->material_allocate(); - storage->material_initialize(sky_shader.default_material); + sky_shader.default_material = material_storage->material_allocate(); + material_storage->material_initialize(sky_shader.default_material); - storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); + material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO)); @@ -943,7 +949,7 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -972,7 +978,7 @@ void sky() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); u.append_id(vfog); uniforms.push_back(u); } @@ -982,10 +988,10 @@ void sky() { { // Need defaults for using fog with clear color - sky_scene_state.fog_shader = storage->shader_allocate(); - storage->shader_initialize(sky_scene_state.fog_shader); + sky_scene_state.fog_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(sky_scene_state.fog_shader); - storage->shader_set_code(sky_scene_state.fog_shader, R"( + material_storage->shader_set_code(sky_scene_state.fog_shader, R"( // Default clear color sky shader. shader_type sky; @@ -996,31 +1002,31 @@ void sky() { COLOR = clear_color.rgb; } )"); - sky_scene_state.fog_material = storage->material_allocate(); - storage->material_initialize(sky_scene_state.fog_material); + sky_scene_state.fog_material = material_storage->material_allocate(); + material_storage->material_initialize(sky_scene_state.fog_material); - storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader); + material_storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader); Vector<RD::Uniform> uniforms; { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } @@ -1050,7 +1056,19 @@ void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) { } RendererSceneSkyRD::~RendererSceneSkyRD() { - // TODO cleanup anything created in init... + // cleanup anything created in init... + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + sky_shader.shader.version_free(md->shader_data->version); + RD::get_singleton()->free(sky_scene_state.directional_light_buffer); + RD::get_singleton()->free(sky_scene_state.uniform_buffer); + memdelete_arr(sky_scene_state.directional_lights); + memdelete_arr(sky_scene_state.last_frame_directional_lights); + material_storage->shader_free(sky_shader.default_shader); + material_storage->material_free(sky_shader.default_material); + material_storage->shader_free(sky_scene_state.fog_shader); + material_storage->material_free(sky_scene_state.fog_material); if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) { RD::get_singleton()->free(sky_scene_state.uniform_set); @@ -1068,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() { } void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); SkyMaterialData *material = nullptr; @@ -1081,7 +1100,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1089,7 +1108,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1163,7 +1182,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b ERR_CONTINUE(base.is_null()); RS::LightType type = storage->light_get_type(base); - if (type == RS::LIGHT_DIRECTIONAL) { + if (type == RS::LIGHT_DIRECTIONAL && storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; Transform3D light_transform = li->transform; Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); @@ -1278,6 +1297,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b } void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); Sky *sky = get_sky(p_env->sky); @@ -1288,7 +1308,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM SkyMaterialData *material = nullptr; if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1296,7 +1316,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1446,6 +1466,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM } void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1463,7 +1484,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1471,13 +1492,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1552,6 +1573,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont } void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1566,7 +1588,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1574,7 +1596,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1636,6 +1658,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u } void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1653,7 +1676,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1661,13 +1684,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 13d24e2508..010e2178a9 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -63,7 +63,7 @@ public: }; private: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; RID index_buffer; @@ -105,7 +105,7 @@ private: // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; - struct SkyShaderData : public RendererStorageRD::ShaderData { + struct SkyShaderData : public RendererRD::ShaderData { bool valid; RID version; @@ -129,7 +129,7 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; @@ -162,8 +162,8 @@ public: UBO ubo; - SkyDirectionalLightData *directional_lights; - SkyDirectionalLightData *last_frame_directional_lights; + SkyDirectionalLightData *directional_lights = nullptr; + SkyDirectionalLightData *last_frame_directional_lights = nullptr; uint32_t max_directional_lights; uint32_t last_frame_directional_light_count; RID directional_light_buffer; @@ -227,8 +227,8 @@ public: RID default_shader_rd; } sky_shader; - struct SkyMaterialData : public RendererStorageRD::MaterialData { - SkyShaderData *shader_data; + struct SkyMaterialData : public RendererRD::MaterialData { + SkyShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -262,7 +262,7 @@ public: Sky *dirty_list = nullptr; //State to track when radiance cubemap needs updating - SkyMaterialData *prev_material; + SkyMaterialData *prev_material = nullptr; Vector3 prev_position; float prev_time; @@ -281,11 +281,11 @@ public: mutable RID_Owner<Sky, true> sky_owner; int roughness_layers; - RendererStorageRD::ShaderData *_create_sky_shader_func(); - static RendererStorageRD::ShaderData *_create_sky_shader_funcs(); + RendererRD::ShaderData *_create_sky_shader_func(); + static RendererRD::ShaderData *_create_sky_shader_funcs(); - RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader); + RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); RendererSceneSkyRD(); void init(RendererStorageRD *p_storage); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index f00931cf47..72f98a4690 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -35,1114 +35,15 @@ #include "core/io/resource_loader.h" #include "core/math/math_defs.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_language.h" -bool RendererStorageRD::can_create_resources_async() const { - return true; -} - -Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { - Ref<Image> image = p_image->duplicate(); - - switch (p_image->get_format()) { - case Image::FORMAT_L8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //luminance - case Image::FORMAT_LA8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; - } break; //luminance-alpha - case Image::FORMAT_R8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RG8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGB8: { - //this format is not mandatory for specification, check if supported first - if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBA8: { - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGBA4444: { - r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGB565: { - r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RF: { - r_format.format = RD::DATA_FORMAT_R32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float - case Image::FORMAT_RGF: { - r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBF: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - image->convert(Image::FORMAT_RGBAF); - } - - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAF: { - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RH: { - r_format.format = RD::DATA_FORMAT_R16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //half float - case Image::FORMAT_RGH: { - r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBH: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->convert(Image::FORMAT_RGBAH); - } - - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAH: { - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RGBE9995: { - r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; -#ifndef _MSC_VER -#warning TODO need to make a function in Image to swap bits for this -#endif - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; - } break; - case Image::FORMAT_DXT1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //s3tc bc1 - case Image::FORMAT_DXT3: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //bc2 - case Image::FORMAT_DXT5: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; //bc3 - case Image::FORMAT_RGTC_R: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGTC_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_BPTC_RGBA: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //btpc bc7 - case Image::FORMAT_BPTC_RGBF: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float bc6h - case Image::FORMAT_BPTC_RGBFU: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //unsigned float bc6hu - case Image::FORMAT_ETC2_R11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //etc2 - case Image::FORMAT_ETC2_R11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //signed: {} break; NOT srgb. - case Image::FORMAT_ETC2_RG11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC2_RG11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC: - case Image::FORMAT_ETC2_RGB8: { - //ETC2 is backwards compatible with ETC1, and all modern platforms support it - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_ETC2_RGBA8: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RGB8A1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_DXT5_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - - default: { - } - } - - return image; -} - -RID RendererStorageRD::texture_allocate() { - return texture_owner.allocate_rid(); -} - -void RendererStorageRD::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(p_image->is_empty()); - - TextureToRDFormat ret_format; - Ref<Image> image = _validate_texture_format(p_image, ret_format); - - Texture texture; - - texture.type = Texture::TYPE_2D; - - texture.width = p_image->get_width(); - texture.height = p_image->get_height(); - texture.layers = 1; - texture.mipmaps = p_image->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_image->get_format(); - texture.validated_format = image->get_format(); - - texture.rd_type = RD::TEXTURE_TYPE_2D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<uint8_t> data = image->get_data(); //use image data - Vector<Vector<uint8_t>> data_slices; - data_slices.push_back(data); - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { - ERR_FAIL_COND(p_layers.size() == 0); - - ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); - ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0)); - - TextureToRDFormat ret_format; - Vector<Ref<Image>> images; - { - int valid_width = 0; - int valid_height = 0; - bool valid_mipmaps = false; - Image::Format valid_format = Image::FORMAT_MAX; - - for (int i = 0; i < p_layers.size(); i++) { - ERR_FAIL_COND(p_layers[i]->is_empty()); - - if (i == 0) { - valid_width = p_layers[i]->get_width(); - valid_height = p_layers[i]->get_height(); - valid_format = p_layers[i]->get_format(); - valid_mipmaps = p_layers[i]->has_mipmaps(); - } else { - ERR_FAIL_COND(p_layers[i]->get_width() != valid_width); - ERR_FAIL_COND(p_layers[i]->get_height() != valid_height); - ERR_FAIL_COND(p_layers[i]->get_format() != valid_format); - ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps); - } - - images.push_back(_validate_texture_format(p_layers[i], ret_format)); - } - } - - Texture texture; - - texture.type = Texture::TYPE_LAYERED; - texture.layered_type = p_layered_type; - - texture.width = p_layers[0]->get_width(); - texture.height = p_layers[0]->get_height(); - texture.layers = p_layers.size(); - texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_layers[0]->get_format(); - texture.validated_format = images[0]->get_format(); - - switch (p_layered_type) { - case RS::TEXTURE_LAYERED_2D_ARRAY: { - texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; - } break; - case RS::TEXTURE_LAYERED_CUBEMAP: { - texture.rd_type = RD::TEXTURE_TYPE_CUBE; - } break; - case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { - texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - } break; - } - - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = texture.layers; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<Vector<uint8_t>> data_slices; - for (int i = 0; i < images.size(); i++) { - Vector<uint8_t> data = images[i]->get_data(); //use image data - data_slices.push_back(data); - } - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { - ERR_FAIL_COND(p_data.size() == 0); - Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); - if (verr != Image::VALIDATE_3D_OK) { - ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); - } - - TextureToRDFormat ret_format; - Image::Format validated_format = Image::FORMAT_MAX; - Vector<uint8_t> all_data; - uint32_t mipmap_count = 0; - Vector<Texture::BufferSlice3D> slices; - { - Vector<Ref<Image>> images; - uint32_t all_data_size = 0; - images.resize(p_data.size()); - for (int i = 0; i < p_data.size(); i++) { - TextureToRDFormat f; - images.write[i] = _validate_texture_format(p_data[i], f); - if (i == 0) { - ret_format = f; - validated_format = images[0]->get_format(); - } - - all_data_size += images[i]->get_data().size(); - } - - all_data.resize(all_data_size); //consolidate all data here - uint32_t offset = 0; - Size2i prev_size; - for (int i = 0; i < p_data.size(); i++) { - uint32_t s = images[i]->get_data().size(); - - memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); - { - Texture::BufferSlice3D slice; - slice.size.width = images[i]->get_width(); - slice.size.height = images[i]->get_height(); - slice.offset = offset; - slice.buffer_size = s; - slices.push_back(slice); - } - offset += s; - - Size2i img_size(images[i]->get_width(), images[i]->get_height()); - if (img_size != prev_size) { - mipmap_count++; - } - prev_size = img_size; - } - } - - Texture texture; - - texture.type = Texture::TYPE_3D; - texture.width = p_width; - texture.height = p_height; - texture.depth = p_depth; - texture.mipmaps = mipmap_count; - texture.format = p_data[0]->get_format(); - texture.validated_format = validated_format; - - texture.buffer_size_3d = all_data.size(); - texture.buffer_slices_3d = slices; - - texture.rd_type = RD::TEXTURE_TYPE_3D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = texture.depth; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<Vector<uint8_t>> data_slices; - data_slices.push_back(all_data); //one slice - - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) { - Texture *tex = texture_owner.get_or_null(p_base); - ERR_FAIL_COND(!tex); - Texture proxy_tex = *tex; - - proxy_tex.rd_view.format_override = tex->rd_format; - proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - if (proxy_tex.rd_texture_srgb.is_valid()) { - proxy_tex.rd_view.format_override = tex->rd_format_srgb; - proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - } - proxy_tex.proxy_to = p_base; - proxy_tex.is_render_target = false; - proxy_tex.is_proxy = true; - proxy_tex.proxies.clear(); - - texture_owner.initialize_rid(p_texture, proxy_tex); - - tex->proxies.push_back(p_texture); -} - -void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { - ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); - - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->is_render_target); - ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); - ERR_FAIL_COND(p_image->get_format() != tex->format); - - if (tex->type == Texture::TYPE_LAYERED) { - ERR_FAIL_INDEX(p_layer, tex->layers); - } - -#ifdef TOOLS_ENABLED - tex->image_cache_2d.unref(); -#endif - TextureToRDFormat f; - Ref<Image> validated = _validate_texture_format(p_image, f); - - RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data()); -} - -void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { - _texture_2d_update(p_texture, p_image, p_layer, false); -} - -void RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_3D); - Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); - if (verr != Image::VALIDATE_3D_OK) { - ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); - } - - Vector<uint8_t> all_data; - { - Vector<Ref<Image>> images; - uint32_t all_data_size = 0; - images.resize(p_data.size()); - for (int i = 0; i < p_data.size(); i++) { - Ref<Image> image = p_data[i]; - if (image->get_format() != tex->validated_format) { - image = image->duplicate(); - image->convert(tex->validated_format); - } - all_data_size += images[i]->get_data().size(); - images.push_back(image); - } - - all_data.resize(all_data_size); //consolidate all data here - uint32_t offset = 0; - - for (int i = 0; i < p_data.size(); i++) { - uint32_t s = images[i]->get_data().size(); - memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); - offset += s; - } - } - - RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); -} - -void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(!tex->is_proxy); - Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); - ERR_FAIL_COND(!proxy_to); - ERR_FAIL_COND(proxy_to->is_proxy); - - if (tex->proxy_to.is_valid()) { - //unlink proxy - if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { - RD::get_singleton()->free(tex->rd_texture); - tex->rd_texture = RID(); - } - if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { - RD::get_singleton()->free(tex->rd_texture_srgb); - tex->rd_texture_srgb = RID(); - } - Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); - ERR_FAIL_COND(!prev_tex); - prev_tex->proxies.erase(p_texture); - } - - *tex = *proxy_to; - - tex->proxy_to = p_proxy_to; - tex->is_render_target = false; - tex->is_proxy = true; - tex->proxies.clear(); - proxy_to->proxies.push_back(p_texture); - - tex->rd_view.format_override = tex->rd_format; - tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - if (tex->rd_texture_srgb.is_valid()) { - tex->rd_view.format_override = tex->rd_format_srgb; - tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - } -} - -//these two APIs can be used together or in combination with the others. -void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - texture_2d_initialize(p_texture, image); -} - -void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { - images.push_back(image); - } else { - //cube - for (int i = 0; i < 6; i++) { - images.push_back(image); - } - } - - texture_2d_layered_initialize(p_texture, images, p_layered_type); -} - -void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - //cube - for (int i = 0; i < 4; i++) { - images.push_back(image); - } - - texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); -} - -Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { - return tex->image_cache_2d; - } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { - tex->image_cache_2d = image; - } -#endif - - return image; -} - -Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - - return image; -} - -Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); - ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); - - Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - - ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); - - Vector<Ref<Image>> ret; - - for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { - const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; - ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); - ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); - Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); - - Ref<Image> img; - img.instantiate(); - img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); - ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); - if (tex->format != tex->validated_format) { - img->convert(tex->format); - } - - ret.push_back(img); - } - - return ret; -} - -void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy - Texture *by_tex = texture_owner.get_or_null(p_by_texture); - ERR_FAIL_COND(!by_tex); - ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy - - if (tex == by_tex) { - return; - } - - if (tex->rd_texture_srgb.is_valid()) { - RD::get_singleton()->free(tex->rd_texture_srgb); - } - RD::get_singleton()->free(tex->rd_texture); - - if (tex->canvas_texture) { - memdelete(tex->canvas_texture); - tex->canvas_texture = nullptr; - } - - Vector<RID> proxies_to_update = tex->proxies; - Vector<RID> proxies_to_redirect = by_tex->proxies; - - *tex = *by_tex; - - tex->proxies = proxies_to_update; //restore proxies, so they can be updated - - if (tex->canvas_texture) { - tex->canvas_texture->diffuse = p_texture; //update - } - - for (int i = 0; i < proxies_to_update.size(); i++) { - texture_proxy_update(proxies_to_update[i], p_texture); - } - for (int i = 0; i < proxies_to_redirect.size(); i++) { - texture_proxy_update(proxies_to_redirect[i], p_texture); - } - //delete last, so proxies can be updated - texture_owner.free(p_by_texture); - - if (decal_atlas.textures.has(p_texture)) { - //belongs to decal atlas.. - - decal_atlas.dirty = true; //mark it dirty since it was most likely modified - } -} - -void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_2D); - tex->width_2d = p_width; - tex->height_2d = p_height; -} - -void RendererStorageRD::texture_set_path(RID p_texture, const String &p_path) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->path = p_path; -} - -String RendererStorageRD::texture_get_path(RID p_texture) const { - return String(); -} - -void RendererStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_3d_callback_ud = p_userdata; - tex->detect_3d_callback = p_callback; -} - -void RendererStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_normal_callback_ud = p_userdata; - tex->detect_normal_callback = p_callback; -} - -void RendererStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_roughness_callback_ud = p_userdata; - tex->detect_roughness_callback = p_callback; -} - -void RendererStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) { -} - -void RendererStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { -} - -void RendererStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { -} - -Size2 RendererStorageRD::texture_size_with_proxy(RID p_proxy) { - return texture_2d_get_size(p_proxy); -} - /* CANVAS TEXTURE */ -void RendererStorageRD::CanvasTexture::clear_sets() { - if (cleared_cache) { - return; - } - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { - RD::get_singleton()->free(uniform_sets[i][j]); - uniform_sets[i][j] = RID(); - } - } - } - cleared_cache = true; -} - -RendererStorageRD::CanvasTexture::~CanvasTexture() { - clear_sets(); -} - void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { @@ -1237,3247 +138,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { } } -RID RendererStorageRD::canvas_texture_allocate() { - return canvas_texture_owner.allocate_rid(); -} -void RendererStorageRD::canvas_texture_initialize(RID p_rid) { - canvas_texture_owner.initialize_rid(p_rid); -} - -void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - switch (p_channel) { - case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { - ct->diffuse = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { - ct->normal_map = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { - ct->specular = p_texture; - } break; - } - - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->specular_color.r = p_specular_color.r; - ct->specular_color.g = p_specular_color.g; - ct->specular_color.b = p_specular_color.b; - ct->specular_color.a = p_shininess; - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_filter = p_filter; - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_repeat = p_repeat; - ct->clear_sets(); -} - -bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { - CanvasTexture *ct = nullptr; - - Texture *t = texture_owner.get_or_null(p_texture); - - if (t) { - //regular texture - if (!t->canvas_texture) { - t->canvas_texture = memnew(CanvasTexture); - t->canvas_texture->diffuse = p_texture; - } - - ct = t->canvas_texture; - } else { - ct = canvas_texture_owner.get_or_null(p_texture); - } - - if (!ct) { - return false; //invalid texture RID - } - - RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; - ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); - - RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; - ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); - - RID uniform_set = ct->uniform_sets[filter][repeat]; - if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //create and update - Vector<RD::Uniform> uniforms; - { //diffuse - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - - t = texture_owner.get_or_null(ct->diffuse); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); - ct->size_cache = Size2i(1, 1); - } else { - u.append_id(t->rd_texture); - ct->size_cache = Size2i(t->width_2d, t->height_2d); - } - uniforms.push_back(u); - } - { //normal - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - - t = texture_owner.get_or_null(ct->normal_map); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); - ct->use_normal_cache = false; - } else { - u.append_id(t->rd_texture); - ct->use_normal_cache = true; - } - uniforms.push_back(u); - } - { //specular - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - - t = texture_owner.get_or_null(ct->specular); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); - ct->use_specular_cache = false; - } else { - u.append_id(t->rd_texture); - ct->use_specular_cache = true; - } - uniforms.push_back(u); - } - { //sampler - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 3; - u.append_id(sampler_rd_get_default(filter, repeat)); - uniforms.push_back(u); - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); - ct->uniform_sets[filter][repeat] = uniform_set; - ct->cleared_cache = false; - } - - r_uniform_set = uniform_set; - r_size = ct->size_cache; - r_specular_shininess = ct->specular_color; - r_use_normal = ct->use_normal_cache; - r_use_specular = ct->use_specular_cache; - - return true; -} - -/* SHADER API */ - -RID RendererStorageRD::shader_allocate() { - return shader_owner.allocate_rid(); -} -void RendererStorageRD::shader_initialize(RID p_rid) { - Shader shader; - shader.data = nullptr; - shader.type = SHADER_TYPE_MAX; - - shader_owner.initialize_rid(p_rid, shader); -} - -void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - - shader->code = p_code; - String mode_string = ShaderLanguage::get_shader_type(p_code); - - ShaderType new_type; - if (mode_string == "canvas_item") { - new_type = SHADER_TYPE_2D; - } else if (mode_string == "particles") { - new_type = SHADER_TYPE_PARTICLES; - } else if (mode_string == "spatial") { - new_type = SHADER_TYPE_3D; - } else if (mode_string == "sky") { - new_type = SHADER_TYPE_SKY; - } else if (mode_string == "fog") { - new_type = SHADER_TYPE_FOG; - } else { - new_type = SHADER_TYPE_MAX; - } - - if (new_type != shader->type) { - if (shader->data) { - memdelete(shader->data); - shader->data = nullptr; - } - - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - material->shader_type = new_type; - if (material->data) { - memdelete(material->data); - material->data = nullptr; - } - } - - shader->type = new_type; - - if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) { - shader->data = shader_data_request_func[new_type](); - } else { - shader->type = SHADER_TYPE_MAX; //invalid - } - - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - if (shader->data) { - material->data = material_data_request_func[new_type](shader->data); - material->data->self = material->self; - material->data->set_next_pass(material->next_pass); - material->data->set_render_priority(material->priority); - } - material->shader_type = new_type; - } - - if (shader->data) { - for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { - for (const KeyValue<int, RID> &E2 : E.value) { - shader->data->set_default_texture_param(E.key, E2.value, E2.key); - } - } - } - } - - if (shader->data) { - shader->data->set_code(p_code); - } - - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - _material_queue_update(material, true, true); - } -} - -String RendererStorageRD::shader_get_code(RID p_shader) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, String()); - return shader->code; -} - -void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - if (shader->data) { - return shader->data->get_param_list(p_param_list); - } -} - -void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - - if (p_texture.is_valid() && texture_owner.owns(p_texture)) { - if (!shader->default_texture_parameter.has(p_name)) { - shader->default_texture_parameter[p_name] = Map<int, RID>(); - } - shader->default_texture_parameter[p_name][p_index] = p_texture; - } else { - if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { - shader->default_texture_parameter[p_name].erase(p_index); - - if (shader->default_texture_parameter[p_name].is_empty()) { - shader->default_texture_parameter.erase(p_name); - } - } - } - if (shader->data) { - shader->data->set_default_texture_param(p_name, p_texture, p_index); - } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - _material_queue_update(material, false, true); - } -} - -RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, RID()); - if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { - return shader->default_texture_parameter[p_name][p_index]; - } - - return RID(); -} - -Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, Variant()); - if (shader->data) { - return shader->data->get_default_parameter(p_param); - } - return Variant(); -} - -void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { - ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); - shader_data_request_func[p_shader_type] = p_function; -} - -RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); - if (shader->data) { - return shader->data->get_native_source_code(); - } - return RS::ShaderNativeSourceCode(); -} - -/* COMMON MATERIAL API */ - -RID RendererStorageRD::material_allocate() { - return material_owner.allocate_rid(); -} -void RendererStorageRD::material_initialize(RID p_rid) { - material_owner.initialize_rid(p_rid); - Material *material = material_owner.get_or_null(p_rid); - material->self = p_rid; -} - -void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { - material->uniform_dirty = material->uniform_dirty || p_uniform; - material->texture_dirty = material->texture_dirty || p_texture; - - if (material->update_element.in_list()) { - return; - } - - material_update_list.add(&material->update_element); -} - -void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - - if (material->data) { - memdelete(material->data); - material->data = nullptr; - } - - if (material->shader) { - material->shader->owners.erase(material); - material->shader = nullptr; - material->shader_type = SHADER_TYPE_MAX; - } - - if (p_shader.is_null()) { - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - material->shader_id = 0; - return; - } - - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - material->shader = shader; - material->shader_type = shader->type; - material->shader_id = p_shader.get_local_index(); - shader->owners.insert(material); - - if (shader->type == SHADER_TYPE_MAX) { - return; - } - - ERR_FAIL_COND(shader->data == nullptr); - - material->data = material_data_request_func[shader->type](shader->data); - material->data->self = p_material; - material->data->set_next_pass(material->next_pass); - material->data->set_render_priority(material->priority); - //updating happens later - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - _material_queue_update(material, true, true); -} - -void RendererStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type() == Variant::NIL) { - material->params.erase(p_param); - } else { - ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed - material->params[p_param] = p_value; - } - - if (material->shader && material->shader->data) { //shader is valid - bool is_texture = material->shader->data->is_param_texture(p_param); - _material_queue_update(material, !is_texture, is_texture); - } else { - _material_queue_update(material, true, true); - } -} - -Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, Variant()); - if (material->params.has(p_param)) { - return material->params[p_param]; - } else { - return Variant(); - } -} - -void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - - if (material->next_pass == p_next_material) { - return; - } - - material->next_pass = p_next_material; - if (material->data) { - material->data->set_next_pass(p_next_material); - } - - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); -} - -void RendererStorageRD::material_set_render_priority(RID p_material, int priority) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - material->priority = priority; - if (material->data) { - material->data->set_render_priority(priority); - } -} - -bool RendererStorageRD::material_is_animated(RID p_material) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, false); - if (material->shader && material->shader->data) { - if (material->shader->data->is_animated()) { - return true; - } else if (material->next_pass.is_valid()) { - return material_is_animated(material->next_pass); - } - } - return false; //by default nothing is animated -} - -bool RendererStorageRD::material_casts_shadows(RID p_material) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, true); - if (material->shader && material->shader->data) { - if (material->shader->data->casts_shadows()) { - return true; - } else if (material->next_pass.is_valid()) { - return material_casts_shadows(material->next_pass); - } - } - return true; //by default everything casts shadows -} - -void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - if (material->shader && material->shader->data) { - material->shader->data->get_instance_param_list(r_parameters); - - if (material->next_pass.is_valid()) { - material_get_instance_shader_parameters(material->next_pass, r_parameters); - } - } -} - -void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - p_instance->update_dependency(&material->dependency); - if (material->next_pass.is_valid()) { - material_update_dependency(material->next_pass, p_instance); - } -} - -void RendererStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { - ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); - material_data_request_func[p_shader_type] = p_function; -} - -_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) { - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = (r[i] != 0) ? 1 : 0; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - bool v = value; - gui[0] = v ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_BVEC2: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - int count = 2 * p_array_size; - - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i] ? 1 : 0; - gui[j + 1] = r[i + 1] ? 1 : 0; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = v & 1 ? 1 : 0; - gui[1] = v & 2 ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_BVEC3: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - int count = 3 * p_array_size; - - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i] ? 1 : 0; - gui[j + 1] = r[i + 1] ? 1 : 0; - gui[j + 2] = r[i + 2] ? 1 : 0; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = (v & 1) ? 1 : 0; - gui[1] = (v & 2) ? 1 : 0; - gui[2] = (v & 4) ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_BVEC4: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - int count = 4 * p_array_size; - - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i] ? 1 : 0; - gui[i + 1] = r[i + 1] ? 1 : 0; - gui[i + 2] = r[i + 2] ? 1 : 0; - gui[i + 3] = r[i + 3] ? 1 : 0; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } else { - int v = value; - gui[0] = (v & 1) ? 1 : 0; - gui[1] = (v & 2) ? 1 : 0; - gui[2] = (v & 4) ? 1 : 0; - gui[3] = (v & 8) ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_INT: { - int32_t *gui = (int32_t *)data; - - if (p_array_size > 0) { - Vector<int> iv = value; - int s = iv.size(); - const int *r = iv.ptr(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = r[i]; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = v; - } - } break; - case ShaderLanguage::TYPE_IVEC2: { - Vector<int> iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_IVEC3: { - Vector<int> iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_IVEC4: { - Vector<int> iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } break; - case ShaderLanguage::TYPE_UINT: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - Vector<int> iv = value; - int s = iv.size(); - const int *r = iv.ptr(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = r[i]; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = v; - } - } break; - case ShaderLanguage::TYPE_UVEC2: { - Vector<int> iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - Vector<int> iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_UVEC4: { - Vector<int> iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i++) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = a[i]; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - float v = value; - gui[0] = v; - } - } break; - case ShaderLanguage::TYPE_VEC2: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedVector2Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = a[i].x; - gui[j + 1] = a[i].y; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - Vector2 v = value; - gui[0] = v.x; - gui[1] = v.y; - } - } break; - case ShaderLanguage::TYPE_VEC3: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedVector3Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = a[i].x; - gui[j + 1] = a[i].y; - gui[j + 2] = a[i].z; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } else { - Vector3 v = value; - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - } - } break; - case ShaderLanguage::TYPE_VEC4: { - float *gui = (float *)data; - - if (p_array_size > 0) { - if (value.get_type() == Variant::PACKED_COLOR_ARRAY) { - const PackedColorArray &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - Color color = a[i]; - if (p_linear_color) { - color = color.to_linear(); - } - gui[j] = color.r; - gui[j + 1] = color.g; - gui[j + 2] = color.b; - gui[j + 3] = color.a; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - gui[j + 3] = 0; - } - } - } else { - const PackedFloat32Array &a = value; - int s = a.size(); - int count = 4 * p_array_size; - - for (int i = 0; i < count; i += 4) { - if (i + 3 < s) { - gui[i] = a[i]; - gui[i + 1] = a[i + 1]; - gui[i + 2] = a[i + 2]; - gui[i + 3] = a[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } - } else { - if (value.get_type() == Variant::COLOR) { - Color v = value; - - if (p_linear_color) { - v = v.to_linear(); - } - - gui[0] = v.r; - gui[1] = v.g; - gui[2] = v.b; - gui[3] = v.a; - } else if (value.get_type() == Variant::RECT2) { - Rect2 v = value; - - gui[0] = v.position.x; - gui[1] = v.position.y; - gui[2] = v.size.x; - gui[3] = v.size.y; - } else if (value.get_type() == Variant::QUATERNION) { - Quaternion v = value; - - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - gui[3] = v.w; - } else { - Plane v = value; - - gui[0] = v.normal.x; - gui[1] = v.normal.y; - gui[2] = v.normal.z; - gui[3] = v.d; - } - } - } break; - case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) { - if (i + 3 < s) { - gui[j] = a[i]; - gui[j + 1] = a[i + 1]; - - gui[j + 4] = a[i + 2]; - gui[j + 5] = a[i + 3]; - } else { - gui[j] = 1; - gui[j + 1] = 0; - - gui[j + 4] = 0; - gui[j + 5] = 1; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - gui[j + 6] = 0; // ignored - gui[j + 7] = 0; // ignored - } - } else { - Transform2D v = value; - - //in std140 members of mat2 are treated as vec4s - gui[0] = v.elements[0][0]; - gui[1] = v.elements[0][1]; - gui[2] = 0; // ignored - gui[3] = 0; // ignored - - gui[4] = v.elements[1][0]; - gui[5] = v.elements[1][1]; - gui[6] = 0; // ignored - gui[7] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_MAT3: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) { - if (i + 8 < s) { - gui[j] = a[i]; - gui[j + 1] = a[i + 1]; - gui[j + 2] = a[i + 2]; - - gui[j + 4] = a[i + 3]; - gui[j + 5] = a[i + 4]; - gui[j + 6] = a[i + 5]; - - gui[j + 8] = a[i + 6]; - gui[j + 9] = a[i + 7]; - gui[j + 10] = a[i + 8]; - } else { - gui[j] = 1; - gui[j + 1] = 0; - gui[j + 2] = 0; - - gui[j + 4] = 0; - gui[j + 5] = 1; - gui[j + 6] = 0; - - gui[j + 8] = 0; - gui[j + 9] = 0; - gui[j + 10] = 1; - } - gui[j + 3] = 0; // ignored - gui[j + 7] = 0; // ignored - gui[j + 11] = 0; // ignored - } - } else { - Basis v = value; - gui[0] = v.elements[0][0]; - gui[1] = v.elements[1][0]; - gui[2] = v.elements[2][0]; - gui[3] = 0; // ignored - - gui[4] = v.elements[0][1]; - gui[5] = v.elements[1][1]; - gui[6] = v.elements[2][1]; - gui[7] = 0; // ignored - - gui[8] = v.elements[0][2]; - gui[9] = v.elements[1][2]; - gui[10] = v.elements[2][2]; - gui[11] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_MAT4: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0; i < p_array_size * 16; i += 16) { - if (i + 15 < s) { - gui[i] = a[i]; - gui[i + 1] = a[i + 1]; - gui[i + 2] = a[i + 2]; - gui[i + 3] = a[i + 3]; - - gui[i + 4] = a[i + 4]; - gui[i + 5] = a[i + 5]; - gui[i + 6] = a[i + 6]; - gui[i + 7] = a[i + 7]; - - gui[i + 8] = a[i + 8]; - gui[i + 9] = a[i + 9]; - gui[i + 10] = a[i + 10]; - gui[i + 11] = a[i + 11]; - - gui[i + 12] = a[i + 12]; - gui[i + 13] = a[i + 13]; - gui[i + 14] = a[i + 14]; - gui[i + 15] = a[i + 15]; - } else { - gui[i] = 1; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - - gui[i + 4] = 0; - gui[i + 5] = 1; - gui[i + 6] = 0; - gui[i + 7] = 0; - - gui[i + 8] = 0; - gui[i + 9] = 0; - gui[i + 10] = 1; - gui[i + 11] = 0; - - gui[i + 12] = 0; - gui[i + 13] = 0; - gui[i + 14] = 0; - gui[i + 15] = 1; - } - } - } else { - Transform3D v = value; - gui[0] = v.basis.elements[0][0]; - gui[1] = v.basis.elements[1][0]; - gui[2] = v.basis.elements[2][0]; - gui[3] = 0; - - gui[4] = v.basis.elements[0][1]; - gui[5] = v.basis.elements[1][1]; - gui[6] = v.basis.elements[2][1]; - gui[7] = 0; - - gui[8] = v.basis.elements[0][2]; - gui[9] = v.basis.elements[1][2]; - gui[10] = v.basis.elements[2][2]; - gui[11] = 0; - - gui[12] = v.origin.x; - gui[13] = v.origin.y; - gui[14] = v.origin.z; - gui[15] = 1; - } - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) { - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - uint32_t *gui = (uint32_t *)data; - *gui = value[0].boolean ? 1 : 0; - } break; - case ShaderLanguage::TYPE_BVEC2: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC3: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - gui[2] = value[2].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC4: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - gui[2] = value[2].boolean ? 1 : 0; - gui[3] = value[3].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_INT: { - int32_t *gui = (int32_t *)data; - gui[0] = value[0].sint; - - } break; - case ShaderLanguage::TYPE_IVEC2: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC3: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC4: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_UINT: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].uint; - - } break; - case ShaderLanguage::TYPE_UVEC2: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].uint; - } - - } break; - case ShaderLanguage::TYPE_UVEC4: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - float *gui = (float *)data; - gui[0] = value[0].real; - - } break; - case ShaderLanguage::TYPE_VEC2: { - float *gui = (float *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC3: { - float *gui = (float *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC4: { - float *gui = (float *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].real; - } - } break; - case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; - - //in std140 members of mat2 are treated as vec4s - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = 0; - gui[3] = 0; - gui[4] = value[2].real; - gui[5] = value[3].real; - gui[6] = 0; - gui[7] = 0; - } break; - case ShaderLanguage::TYPE_MAT3: { - float *gui = (float *)data; - - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = value[2].real; - gui[3] = 0; - gui[4] = value[3].real; - gui[5] = value[4].real; - gui[6] = value[5].real; - gui[7] = 0; - gui[8] = value[6].real; - gui[9] = value[7].real; - gui[10] = value[8].real; - gui[11] = 0; - } break; - case ShaderLanguage::TYPE_MAT4: { - float *gui = (float *)data; - - for (int i = 0; i < 16; i++) { - gui[i] = value[i].real; - } - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) { - if (p_array_size <= 0) { - p_array_size = 1; - } - - switch (type) { - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_INT: - case ShaderLanguage::TYPE_UINT: - case ShaderLanguage::TYPE_FLOAT: { - memset(data, 0, 4 * p_array_size); - } break; - case ShaderLanguage::TYPE_BVEC2: - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_VEC2: { - memset(data, 0, 8 * p_array_size); - } break; - case ShaderLanguage::TYPE_BVEC3: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_VEC3: - case ShaderLanguage::TYPE_BVEC4: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC4: - case ShaderLanguage::TYPE_VEC4: { - memset(data, 0, 16 * p_array_size); - } break; - case ShaderLanguage::TYPE_MAT2: { - memset(data, 0, 32 * p_array_size); - } break; - case ShaderLanguage::TYPE_MAT3: { - memset(data, 0, 48 * p_array_size); - } break; - case ShaderLanguage::TYPE_MAT4: { - memset(data, 0, 64 * p_array_size); - } break; - - default: { - } - } -} - -void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { - bool uses_global_buffer = false; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) { - if (E.value.order < 0) { - continue; // texture, does not go here - } - - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; //instance uniforms don't appear in the buffer - } - - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { - //this is a global variable, get the index to it - RendererStorageRD *rs = base_singleton; - - GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E.key); - uint32_t index = 0; - if (gv) { - index = gv->buffer_index; - } else { - WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly."); - } - - uint32_t offset = p_uniform_offsets[E.value.order]; - uint32_t *intptr = (uint32_t *)&p_buffer[offset]; - *intptr = index; - uses_global_buffer = true; - continue; - } - - //regular uniform - uint32_t offset = p_uniform_offsets[E.value.order]; -#ifdef DEBUG_ENABLED - uint32_t size = 0U; - // The following code enforces a 16-byte alignment of uniform arrays. - if (E.value.array_size > 0) { - size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size; - int m = (16 * E.value.array_size); - if ((size % m) != 0U) { - size += m - (size % m); - } - } else { - size = ShaderLanguage::get_datatype_size(E.value.type); - } - ERR_CONTINUE(offset + size > p_buffer_size); -#endif - uint8_t *data = &p_buffer[offset]; - const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); - - if (V) { - //user provided - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); - - } else if (E.value.default_value.size()) { - //default value - _fill_std140_ubo_value(E.value.type, E.value.default_value, data); - //value=E.value.default_value; - } else { - //zero because it was not provided - if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - //colors must be set as black, with alpha as 1.0 - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color); - } else { - //else just zero it out - _fill_std140_ubo_empty(E.value.type, E.value.array_size, data); - } - } - } - - if (uses_global_buffer != (global_buffer_E != nullptr)) { - RendererStorageRD *rs = base_singleton; - if (uses_global_buffer) { - global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self); - } else { - rs->global_variables.materials_using_buffer.erase(global_buffer_E); - global_buffer_E = nullptr; - } - } -} - -RendererStorageRD::MaterialData::~MaterialData() { - if (global_buffer_E) { - //unregister global buffers - RendererStorageRD *rs = base_singleton; - rs->global_variables.materials_using_buffer.erase(global_buffer_E); - } - - if (global_texture_E) { - //unregister global textures - RendererStorageRD *rs = base_singleton; - - for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { - GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E.key); - if (v) { - v->texture_materials.erase(self); - } - } - //unregister material from those using global textures - rs->global_variables.materials_using_texture.erase(global_texture_E); - } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } -} - -void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { - RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton; -#ifdef TOOLS_ENABLED - Texture *roughness_detect_texture = nullptr; - RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; - Texture *normal_detect_texture = nullptr; -#endif - - bool uses_global_textures = false; - global_textures_pass++; - - for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { - const StringName &uniform_name = p_texture_uniforms[i].name; - int uniform_array_size = p_texture_uniforms[i].array_size; - - Vector<RID> textures; - - if (p_texture_uniforms[i].global) { - RendererStorageRD *rs = base_singleton; - - uses_global_textures = true; - - GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name); - if (v) { - if (v->buffer_index >= 0) { - WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); - - } else { - Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); - if (!E) { - E = used_global_textures.insert(uniform_name, global_textures_pass); - v->texture_materials.insert(self); - } else { - E->get() = global_textures_pass; - } - - textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); - } - - } else { - WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); - } - } else { - const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); - if (V) { - if (V->get().is_array()) { - Array array = (Array)V->get(); - if (uniform_array_size > 0) { - for (int j = 0; j < array.size(); j++) { - textures.push_back(array[j]); - } - } else { - if (array.size() > 0) { - textures.push_back(array[0]); - } - } - } else { - textures.push_back(V->get()); - } - } - - if (uniform_array_size > 0) { - if (textures.size() < uniform_array_size) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - for (int j = textures.size(); j < uniform_array_size; j++) { - if (W && W->get().has(j)) { - textures.push_back(W->get()[j]); - } else { - textures.push_back(RID()); - } - } - } - } else if (textures.is_empty()) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - if (W && W->get().has(0)) { - textures.push_back(W->get()[0]); - } - } - } - - RID rd_texture; - - if (textures.is_empty()) { - //check default usage - switch (p_texture_uniforms[i].type) { - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER2D: - case ShaderLanguage::TYPE_SAMPLER2D: { - switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); - } break; - default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); - } break; - } - } break; - - case ShaderLanguage::TYPE_SAMPLERCUBE: { - switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - } break; - default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); - } break; - } - } break; - case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); - } break; - - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: - case ShaderLanguage::TYPE_SAMPLER3D: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); - } break; - - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); - } break; - - default: { - } - } -#ifdef TOOLS_ENABLED - if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { - roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); - } -#endif - if (uniform_array_size > 0) { - for (int j = 0; j < uniform_array_size; j++) { - p_textures[k++] = rd_texture; - } - } else { - p_textures[k++] = rd_texture; - } - } else { - bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); - - for (int j = 0; j < textures.size(); j++) { - Texture *tex = singleton->texture_owner.get_or_null(textures[j]); - - if (tex) { - rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; -#ifdef TOOLS_ENABLED - if (tex->detect_3d_callback && p_use_linear_color) { - tex->detect_3d_callback(tex->detect_3d_callback_ud); - } - if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { - if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { - normal_detect_texture = tex; - } - tex->detect_normal_callback(tex->detect_normal_callback_ud); - } - if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { - //find the normal texture - roughness_detect_texture = tex; - roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); - } -#endif - } - if (rd_texture.is_null()) { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); - } -#ifdef TOOLS_ENABLED - if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { - roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); - } -#endif - p_textures[k++] = rd_texture; - } - } - } - { - //for textures no longer used, unregister them - List<Map<StringName, uint64_t>::Element *> to_delete; - RendererStorageRD *rs = base_singleton; - - for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { - if (E->get() != global_textures_pass) { - to_delete.push_back(E); - - GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key()); - if (v) { - v->texture_materials.erase(self); - } - } - } - - while (to_delete.front()) { - used_global_textures.erase(to_delete.front()->get()); - to_delete.pop_front(); - } - //handle registering/unregistering global textures - if (uses_global_textures != (global_texture_E != nullptr)) { - if (uses_global_textures) { - global_texture_E = rs->global_variables.materials_using_texture.push_back(self); - } else { - rs->global_variables.materials_using_texture.erase(global_texture_E); - global_texture_E = nullptr; - } - } - } -} - -void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) { - if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { - RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr); - RD::get_singleton()->free(p_uniform_set); - } -} - -bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { - if ((uint32_t)ubo_data.size() != p_ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(p_ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); - } - - uint32_t tex_uniform_count = 0U; - for (int i = 0; i < p_texture_uniforms.size(); i++) { - tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1); - } - - if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); - } - - if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return false; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return false; - } - - Vector<RD::Uniform> uniforms; - - { - if (p_ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.append_id(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { - const int array_size = p_texture_uniforms[i].array_size; - - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + k; - if (array_size > 0) { - for (int j = 0; j < array_size; j++) { - u.append_id(textures[k++]); - } - } else { - u.append_id(textures[k++]); - } - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set); - - RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self); - - return true; -} - -void RendererStorageRD::_material_uniform_set_erased(void *p_material) { - RID rid = *(RID *)p_material; - Material *material = base_singleton->material_owner.get_or_null(rid); - if (material) { - if (material->data) { - // Uniform set may be gone because a dependency was erased. This happens - // if a texture is deleted, so re-create it. - base_singleton->_material_queue_update(material, false, true); - } - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - } -} - -void RendererStorageRD::_update_queued_materials() { - while (material_update_list.first()) { - Material *material = material_update_list.first()->self(); - bool uniforms_changed = false; - - if (material->data) { - uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); - } - material->texture_dirty = false; - material->uniform_dirty = false; - - material_update_list.remove(&material->update_element); - - if (uniforms_changed) { - //some implementations such as 3D renderer cache the matreial uniform set, so update is required - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - } - } -} - -/* MESH API */ - -RID RendererStorageRD::mesh_allocate() { - return mesh_owner.allocate_rid(); -} -void RendererStorageRD::mesh_initialize(RID p_rid) { - mesh_owner.initialize_rid(p_rid, Mesh()); -} - -void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) { - ERR_FAIL_COND(p_blend_shape_count < 0); - - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist - - mesh->blend_shape_count = p_blend_shape_count; -} - -/// Returns stride -void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES); - -#ifdef DEBUG_ENABLED - //do a validation, to catch errors first - { - uint32_t stride = 0; - uint32_t attrib_stride = 0; - uint32_t skin_stride = 0; - - for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { - if ((p_surface.format & (1 << i))) { - switch (i) { - case RS::ARRAY_VERTEX: { - if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) { - stride += sizeof(float) * 2; - } else { - stride += sizeof(float) * 3; - } - - } break; - case RS::ARRAY_NORMAL: { - stride += sizeof(int32_t); - - } break; - case RS::ARRAY_TANGENT: { - stride += sizeof(int32_t); - - } break; - case RS::ARRAY_COLOR: { - attrib_stride += sizeof(uint32_t); - } break; - case RS::ARRAY_TEX_UV: { - attrib_stride += sizeof(float) * 2; - - } break; - case RS::ARRAY_TEX_UV2: { - attrib_stride += sizeof(float) * 2; - - } break; - case RS::ARRAY_CUSTOM0: - case RS::ARRAY_CUSTOM1: - case RS::ARRAY_CUSTOM2: - case RS::ARRAY_CUSTOM3: { - int idx = i - RS::ARRAY_CUSTOM0; - uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; - uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; - uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; - attrib_stride += fmtsize[fmt]; - - } break; - case RS::ARRAY_WEIGHTS: - case RS::ARRAY_BONES: { - //uses a separate array - bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS; - skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8); - } break; - } - } - } - - int expected_size = stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); - - int bs_expected_size = expected_size * mesh->blend_shape_count; - - ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")"); - - int expected_attrib_size = attrib_stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")"); - - if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) { - expected_size = skin_stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); - } - } - -#endif - - Mesh::Surface *s = memnew(Mesh::Surface); - - s->format = p_surface.format; - s->primitive = p_surface.primitive; - - bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); - - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); - s->vertex_buffer_size = p_surface.vertex_data.size(); - - if (p_surface.attribute_data.size()) { - s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); - } - if (p_surface.skin_data.size()) { - s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage); - s->skin_buffer_size = p_surface.skin_data.size(); - } - - s->vertex_count = p_surface.vertex_count; - - if (p_surface.format & RS::ARRAY_FORMAT_BONES) { - mesh->has_bone_weights = true; - } - - if (p_surface.index_count) { - bool is_index_16 = p_surface.vertex_count <= 65536; - - s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); - s->index_count = p_surface.index_count; - s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); - if (p_surface.lods.size()) { - s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); - s->lod_count = p_surface.lods.size(); - - for (int i = 0; i < p_surface.lods.size(); i++) { - uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); - s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); - s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); - s->lods[i].edge_length = p_surface.lods[i].edge_length; - s->lods[i].index_count = indices; - } - } - } - - s->aabb = p_surface.aabb; - s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. - - if (mesh->blend_shape_count > 0) { - s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data); - } - - if (use_as_storage) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(s->vertex_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 1; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - if (s->skin_buffer.is_valid()) { - u.append_id(s->skin_buffer); - } else { - u.append_id(default_rd_storage_buffer); - } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - if (s->blend_shape_buffer.is_valid()) { - u.append_id(s->blend_shape_buffer); - } else { - u.append_id(default_rd_storage_buffer); - } - uniforms.push_back(u); - } - - s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE); - } - - if (mesh->surface_count == 0) { - mesh->bone_aabbs = p_surface.bone_aabbs; - mesh->aabb = p_surface.aabb; - } else { - if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) { - // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone - // Each surface may affect different numbers of bones. - mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); - } - for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); - } - mesh->aabb.merge_with(p_surface.aabb); - } - - s->material = p_surface.material; - - mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); - mesh->surfaces[mesh->surface_count] = s; - mesh->surface_count++; - - for (MeshInstance *mi : mesh->instances) { - _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); - } - - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); - shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - } - - mesh->material_cache.clear(); -} - -int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const { - const Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - return mesh->blend_shape_count; -} - -void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX((int)p_mode, 2); - - mesh->blend_shape_mode = p_mode; -} - -RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); - return mesh->blend_shape_mode; -} - -void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); -} - -void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null()); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r); -} - -void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null()); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r); -} - -void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - mesh->surfaces[p_surface]->material = p_material; - - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - mesh->material_cache.clear(); -} - -RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); - - return mesh->surfaces[p_surface]->material; -} - -RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); - - Mesh::Surface &s = *mesh->surfaces[p_surface]; - - RS::SurfaceData sd; - sd.format = s.format; - sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); - if (s.attribute_buffer.is_valid()) { - sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); - } - if (s.skin_buffer.is_valid()) { - sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer); - } - sd.vertex_count = s.vertex_count; - sd.index_count = s.index_count; - sd.primitive = s.primitive; - - if (sd.index_count) { - sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); - } - sd.aabb = s.aabb; - for (uint32_t i = 0; i < s.lod_count; i++) { - RS::SurfaceData::LOD lod; - lod.edge_length = s.lods[i].edge_length; - lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); - sd.lods.push_back(lod); - } - - sd.bone_aabbs = s.bone_aabbs; - - if (s.blend_shape_buffer.is_valid()) { - sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer); - } - - return sd; -} - -int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - return mesh->surface_count; -} - -void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - mesh->custom_aabb = p_aabb; -} - -AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - return mesh->custom_aabb; -} - -AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - - if (mesh->custom_aabb != AABB()) { - return mesh->custom_aabb; - } - - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - if (!skeleton || skeleton->size == 0) { - return mesh->aabb; - } - - AABB aabb; - - for (uint32_t i = 0; i < mesh->surface_count; i++) { - AABB laabb; - if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { - int bs = mesh->surfaces[i]->bone_aabbs.size(); - const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr(); - - int sbs = skeleton->size; - ERR_CONTINUE(bs > sbs); - const float *baseptr = skeleton->data.ptr(); - - bool first = true; - - if (skeleton->use_2d) { - for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { - continue; //bone is unused - } - - const float *dataptr = baseptr + j * 8; - - Transform3D mtx; - - mtx.basis.elements[0].x = dataptr[0]; - mtx.basis.elements[1].x = dataptr[1]; - mtx.origin.x = dataptr[3]; - - mtx.basis.elements[0].y = dataptr[4]; - mtx.basis.elements[1].y = dataptr[5]; - mtx.origin.y = dataptr[7]; - - AABB baabb = mtx.xform(skbones[j]); - - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } else { - for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { - continue; //bone is unused - } - - const float *dataptr = baseptr + j * 12; - - Transform3D mtx; - - mtx.basis.elements[0][0] = dataptr[0]; - mtx.basis.elements[0][1] = dataptr[1]; - mtx.basis.elements[0][2] = dataptr[2]; - mtx.origin.x = dataptr[3]; - mtx.basis.elements[1][0] = dataptr[4]; - mtx.basis.elements[1][1] = dataptr[5]; - mtx.basis.elements[1][2] = dataptr[6]; - mtx.origin.y = dataptr[7]; - mtx.basis.elements[2][0] = dataptr[8]; - mtx.basis.elements[2][1] = dataptr[9]; - mtx.basis.elements[2][2] = dataptr[10]; - mtx.origin.z = dataptr[11]; - - AABB baabb = mtx.xform(skbones[j]); - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } - - if (laabb.size == Vector3()) { - laabb = mesh->surfaces[i]->aabb; - } - } else { - laabb = mesh->surfaces[i]->aabb; - } - - if (i == 0) { - aabb = laabb; - } else { - aabb.merge_with(laabb); - } - } - - return aabb; -} - -void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - - Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); - if (shadow_mesh) { - shadow_mesh->shadow_owners.erase(mesh); - } - mesh->shadow_mesh = p_shadow_mesh; - - shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); - - if (shadow_mesh) { - shadow_mesh->shadow_owners.insert(mesh); - } - - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); -} - -void RendererStorageRD::mesh_clear(RID p_mesh) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - for (uint32_t i = 0; i < mesh->surface_count; i++) { - Mesh::Surface &s = *mesh->surfaces[i]; - RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions - if (s.attribute_buffer.is_valid()) { - RD::get_singleton()->free(s.attribute_buffer); - } - if (s.skin_buffer.is_valid()) { - RD::get_singleton()->free(s.skin_buffer); - } - if (s.versions) { - memfree(s.versions); //reallocs, so free with memfree. - } - - if (s.index_buffer.is_valid()) { - RD::get_singleton()->free(s.index_buffer); - } - - if (s.lod_count) { - for (uint32_t j = 0; j < s.lod_count; j++) { - RD::get_singleton()->free(s.lods[j].index_buffer); - } - memdelete_arr(s.lods); - } - - if (s.blend_shape_buffer.is_valid()) { - RD::get_singleton()->free(s.blend_shape_buffer); - } - - memdelete(mesh->surfaces[i]); - } - if (mesh->surfaces) { - memfree(mesh->surfaces); - } - - mesh->surfaces = nullptr; - mesh->surface_count = 0; - mesh->material_cache.clear(); - //clear instance data - for (MeshInstance *mi : mesh->instances) { - _mesh_instance_clear(mi); - } - mesh->has_bone_weights = false; - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); - shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - } -} - -bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, false); - - return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); -} - -/* MESH INSTANCE */ - -RID RendererStorageRD::mesh_instance_create(RID p_base) { - Mesh *mesh = mesh_owner.get_or_null(p_base); - ERR_FAIL_COND_V(!mesh, RID()); - - RID rid = mesh_instance_owner.make_rid(); - MeshInstance *mi = mesh_instance_owner.get_or_null(rid); - - mi->mesh = mesh; - - for (uint32_t i = 0; i < mesh->surface_count; i++) { - _mesh_instance_add_surface(mi, mesh, i); - } - - mi->I = mesh->instances.push_back(mi); - - mi->dirty = true; - - return rid; -} -void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - if (mi->skeleton == p_skeleton) { - return; - } - mi->skeleton = p_skeleton; - mi->skeleton_version = 0; - mi->dirty = true; -} - -void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - ERR_FAIL_COND(!mi); - ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size()); - mi->blend_weights[p_shape] = p_weight; - mi->weights_dirty = true; - //will be eventually updated -} - -void RendererStorageRD::_mesh_instance_clear(MeshInstance *mi) { - for (uint32_t i = 0; i < mi->surfaces.size(); i++) { - if (mi->surfaces[i].versions) { - for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { - RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); - } - memfree(mi->surfaces[i].versions); - } - if (mi->surfaces[i].vertex_buffer.is_valid()) { - RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); - } - } - mi->surfaces.clear(); - - if (mi->blend_weights_buffer.is_valid()) { - RD::get_singleton()->free(mi->blend_weights_buffer); - } - mi->blend_weights.clear(); - mi->weights_dirty = false; - mi->skeleton_version = 0; -} - -void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) { - if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) { - mi->blend_weights.resize(mesh->blend_shape_count); - for (uint32_t i = 0; i < mi->blend_weights.size(); i++) { - mi->blend_weights[i] = 0; - } - mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array()); - mi->weights_dirty = true; - } - - MeshInstance::Surface s; - if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { - //surface warrants transform - s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 1; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(s.vertex_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - if (mi->blend_weights_buffer.is_valid()) { - u.append_id(mi->blend_weights_buffer); - } else { - u.append_id(default_rd_storage_buffer); - } - uniforms.push_back(u); - } - s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE); - } - - mi->surfaces.push_back(s); - mi->dirty = true; -} - -void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - - bool needs_update = mi->dirty; - - if (mi->weights_dirty && !mi->weight_update_list.in_list()) { - dirty_mesh_instance_weights.add(&mi->weight_update_list); - needs_update = true; - } - - if (mi->array_update_list.in_list()) { - return; - } - - if (!needs_update && mi->skeleton.is_valid()) { - Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); - if (sk && sk->version != mi->skeleton_version) { - needs_update = true; - } - } - - if (needs_update) { - dirty_mesh_instance_arrays.add(&mi->array_update_list); - } -} - -void RendererStorageRD::update_mesh_instances() { - while (dirty_mesh_instance_weights.first()) { - MeshInstance *mi = dirty_mesh_instance_weights.first()->self(); - - if (mi->blend_weights_buffer.is_valid()) { - RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr()); - } - dirty_mesh_instance_weights.remove(&mi->weight_update_list); - mi->weights_dirty = false; - } - if (dirty_mesh_instance_arrays.first() == nullptr) { - return; //nothing to do - } - - //process skeletons and blend shapes - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - while (dirty_mesh_instance_arrays.first()) { - MeshInstance *mi = dirty_mesh_instance_arrays.first()->self(); - - Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); - - for (uint32_t i = 0; i < mi->surfaces.size(); i++) { - if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) { - continue; - } - - bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE); - if (sk && sk->uniform_set_mi.is_valid()) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON); - } - - SkeletonShader::PushConstant push_constant; - - push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL; - push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT; - push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES); - push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0; - - push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count; - push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; - push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; - push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; - - push_constant.blend_shape_count = mi->mesh->blend_shape_count; - push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; - push_constant.pad0 = 0; - push_constant.pad1 = 0; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant)); - - //dispatch without barrier, so all is done at the same time - RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1); - } - - mi->dirty = false; - if (sk) { - mi->skeleton_version = sk->version; - } - dirty_mesh_instance_arrays.remove(&mi->array_update_list); - } - - RD::get_singleton()->compute_list_end(); -} - -void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) { - Vector<RD::VertexAttribute> attributes; - Vector<RID> buffers; - - uint32_t stride = 0; - uint32_t attribute_stride = 0; - uint32_t skin_stride = 0; - - for (int i = 0; i < RS::ARRAY_INDEX; i++) { - RD::VertexAttribute vd; - RID buffer; - vd.location = i; - - if (!(s->format & (1 << i))) { - // Not supplied by surface, use default value - buffer = mesh_default_rd_buffers[i]; - vd.stride = 0; - switch (i) { - case RS::ARRAY_VERTEX: { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - - } break; - case RS::ARRAY_NORMAL: { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } break; - case RS::ARRAY_TANGENT: { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - case RS::ARRAY_COLOR: { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - - } break; - case RS::ARRAY_TEX_UV: { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - - } break; - case RS::ARRAY_TEX_UV2: { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - } break; - case RS::ARRAY_CUSTOM0: - case RS::ARRAY_CUSTOM1: - case RS::ARRAY_CUSTOM2: - case RS::ARRAY_CUSTOM3: { - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - case RS::ARRAY_BONES: { - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - } break; - case RS::ARRAY_WEIGHTS: { - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - } - } else { - //Supplied, use it - - vd.stride = 1; //mark that it needs a stride set (default uses 0) - - switch (i) { - case RS::ARRAY_VERTEX: { - vd.offset = stride; - - if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - stride += sizeof(float) * 3; - } - - if (mis) { - buffer = mis->vertex_buffer; - } else { - buffer = s->vertex_buffer; - } - - } break; - case RS::ARRAY_NORMAL: { - vd.offset = stride; - - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - - stride += sizeof(uint32_t); - if (mis) { - buffer = mis->vertex_buffer; - } else { - buffer = s->vertex_buffer; - } - } break; - case RS::ARRAY_TANGENT: { - vd.offset = stride; - - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - stride += sizeof(uint32_t); - if (mis) { - buffer = mis->vertex_buffer; - } else { - buffer = s->vertex_buffer; - } - } break; - case RS::ARRAY_COLOR: { - vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - attribute_stride += sizeof(int8_t) * 4; - buffer = s->attribute_buffer; - } break; - case RS::ARRAY_TEX_UV: { - vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - attribute_stride += sizeof(float) * 2; - buffer = s->attribute_buffer; - - } break; - case RS::ARRAY_TEX_UV2: { - vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - attribute_stride += sizeof(float) * 2; - buffer = s->attribute_buffer; - } break; - case RS::ARRAY_CUSTOM0: - case RS::ARRAY_CUSTOM1: - case RS::ARRAY_CUSTOM2: - case RS::ARRAY_CUSTOM3: { - vd.offset = attribute_stride; - - int idx = i - RS::ARRAY_CUSTOM0; - uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; - uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; - uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; - RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; - vd.format = fmtrd[fmt]; - attribute_stride += fmtsize[fmt]; - buffer = s->attribute_buffer; - } break; - case RS::ARRAY_BONES: { - vd.offset = skin_stride; - - vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT; - skin_stride += sizeof(int16_t) * 4; - buffer = s->skin_buffer; - } break; - case RS::ARRAY_WEIGHTS: { - vd.offset = skin_stride; - - vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; - skin_stride += sizeof(int16_t) * 4; - buffer = s->skin_buffer; - } break; - } - } - - if (!(p_input_mask & (1 << i))) { - continue; // Shader does not need this, skip it (but computing stride was important anyway) - } - - attributes.push_back(vd); - buffers.push_back(buffer); - } - - //update final stride - for (int i = 0; i < attributes.size(); i++) { - if (attributes[i].stride == 0) { - continue; //default location - } - int loc = attributes[i].location; - - if (loc < RS::ARRAY_COLOR) { - attributes.write[i].stride = stride; - } else if (loc < RS::ARRAY_BONES) { - attributes.write[i].stride = attribute_stride; - } else { - attributes.write[i].stride = skin_stride; - } - } - - v.input_mask = p_input_mask; - v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); - v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); -} - -////////////////// MULTIMESH - -RID RendererStorageRD::multimesh_allocate() { - return multimesh_owner.allocate_rid(); -} -void RendererStorageRD::multimesh_initialize(RID p_rid) { - multimesh_owner.initialize_rid(p_rid, MultiMesh()); -} - -void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { - return; - } - - if (multimesh->buffer.is_valid()) { - RD::get_singleton()->free(multimesh->buffer); - multimesh->buffer = RID(); - multimesh->uniform_set_2d = RID(); //cleared by dependency - multimesh->uniform_set_3d = RID(); //cleared by dependency - } - - if (multimesh->data_cache_dirty_regions) { - memdelete_arr(multimesh->data_cache_dirty_regions); - multimesh->data_cache_dirty_regions = nullptr; - multimesh->data_cache_used_dirty_regions = 0; - } - - multimesh->instances = p_instances; - multimesh->xform_format = p_transform_format; - multimesh->uses_colors = p_use_colors; - multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12; - multimesh->uses_custom_data = p_use_custom_data; - multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); - multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); - multimesh->buffer_set = false; - - //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); - multimesh->data_cache = Vector<float>(); - multimesh->aabb = AABB(); - multimesh->aabb_dirty = false; - multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); - - if (multimesh->instances) { - multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); - } - - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH); -} - -int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - return multimesh->instances; -} - -void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - if (multimesh->mesh == p_mesh) { - return; - } - multimesh->mesh = p_mesh; - - if (multimesh->instances == 0) { - return; - } - - if (multimesh->data_cache.size()) { - //we have a data cache, just mark it dirt - _multimesh_mark_all_dirty(multimesh, false, true); - } else if (multimesh->instances) { - //need to re-create AABB unfortunately, calling this has a penalty - if (multimesh->buffer_set) { - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - const uint8_t *r = buffer.ptr(); - const float *data = (const float *)r; - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - } - } - - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); -} - -#define MULTIMESH_DIRTY_REGION_SIZE 512 - -void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { - if (multimesh->data_cache.size() > 0) { - return; //already local - } - ERR_FAIL_COND(multimesh->data_cache.size() > 0); - // this means that the user wants to load/save individual elements, - // for this, the data must reside on CPU, so just copy it there. - multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); - { - float *w = multimesh->data_cache.ptrw(); - - if (multimesh->buffer_set) { - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - { - const uint8_t *r = buffer.ptr(); - memcpy(w, r, buffer.size()); - } - } else { - memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); - } - } - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - multimesh->data_cache_used_dirty_regions = 0; -} - -void RendererStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { - uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; -#ifdef DEBUG_ENABLED - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug -#endif - if (!multimesh->data_cache_dirty_regions[region_index]) { - multimesh->data_cache_dirty_regions[region_index] = true; - multimesh->data_cache_used_dirty_regions++; - } - - if (p_aabb) { - multimesh->aabb_dirty = true; - } - - if (!multimesh->dirty) { - multimesh->dirty_list = multimesh_dirty_list; - multimesh_dirty_list = multimesh; - multimesh->dirty = true; - } -} - -void RendererStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { - if (p_data) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - if (!multimesh->data_cache_dirty_regions[i]) { - multimesh->data_cache_dirty_regions[i] = true; - multimesh->data_cache_used_dirty_regions++; - } - } - } - - if (p_aabb) { - multimesh->aabb_dirty = true; - } - - if (!multimesh->dirty) { - multimesh->dirty_list = multimesh_dirty_list; - multimesh_dirty_list = multimesh; - multimesh->dirty = true; - } -} - -void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { - ERR_FAIL_COND(multimesh->mesh.is_null()); - AABB aabb; - AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); - for (int i = 0; i < p_instances; i++) { - const float *data = p_data + multimesh->stride_cache * i; - Transform3D t; - - if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) { - t.basis.elements[0][0] = data[0]; - t.basis.elements[0][1] = data[1]; - t.basis.elements[0][2] = data[2]; - t.origin.x = data[3]; - t.basis.elements[1][0] = data[4]; - t.basis.elements[1][1] = data[5]; - t.basis.elements[1][2] = data[6]; - t.origin.y = data[7]; - t.basis.elements[2][0] = data[8]; - t.basis.elements[2][1] = data[9]; - t.basis.elements[2][2] = data[10]; - t.origin.z = data[11]; - - } else { - t.basis.elements[0].x = data[0]; - t.basis.elements[1].x = data[1]; - t.origin.x = data[3]; - - t.basis.elements[0].y = data[4]; - t.basis.elements[1].y = data[5]; - t.origin.y = data[7]; - } - - if (i == 0) { - aabb = t.xform(mesh_aabb); - } else { - aabb.merge_with(t.xform(mesh_aabb)); - } - } - - multimesh->aabb = aabb; -} - -void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - } - - _multimesh_mark_dirty(multimesh, p_index, true); -} - -void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - } - - _multimesh_mark_dirty(multimesh, p_index, true); -} - -void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(!multimesh->uses_colors); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; - - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - _multimesh_mark_dirty(multimesh, p_index, false); -} - -void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(!multimesh->uses_custom_data); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; - - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - _multimesh_mark_dirty(multimesh, p_index, false); -} - -RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, RID()); - - return multimesh->mesh; -} - -Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform3D()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D()); - ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D()); - - _multimesh_make_local(multimesh); - - Transform3D t; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache; - - t.basis.elements[0][0] = dataptr[0]; - t.basis.elements[0][1] = dataptr[1]; - t.basis.elements[0][2] = dataptr[2]; - t.origin.x = dataptr[3]; - t.basis.elements[1][0] = dataptr[4]; - t.basis.elements[1][1] = dataptr[5]; - t.basis.elements[1][2] = dataptr[6]; - t.origin.y = dataptr[7]; - t.basis.elements[2][0] = dataptr[8]; - t.basis.elements[2][1] = dataptr[9]; - t.basis.elements[2][2] = dataptr[10]; - t.origin.z = dataptr[11]; - } - - return t; -} - -Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform2D()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); - ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D()); - - _multimesh_make_local(multimesh); - - Transform2D t; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache; - - t.elements[0][0] = dataptr[0]; - t.elements[1][0] = dataptr[1]; - t.elements[2][0] = dataptr[3]; - t.elements[0][1] = dataptr[4]; - t.elements[1][1] = dataptr[5]; - t.elements[2][1] = dataptr[7]; - } - - return t; -} - -Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); - ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); - - _multimesh_make_local(multimesh); - - Color c; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; - - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - } - - return c; -} - -Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); - ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); - - _multimesh_make_local(multimesh); - - Color c; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; - - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - } - - return c; -} - -void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); - - { - const float *r = p_buffer.ptr(); - RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r); - multimesh->buffer_set = true; - } - - if (multimesh->data_cache.size()) { - //if we have a data cache, just update it - multimesh->data_cache = p_buffer; - { - //clear dirty since nothing will be dirty anymore - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - multimesh->data_cache_used_dirty_regions = 0; - } - - _multimesh_mark_all_dirty(multimesh, false, true); //update AABB - } else if (multimesh->mesh.is_valid()) { - //if we have a mesh set, we need to re-generate the AABB from the new data - const float *data = p_buffer.ptr(); - - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); - } -} - -Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Vector<float>()); - if (multimesh->buffer.is_null()) { - return Vector<float>(); - } else if (multimesh->data_cache.size()) { - return multimesh->data_cache; - } else { - //get from memory - - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - Vector<float> ret; - ret.resize(multimesh->instances * multimesh->stride_cache); - { - float *w = ret.ptrw(); - const uint8_t *r = buffer.ptr(); - memcpy(w, r, buffer.size()); - } - - return ret; - } -} - -void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); - if (multimesh->visible_instances == p_visible) { - return; - } - - if (multimesh->data_cache.size()) { - //there is a data cache.. - _multimesh_mark_all_dirty(multimesh, false, true); - } - - multimesh->visible_instances = p_visible; - - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); -} - -int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - return multimesh->visible_instances; -} - -AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, AABB()); - if (multimesh->aabb_dirty) { - const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes(); - } - return multimesh->aabb; -} - -void RendererStorageRD::_update_dirty_multimeshes() { - while (multimesh_dirty_list) { - MultiMesh *multimesh = multimesh_dirty_list; - - if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists - const float *data = multimesh->data_cache.ptr(); - - uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; - - if (multimesh->data_cache_used_dirty_regions) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - - uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); - - if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { - //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much - RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); - } else { - //not that many regions? update them all - for (uint32_t i = 0; i < visible_region_count; i++) { - if (multimesh->data_cache_dirty_regions[i]) { - uint32_t offset = i * region_size; - uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); - uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i; - RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]); - } - } - } - - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - - multimesh->data_cache_used_dirty_regions = 0; - } - - if (multimesh->aabb_dirty) { - //aabb is dirty.. - _multimesh_re_create_aabb(multimesh, data, visible_instances); - multimesh->aabb_dirty = false; - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); - } - } - - multimesh_dirty_list = multimesh->dirty_list; - - multimesh->dirty_list = nullptr; - multimesh->dirty = false; - } - - multimesh_dirty_list = nullptr; -} - /* PARTICLES */ RID RendererStorageRD::particles_allocate() { @@ -4761,7 +421,7 @@ void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4); memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size()); - particles->emission_buffer = (ParticleEmissionBuffer *)particles->emission_buffer_data.ptrw(); + particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw()); particles->emission_buffer->particle_max = particles->amount; particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data); @@ -4885,7 +545,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) { float longest_axis_size = 0; for (int i = 0; i < particles->draw_passes.size(); i++) { if (particles->draw_passes[i].is_valid()) { - AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID()); + AABB maabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID()); longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size); } } @@ -4946,6 +606,9 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool } void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -4971,7 +634,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (p_particles->emission_storage_buffer.is_valid()) { u.append_id(p_particles->emission_storage_buffer); } else { - u.append_id(default_rd_storage_buffer); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); } uniforms.push_back(u); } @@ -4986,7 +649,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt } u.append_id(sub_emitter->emission_storage_buffer); } else { - u.append_id(default_rd_storage_buffer); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); } uniforms.push_back(u); } @@ -5248,14 +911,14 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { RID rd_tex; if (i < collision_3d_textures_used) { - Texture *t = texture_owner.get_or_null(collision_3d_textures[i]); - if (t && t->type == Texture::TYPE_3D) { + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); + if (t && t->type == RendererRD::Texture::TYPE_3D) { rd_tex = t->rd_texture; } } if (rd_tex == RID()) { - rd_tex = default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE]; + rd_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(rd_tex); } @@ -5268,7 +931,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (collision_heightmap_texture.is_valid()) { u.append_id(collision_heightmap_texture); } else { - u.append_id(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); } @@ -5334,9 +997,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = (ParticlesMaterialData *)material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES); + ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, RendererRD::SHADER_TYPE_PARTICLES)); if (!m) { - m = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES); + m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -5489,7 +1152,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & void RendererStorageRD::_particles_update_buffers(Particles *particles) { uint32_t userdata_count = 0; - const Material *material = material_owner.get_or_null(particles->process_material); + const RendererRD::Material *material = RendererRD::MaterialStorage::get_singleton()->get_material(particles->process_material); if (material && material->shader && material->shader->data) { const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); userdata_count = shader_data->userdata_count; @@ -5629,7 +1292,7 @@ void RendererStorageRD::update_particles() { if (particles->trail_bind_pose_buffer.is_valid()) { u.append_id(particles->trail_bind_pose_buffer); } else { - u.append_id(default_rd_storage_buffer); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); } uniforms.push_back(u); } @@ -5876,13 +1539,13 @@ void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> * } } -void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -5931,7 +1594,7 @@ RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() { } } -RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func() { +RendererRD::ShaderData *RendererStorageRD::_create_particles_shader_func() { ParticlesShaderData *shader_data = memnew(ParticlesShaderData); return shader_data; } @@ -5944,7 +1607,7 @@ RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { +RendererRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -6265,195 +1928,6 @@ void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, b } } -/* SKELETON API */ - -RID RendererStorageRD::skeleton_allocate() { - return skeleton_owner.allocate_rid(); -} -void RendererStorageRD::skeleton_initialize(RID p_rid) { - skeleton_owner.initialize_rid(p_rid, Skeleton()); -} - -void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { - if (!skeleton->dirty) { - skeleton->dirty = true; - skeleton->dirty_list = skeleton_dirty_list; - skeleton_dirty_list = skeleton; - } -} - -void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_COND(p_bones < 0); - - if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) { - return; - } - - skeleton->size = p_bones; - skeleton->use_2d = p_2d_skeleton; - skeleton->uniform_set_3d = RID(); - - if (skeleton->buffer.is_valid()) { - RD::get_singleton()->free(skeleton->buffer); - skeleton->buffer = RID(); - skeleton->data.clear(); - skeleton->uniform_set_mi = RID(); - } - - if (skeleton->size) { - skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12)); - skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float)); - memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float)); - - _skeleton_make_dirty(skeleton); - - { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(skeleton->buffer); - uniforms.push_back(u); - } - skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); - } - } - - skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA); -} - -int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, 0); - - return skeleton->size; -} - -void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(skeleton->use_2d); - - float *dataptr = skeleton->data.ptrw() + p_bone * 12; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - - _skeleton_make_dirty(skeleton); -} - -Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform3D()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D()); - ERR_FAIL_COND_V(skeleton->use_2d, Transform3D()); - - const float *dataptr = skeleton->data.ptr() + p_bone * 12; - - Transform3D t; - - t.basis.elements[0][0] = dataptr[0]; - t.basis.elements[0][1] = dataptr[1]; - t.basis.elements[0][2] = dataptr[2]; - t.origin.x = dataptr[3]; - t.basis.elements[1][0] = dataptr[4]; - t.basis.elements[1][1] = dataptr[5]; - t.basis.elements[1][2] = dataptr[6]; - t.origin.y = dataptr[7]; - t.basis.elements[2][0] = dataptr[8]; - t.basis.elements[2][1] = dataptr[9]; - t.basis.elements[2][2] = dataptr[10]; - t.origin.z = dataptr[11]; - - return t; -} - -void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(!skeleton->use_2d); - - float *dataptr = skeleton->data.ptrw() + p_bone * 8; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - - _skeleton_make_dirty(skeleton); -} - -Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform2D()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); - ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); - - const float *dataptr = skeleton->data.ptr() + p_bone * 8; - - Transform2D t; - t.elements[0][0] = dataptr[0]; - t.elements[1][0] = dataptr[1]; - t.elements[2][0] = dataptr[3]; - t.elements[0][1] = dataptr[4]; - t.elements[1][1] = dataptr[5]; - t.elements[2][1] = dataptr[7]; - - return t; -} - -void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND(!skeleton->use_2d); - - skeleton->base_transform_2d = p_base_transform; -} - -void RendererStorageRD::_update_dirty_skeletons() { - while (skeleton_dirty_list) { - Skeleton *skeleton = skeleton_dirty_list; - - if (skeleton->size) { - RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr()); - } - - skeleton_dirty_list = skeleton->dirty_list; - - skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES); - - skeleton->version++; - - skeleton->dirty = false; - skeleton->dirty_list = nullptr; - } - - skeleton_dirty_list = nullptr; -} - /* LIGHT */ void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) { @@ -6556,6 +2030,7 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) { } void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) { + RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton(); Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND(!light); @@ -6564,14 +2039,14 @@ void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) { } if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) { - texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); + decal_atlas_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); } light->projector = p_texture; if (light->type != RS::LIGHT_DIRECTIONAL) { if (light->projector.is_valid()) { - texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); + decal_atlas_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); } light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); } @@ -6676,18 +2151,18 @@ bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const { return light->directional_blend_splits; } -void RendererStorageRD::light_directional_set_sky_only(RID p_light, bool p_sky_only) { +void RendererStorageRD::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) { Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND(!light); - light->directional_sky_only = p_sky_only; + light->directional_sky_mode = p_mode; } -bool RendererStorageRD::light_directional_is_sky_only(RID p_light) const { +RS::LightDirectionalSkyMode RendererStorageRD::light_directional_get_sky_mode(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, false); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY); - return light->directional_sky_only; + return light->directional_sky_mode; } RS::LightDirectionalShadowMode RendererStorageRD::light_directional_get_shadow_mode(RID p_light) { @@ -6968,97 +2443,6 @@ float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) return reflection_probe->ambient_color_energy; } -RID RendererStorageRD::decal_allocate() { - return decal_owner.allocate_rid(); -} -void RendererStorageRD::decal_initialize(RID p_decal) { - decal_owner.initialize_rid(p_decal, Decal()); -} - -void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->extents = p_extents; - decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX); - - if (decal->textures[p_type] == p_texture) { - return; - } - - ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); - - if (decal->textures[p_type].is_valid() && texture_owner.owns(decal->textures[p_type])) { - texture_remove_from_decal_atlas(decal->textures[p_type]); - } - - decal->textures[p_type] = p_texture; - - if (decal->textures[p_type].is_valid()) { - texture_add_to_decal_atlas(decal->textures[p_type]); - } - - decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL); -} - -void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->emission_energy = p_energy; -} - -void RendererStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->albedo_mix = p_mix; -} - -void RendererStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->modulate = p_modulate; -} - -void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->cull_mask = p_layers; - decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->distance_fade = p_enabled; - decal->distance_fade_begin = p_begin; - decal->distance_fade_length = p_length; -} - -void RendererStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->upper_fade = p_above; - decal->lower_fade = p_below; -} - -void RendererStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); - decal->normal_fade = p_fade; -} - -AABB RendererStorageRD::decal_get_aabb(RID p_decal) const { - Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND_V(!decal, AABB()); - - return AABB(-decal->extents, decal->extents * 2.0); -} - RID RendererStorageRD::voxel_gi_allocate() { return voxel_gi_owner.allocate_rid(); } @@ -7398,6 +2782,8 @@ void RendererStorageRD::lightmap_initialize(RID p_lightmap) { } void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); ERR_FAIL_COND(!lm); @@ -7405,17 +2791,17 @@ void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool //erase lightmap users if (lm->light_texture.is_valid()) { - Texture *t = texture_owner.get_or_null(lm->light_texture); + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - Texture *t = texture_owner.get_or_null(p_light); + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; - RID default_2d_array = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); if (!t) { if (using_lightmap_array) { if (lm->array_index >= 0) { @@ -7593,9 +2979,9 @@ void RendererStorageRD::_clear_render_target(RenderTarget *rt) { void RendererStorageRD::_update_render_target(RenderTarget *rt) { if (rt->texture.is_null()) { //create a placeholder until updated - rt->texture = texture_allocate(); - texture_2d_placeholder_initialize(rt->texture); - Texture *tex = texture_owner.get_or_null(rt->texture); + rt->texture = RendererRD::TextureStorage::get_singleton()->texture_allocate(); + RendererRD::TextureStorage::get_singleton()->texture_2d_placeholder_initialize(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); tex->is_render_target = true; } @@ -7642,7 +3028,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) { { //update texture - Texture *tex = texture_owner.get_or_null(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); //free existing textures if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { @@ -7678,7 +3064,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) { Vector<RID> proxies = tex->proxies; //make a copy, since update may change it for (int i = 0; i < proxies.size(); i++) { - texture_proxy_update(proxies[i], rt->texture); + RendererRD::TextureStorage::get_singleton()->texture_proxy_update(proxies[i], rt->texture); } } } @@ -8257,11 +3643,11 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta } void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) { - if (mesh_owner.owns(p_base)) { - Mesh *mesh = mesh_owner.get_or_null(p_base); + if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) { + RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base); p_instance->update_dependency(&mesh->dependency); - } else if (multimesh_owner.owns(p_base)) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_base); + } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) { + RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base); p_instance->update_dependency(&multimesh->dependency); if (multimesh->mesh.is_valid()) { base_update_dependency(multimesh->mesh, p_instance); @@ -8269,8 +3655,8 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_ } else if (reflection_probe_owner.owns(p_base)) { ReflectionProbe *rp = reflection_probe_owner.get_or_null(p_base); p_instance->update_dependency(&rp->dependency); - } else if (decal_owner.owns(p_base)) { - Decal *decal = decal_owner.get_or_null(p_base); + } else if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_base)) { + RendererRD::Decal *decal = RendererRD::DecalAtlasStorage::get_singleton()->get_decal(p_base); p_instance->update_dependency(&decal->dependency); } else if (voxel_gi_owner.owns(p_base)) { VoxelGI *gip = voxel_gi_owner.get_or_null(p_base); @@ -8296,24 +3682,17 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_ } } -void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); - - p_instance->update_dependency(&skeleton->dependency); -} - RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { - if (mesh_owner.owns(p_rid)) { + if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { return RS::INSTANCE_MESH; } - if (multimesh_owner.owns(p_rid)) { + if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { return RS::INSTANCE_MULTIMESH; } if (reflection_probe_owner.owns(p_rid)) { return RS::INSTANCE_REFLECTION_PROBE; } - if (decal_owner.owns(p_rid)) { + if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_rid)) { return RS::INSTANCE_DECAL; } if (voxel_gi_owner.owns(p_rid)) { @@ -8341,907 +3720,12 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { return RS::INSTANCE_NONE; } -void RendererStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) { - if (!decal_atlas.textures.has(p_texture)) { - DecalAtlas::Texture t; - t.users = 1; - t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0; - decal_atlas.textures[p_texture] = t; - decal_atlas.dirty = true; - } else { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); - t->users++; - if (p_panorama_to_dp) { - t->panorama_to_dp_users++; - } - } -} - -void RendererStorageRD::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); - ERR_FAIL_COND(!t); - t->users--; - if (p_panorama_to_dp) { - ERR_FAIL_COND(t->panorama_to_dp_users == 0); - t->panorama_to_dp_users--; - } - if (t->users == 0) { - decal_atlas.textures.erase(p_texture); - //do not mark it dirty, there is no need to since it remains working - } -} - -RID RendererStorageRD::decal_atlas_get_texture() const { - return decal_atlas.texture; -} - -RID RendererStorageRD::decal_atlas_get_texture_srgb() const { - return decal_atlas.texture_srgb; -} - -void RendererStorageRD::_update_decal_atlas() { - if (!decal_atlas.dirty) { - return; //nothing to do - } - - decal_atlas.dirty = false; - - if (decal_atlas.texture.is_valid()) { - RD::get_singleton()->free(decal_atlas.texture); - decal_atlas.texture = RID(); - decal_atlas.texture_srgb = RID(); - decal_atlas.texture_mipmaps.clear(); - } - - int border = 1 << decal_atlas.mipmaps; - - if (decal_atlas.textures.size()) { - //generate atlas - Vector<DecalAtlas::SortItem> itemsv; - itemsv.resize(decal_atlas.textures.size()); - int base_size = 8; - const RID *K = nullptr; - - int idx = 0; - while ((K = decal_atlas.textures.next(K))) { - DecalAtlas::SortItem &si = itemsv.write[idx]; - - Texture *src_tex = texture_owner.get_or_null(*K); - - si.size.width = (src_tex->width / border) + 1; - si.size.height = (src_tex->height / border) + 1; - si.pixel_size = Size2i(src_tex->width, src_tex->height); - - if (base_size < si.size.width) { - base_size = nearest_power_of_2_templated(si.size.width); - } - - si.texture = *K; - idx++; - } - - //sort items by size - itemsv.sort(); - - //attempt to create atlas - int item_count = itemsv.size(); - DecalAtlas::SortItem *items = itemsv.ptrw(); - - int atlas_height = 0; - - while (true) { - Vector<int> v_offsetsv; - v_offsetsv.resize(base_size); - - int *v_offsets = v_offsetsv.ptrw(); - memset(v_offsets, 0, sizeof(int) * base_size); - - int max_height = 0; - - for (int i = 0; i < item_count; i++) { - //best fit - DecalAtlas::SortItem &si = items[i]; - int best_idx = -1; - int best_height = 0x7FFFFFFF; - for (int j = 0; j <= base_size - si.size.width; j++) { - int height = 0; - for (int k = 0; k < si.size.width; k++) { - int h = v_offsets[k + j]; - if (h > height) { - height = h; - if (height > best_height) { - break; //already bad - } - } - } - - if (height < best_height) { - best_height = height; - best_idx = j; - } - } - - //update - for (int k = 0; k < si.size.width; k++) { - v_offsets[k + best_idx] = best_height + si.size.height; - } - - si.pos.x = best_idx; - si.pos.y = best_height; - - if (si.pos.y + si.size.height > max_height) { - max_height = si.pos.y + si.size.height; - } - } - - if (max_height <= base_size * 2) { - atlas_height = max_height; - break; //good ratio, break; - } - - base_size *= 2; - } - - decal_atlas.size.width = base_size * border; - decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border); - - for (int i = 0; i < item_count; i++) { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture); - t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2); - t->uv_rect.size = items[i].pixel_size; - - t->uv_rect.position /= Size2(decal_atlas.size); - t->uv_rect.size /= Size2(decal_atlas.size); - } - } else { - //use border as size, so it at least has enough mipmaps - decal_atlas.size.width = border; - decal_atlas.size.height = border; - } - - //blit textures - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = decal_atlas.size.width; - tformat.height = decal_atlas.size.height; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D; - tformat.mipmaps = decal_atlas.mipmaps; - tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM); - tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB); - - decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1); - - { - //create the framebuffer - - Size2i s = decal_atlas.size; - - for (int i = 0; i < decal_atlas.mipmaps; i++) { - DecalAtlas::MipMap mm; - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i); - Vector<RID> fb; - fb.push_back(mm.texture); - mm.fb = RD::get_singleton()->framebuffer_create(fb); - mm.size = s; - decal_atlas.texture_mipmaps.push_back(mm); - - s.width = MAX(1, s.width >> 1); - s.height = MAX(1, s.height >> 1); - } - { - //create the SRGB variant - RD::TextureView rd_view; - rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB; - decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture); - } - } - - RID prev_texture; - for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) { - const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i]; - - Color clear_color(0, 0, 0, 0); - - if (decal_atlas.textures.size()) { - if (i == 0) { - Vector<Color> cc; - cc.push_back(clear_color); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc); - - const RID *K = nullptr; - while ((K = decal_atlas.textures.next(K))) { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K); - Texture *src_tex = texture_owner.get_or_null(*K); - effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); - } - - RD::get_singleton()->draw_list_end(); - - prev_texture = mm.texture; - } else { - effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size)); - prev_texture = mm.texture; - } - } else { - RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1); - } - } -} - -int32_t RendererStorageRD::_global_variable_allocate(uint32_t p_elements) { - int32_t idx = 0; - while (idx + p_elements <= global_variables.buffer_size) { - if (global_variables.buffer_usage[idx].elements == 0) { - bool valid = true; - for (uint32_t i = 1; i < p_elements; i++) { - if (global_variables.buffer_usage[idx + i].elements > 0) { - valid = false; - idx += i + global_variables.buffer_usage[idx + i].elements; - break; - } - } - - if (!valid) { - continue; //if not valid, idx is in new position - } - - return idx; - } else { - idx += global_variables.buffer_usage[idx].elements; - } - } - - return -1; -} - -void RendererStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { - switch (p_type) { - case RS::GLOBAL_VAR_TYPE_BOOL: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - bool b = p_value; - bv.x = b ? 1.0 : 0.0; - bv.y = 0.0; - bv.z = 0.0; - bv.w = 0.0; - - } break; - case RS::GLOBAL_VAR_TYPE_BVEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - uint32_t bvec = p_value; - bv.x = (bvec & 1) ? 1.0 : 0.0; - bv.y = (bvec & 2) ? 1.0 : 0.0; - bv.z = 0.0; - bv.w = 0.0; - } break; - case RS::GLOBAL_VAR_TYPE_BVEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - uint32_t bvec = p_value; - bv.x = (bvec & 1) ? 1.0 : 0.0; - bv.y = (bvec & 2) ? 1.0 : 0.0; - bv.z = (bvec & 4) ? 1.0 : 0.0; - bv.w = 0.0; - } break; - case RS::GLOBAL_VAR_TYPE_BVEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - uint32_t bvec = p_value; - bv.x = (bvec & 1) ? 1.0 : 0.0; - bv.y = (bvec & 2) ? 1.0 : 0.0; - bv.z = (bvec & 4) ? 1.0 : 0.0; - bv.w = (bvec & 8) ? 1.0 : 0.0; - } break; - case RS::GLOBAL_VAR_TYPE_INT: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - int32_t v = p_value; - bv.x = v; - bv.y = 0; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_IVEC2: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Vector2i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_IVEC3: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Vector3i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = v.z; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_IVEC4: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Vector<int32_t> v = p_value; - bv.x = v.size() >= 1 ? v[0] : 0; - bv.y = v.size() >= 2 ? v[1] : 0; - bv.z = v.size() >= 3 ? v[2] : 0; - bv.w = v.size() >= 4 ? v[3] : 0; - } break; - case RS::GLOBAL_VAR_TYPE_RECT2I: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Rect2i v = p_value; - bv.x = v.position.x; - bv.y = v.position.y; - bv.z = v.size.x; - bv.w = v.size.y; - } break; - case RS::GLOBAL_VAR_TYPE_UINT: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - uint32_t v = p_value; - bv.x = v; - bv.y = 0; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_UVEC2: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - Vector2i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_UVEC3: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - Vector3i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = v.z; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_UVEC4: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - Vector<int32_t> v = p_value; - bv.x = v.size() >= 1 ? v[0] : 0; - bv.y = v.size() >= 2 ? v[1] : 0; - bv.z = v.size() >= 3 ? v[2] : 0; - bv.w = v.size() >= 4 ? v[3] : 0; - } break; - case RS::GLOBAL_VAR_TYPE_FLOAT: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - float v = p_value; - bv.x = v; - bv.y = 0; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_VEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Vector2 v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_VEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Vector3 v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = v.z; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_VEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Plane v = p_value; - bv.x = v.normal.x; - bv.y = v.normal.y; - bv.z = v.normal.z; - bv.w = v.d; - } break; - case RS::GLOBAL_VAR_TYPE_COLOR: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Color v = p_value; - bv.x = v.r; - bv.y = v.g; - bv.z = v.b; - bv.w = v.a; - - GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; - v = v.to_linear(); - bv_linear.x = v.r; - bv_linear.y = v.g; - bv_linear.z = v.b; - bv_linear.w = v.a; - - } break; - case RS::GLOBAL_VAR_TYPE_RECT2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Rect2 v = p_value; - bv.x = v.position.x; - bv.y = v.position.y; - bv.z = v.size.x; - bv.w = v.size.y; - } break; - case RS::GLOBAL_VAR_TYPE_MAT2: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Vector<float> m2 = p_value; - if (m2.size() < 4) { - m2.resize(4); - } - bv[0].x = m2[0]; - bv[0].y = m2[1]; - bv[0].z = 0; - bv[0].w = 0; - - bv[1].x = m2[2]; - bv[1].y = m2[3]; - bv[1].z = 0; - bv[1].w = 0; - - } break; - case RS::GLOBAL_VAR_TYPE_MAT3: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Basis v = p_value; - bv[0].x = v.elements[0][0]; - bv[0].y = v.elements[1][0]; - bv[0].z = v.elements[2][0]; - bv[0].w = 0; - - bv[1].x = v.elements[0][1]; - bv[1].y = v.elements[1][1]; - bv[1].z = v.elements[2][1]; - bv[1].w = 0; - - bv[2].x = v.elements[0][2]; - bv[2].y = v.elements[1][2]; - bv[2].z = v.elements[2][2]; - bv[2].w = 0; - - } break; - case RS::GLOBAL_VAR_TYPE_MAT4: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - - Vector<float> m2 = p_value; - if (m2.size() < 16) { - m2.resize(16); - } - - bv[0].x = m2[0]; - bv[0].y = m2[1]; - bv[0].z = m2[2]; - bv[0].w = m2[3]; - - bv[1].x = m2[4]; - bv[1].y = m2[5]; - bv[1].z = m2[6]; - bv[1].w = m2[7]; - - bv[2].x = m2[8]; - bv[2].y = m2[9]; - bv[2].z = m2[10]; - bv[2].w = m2[11]; - - bv[3].x = m2[12]; - bv[3].y = m2[13]; - bv[3].z = m2[14]; - bv[3].w = m2[15]; - - } break; - case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Transform2D v = p_value; - bv[0].x = v.elements[0][0]; - bv[0].y = v.elements[0][1]; - bv[0].z = 0; - bv[0].w = 0; - - bv[1].x = v.elements[1][0]; - bv[1].y = v.elements[1][1]; - bv[1].z = 0; - bv[1].w = 0; - - bv[2].x = v.elements[2][0]; - bv[2].y = v.elements[2][1]; - bv[2].z = 1; - bv[2].w = 0; - - } break; - case RS::GLOBAL_VAR_TYPE_TRANSFORM: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Transform3D v = p_value; - bv[0].x = v.basis.elements[0][0]; - bv[0].y = v.basis.elements[1][0]; - bv[0].z = v.basis.elements[2][0]; - bv[0].w = 0; - - bv[1].x = v.basis.elements[0][1]; - bv[1].y = v.basis.elements[1][1]; - bv[1].z = v.basis.elements[2][1]; - bv[1].w = 0; - - bv[2].x = v.basis.elements[0][2]; - bv[2].y = v.basis.elements[1][2]; - bv[2].z = v.basis.elements[2][2]; - bv[2].w = 0; - - bv[3].x = v.origin.x; - bv[3].y = v.origin.y; - bv[3].z = v.origin.z; - bv[3].w = 1; - - } break; - default: { - ERR_FAIL(); - } - } -} - -void RendererStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { - int32_t prev_chunk = -1; - - for (int32_t i = 0; i < p_elements; i++) { - int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (chunk != prev_chunk) { - if (!global_variables.buffer_dirty_regions[chunk]) { - global_variables.buffer_dirty_regions[chunk] = true; - global_variables.buffer_dirty_region_count++; - } - } - - prev_chunk = chunk; - } -} - -void RendererStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { - ERR_FAIL_COND(global_variables.variables.has(p_name)); - GlobalVariables::Variable gv; - gv.type = p_type; - gv.value = p_value; - gv.buffer_index = -1; - - if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { - //is texture - global_variables.must_update_texture_materials = true; //normally there are none - } else { - gv.buffer_elements = 1; - if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { - //color needs to elements to store srgb and linear - gv.buffer_elements = 2; - } - if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) { - //color needs to elements to store srgb and linear - gv.buffer_elements = 3; - } - if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) { - //color needs to elements to store srgb and linear - gv.buffer_elements = 4; - } - - //is vector, allocate in buffer and update index - gv.buffer_index = _global_variable_allocate(gv.buffer_elements); - ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); - global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - - global_variables.must_update_buffer_materials = true; //normally there are none - } - - global_variables.variables[p_name] = gv; -} - -void RendererStorageRD::global_variable_remove(const StringName &p_name) { - if (!global_variables.variables.has(p_name)) { - return; - } - GlobalVariables::Variable &gv = global_variables.variables[p_name]; - - if (gv.buffer_index >= 0) { - global_variables.buffer_usage[gv.buffer_index].elements = 0; - global_variables.must_update_buffer_materials = true; - } else { - global_variables.must_update_texture_materials = true; - } - - global_variables.variables.erase(p_name); -} - -Vector<StringName> RendererStorageRD::global_variable_get_list() const { - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); - } - - const StringName *K = nullptr; - Vector<StringName> names; - while ((K = global_variables.variables.next(K))) { - names.push_back(*K); - } - names.sort_custom<StringName::AlphCompare>(); - return names; -} - -void RendererStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND(!global_variables.variables.has(p_name)); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; - gv.value = p_value; - if (gv.override.get_type() == Variant::NIL) { - if (gv.buffer_index >= 0) { - //buffer - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - } else { - //texture - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { - Material *material = material_owner.get_or_null(E->get()); - ERR_CONTINUE(!material); - _material_queue_update(material, false, true); - } - } - } -} - -void RendererStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) { - if (!global_variables.variables.has(p_name)) { - return; //variable may not exist - } - - ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - - GlobalVariables::Variable &gv = global_variables.variables[p_name]; - - gv.override = p_value; - - if (gv.buffer_index >= 0) { - //buffer - if (gv.override.get_type() == Variant::NIL) { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - } else { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); - } - - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - } else { - //texture - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { - Material *material = material_owner.get_or_null(E->get()); - ERR_CONTINUE(!material); - _material_queue_update(material, false, true); - } - } -} - -Variant RendererStorageRD::global_variable_get(const StringName &p_name) const { - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); - } - - if (!global_variables.variables.has(p_name)) { - return Variant(); - } - - return global_variables.variables[p_name].value; -} - -RS::GlobalVariableType RendererStorageRD::global_variable_get_type_internal(const StringName &p_name) const { - if (!global_variables.variables.has(p_name)) { - return RS::GLOBAL_VAR_TYPE_MAX; - } - - return global_variables.variables[p_name].type; -} - -RS::GlobalVariableType RendererStorageRD::global_variable_get_type(const StringName &p_name) const { - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); - } - - return global_variable_get_type_internal(p_name); -} - -void RendererStorageRD::global_variables_load_settings(bool p_load_textures) { - List<PropertyInfo> settings; - ProjectSettings::get_singleton()->get_property_list(&settings); - - for (const PropertyInfo &E : settings) { - if (E.name.begins_with("shader_globals/")) { - StringName name = E.name.get_slice("/", 1); - Dictionary d = ProjectSettings::get_singleton()->get(E.name); - - ERR_CONTINUE(!d.has("type")); - ERR_CONTINUE(!d.has("value")); - - String type = d["type"]; - - static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = { - "bool", - "bvec2", - "bvec3", - "bvec4", - "int", - "ivec2", - "ivec3", - "ivec4", - "rect2i", - "uint", - "uvec2", - "uvec3", - "uvec4", - "float", - "vec2", - "vec3", - "vec4", - "color", - "rect2", - "mat2", - "mat3", - "mat4", - "transform_2d", - "transform", - "sampler2D", - "sampler2DArray", - "sampler3D", - "samplerCube", - }; - - RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; - - for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { - if (global_var_type_names[i] == type) { - gvtype = RS::GlobalVariableType(i); - break; - } - } - - ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid - - Variant value = d["value"]; - - if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { - //textire - if (!p_load_textures) { - value = RID(); - continue; - } - - String path = value; - RES resource = ResourceLoader::load(path); - ERR_CONTINUE(resource.is_null()); - value = resource; - } - - if (global_variables.variables.has(name)) { - //has it, update it - global_variable_set(name, value); - } else { - global_variable_add(name, gvtype, value); - } - } - } -} - -void RendererStorageRD::global_variables_clear() { - global_variables.variables.clear(); //not right but for now enough -} - -RID RendererStorageRD::global_variables_get_storage_buffer() const { - return global_variables.buffer; -} - -int32_t RendererStorageRD::global_variables_instance_allocate(RID p_instance) { - ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); - int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - global_variables.instance_buffer_pos[p_instance] = pos; //save anyway - ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); - global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; - return pos; -} - -void RendererStorageRD::global_variables_instance_free(RID p_instance) { - ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); - int32_t pos = global_variables.instance_buffer_pos[p_instance]; - if (pos >= 0) { - global_variables.buffer_usage[pos].elements = 0; - } - global_variables.instance_buffer_pos.erase(p_instance); -} - -void RendererStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { - if (!global_variables.instance_buffer_pos.has(p_instance)) { - return; //just not allocated, ignore - } - int32_t pos = global_variables.instance_buffer_pos[p_instance]; - - if (pos < 0) { - return; //again, not allocated, ignore - } - ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported - - ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = { - ShaderLanguage::TYPE_MAX, //nil - ShaderLanguage::TYPE_BOOL, //bool - ShaderLanguage::TYPE_INT, //int - ShaderLanguage::TYPE_FLOAT, //float - ShaderLanguage::TYPE_MAX, //string - ShaderLanguage::TYPE_VEC2, //vec2 - ShaderLanguage::TYPE_IVEC2, //vec2i - ShaderLanguage::TYPE_VEC4, //rect2 - ShaderLanguage::TYPE_IVEC4, //rect2i - ShaderLanguage::TYPE_VEC3, // vec3 - ShaderLanguage::TYPE_IVEC3, //vec3i - ShaderLanguage::TYPE_MAX, //xform2d not supported here - ShaderLanguage::TYPE_VEC4, //plane - ShaderLanguage::TYPE_VEC4, //quat - ShaderLanguage::TYPE_MAX, //aabb not supported here - ShaderLanguage::TYPE_MAX, //basis not supported here - ShaderLanguage::TYPE_MAX, //xform not supported here - ShaderLanguage::TYPE_VEC4 //color - }; - - ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()]; - - ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported - - pos += p_index; - - _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer - _global_variable_mark_buffer_dirty(pos, 1); -} - -void RendererStorageRD::_update_global_variables() { - if (global_variables.buffer_dirty_region_count > 0) { - uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (total_regions / global_variables.buffer_dirty_region_count <= 4) { - // 25% of regions dirty, just update all buffer - RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); - } else { - uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - - for (uint32_t i = 0; i < total_regions; i++) { - if (global_variables.buffer_dirty_regions[i]) { - RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); - - global_variables.buffer_dirty_regions[i] = false; - } - } - } - - global_variables.buffer_dirty_region_count = 0; - } - - if (global_variables.must_update_buffer_materials) { - // only happens in the case of a buffer variable added or removed, - // so not often. - for (const RID &E : global_variables.materials_using_buffer) { - Material *material = material_owner.get_or_null(E); - ERR_CONTINUE(!material); //wtf - - _material_queue_update(material, true, false); - } - - global_variables.must_update_buffer_materials = false; - } - - if (global_variables.must_update_texture_materials) { - // only happens in the case of a buffer variable added or removed, - // so not often. - for (const RID &E : global_variables.materials_using_texture) { - Material *material = material_owner.get_or_null(E); - ERR_CONTINUE(!material); //wtf - - _material_queue_update(material, false, true); - } - - global_variables.must_update_texture_materials = false; - } -} - void RendererStorageRD::update_dirty_resources() { - _update_global_variables(); //must do before materials, so it can queue them for update - _update_queued_materials(); - _update_dirty_multimeshes(); - _update_dirty_skeletons(); - _update_decal_atlas(); + RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update + RendererRD::MaterialStorage::get_singleton()->_update_queued_materials(); + RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes(); + RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons(); + RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas(); } bool RendererStorageRD::has_os_feature(const String &p_feature) const { @@ -9265,114 +3749,28 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const { } bool RendererStorageRD::free(RID p_rid) { - if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.get_or_null(p_rid); - - ERR_FAIL_COND_V(!t, false); - ERR_FAIL_COND_V(t->is_render_target, false); - - if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) { - //erase this first, as it's a dependency of the one below - RD::get_singleton()->free(t->rd_texture_srgb); - } - if (RD::get_singleton()->texture_is_valid(t->rd_texture)) { - RD::get_singleton()->free(t->rd_texture); - } - - if (t->is_proxy && t->proxy_to.is_valid()) { - Texture *proxy_to = texture_owner.get_or_null(t->proxy_to); - if (proxy_to) { - proxy_to->proxies.erase(p_rid); - } - } - - if (decal_atlas.textures.has(p_rid)) { - decal_atlas.textures.erase(p_rid); - //there is not much a point of making it dirty, just let it be. - } - - for (int i = 0; i < t->proxies.size(); i++) { - Texture *p = texture_owner.get_or_null(t->proxies[i]); - ERR_CONTINUE(!p); - p->proxy_to = RID(); - p->rd_texture = RID(); - p->rd_texture_srgb = RID(); - } - - if (t->canvas_texture) { - memdelete(t->canvas_texture); - } - texture_owner.free(p_rid); - - } else if (canvas_texture_owner.owns(p_rid)) { - canvas_texture_owner.free(p_rid); - } else if (shader_owner.owns(p_rid)) { - Shader *shader = shader_owner.get_or_null(p_rid); - //make material unreference this - while (shader->owners.size()) { - material_set_shader(shader->owners.front()->get()->self, RID()); - } - //clear data if exists - if (shader->data) { - memdelete(shader->data); - } - shader_owner.free(p_rid); - - } else if (material_owner.owns(p_rid)) { - Material *material = material_owner.get_or_null(p_rid); - material_set_shader(p_rid, RID()); //clean up shader - material->dependency.deleted_notify(p_rid); - - material_owner.free(p_rid); - } else if (mesh_owner.owns(p_rid)) { - mesh_clear(p_rid); - mesh_set_shadow_mesh(p_rid, RID()); - Mesh *mesh = mesh_owner.get_or_null(p_rid); - mesh->dependency.deleted_notify(p_rid); - if (mesh->instances.size()) { - ERR_PRINT("deleting mesh with active instances"); - } - if (mesh->shadow_owners.size()) { - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); - shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - } - } - mesh_owner.free(p_rid); - } else if (mesh_instance_owner.owns(p_rid)) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid); - _mesh_instance_clear(mi); - mi->mesh->instances.erase(mi->I); - mi->I = nullptr; - - mesh_instance_owner.free(p_rid); - - } else if (multimesh_owner.owns(p_rid)) { - _update_dirty_multimeshes(); - multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); - MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid); - multimesh->dependency.deleted_notify(p_rid); - multimesh_owner.free(p_rid); - } else if (skeleton_owner.owns(p_rid)) { - _update_dirty_skeletons(); - skeleton_allocate_data(p_rid, 0); - Skeleton *skeleton = skeleton_owner.get_or_null(p_rid); - skeleton->dependency.deleted_notify(p_rid); - skeleton_owner.free(p_rid); + if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); + } else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid); + } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) { + RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid); + } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) { + RendererRD::MaterialStorage::get_singleton()->material_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { + RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) { + RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid); } else if (reflection_probe_owner.owns(p_rid)) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); reflection_probe->dependency.deleted_notify(p_rid); reflection_probe_owner.free(p_rid); - } else if (decal_owner.owns(p_rid)) { - Decal *decal = decal_owner.get_or_null(p_rid); - for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) { - if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) { - texture_remove_from_decal_atlas(decal->textures[i]); - } - } - decal->dependency.deleted_notify(p_rid); - decal_owner.free(p_rid); + } else if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_rid)) { + RendererRD::DecalAtlasStorage::get_singleton()->decal_free(p_rid); } else if (voxel_gi_owner.owns(p_rid)) { voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid); @@ -9421,7 +3819,7 @@ bool RendererStorageRD::free(RID p_rid) { _clear_render_target(rt); if (rt->texture.is_valid()) { - Texture *tex = texture_owner.get_or_null(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); tex->is_render_target = false; free(rt->texture); } @@ -9504,258 +3902,8 @@ RendererStorageRD *RendererStorageRD::base_singleton = nullptr; RendererStorageRD::RendererStorageRD() { base_singleton = this; - for (int i = 0; i < SHADER_TYPE_MAX; i++) { - shader_data_request_func[i] = nullptr; - } - - static_assert(sizeof(GlobalVariables::Value) == 16); - - global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); - global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); - memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); - global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); - global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); - - { //create default textures - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - - //take the chance and initialize decal atlas to something - decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - decal_atlas.texture_srgb = decal_atlas.texture; - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 128); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap white array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default 3D - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.depth = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_3D; - - Vector<uint8_t> pv; - pv.resize(64 * 4); - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 1; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); //default samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { @@ -9845,123 +3993,9 @@ RendererStorageRD::RendererStorageRD() { //custom sampler sampler_rd_configure_custom(0.0f); - //default rd buffers - { - Vector<uint8_t> buffer; - { - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //normal - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //tangent - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //color - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 1.0; - fptr[2] = 1.0; - fptr[3] = 1.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //tex uv 1 - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - { //tex uv 2 - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //bones - buffer.resize(sizeof(uint32_t) * 4); - { - uint8_t *w = buffer.ptrw(); - uint32_t *fptr = (uint32_t *)w; - fptr[0] = 0; - fptr[1] = 0; - fptr[2] = 0; - fptr[3] = 0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //weights - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - } - using_lightmap_array = true; // high end if (using_lightmap_array) { - uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); if (textures_per_stage <= 256) { lightmap_textures.resize(32); @@ -9970,7 +4004,7 @@ RendererStorageRD::RendererStorageRD() { } for (int i = 0; i < lightmap_textures.size(); i++) { - lightmap_textures.write[i] = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } } @@ -9984,8 +4018,8 @@ RendererStorageRD::RendererStorageRD() { particles_modes.push_back(""); particles_shader.shader.initialize(particles_modes, String()); } - shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); - material_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); + RendererRD::MaterialStorage::get_singleton()->shader_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); + RendererRD::MaterialStorage::get_singleton()->material_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -10049,9 +4083,9 @@ RendererStorageRD::RendererStorageRD() { { // default material and shader for particles shader - particles_shader.default_shader = shader_allocate(); - shader_initialize(particles_shader.default_shader); - shader_set_code(particles_shader.default_shader, R"( + particles_shader.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(particles_shader.default_shader); + material_storage->shader_set_code(particles_shader.default_shader, R"( // Default particles shader. shader_type particles; @@ -10060,11 +4094,11 @@ void process() { COLOR = vec4(1.0); } )"); - particles_shader.default_material = material_allocate(); - material_initialize(particles_shader.default_material); - material_set_shader(particles_shader.default_material, particles_shader.default_shader); + particles_shader.default_material = material_storage->material_allocate(); + material_storage->material_initialize(particles_shader.default_material); + material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES); + ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -10094,15 +4128,13 @@ void process() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.append_id(global_variables_get_storage_buffer()); + u.append_id(material_storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0); } - default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); - { Vector<String> copy_modes; for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { @@ -10145,42 +4177,10 @@ void process() { rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i)); } } - { - Vector<String> skeleton_modes; - skeleton_modes.push_back("\n#define MODE_2D\n"); - skeleton_modes.push_back(""); - - skeleton_shader.shader.initialize(skeleton_modes); - skeleton_shader.version = skeleton_shader.shader.version_create(); - for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) { - skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i); - skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]); - } - - { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(default_rd_storage_buffer); - uniforms.push_back(u); - } - skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); - } - } } RendererStorageRD::~RendererStorageRD() { - memdelete_arr(global_variables.buffer_values); - memdelete_arr(global_variables.buffer_usage); - memdelete_arr(global_variables.buffer_dirty_regions); - RD::get_singleton()->free(global_variables.buffer); - - //def textures - for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { - RD::get_singleton()->free(default_rd_textures[i]); - } + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); //def samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { @@ -10198,28 +4198,11 @@ RendererStorageRD::~RendererStorageRD() { } } - //def buffers - for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { - RD::get_singleton()->free(mesh_default_rd_buffers[i]); - } - particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); rt_sdf.shader.version_free(rt_sdf.shader_version); - skeleton_shader.shader.version_free(skeleton_shader.version); - - RenderingServer::get_singleton()->free(particles_shader.default_material); - RenderingServer::get_singleton()->free(particles_shader.default_shader); - - RD::get_singleton()->free(default_rd_storage_buffer); - - if (decal_atlas.textures.size()) { - ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas."); - } - - if (decal_atlas.texture.is_valid()) { - RD::get_singleton()->free(decal_atlas.texture); - } + material_storage->material_free(particles_shader.default_material); + material_storage->shader_free(particles_shader.default_shader); if (effects) { memdelete(effects); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 9416d04cdd..4c45dd4295 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -39,11 +39,12 @@ #include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" + class RendererStorageRD : public RendererStorage { public: static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { @@ -124,496 +125,11 @@ public: } } - enum ShaderType { - SHADER_TYPE_2D, - SHADER_TYPE_3D, - SHADER_TYPE_PARTICLES, - SHADER_TYPE_SKY, - SHADER_TYPE_FOG, - SHADER_TYPE_MAX - }; - - struct ShaderData { - virtual void set_code(const String &p_Code) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; - virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; - - virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0; - virtual bool is_param_texture(const StringName &p_param) const = 0; - virtual bool is_animated() const = 0; - virtual bool casts_shadows() const = 0; - virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; - virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } - - virtual ~ShaderData() {} - }; - - typedef ShaderData *(*ShaderDataRequestFunction)(); - - struct MaterialData { - void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - - virtual void set_render_priority(int p_priority) = 0; - virtual void set_next_pass(RID p_pass) = 0; - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; - virtual ~MaterialData(); - - //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void free_parameters_uniform_set(RID p_uniform_set); - - private: - friend class RendererStorageRD; - RID self; - List<RID>::Element *global_buffer_E = nullptr; - List<RID>::Element *global_texture_E = nullptr; - uint64_t global_textures_pass = 0; - Map<StringName, uint64_t> used_global_textures; - - //internally by update_parameters_uniform_set - Vector<uint8_t> ubo_data; - RID uniform_buffer; - Vector<RID> texture_cache; - }; - typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); - static void _material_uniform_set_erased(void *p_material); - - enum DefaultRDTexture { - DEFAULT_RD_TEXTURE_WHITE, - DEFAULT_RD_TEXTURE_BLACK, - DEFAULT_RD_TEXTURE_NORMAL, - DEFAULT_RD_TEXTURE_ANISO, - DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, - DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, - DEFAULT_RD_TEXTURE_3D_WHITE, - DEFAULT_RD_TEXTURE_3D_BLACK, - DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, - DEFAULT_RD_TEXTURE_2D_UINT, - DEFAULT_RD_TEXTURE_MAX - }; - - enum DefaultRDBuffer { - DEFAULT_RD_BUFFER_VERTEX, - DEFAULT_RD_BUFFER_NORMAL, - DEFAULT_RD_BUFFER_TANGENT, - DEFAULT_RD_BUFFER_COLOR, - DEFAULT_RD_BUFFER_TEX_UV, - DEFAULT_RD_BUFFER_TEX_UV2, - DEFAULT_RD_BUFFER_CUSTOM0, - DEFAULT_RD_BUFFER_CUSTOM1, - DEFAULT_RD_BUFFER_CUSTOM2, - DEFAULT_RD_BUFFER_CUSTOM3, - DEFAULT_RD_BUFFER_BONES, - DEFAULT_RD_BUFFER_WEIGHTS, - DEFAULT_RD_BUFFER_MAX, - }; - private: - /* CANVAS TEXTURE API (2D) */ - - struct CanvasTexture { - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - void clear_sets(); - ~CanvasTexture(); - }; - - RID_Owner<CanvasTexture, true> canvas_texture_owner; - /* TEXTURE API */ - struct Texture { - enum Type { - TYPE_2D, - TYPE_LAYERED, - TYPE_3D - }; - - Type type; - RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - - RenderingDevice::TextureType rd_type; - RID rd_texture; - RID rd_texture_srgb; - RenderingDevice::DataFormat rd_format; - RenderingDevice::DataFormat rd_format_srgb; - - RD::TextureView rd_view; - - Image::Format format; - Image::Format validated_format; - - int width; - int height; - int depth; - int layers; - int mipmaps; - - int height_2d; - int width_2d; - - struct BufferSlice3D { - Size2i size; - uint32_t offset = 0; - uint32_t buffer_size = 0; - }; - Vector<BufferSlice3D> buffer_slices_3d; - uint32_t buffer_size_3d = 0; - - bool is_render_target; - bool is_proxy; - Ref<Image> image_cache_2d; - String path; - - RID proxy_to; - Vector<RID> proxies; - Set<RID> lightmap_users; - - RS::TextureDetectCallback detect_3d_callback = nullptr; - void *detect_3d_callback_ud = nullptr; - - RS::TextureDetectCallback detect_normal_callback = nullptr; - void *detect_normal_callback_ud = nullptr; - - RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; - void *detect_roughness_callback_ud = nullptr; - - CanvasTexture *canvas_texture = nullptr; - }; - - struct TextureToRDFormat { - RD::DataFormat format; - RD::DataFormat format_srgb; - RD::TextureSwizzle swizzle_r; - RD::TextureSwizzle swizzle_g; - RD::TextureSwizzle swizzle_b; - RD::TextureSwizzle swizzle_a; - TextureToRDFormat() { - format = RD::DATA_FORMAT_MAX; - format_srgb = RD::DATA_FORMAT_MAX; - swizzle_r = RD::TEXTURE_SWIZZLE_R; - swizzle_g = RD::TEXTURE_SWIZZLE_G; - swizzle_b = RD::TEXTURE_SWIZZLE_B; - swizzle_a = RD::TEXTURE_SWIZZLE_A; - } - }; - - //textures can be created from threads, so this RID_Owner is thread safe - mutable RID_Owner<Texture, true> texture_owner; - - Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); - - RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - RID default_rd_storage_buffer; - - /* DECAL ATLAS */ - - struct DecalAtlas { - struct Texture { - int panorama_to_dp_users; - int users; - Rect2 uv_rect; - }; - - struct SortItem { - RID texture; - Size2i pixel_size; - Size2i size; - Point2i pos; - - bool operator<(const SortItem &p_item) const { - //sort larger to smaller - if (size.height == p_item.size.height) { - return size.width > p_item.size.width; - } else { - return size.height > p_item.size.height; - } - } - }; - - HashMap<RID, Texture> textures; - bool dirty = true; - int mipmaps = 5; - - RID texture; - RID texture_srgb; - struct MipMap { - RID fb; - RID texture; - Size2i size; - }; - Vector<MipMap> texture_mipmaps; - - Size2i size; - - } decal_atlas; - - void _update_decal_atlas(); - - /* SHADER */ - - struct Material; - - struct Shader { - ShaderData *data; - String code; - ShaderType type; - Map<StringName, Map<int, RID>> default_texture_parameter; - Set<Material *> owners; - }; - - ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; - mutable RID_Owner<Shader, true> shader_owner; - - /* Material */ - - struct Material { - RID self; - MaterialData *data = nullptr; - Shader *shader = nullptr; - //shortcut to shader data and type - ShaderType shader_type = SHADER_TYPE_MAX; - uint32_t shader_id = 0; - bool uniform_dirty = false; - bool texture_dirty = false; - Map<StringName, Variant> params; - int32_t priority = 0; - RID next_pass; - SelfList<Material> update_element; - - Dependency dependency; - - Material() : - update_element(this) {} - }; - - MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; - mutable RID_Owner<Material, true> material_owner; - - SelfList<Material>::List material_update_list; - void _material_queue_update(Material *material, bool p_uniform, bool p_texture); - void _update_queued_materials(); - - /* Mesh */ - - struct MeshInstance; - - struct Mesh { - struct Surface { - RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; - uint32_t format = 0; - - RID vertex_buffer; - RID attribute_buffer; - RID skin_buffer; - uint32_t vertex_count = 0; - uint32_t vertex_buffer_size = 0; - uint32_t skin_buffer_size = 0; - - // A different pipeline needs to be allocated - // depending on the inputs available in the - // material. - // There are never that many geometry/material - // combinations, so a simple array is the most - // cache-efficient structure. - - struct Version { - uint32_t input_mask = 0; - RD::VertexFormatID vertex_format = 0; - RID vertex_array; - }; - - SpinLock version_lock; //needed to access versions - Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; - - RID index_buffer; - RID index_array; - uint32_t index_count = 0; - - struct LOD { - float edge_length = 0.0; - uint32_t index_count = 0; - RID index_buffer; - RID index_array; - }; - - LOD *lods = nullptr; - uint32_t lod_count = 0; - - AABB aabb; - - Vector<AABB> bone_aabbs; - - RID blend_shape_buffer; - - RID material; - - uint32_t render_index = 0; - uint64_t render_pass = 0; - - uint32_t multimesh_render_index = 0; - uint64_t multimesh_render_pass = 0; - - uint32_t particles_render_index = 0; - uint64_t particles_render_pass = 0; - - RID uniform_set; - }; - - uint32_t blend_shape_count = 0; - RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; - - Surface **surfaces = nullptr; - uint32_t surface_count = 0; - - Vector<AABB> bone_aabbs; - - bool has_bone_weights = false; - - AABB aabb; - AABB custom_aabb; - - Vector<RID> material_cache; - - List<MeshInstance *> instances; - - RID shadow_mesh; - Set<Mesh *> shadow_owners; - - Dependency dependency; - }; - - mutable RID_Owner<Mesh, true> mesh_owner; - - struct MeshInstance { - Mesh *mesh; - RID skeleton; - struct Surface { - RID vertex_buffer; - RID uniform_set; - - Mesh::Surface::Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; - }; - LocalVector<Surface> surfaces; - LocalVector<float> blend_weights; - - RID blend_weights_buffer; - List<MeshInstance *>::Element *I = nullptr; //used to erase itself - uint64_t skeleton_version = 0; - bool dirty = false; - bool weights_dirty = false; - SelfList<MeshInstance> weight_update_list; - SelfList<MeshInstance> array_update_list; - MeshInstance() : - weight_update_list(this), array_update_list(this) {} - }; - - void _mesh_instance_clear(MeshInstance *mi); - void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); - - mutable RID_Owner<MeshInstance> mesh_instance_owner; - - SelfList<MeshInstance>::List dirty_mesh_instance_weights; - SelfList<MeshInstance>::List dirty_mesh_instance_arrays; - - struct SkeletonShader { - struct PushConstant { - uint32_t has_normal; - uint32_t has_tangent; - uint32_t has_skeleton; - uint32_t has_blend_shape; - - uint32_t vertex_count; - uint32_t vertex_stride; - uint32_t skin_stride; - uint32_t skin_weight_offset; - - uint32_t blend_shape_count; - uint32_t normalized_blend_shapes; - uint32_t pad0; - uint32_t pad1; - }; - - enum { - UNIFORM_SET_INSTANCE = 0, - UNIFORM_SET_SURFACE = 1, - UNIFORM_SET_SKELETON = 2, - }; - enum { - SHADER_MODE_2D, - SHADER_MODE_3D, - SHADER_MODE_MAX - }; - - SkeletonShaderRD shader; - RID version; - RID version_shader[SHADER_MODE_MAX]; - RID pipeline[SHADER_MODE_MAX]; - - RID default_skeleton_uniform_set; - } skeleton_shader; - - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); - - RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - - /* MultiMesh */ - struct MultiMesh { - RID mesh; - int instances = 0; - RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; - bool uses_colors = false; - bool uses_custom_data = false; - int visible_instances = -1; - AABB aabb; - bool aabb_dirty = false; - bool buffer_set = false; - uint32_t stride_cache = 0; - uint32_t color_offset_cache = 0; - uint32_t custom_data_offset_cache = 0; - - Vector<float> data_cache; //used if individual setting is used - bool *data_cache_dirty_regions = nullptr; - uint32_t data_cache_used_dirty_regions = 0; - - RID buffer; //storage buffer - RID uniform_set_3d; - RID uniform_set_2d; - - bool dirty = false; - MultiMesh *dirty_list = nullptr; - - Dependency dependency; - }; - - mutable RID_Owner<MultiMesh, true> multimesh_owner; - - MultiMesh *multimesh_dirty_list = nullptr; - - _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; - _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); - _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); - _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); - void _update_dirty_multimeshes(); /* PARTICLES */ @@ -876,7 +392,7 @@ private: Particles *particle_update_list = nullptr; - struct ParticlesShaderData : public ShaderData { + struct ParticlesShaderData : public RendererRD::ShaderData { bool valid; RID version; bool uses_collision = false; @@ -902,7 +418,7 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; @@ -913,12 +429,12 @@ private: virtual ~ParticlesShaderData(); }; - ShaderData *_create_particles_shader_func(); - static RendererStorageRD::ShaderData *_create_particles_shader_funcs() { + RendererRD::ShaderData *_create_particles_shader_func(); + static RendererRD::ShaderData *_create_particles_shader_funcs() { return base_singleton->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialData { + struct ParticlesMaterialData : public RendererRD::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; @@ -928,8 +444,8 @@ private: virtual ~ParticlesMaterialData(); }; - MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { + RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); + static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) { return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); } @@ -991,34 +507,6 @@ private: mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner; - /* Skeleton */ - - struct Skeleton { - bool use_2d = false; - int size = 0; - Vector<float> data; - RID buffer; - - bool dirty = false; - Skeleton *dirty_list = nullptr; - Transform2D base_transform_2d; - - RID uniform_set_3d; - RID uniform_set_mi; - - uint64_t version = 1; - - Dependency dependency; - }; - - mutable RID_Owner<Skeleton, true> skeleton_owner; - - _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton); - - Skeleton *skeleton_dirty_list = nullptr; - - void _update_dirty_skeletons(); - /* LIGHT */ struct Light { @@ -1039,7 +527,7 @@ private: RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; bool directional_blend_splits = false; - bool directional_sky_only = false; + RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; uint64_t version = 0; Dependency dependency; @@ -1070,27 +558,6 @@ private: mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner; - /* DECAL */ - - struct Decal { - Vector3 extents = Vector3(1, 1, 1); - RID textures[RS::DECAL_TEXTURE_MAX]; - float emission_energy = 1.0; - float albedo_mix = 1.0; - Color modulate = Color(1, 1, 1, 1); - uint32_t cull_mask = (1 << 20) - 1; - float upper_fade = 0.3; - float lower_fade = 0.3; - bool distance_fade = false; - float distance_fade_begin = 10; - float distance_fade_length = 1; - float normal_fade = 0.0; - - Dependency dependency; - }; - - mutable RID_Owner<Decal, true> decal_owner; - /* VOXEL GI */ struct VoxelGI { @@ -1237,163 +704,13 @@ private: RID pipelines[SHADER_MAX]; } rt_sdf; - /* GLOBAL SHADER VARIABLES */ - - struct GlobalVariables { - enum { - BUFFER_DIRTY_REGION_SIZE = 1024 - }; - struct Variable { - Set<RID> texture_materials; // materials using this - - RS::GlobalVariableType type; - Variant value; - Variant override; - int32_t buffer_index; //for vectors - int32_t buffer_elements; //for vectors - }; - - HashMap<StringName, Variable> variables; - - struct Value { - float x; - float y; - float z; - float w; - }; - - struct ValueInt { - int32_t x; - int32_t y; - int32_t z; - int32_t w; - }; - - struct ValueUInt { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; - }; - - struct ValueUsage { - uint32_t elements = 0; - }; - - List<RID> materials_using_buffer; - List<RID> materials_using_texture; - - RID buffer; - Value *buffer_values; - ValueUsage *buffer_usage; - bool *buffer_dirty_regions; - uint32_t buffer_dirty_region_count = 0; - - uint32_t buffer_size; - - bool must_update_texture_materials = false; - bool must_update_buffer_materials = false; - - HashMap<RID, int32_t> instance_buffer_pos; - - } global_variables; - - int32_t _global_variable_allocate(uint32_t p_elements); - void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); - void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); - - void _update_global_variables(); /* EFFECTS */ EffectsRD *effects = nullptr; public: - virtual bool can_create_resources_async() const; - - /* TEXTURE API */ - - virtual RID texture_allocate(); - - virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image); - virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type); - virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent - virtual void texture_proxy_initialize(RID p_texture, RID p_base); - - virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate); - - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data); - virtual void texture_proxy_update(RID p_texture, RID p_proxy_to); - - //these two APIs can be used together or in combination with the others. - virtual void texture_2d_placeholder_initialize(RID p_texture); - virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type); - virtual void texture_3d_placeholder_initialize(RID p_texture); - - virtual Ref<Image> texture_2d_get(RID p_texture) const; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const; - - virtual void texture_replace(RID p_texture, RID p_by_texture); - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); - - virtual void texture_set_path(RID p_texture, const String &p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata); - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info); - - virtual void texture_set_proxy(RID p_proxy, RID p_base); - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); - - virtual Size2 texture_size_with_proxy(RID p_proxy); - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); - - RID decal_atlas_get_texture() const; - RID decal_atlas_get_texture_srgb() const; - _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); - if (!t) { - return Rect2(); - } - - return t->uv_rect; - } - //internal usage - _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { - if (p_texture.is_null()) { - return RID(); - } - Texture *tex = texture_owner.get_or_null(p_texture); - - if (!tex) { - return RID(); - } - return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; - } - - _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { - if (p_texture.is_null()) { - return Size2i(); - } - Texture *tex = texture_owner.get_or_null(p_texture); - - if (!tex) { - return Size2i(); - } - return Size2i(tex->width_2d, tex->height_2d); - } - - _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { - return default_rd_textures[p_texture]; - } _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { return default_rd_samplers[p_filter][p_repeat]; } @@ -1405,425 +722,6 @@ public: void sampler_rd_set_default(float p_mipmap_bias); - /* CANVAS TEXTURE API */ - - RID canvas_texture_allocate(); - void canvas_texture_initialize(RID p_canvas_texture); - - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture); - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess); - - virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter); - virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat); - - bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); - - /* SHADER API */ - - RID shader_allocate(); - void shader_initialize(RID p_shader); - - void shader_set_code(RID p_shader, const String &p_code); - String shader_get_code(RID p_shader) const; - void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index); - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const; - Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; - void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); - - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const; - - /* COMMON MATERIAL API */ - - RID material_allocate(); - void material_initialize(RID p_material); - - void material_set_shader(RID p_material, RID p_shader); - - void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value); - Variant material_get_param(RID p_material, const StringName &p_param) const; - - void material_set_next_pass(RID p_material, RID p_next_material); - void material_set_render_priority(RID p_material, int priority); - - bool material_is_animated(RID p_material); - bool material_casts_shadows(RID p_material); - - void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters); - - void material_update_dependency(RID p_material, DependencyTracker *p_instance); - - void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); - - _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { - Material *material = material_owner.get_or_null(p_material); - return material->shader_id; - } - - _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { - Material *material = material_owner.get_or_null(p_material); - if (!material || material->shader_type != p_shader_type) { - return nullptr; - } else { - return material->data; - } - } - - /* MESH API */ - - RID mesh_allocate(); - void mesh_initialize(RID p_mesh); - - virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count); - - /// Return stride - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface); - - virtual int mesh_get_blend_shape_count(RID p_mesh) const; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode); - virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; - - virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); - virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); - virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const; - - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()); - virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh); - - virtual void mesh_clear(RID p_mesh); - - virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton); - - /* MESH INSTANCE */ - - virtual RID mesh_instance_create(RID p_base); - virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton); - virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight); - virtual void mesh_instance_check_for_update(RID p_mesh_instance); - virtual void update_mesh_instances(); - - _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); - r_surface_count = mesh->surface_count; - if (r_surface_count == 0) { - return nullptr; - } - if (mesh->material_cache.is_empty()) { - mesh->material_cache.resize(mesh->surface_count); - for (uint32_t i = 0; i < r_surface_count; i++) { - mesh->material_cache.write[i] = mesh->surfaces[i]->material; - } - } - - return mesh->material_cache.ptr(); - } - - _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); - ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr); - - return mesh->surfaces[p_surface_index]; - } - - _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - - return mesh->shadow_mesh; - } - - _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) { - Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface); - return surface->primitive; - } - - _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - return s->lod_count > 0; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - return s->index_count ? s->index_count : s->vertex_count; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - - int32_t current_lod = -1; - if (r_index_count) { - *r_index_count = s->index_count; - } - for (uint32_t i = 0; i < s->lod_count; i++) { - float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold; - if (screen_size > p_mesh_lod_threshold) { - break; - } - current_lod = i; - } - if (current_lod == -1) { - return 0; - } else { - if (r_index_count) { - *r_index_count = s->lods[current_lod].index_count; - } - return current_lod + 1; - } - } - - _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - - if (p_lod == 0) { - return s->index_array; - } else { - return s->lods[p_lod - 1].index_array; - } - } - - _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - - s->version_lock.lock(); - - //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way - - for (uint32_t i = 0; i < s->version_count; i++) { - if (s->versions[i].input_mask != p_input_mask) { - continue; - } - //we have this version, hooray - r_vertex_format = s->versions[i].vertex_format; - r_vertex_array_rd = s->versions[i].vertex_array; - s->version_lock.unlock(); - return; - } - - uint32_t version = s->version_count; - s->version_count++; - s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); - - _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask); - - r_vertex_format = s->versions[version].vertex_format; - r_vertex_array_rd = s->versions[version].vertex_array; - - s->version_lock.unlock(); - } - - _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - ERR_FAIL_COND(!mi); - Mesh *mesh = mi->mesh; - ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); - - MeshInstance::Surface *mis = &mi->surfaces[p_surface_index]; - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - s->version_lock.lock(); - - //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way - - for (uint32_t i = 0; i < mis->version_count; i++) { - if (mis->versions[i].input_mask != p_input_mask) { - continue; - } - //we have this version, hooray - r_vertex_format = mis->versions[i].vertex_format; - r_vertex_array_rd = mis->versions[i].vertex_array; - s->version_lock.unlock(); - return; - } - - uint32_t version = mis->version_count; - mis->version_count++; - mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); - - _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis); - - r_vertex_format = mis->versions[version].vertex_format; - r_vertex_array_rd = mis->versions[version].vertex_array; - - s->version_lock.unlock(); - } - - _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { - ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); - return mesh_default_rd_buffers[p_buffer]; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->render_pass != p_render_pass) { - (*r_index)++; - s->render_pass = p_render_pass; - s->render_index = *r_index; - } - - return s->render_index; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->multimesh_render_pass != p_render_pass) { - (*r_index)++; - s->multimesh_render_pass = p_render_pass; - s->multimesh_render_index = *r_index; - } - - return s->multimesh_render_index; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->particles_render_pass != p_render_pass) { - (*r_index)++; - s->particles_render_pass = p_render_pass; - s->particles_render_index = *r_index; - } - - return s->particles_render_index; - } - - /* MULTIMESH API */ - - RID multimesh_allocate(); - void multimesh_initialize(RID p_multimesh); - - void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false); - int multimesh_get_instance_count(RID p_multimesh) const; - - void multimesh_set_mesh(RID p_multimesh, RID p_mesh); - void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform); - void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); - void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); - void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color); - - RID multimesh_get_mesh(RID p_multimesh) const; - - Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const; - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; - Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; - - void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer); - Vector<float> multimesh_get_buffer(RID p_multimesh) const; - - void multimesh_set_visible_instances(RID p_multimesh, int p_visible); - int multimesh_get_visible_instances(RID p_multimesh) const; - - AABB multimesh_get_aabb(RID p_multimesh) const; - - _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - return multimesh->xform_format; - } - - _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - return multimesh->uses_colors; - } - - _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - return multimesh->uses_custom_data; - } - - _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - if (multimesh->visible_instances >= 0) { - return multimesh->visible_instances; - } - return multimesh->instances; - } - - _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - if (!multimesh->uniform_set_3d.is_valid()) { - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(multimesh->buffer); - uniforms.push_back(u); - multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return multimesh->uniform_set_3d; - } - - _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - if (!multimesh->uniform_set_2d.is_valid()) { - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(multimesh->buffer); - uniforms.push_back(u); - multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return multimesh->uniform_set_2d; - } - - /* SKELETON API */ - - RID skeleton_allocate(); - void skeleton_initialize(RID p_skeleton); - - void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false); - void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); - void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform); - int skeleton_get_bone_count(RID p_skeleton) const; - void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform); - Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; - void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); - Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; - - _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) { - return skeleton_owner.get_or_null(p_skeleton) != nullptr; - } - - _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, RID()); - ERR_FAIL_COND_V(skeleton->size == 0, RID()); - if (skeleton->use_2d) { - return RID(); - } - if (!skeleton->uniform_set_3d.is_valid()) { - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(skeleton->buffer); - uniforms.push_back(u); - skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return skeleton->uniform_set_3d; - } /* Light API */ void _light_initialize(RID p_rid, RS::LightType p_type); @@ -1853,8 +751,8 @@ public: void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode); void light_directional_set_blend_splits(RID p_light, bool p_enable); bool light_directional_get_blend_splits(RID p_light) const; - void light_directional_set_sky_only(RID p_light, bool p_sky_only); - bool light_directional_is_sky_only(RID p_light) const; + void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode); + RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const; RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); @@ -1926,7 +824,7 @@ public: const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); - return texture_owner.owns(light->projector); + return light_owner.owns(light->projector); } _FORCE_INLINE_ bool light_is_negative(RID p_light) const { @@ -1993,84 +891,6 @@ public: float reflection_probe_get_ambient_color_energy(RID p_probe) const; void base_update_dependency(RID p_base, DependencyTracker *p_instance); - void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance); - - /* DECAL API */ - - RID decal_allocate(); - void decal_initialize(RID p_decal); - - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents); - virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture); - virtual void decal_set_emission_energy(RID p_decal, float p_energy); - virtual void decal_set_albedo_mix(RID p_decal, float p_mix); - virtual void decal_set_modulate(RID p_decal, const Color &p_modulate); - virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers); - virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length); - virtual void decal_set_fade(RID p_decal, float p_above, float p_below); - virtual void decal_set_normal_fade(RID p_decal, float p_fade); - - _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->extents; - } - - _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->textures[p_texture]; - } - - _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->modulate; - } - - _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->emission_energy; - } - - _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->albedo_mix; - } - - _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->cull_mask; - } - - _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->upper_fade; - } - - _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->lower_fade; - } - - _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->normal_fade; - } - - _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->distance_fade; - } - - _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->distance_fade_begin; - } - - _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) { - const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->distance_fade_length; - } - - virtual AABB decal_get_aabb(RID p_decal) const; /* VOXEL GI API */ @@ -2329,27 +1149,6 @@ public: virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform); virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active); - /* GLOBAL VARIABLES API */ - - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value); - virtual void global_variable_remove(const StringName &p_name); - virtual Vector<StringName> global_variable_get_list() const; - - virtual void global_variable_set(const StringName &p_name, const Variant &p_value); - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value); - virtual Variant global_variable_get(const StringName &p_name) const; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const; - RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; - - virtual void global_variables_load_settings(bool p_load_textures = true); - virtual void global_variables_clear(); - - virtual int32_t global_variables_instance_allocate(RID p_instance); - virtual void global_variables_instance_free(RID p_instance); - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value); - - RID global_variables_get_storage_buffer() const; - /* RENDER TARGET API */ RID render_target_create(); @@ -2422,8 +1221,6 @@ public: virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; virtual String get_captured_timestamp_name(uint32_t p_index) const; - RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } - static RendererStorageRD *base_singleton; void init_effects(bool p_prefer_raster_effects); diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 65a621b203..fbc641ee9e 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -82,7 +82,7 @@ void main() { #endif - mat4 world_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0)); + mat4 model_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0)); #define FLAGS_INSTANCING_MASK 0x7F #define FLAGS_INSTANCING_HAS_COLORS (1 << 7) @@ -156,7 +156,7 @@ void main() { } matrix = transpose(matrix); - world_matrix = world_matrix * matrix; + model_matrix = model_matrix * matrix; } } @@ -179,7 +179,7 @@ void main() { #endif #if !defined(SKIP_TRANSFORM_USED) - vertex = (world_matrix * vec4(vertex, 0.0, 1.0)).xy; + vertex = (model_matrix * vec4(vertex, 0.0, 1.0)).xy; #endif color_interp = color; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index a8648fc96a..abe1a09b06 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -99,6 +99,18 @@ layout(location = 8) out float dp_clip; layout(location = 9) out flat uint instance_index_interp; +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + invariant gl_Position; #GLOBALS @@ -118,13 +130,13 @@ void main() { instance_index_interp = instance_index; - mat4 world_matrix = instances.data[instance_index].transform; + mat4 model_matrix = instances.data[instance_index].transform; - mat3 world_normal_matrix; + mat3 model_normal_matrix; if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { - world_normal_matrix = transpose(inverse(mat3(world_matrix))); + model_normal_matrix = transpose(inverse(mat3(model_matrix))); } else { - world_normal_matrix = mat3(world_matrix); + model_normal_matrix = mat3(model_matrix); } if (is_multimesh) { @@ -217,8 +229,8 @@ void main() { #endif //transpose matrix = transpose(matrix); - world_matrix = world_matrix * matrix; - world_normal_matrix = world_normal_matrix * mat3(matrix); + model_matrix = model_matrix * matrix; + model_normal_matrix = model_normal_matrix * mat3(matrix); } vec3 vertex = vertex_attrib; @@ -244,29 +256,35 @@ void main() { vec4 position; #endif +#ifdef USE_MULTIVIEW + mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; + mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; +#else mat4 projection_matrix = scene_data.projection_matrix; + mat4 inv_projection_matrix = scene_data.inv_projection_matrix; +#endif //USE_MULTIVIEW //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = (world_matrix * vec4(vertex, 1.0)).xyz; + vertex = (model_matrix * vec4(vertex, 1.0)).xyz; #ifdef NORMAL_USED - normal = world_normal_matrix * normal; + normal = model_normal_matrix * normal; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - tangent = world_normal_matrix * tangent; - binormal = world_normal_matrix * binormal; + tangent = model_normal_matrix * tangent; + binormal = model_normal_matrix * binormal; #endif #endif float roughness = 1.0; - mat4 modelview = scene_data.inv_camera_matrix * world_matrix; - mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix; + mat4 modelview = scene_data.view_matrix * model_matrix; + mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix; { #CODE : VERTEX @@ -291,14 +309,14 @@ void main() { //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz; + vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz; #ifdef NORMAL_USED - normal = (scene_data.inv_camera_matrix * vec4(normal, 0.0)).xyz; + normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - binormal = (scene_data.inv_camera_matrix * vec4(binormal, 0.0)).xyz; - tangent = (scene_data.inv_camera_matrix * vec4(tangent, 0.0)).xyz; + binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz; + tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz; #endif #endif @@ -421,10 +439,28 @@ layout(location = 8) in float dp_clip; layout(location = 9) in flat uint instance_index_interp; +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + //defines to keep compatibility with vertex -#define world_matrix instances.data[instance_index].transform +#define model_matrix instances.data[draw_call.instance_index].transform +#ifdef USE_MULTIVIEW +#define projection_matrix scene_data.projection_matrix_view[ViewIndex] +#define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex] +#else #define projection_matrix scene_data.projection_matrix +#define inv_projection_matrix scene_data.inv_projection_matrix +#endif #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) //both required for transmittance to be enabled @@ -463,14 +499,14 @@ layout(location = 1) out uvec2 voxel_gi_buffer; #endif //MODE_RENDER_NORMAL #else // RENDER DEPTH -#ifdef MODE_MULTIPLE_RENDER_TARGETS +#ifdef MODE_SEPARATE_SPECULAR layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter) #else layout(location = 0) out vec4 frag_color; -#endif // MODE_MULTIPLE_RENDER_TARGETS +#endif // MODE_SEPARATE_SPECULAR #endif // RENDER DEPTH @@ -536,7 +572,7 @@ vec4 fog_process(vec3 vertex) { float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); if (abs(scene_data.fog_height_density) >= 0.0001) { - float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y; + float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y; float y_dist = y - scene_data.fog_height; @@ -1007,7 +1043,7 @@ void main() { if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture uint index = instances.data[instance_index].gi_offset; - vec3 wnormal = mat3(scene_data.camera_matrix) * normal; + vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal; const float c1 = 0.429043; const float c2 = 0.511664; const float c3 = 0.743125; @@ -1061,9 +1097,9 @@ void main() { if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture //make vertex orientation the world one, but still align to camera - vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex; - vec3 cam_normal = mat3(scene_data.camera_matrix) * normal; - vec3 cam_reflection = mat3(scene_data.camera_matrix) * reflect(-view, normal); + vec3 cam_pos = mat3(scene_data.inv_view_matrix) * vertex; + vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normal; + vec3 cam_reflection = mat3(scene_data.inv_view_matrix) * reflect(-view, normal); //apply y-mult cam_pos.y *= sdfgi.y_mult; @@ -1803,7 +1839,7 @@ void main() { vec3(0, -1, 0), vec3(0, 0, -1)); - vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp); + vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normalize(normal_interp); float closest_dist = -1e20; @@ -1930,7 +1966,7 @@ void main() { //restore fog fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba)); -#ifdef MODE_MULTIPLE_RENDER_TARGETS +#ifdef MODE_SEPARATE_SPECULAR #ifdef MODE_UNSHADED diffuse_buffer = vec4(albedo.rgb, 0.0); @@ -1948,7 +1984,7 @@ void main() { diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a); specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); -#else //MODE_MULTIPLE_RENDER_TARGETS +#else //MODE_SEPARATE_SPECULAR #ifdef MODE_UNSHADED frag_color = vec4(albedo, alpha); @@ -1960,7 +1996,7 @@ void main() { // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); -#endif //MODE_MULTIPLE_RENDER_TARGETS +#endif //MODE_SEPARATE_SPECULAR #endif //MODE_RENDER_DEPTH } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index 3b110aded2..f2672f10e7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -2,6 +2,7 @@ #define ROUGHNESS_MAX_LOD 5 #define MAX_VOXEL_GI_INSTANCES 8 +#define MAX_VIEWS 2 #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) @@ -12,6 +13,10 @@ #endif +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + #include "cluster_data_inc.glsl" #include "decal_data_inc.glsl" @@ -169,9 +174,12 @@ sdfgi; layout(set = 1, binding = 0, std140) uniform SceneData { mat4 projection_matrix; mat4 inv_projection_matrix; + mat4 inv_view_matrix; + mat4 view_matrix; - mat4 camera_matrix; - mat4 inv_camera_matrix; + // only used for multiview + mat4 projection_matrix_view[MAX_VIEWS]; + mat4 inv_projection_matrix_view[MAX_VIEWS]; vec2 viewport_size; vec2 screen_pixel_size; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 0fcf449659..6911cab27b 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -122,13 +122,13 @@ void main() { bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH); - mat4 world_matrix = draw_call.transform; + mat4 model_matrix = draw_call.transform; - mat3 world_normal_matrix; + mat3 model_normal_matrix; if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { - world_normal_matrix = transpose(inverse(mat3(world_matrix))); + model_normal_matrix = transpose(inverse(mat3(model_matrix))); } else { - world_normal_matrix = mat3(world_matrix); + model_normal_matrix = mat3(model_matrix); } if (is_multimesh) { @@ -221,8 +221,8 @@ void main() { #endif //transpose matrix = transpose(matrix); - world_matrix = world_matrix * matrix; - world_normal_matrix = world_normal_matrix * mat3(matrix); + model_matrix = model_matrix * matrix; + model_normal_matrix = model_normal_matrix * mat3(matrix); } vec3 vertex = vertex_attrib; @@ -259,24 +259,24 @@ void main() { //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = (world_matrix * vec4(vertex, 1.0)).xyz; + vertex = (model_matrix * vec4(vertex, 1.0)).xyz; #ifdef NORMAL_USED - normal = world_normal_matrix * normal; + normal = model_normal_matrix * normal; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - tangent = world_normal_matrix * tangent; - binormal = world_normal_matrix * binormal; + tangent = model_normal_matrix * tangent; + binormal = model_normal_matrix * binormal; #endif #endif float roughness = 1.0; - mat4 modelview = scene_data.inv_camera_matrix * world_matrix; - mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix; + mat4 modelview = scene_data.view_matrix * model_matrix; + mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix; { #CODE : VERTEX @@ -303,14 +303,14 @@ void main() { //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz; + vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz; #ifdef NORMAL_USED - normal = (scene_data.inv_camera_matrix * vec4(normal, 0.0)).xyz; + normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - binormal = (scene_data.inv_camera_matrix * vec4(binormal, 0.0)).xyz; - tangent = (scene_data.inv_camera_matrix * vec4(tangent, 0.0)).xyz; + binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz; + tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz; #endif #endif @@ -458,7 +458,7 @@ layout(location = 8) highp in float dp_clip; //defines to keep compatibility with vertex -#define world_matrix draw_call.transform +#define model_matrix draw_call.transform #ifdef USE_MULTIVIEW #define projection_matrix scene_data.projection_matrix_view[ViewIndex] #else @@ -560,7 +560,7 @@ vec4 fog_process(vec3 vertex) { float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); if (abs(scene_data.fog_height_density) >= 0.0001) { - float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y; + float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y; float y_dist = y - scene_data.fog_height; @@ -967,7 +967,7 @@ void main() { if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture uint index = draw_call.gi_offset; - vec3 wnormal = mat3(scene_data.camera_matrix) * normal; + vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal; const float c1 = 0.429043; const float c2 = 0.511664; const float c3 = 0.743125; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index 7a624c3b95..91ef19ab67 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -128,8 +128,8 @@ global_variables; layout(set = 1, binding = 0, std140) uniform SceneData { highp mat4 projection_matrix; highp mat4 inv_projection_matrix; - highp mat4 camera_matrix; - highp mat4 inv_camera_matrix; + highp mat4 inv_view_matrix; + highp mat4 view_matrix; // only used for multiview highp mat4 projection_matrix_view[MAX_VIEWS]; diff --git a/servers/rendering/renderer_rd/storage_rd/SCsub b/servers/rendering/renderer_rd/storage_rd/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp new file mode 100644 index 0000000000..3299b93ee2 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* canvas_texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "canvas_texture_storage.h" +#include "texture_storage.h" + +// Until we move things into their own storage classes, also include our old class +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// CanvasTexture + +void CanvasTexture::clear_sets() { + if (cleared_cache) { + return; + } + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { + RD::get_singleton()->free(uniform_sets[i][j]); + uniform_sets[i][j] = RID(); + } + } + } + cleared_cache = true; +} + +CanvasTexture::~CanvasTexture() { + clear_sets(); +} + +/////////////////////////////////////////////////////////////////////////// +// CanvasTextureStorage + +CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr; + +CanvasTextureStorage *CanvasTextureStorage::get_singleton() { + return singleton; +} + +CanvasTextureStorage::CanvasTextureStorage() { + singleton = this; +} + +CanvasTextureStorage::~CanvasTextureStorage() { + singleton = nullptr; +} + +RID CanvasTextureStorage::canvas_texture_allocate() { + return canvas_texture_owner.allocate_rid(); +} + +void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) { + canvas_texture_owner.initialize_rid(p_rid); +} + +void CanvasTextureStorage::canvas_texture_free(RID p_rid) { + canvas_texture_owner.free(p_rid); +} + +void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + switch (p_channel) { + case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { + ct->diffuse = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { + ct->normal_map = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { + ct->specular = p_texture; + } break; + } + + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + ct->specular_color.r = p_specular_color.r; + ct->specular_color.g = p_specular_color.g; + ct->specular_color.b = p_specular_color.b; + ct->specular_color.a = p_shininess; + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + ct->texture_filter = p_filter; + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + ct->texture_repeat = p_repeat; + ct->clear_sets(); +} + +bool CanvasTextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { + RendererStorageRD *storage = RendererStorageRD::base_singleton; + + CanvasTexture *ct = nullptr; + TextureStorage *texture_storage = TextureStorage::get_singleton(); + Texture *t = texture_storage->get_texture(p_texture); + + // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture + + if (t) { + //regular texture + if (!t->canvas_texture) { + t->canvas_texture = memnew(CanvasTexture); + t->canvas_texture->diffuse = p_texture; + } + + ct = t->canvas_texture; + } else { + ct = get_canvas_texture(p_texture); + } + + if (!ct) { + return false; //invalid texture RID + } + + RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; + ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); + + RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; + ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); + + RID uniform_set = ct->uniform_sets[filter][repeat]; + if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //create and update + Vector<RD::Uniform> uniforms; + { //diffuse + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + + t = texture_storage->get_texture(ct->diffuse); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->size_cache = Size2i(1, 1); + } else { + u.append_id(t->rd_texture); + ct->size_cache = Size2i(t->width_2d, t->height_2d); + } + uniforms.push_back(u); + } + { //normal + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + + t = texture_storage->get_texture(ct->normal_map); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); + ct->use_normal_cache = false; + } else { + u.append_id(t->rd_texture); + ct->use_normal_cache = true; + } + uniforms.push_back(u); + } + { //specular + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + + t = texture_storage->get_texture(ct->specular); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->use_specular_cache = false; + } else { + u.append_id(t->rd_texture); + ct->use_specular_cache = true; + } + uniforms.push_back(u); + } + { //sampler + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.append_id(storage->sampler_rd_get_default(filter, repeat)); + uniforms.push_back(u); + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); + ct->uniform_sets[filter][repeat] = uniform_set; + ct->cleared_cache = false; + } + + r_uniform_set = uniform_set; + r_size = ct->size_cache; + r_specular_shininess = ct->specular_color; + r_use_normal = ct->use_normal_cache; + r_use_specular = ct->use_specular_cache; + + return true; +} diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h new file mode 100644 index 0000000000..6d3868edd5 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_RD_H +#define CANVAS_TEXTURE_STORAGE_RD_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace RendererRD { + +class CanvasTexture { +public: + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; + + void clear_sets(); + ~CanvasTexture(); +}; + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +private: + static CanvasTextureStorage *singleton; + + RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner; + +public: + static CanvasTextureStorage *get_singleton(); + + CanvasTextureStorage(); + virtual ~CanvasTextureStorage(); + + CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + + virtual RID canvas_texture_allocate() override; + virtual void canvas_texture_initialize(RID p_rid) override; + virtual void canvas_texture_free(RID p_rid) override; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; + + bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); +}; + +} // namespace RendererRD + +#endif // !CANVAS_TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp b/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp new file mode 100644 index 0000000000..73acc0fdd6 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp @@ -0,0 +1,437 @@ +/*************************************************************************/ +/* decal_atlas_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "decal_atlas_storage.h" +#include "texture_storage.h" + +// Should be able to remove this once we move effects into their own file and include the correct effects +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" + +using namespace RendererRD; + +DecalAtlasStorage *DecalAtlasStorage::singleton = nullptr; + +DecalAtlasStorage *DecalAtlasStorage::get_singleton() { + return singleton; +} + +DecalAtlasStorage::DecalAtlasStorage() { + singleton = this; + + { // default atlas texture + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 255); + } + + { + //take the chance and initialize decal atlas to something + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + decal_atlas.texture_srgb = decal_atlas.texture; + } + } +} + +DecalAtlasStorage::~DecalAtlasStorage() { + if (decal_atlas.textures.size()) { + ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas."); + } + + if (decal_atlas.texture.is_valid()) { + RD::get_singleton()->free(decal_atlas.texture); + } + + singleton = nullptr; +} + +RID DecalAtlasStorage::decal_atlas_get_texture() const { + return decal_atlas.texture; +} + +RID DecalAtlasStorage::decal_atlas_get_texture_srgb() const { + return decal_atlas.texture_srgb; +} + +RID DecalAtlasStorage::decal_allocate() { + return decal_owner.allocate_rid(); +} + +void DecalAtlasStorage::decal_initialize(RID p_decal) { + decal_owner.initialize_rid(p_decal, Decal()); +} + +void DecalAtlasStorage::decal_free(RID p_rid) { + Decal *decal = decal_owner.get_or_null(p_rid); + for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) { + if (decal->textures[i].is_valid() && TextureStorage::get_singleton()->owns_texture(decal->textures[i])) { + texture_remove_from_decal_atlas(decal->textures[i]); + } + } + decal->dependency.deleted_notify(p_rid); + decal_owner.free(p_rid); +} + +void DecalAtlasStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->extents = p_extents; + decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void DecalAtlasStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX); + + if (decal->textures[p_type] == p_texture) { + return; + } + + ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture)); + + if (decal->textures[p_type].is_valid() && TextureStorage::get_singleton()->owns_texture(decal->textures[p_type])) { + texture_remove_from_decal_atlas(decal->textures[p_type]); + } + + decal->textures[p_type] = p_texture; + + if (decal->textures[p_type].is_valid()) { + texture_add_to_decal_atlas(decal->textures[p_type]); + } + + decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL); +} + +void DecalAtlasStorage::decal_set_emission_energy(RID p_decal, float p_energy) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->emission_energy = p_energy; +} + +void DecalAtlasStorage::decal_set_albedo_mix(RID p_decal, float p_mix) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->albedo_mix = p_mix; +} + +void DecalAtlasStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->modulate = p_modulate; +} + +void DecalAtlasStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->cull_mask = p_layers; + decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void DecalAtlasStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->distance_fade = p_enabled; + decal->distance_fade_begin = p_begin; + decal->distance_fade_length = p_length; +} + +void DecalAtlasStorage::decal_set_fade(RID p_decal, float p_above, float p_below) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->upper_fade = p_above; + decal->lower_fade = p_below; +} + +void DecalAtlasStorage::decal_set_normal_fade(RID p_decal, float p_fade) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND(!decal); + decal->normal_fade = p_fade; +} + +void DecalAtlasStorage::decal_atlas_mark_dirty_on_texture(RID p_texture) { + if (decal_atlas.textures.has(p_texture)) { + //belongs to decal atlas.. + + decal_atlas.dirty = true; //mark it dirty since it was most likely modified + } +} + +void DecalAtlasStorage::decal_atlas_remove_texture(RID p_texture) { + if (decal_atlas.textures.has(p_texture)) { + decal_atlas.textures.erase(p_texture); + //there is not much a point of making it dirty, just let it be. + } +} + +AABB DecalAtlasStorage::decal_get_aabb(RID p_decal) const { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND_V(!decal, AABB()); + + return AABB(-decal->extents, decal->extents * 2.0); +} + +void DecalAtlasStorage::update_decal_atlas() { + EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); + + if (!decal_atlas.dirty) { + return; //nothing to do + } + + decal_atlas.dirty = false; + + if (decal_atlas.texture.is_valid()) { + RD::get_singleton()->free(decal_atlas.texture); + decal_atlas.texture = RID(); + decal_atlas.texture_srgb = RID(); + decal_atlas.texture_mipmaps.clear(); + } + + int border = 1 << decal_atlas.mipmaps; + + if (decal_atlas.textures.size()) { + //generate atlas + Vector<DecalAtlas::SortItem> itemsv; + itemsv.resize(decal_atlas.textures.size()); + int base_size = 8; + const RID *K = nullptr; + + int idx = 0; + while ((K = decal_atlas.textures.next(K))) { + DecalAtlas::SortItem &si = itemsv.write[idx]; + + Texture *src_tex = TextureStorage::get_singleton()->get_texture(*K); + + si.size.width = (src_tex->width / border) + 1; + si.size.height = (src_tex->height / border) + 1; + si.pixel_size = Size2i(src_tex->width, src_tex->height); + + if (base_size < si.size.width) { + base_size = nearest_power_of_2_templated(si.size.width); + } + + si.texture = *K; + idx++; + } + + //sort items by size + itemsv.sort(); + + //attempt to create atlas + int item_count = itemsv.size(); + DecalAtlas::SortItem *items = itemsv.ptrw(); + + int atlas_height = 0; + + while (true) { + Vector<int> v_offsetsv; + v_offsetsv.resize(base_size); + + int *v_offsets = v_offsetsv.ptrw(); + memset(v_offsets, 0, sizeof(int) * base_size); + + int max_height = 0; + + for (int i = 0; i < item_count; i++) { + //best fit + DecalAtlas::SortItem &si = items[i]; + int best_idx = -1; + int best_height = 0x7FFFFFFF; + for (int j = 0; j <= base_size - si.size.width; j++) { + int height = 0; + for (int k = 0; k < si.size.width; k++) { + int h = v_offsets[k + j]; + if (h > height) { + height = h; + if (height > best_height) { + break; //already bad + } + } + } + + if (height < best_height) { + best_height = height; + best_idx = j; + } + } + + //update + for (int k = 0; k < si.size.width; k++) { + v_offsets[k + best_idx] = best_height + si.size.height; + } + + si.pos.x = best_idx; + si.pos.y = best_height; + + if (si.pos.y + si.size.height > max_height) { + max_height = si.pos.y + si.size.height; + } + } + + if (max_height <= base_size * 2) { + atlas_height = max_height; + break; //good ratio, break; + } + + base_size *= 2; + } + + decal_atlas.size.width = base_size * border; + decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border); + + for (int i = 0; i < item_count; i++) { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture); + t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2); + t->uv_rect.size = items[i].pixel_size; + + t->uv_rect.position /= Size2(decal_atlas.size); + t->uv_rect.size /= Size2(decal_atlas.size); + } + } else { + //use border as size, so it at least has enough mipmaps + decal_atlas.size.width = border; + decal_atlas.size.height = border; + } + + //blit textures + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = decal_atlas.size.width; + tformat.height = decal_atlas.size.height; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + tformat.mipmaps = decal_atlas.mipmaps; + tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM); + tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB); + + decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1); + + { + //create the framebuffer + + Size2i s = decal_atlas.size; + + for (int i = 0; i < decal_atlas.mipmaps; i++) { + DecalAtlas::MipMap mm; + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i); + Vector<RID> fb; + fb.push_back(mm.texture); + mm.fb = RD::get_singleton()->framebuffer_create(fb); + mm.size = s; + decal_atlas.texture_mipmaps.push_back(mm); + + s.width = MAX(1, s.width >> 1); + s.height = MAX(1, s.height >> 1); + } + { + //create the SRGB variant + RD::TextureView rd_view; + rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB; + decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture); + } + } + + RID prev_texture; + for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) { + const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i]; + + Color clear_color(0, 0, 0, 0); + + if (decal_atlas.textures.size()) { + if (i == 0) { + Vector<Color> cc; + cc.push_back(clear_color); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc); + + const RID *K = nullptr; + while ((K = decal_atlas.textures.next(K))) { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K); + Texture *src_tex = TextureStorage::get_singleton()->get_texture(*K); + effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); + } + + RD::get_singleton()->draw_list_end(); + + prev_texture = mm.texture; + } else { + effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size)); + prev_texture = mm.texture; + } + } else { + RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1); + } + } +} + +void DecalAtlasStorage::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) { + if (!decal_atlas.textures.has(p_texture)) { + DecalAtlas::Texture t; + t.users = 1; + t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0; + decal_atlas.textures[p_texture] = t; + decal_atlas.dirty = true; + } else { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); + t->users++; + if (p_panorama_to_dp) { + t->panorama_to_dp_users++; + } + } +} + +void DecalAtlasStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); + ERR_FAIL_COND(!t); + t->users--; + if (p_panorama_to_dp) { + ERR_FAIL_COND(t->panorama_to_dp_users == 0); + t->panorama_to_dp_users--; + } + if (t->users == 0) { + decal_atlas.textures.erase(p_texture); + //do not mark it dirty, there is no need to since it remains working + } +} diff --git a/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h b/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h new file mode 100644 index 0000000000..a217a0f8b6 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h @@ -0,0 +1,211 @@ +/*************************************************************************/ +/* decal_atlas_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DECAL_ATLAS_STORAGE_RD_H +#define DECAL_ATLAS_STORAGE_RD_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering/storage/decal_atlas_storage.h" + +namespace RendererRD { + +struct DecalAtlas { + struct Texture { + int panorama_to_dp_users; + int users; + Rect2 uv_rect; + }; + + struct SortItem { + RID texture; + Size2i pixel_size; + Size2i size; + Point2i pos; + + bool operator<(const SortItem &p_item) const { + //sort larger to smaller + if (size.height == p_item.size.height) { + return size.width > p_item.size.width; + } else { + return size.height > p_item.size.height; + } + } + }; + + HashMap<RID, Texture> textures; + bool dirty = true; + int mipmaps = 5; + + RID texture; + RID texture_srgb; + struct MipMap { + RID fb; + RID texture; + Size2i size; + }; + Vector<MipMap> texture_mipmaps; + + Size2i size; +}; + +struct Decal { + Vector3 extents = Vector3(1, 1, 1); + RID textures[RS::DECAL_TEXTURE_MAX]; + float emission_energy = 1.0; + float albedo_mix = 1.0; + Color modulate = Color(1, 1, 1, 1); + uint32_t cull_mask = (1 << 20) - 1; + float upper_fade = 0.3; + float lower_fade = 0.3; + bool distance_fade = false; + float distance_fade_begin = 10; + float distance_fade_length = 1; + float normal_fade = 0.0; + + RendererStorage::Dependency dependency; +}; + +class DecalAtlasStorage : public RendererDecalAtlasStorage { +private: + static DecalAtlasStorage *singleton; + + DecalAtlas decal_atlas; + + mutable RID_Owner<Decal, true> decal_owner; + +public: + static DecalAtlasStorage *get_singleton(); + + void update_decal_atlas(); + + DecalAtlasStorage(); + virtual ~DecalAtlasStorage(); + + Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); }; + bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); }; + + RID decal_atlas_get_texture() const; + RID decal_atlas_get_texture_srgb() const; + _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); + if (!t) { + return Rect2(); + } + + return t->uv_rect; + } + + virtual RID decal_allocate() override; + virtual void decal_initialize(RID p_decal) override; + virtual void decal_free(RID p_rid) override; + + virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override; + virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override; + virtual void decal_set_emission_energy(RID p_decal, float p_energy) override; + virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override; + virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override; + virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override; + virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override; + virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override; + virtual void decal_set_normal_fade(RID p_decal, float p_fade) override; + + void decal_atlas_mark_dirty_on_texture(RID p_texture); + void decal_atlas_remove_texture(RID p_texture); + + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override; + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override; + + _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->extents; + } + + _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->textures[p_texture]; + } + + _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->modulate; + } + + _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->emission_energy; + } + + _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->albedo_mix; + } + + _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->cull_mask; + } + + _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->upper_fade; + } + + _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->lower_fade; + } + + _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->normal_fade; + } + + _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->distance_fade; + } + + _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->distance_fade_begin; + } + + _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) { + const Decal *decal = decal_owner.get_or_null(p_decal); + return decal->distance_fade_length; + } + + virtual AABB decal_get_aabb(RID p_decal) const override; +}; + +} // namespace RendererRD + +#endif // !DECAL_ATLAS_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp new file mode 100644 index 0000000000..9e3d124bbb --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -0,0 +1,2392 @@ +/*************************************************************************/ +/* material_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "material_storage.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/io/resource_loader.h" +#include "texture_storage.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// UBI helper functions + +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) { + switch (type) { + case ShaderLanguage::TYPE_BOOL: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = (r[i] != 0) ? 1 : 0; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + bool v = value; + gui[0] = v ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_BVEC2: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + int count = 2 * p_array_size; + + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i] ? 1 : 0; + gui[j + 1] = r[i + 1] ? 1 : 0; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = v & 1 ? 1 : 0; + gui[1] = v & 2 ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_BVEC3: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + int count = 3 * p_array_size; + + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i] ? 1 : 0; + gui[j + 1] = r[i + 1] ? 1 : 0; + gui[j + 2] = r[i + 2] ? 1 : 0; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = (v & 1) ? 1 : 0; + gui[1] = (v & 2) ? 1 : 0; + gui[2] = (v & 4) ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_BVEC4: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + int count = 4 * p_array_size; + + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i] ? 1 : 0; + gui[i + 1] = r[i + 1] ? 1 : 0; + gui[i + 2] = r[i + 2] ? 1 : 0; + gui[i + 3] = r[i + 3] ? 1 : 0; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } else { + int v = value; + gui[0] = (v & 1) ? 1 : 0; + gui[1] = (v & 2) ? 1 : 0; + gui[2] = (v & 4) ? 1 : 0; + gui[3] = (v & 8) ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_INT: { + int32_t *gui = (int32_t *)data; + + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + const int *r = iv.ptr(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = r[i]; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = v; + } + } break; + case ShaderLanguage::TYPE_IVEC2: { + Vector<int> iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 2 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_IVEC3: { + Vector<int> iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_IVEC4: { + Vector<int> iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } break; + case ShaderLanguage::TYPE_UINT: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + const int *r = iv.ptr(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = r[i]; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = v; + } + } break; + case ShaderLanguage::TYPE_UVEC2: { + Vector<int> iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 2 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + Vector<int> iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_UVEC4: { + Vector<int> iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i++) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = a[i]; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + float v = value; + gui[0] = v; + } + } break; + case ShaderLanguage::TYPE_VEC2: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedVector2Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = a[i].x; + gui[j + 1] = a[i].y; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + Vector2 v = value; + gui[0] = v.x; + gui[1] = v.y; + } + } break; + case ShaderLanguage::TYPE_VEC3: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedVector3Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = a[i].x; + gui[j + 1] = a[i].y; + gui[j + 2] = a[i].z; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } else { + Vector3 v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + } + } break; + case ShaderLanguage::TYPE_VEC4: { + float *gui = (float *)data; + + if (p_array_size > 0) { + if (value.get_type() == Variant::PACKED_COLOR_ARRAY) { + const PackedColorArray &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + Color color = a[i]; + if (p_linear_color) { + color = color.to_linear(); + } + gui[j] = color.r; + gui[j + 1] = color.g; + gui[j + 2] = color.b; + gui[j + 3] = color.a; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + gui[j + 3] = 0; + } + } + } else { + const PackedFloat32Array &a = value; + int s = a.size(); + int count = 4 * p_array_size; + + for (int i = 0; i < count; i += 4) { + if (i + 3 < s) { + gui[i] = a[i]; + gui[i + 1] = a[i + 1]; + gui[i + 2] = a[i + 2]; + gui[i + 3] = a[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } + } else { + if (value.get_type() == Variant::COLOR) { + Color v = value; + + if (p_linear_color) { + v = v.to_linear(); + } + + gui[0] = v.r; + gui[1] = v.g; + gui[2] = v.b; + gui[3] = v.a; + } else if (value.get_type() == Variant::RECT2) { + Rect2 v = value; + + gui[0] = v.position.x; + gui[1] = v.position.y; + gui[2] = v.size.x; + gui[3] = v.size.y; + } else if (value.get_type() == Variant::QUATERNION) { + Quaternion v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; + } else { + Plane v = value; + + gui[0] = v.normal.x; + gui[1] = v.normal.y; + gui[2] = v.normal.z; + gui[3] = v.d; + } + } + } break; + case ShaderLanguage::TYPE_MAT2: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) { + if (i + 3 < s) { + gui[j] = a[i]; + gui[j + 1] = a[i + 1]; + + gui[j + 4] = a[i + 2]; + gui[j + 5] = a[i + 3]; + } else { + gui[j] = 1; + gui[j + 1] = 0; + + gui[j + 4] = 0; + gui[j + 5] = 1; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + gui[j + 6] = 0; // ignored + gui[j + 7] = 0; // ignored + } + } else { + Transform2D v = value; + + //in std140 members of mat2 are treated as vec4s + gui[0] = v.elements[0][0]; + gui[1] = v.elements[0][1]; + gui[2] = 0; // ignored + gui[3] = 0; // ignored + + gui[4] = v.elements[1][0]; + gui[5] = v.elements[1][1]; + gui[6] = 0; // ignored + gui[7] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_MAT3: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) { + if (i + 8 < s) { + gui[j] = a[i]; + gui[j + 1] = a[i + 1]; + gui[j + 2] = a[i + 2]; + + gui[j + 4] = a[i + 3]; + gui[j + 5] = a[i + 4]; + gui[j + 6] = a[i + 5]; + + gui[j + 8] = a[i + 6]; + gui[j + 9] = a[i + 7]; + gui[j + 10] = a[i + 8]; + } else { + gui[j] = 1; + gui[j + 1] = 0; + gui[j + 2] = 0; + + gui[j + 4] = 0; + gui[j + 5] = 1; + gui[j + 6] = 0; + + gui[j + 8] = 0; + gui[j + 9] = 0; + gui[j + 10] = 1; + } + gui[j + 3] = 0; // ignored + gui[j + 7] = 0; // ignored + gui[j + 11] = 0; // ignored + } + } else { + Basis v = value; + gui[0] = v.elements[0][0]; + gui[1] = v.elements[1][0]; + gui[2] = v.elements[2][0]; + gui[3] = 0; // ignored + + gui[4] = v.elements[0][1]; + gui[5] = v.elements[1][1]; + gui[6] = v.elements[2][1]; + gui[7] = 0; // ignored + + gui[8] = v.elements[0][2]; + gui[9] = v.elements[1][2]; + gui[10] = v.elements[2][2]; + gui[11] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_MAT4: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0; i < p_array_size * 16; i += 16) { + if (i + 15 < s) { + gui[i] = a[i]; + gui[i + 1] = a[i + 1]; + gui[i + 2] = a[i + 2]; + gui[i + 3] = a[i + 3]; + + gui[i + 4] = a[i + 4]; + gui[i + 5] = a[i + 5]; + gui[i + 6] = a[i + 6]; + gui[i + 7] = a[i + 7]; + + gui[i + 8] = a[i + 8]; + gui[i + 9] = a[i + 9]; + gui[i + 10] = a[i + 10]; + gui[i + 11] = a[i + 11]; + + gui[i + 12] = a[i + 12]; + gui[i + 13] = a[i + 13]; + gui[i + 14] = a[i + 14]; + gui[i + 15] = a[i + 15]; + } else { + gui[i] = 1; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + + gui[i + 4] = 0; + gui[i + 5] = 1; + gui[i + 6] = 0; + gui[i + 7] = 0; + + gui[i + 8] = 0; + gui[i + 9] = 0; + gui[i + 10] = 1; + gui[i + 11] = 0; + + gui[i + 12] = 0; + gui[i + 13] = 0; + gui[i + 14] = 0; + gui[i + 15] = 1; + } + } + } else { + Transform3D v = value; + gui[0] = v.basis.elements[0][0]; + gui[1] = v.basis.elements[1][0]; + gui[2] = v.basis.elements[2][0]; + gui[3] = 0; + + gui[4] = v.basis.elements[0][1]; + gui[5] = v.basis.elements[1][1]; + gui[6] = v.basis.elements[2][1]; + gui[7] = 0; + + gui[8] = v.basis.elements[0][2]; + gui[9] = v.basis.elements[1][2]; + gui[10] = v.basis.elements[2][2]; + gui[11] = 0; + + gui[12] = v.origin.x; + gui[13] = v.origin.y; + gui[14] = v.origin.z; + gui[15] = 1; + } + } break; + default: { + } + } +} + +_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) { + switch (type) { + case ShaderLanguage::TYPE_BOOL: { + uint32_t *gui = (uint32_t *)data; + *gui = value[0].boolean ? 1 : 0; + } break; + case ShaderLanguage::TYPE_BVEC2: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + gui[2] = value[2].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + gui[2] = value[2].boolean ? 1 : 0; + gui[3] = value[3].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_INT: { + int32_t *gui = (int32_t *)data; + gui[0] = value[0].sint; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_IVEC4: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_UINT: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].uint; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].uint; + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].uint; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].uint; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + float *gui = (float *)data; + gui[0] = value[0].real; + + } break; + case ShaderLanguage::TYPE_VEC2: { + float *gui = (float *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC3: { + float *gui = (float *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC4: { + float *gui = (float *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT2: { + float *gui = (float *)data; + + //in std140 members of mat2 are treated as vec4s + gui[0] = value[0].real; + gui[1] = value[1].real; + gui[2] = 0; + gui[3] = 0; + gui[4] = value[2].real; + gui[5] = value[3].real; + gui[6] = 0; + gui[7] = 0; + } break; + case ShaderLanguage::TYPE_MAT3: { + float *gui = (float *)data; + + gui[0] = value[0].real; + gui[1] = value[1].real; + gui[2] = value[2].real; + gui[3] = 0; + gui[4] = value[3].real; + gui[5] = value[4].real; + gui[6] = value[5].real; + gui[7] = 0; + gui[8] = value[6].real; + gui[9] = value[7].real; + gui[10] = value[8].real; + gui[11] = 0; + } break; + case ShaderLanguage::TYPE_MAT4: { + float *gui = (float *)data; + + for (int i = 0; i < 16; i++) { + gui[i] = value[i].real; + } + } break; + default: { + } + } +} + +_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) { + if (p_array_size <= 0) { + p_array_size = 1; + } + + switch (type) { + case ShaderLanguage::TYPE_BOOL: + case ShaderLanguage::TYPE_INT: + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_FLOAT: { + memset(data, 0, 4 * p_array_size); + } break; + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_VEC2: { + memset(data, 0, 8 * p_array_size); + } break; + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_VEC3: + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: + case ShaderLanguage::TYPE_VEC4: { + memset(data, 0, 16 * p_array_size); + } break; + case ShaderLanguage::TYPE_MAT2: { + memset(data, 0, 32 * p_array_size); + } break; + case ShaderLanguage::TYPE_MAT3: { + memset(data, 0, 48 * p_array_size); + } break; + case ShaderLanguage::TYPE_MAT4: { + memset(data, 0, 64 * p_array_size); + } break; + + default: { + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// MaterialData + +void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + bool uses_global_buffer = false; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) { + if (E.value.order < 0) { + continue; // texture, does not go here + } + + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; //instance uniforms don't appear in the buffer + } + + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { + //this is a global variable, get the index to it + GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key); + uint32_t index = 0; + if (gv) { + index = gv->buffer_index; + } else { + WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly."); + } + + uint32_t offset = p_uniform_offsets[E.value.order]; + uint32_t *intptr = (uint32_t *)&p_buffer[offset]; + *intptr = index; + uses_global_buffer = true; + continue; + } + + //regular uniform + uint32_t offset = p_uniform_offsets[E.value.order]; +#ifdef DEBUG_ENABLED + uint32_t size = 0U; + // The following code enforces a 16-byte alignment of uniform arrays. + if (E.value.array_size > 0) { + size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size; + int m = (16 * E.value.array_size); + if ((size % m) != 0U) { + size += m - (size % m); + } + } else { + size = ShaderLanguage::get_datatype_size(E.value.type); + } + ERR_CONTINUE(offset + size > p_buffer_size); +#endif + uint8_t *data = &p_buffer[offset]; + const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); + + if (V) { + //user provided + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); + + } else if (E.value.default_value.size()) { + //default value + _fill_std140_ubo_value(E.value.type, E.value.default_value, data); + //value=E.value.default_value; + } else { + //zero because it was not provided + if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + //colors must be set as black, with alpha as 1.0 + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color); + } else { + //else just zero it out + _fill_std140_ubo_empty(E.value.type, E.value.array_size, data); + } + } + } + + if (uses_global_buffer != (global_buffer_E != nullptr)) { + if (uses_global_buffer) { + global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self); + } else { + material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + global_buffer_E = nullptr; + } + } +} + +MaterialData::~MaterialData() { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + + if (global_buffer_E) { + //unregister global buffers + material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + } + + if (global_texture_E) { + //unregister global textures + + for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + if (v) { + v->texture_materials.erase(self); + } + } + //unregister material from those using global textures + material_storage->global_variables.materials_using_texture.erase(global_texture_E); + } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } +} + +void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { + TextureStorage *texture_storage = TextureStorage::get_singleton(); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + +#ifdef TOOLS_ENABLED + Texture *roughness_detect_texture = nullptr; + RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; + Texture *normal_detect_texture = nullptr; +#endif + + bool uses_global_textures = false; + global_textures_pass++; + + for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { + const StringName &uniform_name = p_texture_uniforms[i].name; + int uniform_array_size = p_texture_uniforms[i].array_size; + + Vector<RID> textures; + + if (p_texture_uniforms[i].global) { + uses_global_textures = true; + + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name); + if (v) { + if (v->buffer_index >= 0) { + WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); + + } else { + Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); + if (!E) { + E = used_global_textures.insert(uniform_name, global_textures_pass); + v->texture_materials.insert(self); + } else { + E->get() = global_textures_pass; + } + + textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); + } + + } else { + WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); + } + } else { + const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); + if (V) { + if (V->get().is_array()) { + Array array = (Array)V->get(); + if (uniform_array_size > 0) { + for (int j = 0; j < array.size(); j++) { + textures.push_back(array[j]); + } + } else { + if (array.size() > 0) { + textures.push_back(array[0]); + } + } + } else { + textures.push_back(V->get()); + } + } + + if (uniform_array_size > 0) { + if (textures.size() < uniform_array_size) { + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + for (int j = textures.size(); j < uniform_array_size; j++) { + if (W && W->get().has(j)) { + textures.push_back(W->get()[j]); + } else { + textures.push_back(RID()); + } + } + } + } else if (textures.is_empty()) { + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + if (W && W->get().has(0)) { + textures.push_back(W->get()[0]); + } + } + } + + RID rd_texture; + + if (textures.is_empty()) { + //check default usage + switch (p_texture_uniforms[i].type) { + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: + case ShaderLanguage::TYPE_SAMPLER2D: { + switch (p_texture_uniforms[i].hint) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; + default: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + } break; + } + } break; + + case ShaderLanguage::TYPE_SAMPLERCUBE: { + switch (p_texture_uniforms[i].hint) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + } break; + default: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); + } break; + } + } break; + case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + } break; + + case ShaderLanguage::TYPE_ISAMPLER3D: + case ShaderLanguage::TYPE_USAMPLER3D: + case ShaderLanguage::TYPE_SAMPLER3D: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + } break; + + case ShaderLanguage::TYPE_ISAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_SAMPLER2DARRAY: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + } break; + + default: { + } + } +#ifdef TOOLS_ENABLED + if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { + roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); + } +#endif + if (uniform_array_size > 0) { + for (int j = 0; j < uniform_array_size; j++) { + p_textures[k++] = rd_texture; + } + } else { + p_textures[k++] = rd_texture; + } + } else { + bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); + + for (int j = 0; j < textures.size(); j++) { + Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); + + if (tex) { + rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; +#ifdef TOOLS_ENABLED + if (tex->detect_3d_callback && p_use_linear_color) { + tex->detect_3d_callback(tex->detect_3d_callback_ud); + } + if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { + if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { + normal_detect_texture = tex; + } + tex->detect_normal_callback(tex->detect_normal_callback_ud); + } + if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { + //find the normal texture + roughness_detect_texture = tex; + roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); + } +#endif + } + if (rd_texture.is_null()) { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + } +#ifdef TOOLS_ENABLED + if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { + roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); + } +#endif + p_textures[k++] = rd_texture; + } + } + } + { + //for textures no longer used, unregister them + List<Map<StringName, uint64_t>::Element *> to_delete; + for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { + if (E->get() != global_textures_pass) { + to_delete.push_back(E); + + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key()); + if (v) { + v->texture_materials.erase(self); + } + } + } + + while (to_delete.front()) { + used_global_textures.erase(to_delete.front()->get()); + to_delete.pop_front(); + } + //handle registering/unregistering global textures + if (uses_global_textures != (global_texture_E != nullptr)) { + if (uses_global_textures) { + global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self); + } else { + material_storage->global_variables.materials_using_texture.erase(global_texture_E); + global_texture_E = nullptr; + } + } + } +} + +void MaterialData::free_parameters_uniform_set(RID p_uniform_set) { + if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { + RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr); + RD::get_singleton()->free(p_uniform_set); + } +} + +bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { + if ((uint32_t)ubo_data.size() != p_ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(p_ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); + } + + uint32_t tex_uniform_count = 0U; + for (int i = 0; i < p_texture_uniforms.size(); i++) { + tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1); + } + + if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); + } + + if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { + // This material does not require an uniform set, so don't create it. + return false; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return false; + } + + Vector<RD::Uniform> uniforms; + + { + if (p_ubo_size) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.append_id(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { + const int array_size = p_texture_uniforms[i].array_size; + + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1 + k; + if (array_size > 0) { + for (int j = 0; j < array_size; j++) { + u.append_id(textures[k++]); + } + } else { + u.append_id(textures[k++]); + } + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set); + + RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self); + + return true; +} + +/////////////////////////////////////////////////////////////////////////// +// MaterialStorage + +MaterialStorage *MaterialStorage::singleton = nullptr; + +MaterialStorage *MaterialStorage::get_singleton() { + return singleton; +} + +MaterialStorage::MaterialStorage() { + singleton = this; + + for (int i = 0; i < SHADER_TYPE_MAX; i++) { + shader_data_request_func[i] = nullptr; + } + + static_assert(sizeof(GlobalVariables::Value) == 16); + + global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); + global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); + memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); + global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); + global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); + memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); + global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); +} + +MaterialStorage::~MaterialStorage() { + memdelete_arr(global_variables.buffer_values); + memdelete_arr(global_variables.buffer_usage); + memdelete_arr(global_variables.buffer_dirty_regions); + RD::get_singleton()->free(global_variables.buffer); + + singleton = nullptr; +} + +/* GLOBAL VARIABLE API */ + +int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { + int32_t idx = 0; + while (idx + p_elements <= global_variables.buffer_size) { + if (global_variables.buffer_usage[idx].elements == 0) { + bool valid = true; + for (uint32_t i = 1; i < p_elements; i++) { + if (global_variables.buffer_usage[idx + i].elements > 0) { + valid = false; + idx += i + global_variables.buffer_usage[idx + i].elements; + break; + } + } + + if (!valid) { + continue; //if not valid, idx is in new position + } + + return idx; + } else { + idx += global_variables.buffer_usage[idx].elements; + } + } + + return -1; +} + +void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { + switch (p_type) { + case RS::GLOBAL_VAR_TYPE_BOOL: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + bool b = p_value; + bv.x = b ? 1.0 : 0.0; + bv.y = 0.0; + bv.z = 0.0; + bv.w = 0.0; + + } break; + case RS::GLOBAL_VAR_TYPE_BVEC2: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + uint32_t bvec = p_value; + bv.x = (bvec & 1) ? 1.0 : 0.0; + bv.y = (bvec & 2) ? 1.0 : 0.0; + bv.z = 0.0; + bv.w = 0.0; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC3: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + uint32_t bvec = p_value; + bv.x = (bvec & 1) ? 1.0 : 0.0; + bv.y = (bvec & 2) ? 1.0 : 0.0; + bv.z = (bvec & 4) ? 1.0 : 0.0; + bv.w = 0.0; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC4: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + uint32_t bvec = p_value; + bv.x = (bvec & 1) ? 1.0 : 0.0; + bv.y = (bvec & 2) ? 1.0 : 0.0; + bv.z = (bvec & 4) ? 1.0 : 0.0; + bv.w = (bvec & 8) ? 1.0 : 0.0; + } break; + case RS::GLOBAL_VAR_TYPE_INT: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + int32_t v = p_value; + bv.x = v; + bv.y = 0; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC2: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Vector2i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC3: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Vector3i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = v.z; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC4: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Vector<int32_t> v = p_value; + bv.x = v.size() >= 1 ? v[0] : 0; + bv.y = v.size() >= 2 ? v[1] : 0; + bv.z = v.size() >= 3 ? v[2] : 0; + bv.w = v.size() >= 4 ? v[3] : 0; + } break; + case RS::GLOBAL_VAR_TYPE_RECT2I: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Rect2i v = p_value; + bv.x = v.position.x; + bv.y = v.position.y; + bv.z = v.size.x; + bv.w = v.size.y; + } break; + case RS::GLOBAL_VAR_TYPE_UINT: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + uint32_t v = p_value; + bv.x = v; + bv.y = 0; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC2: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + Vector2i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC3: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + Vector3i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = v.z; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC4: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + Vector<int32_t> v = p_value; + bv.x = v.size() >= 1 ? v[0] : 0; + bv.y = v.size() >= 2 ? v[1] : 0; + bv.z = v.size() >= 3 ? v[2] : 0; + bv.w = v.size() >= 4 ? v[3] : 0; + } break; + case RS::GLOBAL_VAR_TYPE_FLOAT: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + float v = p_value; + bv.x = v; + bv.y = 0; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_VEC2: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Vector2 v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_VEC3: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Vector3 v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = v.z; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_VEC4: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Plane v = p_value; + bv.x = v.normal.x; + bv.y = v.normal.y; + bv.z = v.normal.z; + bv.w = v.d; + } break; + case RS::GLOBAL_VAR_TYPE_COLOR: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Color v = p_value; + bv.x = v.r; + bv.y = v.g; + bv.z = v.b; + bv.w = v.a; + + GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; + v = v.to_linear(); + bv_linear.x = v.r; + bv_linear.y = v.g; + bv_linear.z = v.b; + bv_linear.w = v.a; + + } break; + case RS::GLOBAL_VAR_TYPE_RECT2: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Rect2 v = p_value; + bv.x = v.position.x; + bv.y = v.position.y; + bv.z = v.size.x; + bv.w = v.size.y; + } break; + case RS::GLOBAL_VAR_TYPE_MAT2: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Vector<float> m2 = p_value; + if (m2.size() < 4) { + m2.resize(4); + } + bv[0].x = m2[0]; + bv[0].y = m2[1]; + bv[0].z = 0; + bv[0].w = 0; + + bv[1].x = m2[2]; + bv[1].y = m2[3]; + bv[1].z = 0; + bv[1].w = 0; + + } break; + case RS::GLOBAL_VAR_TYPE_MAT3: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Basis v = p_value; + bv[0].x = v.elements[0][0]; + bv[0].y = v.elements[1][0]; + bv[0].z = v.elements[2][0]; + bv[0].w = 0; + + bv[1].x = v.elements[0][1]; + bv[1].y = v.elements[1][1]; + bv[1].z = v.elements[2][1]; + bv[1].w = 0; + + bv[2].x = v.elements[0][2]; + bv[2].y = v.elements[1][2]; + bv[2].z = v.elements[2][2]; + bv[2].w = 0; + + } break; + case RS::GLOBAL_VAR_TYPE_MAT4: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + + Vector<float> m2 = p_value; + if (m2.size() < 16) { + m2.resize(16); + } + + bv[0].x = m2[0]; + bv[0].y = m2[1]; + bv[0].z = m2[2]; + bv[0].w = m2[3]; + + bv[1].x = m2[4]; + bv[1].y = m2[5]; + bv[1].z = m2[6]; + bv[1].w = m2[7]; + + bv[2].x = m2[8]; + bv[2].y = m2[9]; + bv[2].z = m2[10]; + bv[2].w = m2[11]; + + bv[3].x = m2[12]; + bv[3].y = m2[13]; + bv[3].z = m2[14]; + bv[3].w = m2[15]; + + } break; + case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Transform2D v = p_value; + bv[0].x = v.elements[0][0]; + bv[0].y = v.elements[0][1]; + bv[0].z = 0; + bv[0].w = 0; + + bv[1].x = v.elements[1][0]; + bv[1].y = v.elements[1][1]; + bv[1].z = 0; + bv[1].w = 0; + + bv[2].x = v.elements[2][0]; + bv[2].y = v.elements[2][1]; + bv[2].z = 1; + bv[2].w = 0; + + } break; + case RS::GLOBAL_VAR_TYPE_TRANSFORM: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Transform3D v = p_value; + bv[0].x = v.basis.elements[0][0]; + bv[0].y = v.basis.elements[1][0]; + bv[0].z = v.basis.elements[2][0]; + bv[0].w = 0; + + bv[1].x = v.basis.elements[0][1]; + bv[1].y = v.basis.elements[1][1]; + bv[1].z = v.basis.elements[2][1]; + bv[1].w = 0; + + bv[2].x = v.basis.elements[0][2]; + bv[2].y = v.basis.elements[1][2]; + bv[2].z = v.basis.elements[2][2]; + bv[2].w = 0; + + bv[3].x = v.origin.x; + bv[3].y = v.origin.y; + bv[3].z = v.origin.z; + bv[3].w = 1; + + } break; + default: { + ERR_FAIL(); + } + } +} + +void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { + int32_t prev_chunk = -1; + + for (int32_t i = 0; i < p_elements; i++) { + int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + if (chunk != prev_chunk) { + if (!global_variables.buffer_dirty_regions[chunk]) { + global_variables.buffer_dirty_regions[chunk] = true; + global_variables.buffer_dirty_region_count++; + } + } + + prev_chunk = chunk; + } +} + +void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { + ERR_FAIL_COND(global_variables.variables.has(p_name)); + GlobalVariables::Variable gv; + gv.type = p_type; + gv.value = p_value; + gv.buffer_index = -1; + + if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { + //is texture + global_variables.must_update_texture_materials = true; //normally there are none + } else { + gv.buffer_elements = 1; + if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { + //color needs to elements to store srgb and linear + gv.buffer_elements = 2; + } + if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) { + //color needs to elements to store srgb and linear + gv.buffer_elements = 3; + } + if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) { + //color needs to elements to store srgb and linear + gv.buffer_elements = 4; + } + + //is vector, allocate in buffer and update index + gv.buffer_index = _global_variable_allocate(gv.buffer_elements); + ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); + global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + + global_variables.must_update_buffer_materials = true; //normally there are none + } + + global_variables.variables[p_name] = gv; +} + +void MaterialStorage::global_variable_remove(const StringName &p_name) { + if (!global_variables.variables.has(p_name)) { + return; + } + GlobalVariables::Variable &gv = global_variables.variables[p_name]; + + if (gv.buffer_index >= 0) { + global_variables.buffer_usage[gv.buffer_index].elements = 0; + global_variables.must_update_buffer_materials = true; + } else { + global_variables.must_update_texture_materials = true; + } + + global_variables.variables.erase(p_name); +} + +Vector<StringName> MaterialStorage::global_variable_get_list() const { + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); + } + + const StringName *K = nullptr; + Vector<StringName> names; + while ((K = global_variables.variables.next(K))) { + names.push_back(*K); + } + names.sort_custom<StringName::AlphCompare>(); + return names; +} + +void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) { + ERR_FAIL_COND(!global_variables.variables.has(p_name)); + GlobalVariables::Variable &gv = global_variables.variables[p_name]; + gv.value = p_value; + if (gv.override.get_type() == Variant::NIL) { + if (gv.buffer_index >= 0) { + //buffer + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + } else { + //texture + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + Material *material = material_storage->get_material(E->get()); + ERR_CONTINUE(!material); + material_storage->_material_queue_update(material, false, true); + } + } + } +} + +void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) { + if (!global_variables.variables.has(p_name)) { + return; //variable may not exist + } + + ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); + + GlobalVariables::Variable &gv = global_variables.variables[p_name]; + + gv.override = p_value; + + if (gv.buffer_index >= 0) { + //buffer + if (gv.override.get_type() == Variant::NIL) { + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + } else { + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); + } + + _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + } else { + //texture + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + Material *material = material_storage->get_material(E->get()); + ERR_CONTINUE(!material); + material_storage->_material_queue_update(material, false, true); + } + } +} + +Variant MaterialStorage::global_variable_get(const StringName &p_name) const { + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); + } + + if (!global_variables.variables.has(p_name)) { + return Variant(); + } + + return global_variables.variables[p_name].value; +} + +RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const { + if (!global_variables.variables.has(p_name)) { + return RS::GLOBAL_VAR_TYPE_MAX; + } + + return global_variables.variables[p_name].type; +} + +RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const { + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); + } + + return global_variable_get_type_internal(p_name); +} + +void MaterialStorage::global_variables_load_settings(bool p_load_textures) { + List<PropertyInfo> settings; + ProjectSettings::get_singleton()->get_property_list(&settings); + + for (const PropertyInfo &E : settings) { + if (E.name.begins_with("shader_globals/")) { + StringName name = E.name.get_slice("/", 1); + Dictionary d = ProjectSettings::get_singleton()->get(E.name); + + ERR_CONTINUE(!d.has("type")); + ERR_CONTINUE(!d.has("value")); + + String type = d["type"]; + + static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = { + "bool", + "bvec2", + "bvec3", + "bvec4", + "int", + "ivec2", + "ivec3", + "ivec4", + "rect2i", + "uint", + "uvec2", + "uvec3", + "uvec4", + "float", + "vec2", + "vec3", + "vec4", + "color", + "rect2", + "mat2", + "mat3", + "mat4", + "transform_2d", + "transform", + "sampler2D", + "sampler2DArray", + "sampler3D", + "samplerCube", + }; + + RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; + + for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { + if (global_var_type_names[i] == type) { + gvtype = RS::GlobalVariableType(i); + break; + } + } + + ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid + + Variant value = d["value"]; + + if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { + //textire + if (!p_load_textures) { + value = RID(); + continue; + } + + String path = value; + RES resource = ResourceLoader::load(path); + ERR_CONTINUE(resource.is_null()); + value = resource; + } + + if (global_variables.variables.has(name)) { + //has it, update it + global_variable_set(name, value); + } else { + global_variable_add(name, gvtype, value); + } + } + } +} + +void MaterialStorage::global_variables_clear() { + global_variables.variables.clear(); //not right but for now enough +} + +RID MaterialStorage::global_variables_get_storage_buffer() const { + return global_variables.buffer; +} + +int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) { + ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); + int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + global_variables.instance_buffer_pos[p_instance] = pos; //save anyway + ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); + global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; + return pos; +} + +void MaterialStorage::global_variables_instance_free(RID p_instance) { + ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); + int32_t pos = global_variables.instance_buffer_pos[p_instance]; + if (pos >= 0) { + global_variables.buffer_usage[pos].elements = 0; + } + global_variables.instance_buffer_pos.erase(p_instance); +} + +void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { + if (!global_variables.instance_buffer_pos.has(p_instance)) { + return; //just not allocated, ignore + } + int32_t pos = global_variables.instance_buffer_pos[p_instance]; + + if (pos < 0) { + return; //again, not allocated, ignore + } + ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported + + ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = { + ShaderLanguage::TYPE_MAX, //nil + ShaderLanguage::TYPE_BOOL, //bool + ShaderLanguage::TYPE_INT, //int + ShaderLanguage::TYPE_FLOAT, //float + ShaderLanguage::TYPE_MAX, //string + ShaderLanguage::TYPE_VEC2, //vec2 + ShaderLanguage::TYPE_IVEC2, //vec2i + ShaderLanguage::TYPE_VEC4, //rect2 + ShaderLanguage::TYPE_IVEC4, //rect2i + ShaderLanguage::TYPE_VEC3, // vec3 + ShaderLanguage::TYPE_IVEC3, //vec3i + ShaderLanguage::TYPE_MAX, //xform2d not supported here + ShaderLanguage::TYPE_VEC4, //plane + ShaderLanguage::TYPE_VEC4, //quat + ShaderLanguage::TYPE_MAX, //aabb not supported here + ShaderLanguage::TYPE_MAX, //basis not supported here + ShaderLanguage::TYPE_MAX, //xform not supported here + ShaderLanguage::TYPE_VEC4 //color + }; + + ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()]; + + ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported + + pos += p_index; + + _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer + _global_variable_mark_buffer_dirty(pos, 1); +} + +void MaterialStorage::_update_global_variables() { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + if (global_variables.buffer_dirty_region_count > 0) { + uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + if (total_regions / global_variables.buffer_dirty_region_count <= 4) { + // 25% of regions dirty, just update all buffer + RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values); + memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); + } else { + uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + + for (uint32_t i = 0; i < total_regions; i++) { + if (global_variables.buffer_dirty_regions[i]) { + RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); + + global_variables.buffer_dirty_regions[i] = false; + } + } + } + + global_variables.buffer_dirty_region_count = 0; + } + + if (global_variables.must_update_buffer_materials) { + // only happens in the case of a buffer variable added or removed, + // so not often. + for (const RID &E : global_variables.materials_using_buffer) { + Material *material = material_storage->get_material(E); + ERR_CONTINUE(!material); //wtf + + material_storage->_material_queue_update(material, true, false); + } + + global_variables.must_update_buffer_materials = false; + } + + if (global_variables.must_update_texture_materials) { + // only happens in the case of a buffer variable added or removed, + // so not often. + for (const RID &E : global_variables.materials_using_texture) { + Material *material = material_storage->get_material(E); + ERR_CONTINUE(!material); //wtf + + material_storage->_material_queue_update(material, false, true); + } + + global_variables.must_update_texture_materials = false; + } +} + +/* SHADER API */ + +RID MaterialStorage::shader_allocate() { + return shader_owner.allocate_rid(); +} + +void MaterialStorage::shader_initialize(RID p_rid) { + Shader shader; + shader.data = nullptr; + shader.type = SHADER_TYPE_MAX; + + shader_owner.initialize_rid(p_rid, shader); +} + +void MaterialStorage::shader_free(RID p_rid) { + Shader *shader = shader_owner.get_or_null(p_rid); + ERR_FAIL_COND(!shader); + + //make material unreference this + while (shader->owners.size()) { + material_set_shader(shader->owners.front()->get()->self, RID()); + } + + //clear data if exists + if (shader->data) { + memdelete(shader->data); + } + shader_owner.free(p_rid); +} + +void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + shader->code = p_code; + String mode_string = ShaderLanguage::get_shader_type(p_code); + + ShaderType new_type; + if (mode_string == "canvas_item") { + new_type = SHADER_TYPE_2D; + } else if (mode_string == "particles") { + new_type = SHADER_TYPE_PARTICLES; + } else if (mode_string == "spatial") { + new_type = SHADER_TYPE_3D; + } else if (mode_string == "sky") { + new_type = SHADER_TYPE_SKY; + } else if (mode_string == "fog") { + new_type = SHADER_TYPE_FOG; + } else { + new_type = SHADER_TYPE_MAX; + } + + if (new_type != shader->type) { + if (shader->data) { + memdelete(shader->data); + shader->data = nullptr; + } + + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + material->shader_type = new_type; + if (material->data) { + memdelete(material->data); + material->data = nullptr; + } + } + + shader->type = new_type; + + if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) { + shader->data = shader_data_request_func[new_type](); + } else { + shader->type = SHADER_TYPE_MAX; //invalid + } + + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + if (shader->data) { + material->data = material_get_data_request_function(new_type)(shader->data); + material->data->self = material->self; + material->data->set_next_pass(material->next_pass); + material->data->set_render_priority(material->priority); + } + material->shader_type = new_type; + } + + if (shader->data) { + for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<int, RID> &E2 : E.value) { + shader->data->set_default_texture_param(E.key, E2.value, E2.key); + } + } + } + } + + if (shader->data) { + shader->data->set_code(p_code); + } + + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + _material_queue_update(material, true, true); + } +} + +String MaterialStorage::shader_get_code(RID p_shader) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, String()); + return shader->code; +} + +void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + if (shader->data) { + return shader->data->get_param_list(p_param_list); + } +} + +void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) { + if (!shader->default_texture_parameter.has(p_name)) { + shader->default_texture_parameter[p_name] = Map<int, RID>(); + } + shader->default_texture_parameter[p_name][p_index] = p_texture; + } else { + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + shader->default_texture_parameter[p_name].erase(p_index); + + if (shader->default_texture_parameter[p_name].is_empty()) { + shader->default_texture_parameter.erase(p_name); + } + } + } + if (shader->data) { + shader->data->set_default_texture_param(p_name, p_texture, p_index); + } + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + _material_queue_update(material, false, true); + } +} + +RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, RID()); + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + return shader->default_texture_parameter[p_name][p_index]; + } + + return RID(); +} + +Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, Variant()); + if (shader->data) { + return shader->data->get_default_parameter(p_param); + } + return Variant(); +} + +void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { + ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); + shader_data_request_func[p_shader_type] = p_function; +} + +RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); + if (shader->data) { + return shader->data->get_native_source_code(); + } + return RS::ShaderNativeSourceCode(); +} + +/* MATERIAL API */ + +void MaterialStorage::_material_uniform_set_erased(void *p_material) { + RID rid = *(RID *)p_material; + Material *material = MaterialStorage::get_singleton()->get_material(rid); + if (material) { + if (material->data) { + // Uniform set may be gone because a dependency was erased. This happens + // if a texture is deleted, so re-create it. + MaterialStorage::get_singleton()->_material_queue_update(material, false, true); + } + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + } +} + +void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { + material->uniform_dirty = material->uniform_dirty || p_uniform; + material->texture_dirty = material->texture_dirty || p_texture; + + if (material->update_element.in_list()) { + return; + } + + material_update_list.add(&material->update_element); +} + +void MaterialStorage::_update_queued_materials() { + while (material_update_list.first()) { + Material *material = material_update_list.first()->self(); + bool uniforms_changed = false; + + if (material->data) { + uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); + } + material->texture_dirty = false; + material->uniform_dirty = false; + + material_update_list.remove(&material->update_element); + + if (uniforms_changed) { + //some implementations such as 3D renderer cache the matreial uniform set, so update is required + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + } + } +} + +RID MaterialStorage::material_allocate() { + return material_owner.allocate_rid(); +} + +void MaterialStorage::material_initialize(RID p_rid) { + material_owner.initialize_rid(p_rid); + Material *material = material_owner.get_or_null(p_rid); + material->self = p_rid; +} + +void MaterialStorage::material_free(RID p_rid) { + Material *material = material_owner.get_or_null(p_rid); + ERR_FAIL_COND(!material); + + material_set_shader(p_rid, RID()); //clean up shader + material->dependency.deleted_notify(p_rid); + + material_owner.free(p_rid); +} + +void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + + if (material->data) { + memdelete(material->data); + material->data = nullptr; + } + + if (material->shader) { + material->shader->owners.erase(material); + material->shader = nullptr; + material->shader_type = SHADER_TYPE_MAX; + } + + if (p_shader.is_null()) { + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->shader_id = 0; + return; + } + + Shader *shader = get_shader(p_shader); + ERR_FAIL_COND(!shader); + material->shader = shader; + material->shader_type = shader->type; + material->shader_id = p_shader.get_local_index(); + shader->owners.insert(material); + + if (shader->type == SHADER_TYPE_MAX) { + return; + } + + ERR_FAIL_COND(shader->data == nullptr); + + material->data = material_data_request_func[shader->type](shader->data); + material->data->self = p_material; + material->data->set_next_pass(material->next_pass); + material->data->set_render_priority(material->priority); + //updating happens later + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + _material_queue_update(material, true, true); +} + +void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + + if (p_value.get_type() == Variant::NIL) { + material->params.erase(p_param); + } else { + ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed + material->params[p_param] = p_value; + } + + if (material->shader && material->shader->data) { //shader is valid + bool is_texture = material->shader->data->is_param_texture(p_param); + _material_queue_update(material, !is_texture, is_texture); + } else { + _material_queue_update(material, true, true); + } +} + +Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND_V(!material, Variant()); + if (material->params.has(p_param)) { + return material->params[p_param]; + } else { + return Variant(); + } +} + +void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + + if (material->next_pass == p_next_material) { + return; + } + + material->next_pass = p_next_material; + if (material->data) { + material->data->set_next_pass(p_next_material); + } + + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); +} + +void MaterialStorage::material_set_render_priority(RID p_material, int priority) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + material->priority = priority; + if (material->data) { + material->data->set_render_priority(priority); + } +} + +bool MaterialStorage::material_is_animated(RID p_material) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND_V(!material, false); + if (material->shader && material->shader->data) { + if (material->shader->data->is_animated()) { + return true; + } else if (material->next_pass.is_valid()) { + return material_is_animated(material->next_pass); + } + } + return false; //by default nothing is animated +} + +bool MaterialStorage::material_casts_shadows(RID p_material) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND_V(!material, true); + if (material->shader && material->shader->data) { + if (material->shader->data->casts_shadows()) { + return true; + } else if (material->next_pass.is_valid()) { + return material_casts_shadows(material->next_pass); + } + } + return true; //by default everything casts shadows +} + +void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + if (material->shader && material->shader->data) { + material->shader->data->get_instance_param_list(r_parameters); + + if (material->next_pass.is_valid()) { + material_get_instance_shader_parameters(material->next_pass, r_parameters); + } + } +} + +void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + p_instance->update_dependency(&material->dependency); + if (material->next_pass.is_valid()) { + material_update_dependency(material->next_pass, p_instance); + } +} + +void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { + ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); + material_data_request_func[p_shader_type] = p_function; +} + +MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) { + ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr); + return material_data_request_func[p_shader_type]; +} diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h new file mode 100644 index 0000000000..270d9f0982 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -0,0 +1,315 @@ +/*************************************************************************/ +/* material_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MATERIAL_STORAGE_RD_H +#define MATERIAL_STORAGE_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/shader_compiler.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering/storage/material_storage.h" + +namespace RendererRD { + +class MaterialStorage; + +/* SHADER Structs */ + +enum ShaderType { + SHADER_TYPE_2D, + SHADER_TYPE_3D, + SHADER_TYPE_PARTICLES, + SHADER_TYPE_SKY, + SHADER_TYPE_FOG, + SHADER_TYPE_MAX +}; + +struct ShaderData { + virtual void set_code(const String &p_Code) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; + virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; + + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; + virtual bool is_param_texture(const StringName &p_param) const = 0; + virtual bool is_animated() const = 0; + virtual bool casts_shadows() const = 0; + virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; + virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } + + virtual ~ShaderData() {} +}; + +typedef ShaderData *(*ShaderDataRequestFunction)(); + +struct Material; + +struct Shader { + ShaderData *data = nullptr; + String code; + ShaderType type; + Map<StringName, Map<int, RID>> default_texture_parameter; + Set<Material *> owners; +}; + +/* Material structs */ + +struct MaterialData { + void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + + virtual void set_render_priority(int p_priority) = 0; + virtual void set_next_pass(RID p_pass) = 0; + virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual ~MaterialData(); + + //to be used internally by update_parameters, in the most common configuration of material parameters + bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void free_parameters_uniform_set(RID p_uniform_set); + +private: + friend class MaterialStorage; + RID self; + List<RID>::Element *global_buffer_E = nullptr; + List<RID>::Element *global_texture_E = nullptr; + uint64_t global_textures_pass = 0; + Map<StringName, uint64_t> used_global_textures; + + //internally by update_parameters_uniform_set + Vector<uint8_t> ubo_data; + RID uniform_buffer; + Vector<RID> texture_cache; +}; + +typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); + +struct Material { + RID self; + MaterialData *data = nullptr; + Shader *shader = nullptr; + //shortcut to shader data and type + ShaderType shader_type = SHADER_TYPE_MAX; + uint32_t shader_id = 0; + bool uniform_dirty = false; + bool texture_dirty = false; + Map<StringName, Variant> params; + int32_t priority = 0; + RID next_pass; + SelfList<Material> update_element; + + RendererStorage::Dependency dependency; + + Material() : + update_element(this) {} +}; + +/* Global variable structs */ +struct GlobalVariables { + enum { + BUFFER_DIRTY_REGION_SIZE = 1024 + }; + struct Variable { + Set<RID> texture_materials; // materials using this + + RS::GlobalVariableType type; + Variant value; + Variant override; + int32_t buffer_index; //for vectors + int32_t buffer_elements; //for vectors + }; + + HashMap<StringName, Variable> variables; + + struct Value { + float x; + float y; + float z; + float w; + }; + + struct ValueInt { + int32_t x; + int32_t y; + int32_t z; + int32_t w; + }; + + struct ValueUInt { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; + }; + + struct ValueUsage { + uint32_t elements = 0; + }; + + List<RID> materials_using_buffer; + List<RID> materials_using_texture; + + RID buffer; + Value *buffer_values = nullptr; + ValueUsage *buffer_usage = nullptr; + bool *buffer_dirty_regions = nullptr; + uint32_t buffer_dirty_region_count = 0; + + uint32_t buffer_size; + + bool must_update_texture_materials = false; + bool must_update_buffer_materials = false; + + HashMap<RID, int32_t> instance_buffer_pos; +}; + +class MaterialStorage : public RendererMaterialStorage { +private: + friend struct MaterialData; + static MaterialStorage *singleton; + + /* GLOBAL VARIABLE API */ + + GlobalVariables global_variables; + + int32_t _global_variable_allocate(uint32_t p_elements); + void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); + void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); + + /* SHADER API */ + + ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner<Shader, true> shader_owner; + + /* MATERIAL API */ + MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner<Material, true> material_owner; + + SelfList<Material>::List material_update_list; + + static void _material_uniform_set_erased(void *p_material); + +public: + static MaterialStorage *get_singleton(); + + MaterialStorage(); + virtual ~MaterialStorage(); + + /* GLOBAL VARIABLE API */ + + void _update_global_variables(); + + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override; + virtual void global_variable_remove(const StringName &p_name) override; + virtual Vector<StringName> global_variable_get_list() const override; + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override; + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override; + virtual Variant global_variable_get(const StringName &p_name) const override; + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override; + RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; + + virtual void global_variables_load_settings(bool p_load_textures = true) override; + virtual void global_variables_clear() override; + + virtual int32_t global_variables_instance_allocate(RID p_instance) override; + virtual void global_variables_instance_free(RID p_instance) override; + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override; + + RID global_variables_get_storage_buffer() const; + + /* SHADER API */ + + Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }; + bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; + + virtual RID shader_allocate() override; + virtual void shader_initialize(RID p_shader) override; + virtual void shader_free(RID p_rid) override; + + virtual void shader_set_code(RID p_shader, const String &p_code) override; + virtual String shader_get_code(RID p_shader) const override; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override; + virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override; + void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override; + + /* MATERIAL API */ + + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; + bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; + + void _material_queue_update(Material *material, bool p_uniform, bool p_texture); + void _update_queued_materials(); + + virtual RID material_allocate() override; + virtual void material_initialize(RID p_material) override; + virtual void material_free(RID p_rid) override; + + virtual void material_set_shader(RID p_material, RID p_shader) override; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const override; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) override; + virtual void material_set_render_priority(RID p_material, int priority) override; + + virtual bool material_is_animated(RID p_material) override; + virtual bool material_casts_shadows(RID p_material) override; + + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; + + virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override; + + void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); + MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type); + + _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { + Material *material = material_owner.get_or_null(p_material); + return material->shader_id; + } + + _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { + Material *material = material_owner.get_or_null(p_material); + if (!material || material->shader_type != p_shader_type) { + return nullptr; + } else { + return material->data; + } + } +}; + +} // namespace RendererRD + +#endif // !MATERIAL_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp new file mode 100644 index 0000000000..8c60264ce3 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -0,0 +1,1921 @@ +/*************************************************************************/ +/* mesh_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "mesh_storage.h" + +using namespace RendererRD; + +MeshStorage *MeshStorage::singleton = nullptr; + +MeshStorage *MeshStorage::get_singleton() { + return singleton; +} + +MeshStorage::MeshStorage() { + singleton = this; + + default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); + + //default rd buffers + { + Vector<uint8_t> buffer; + { + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //normal + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //tangent + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //color + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 1.0; + fptr[2] = 1.0; + fptr[3] = 1.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //tex uv 1 + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + { //tex uv 2 + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //bones + buffer.resize(sizeof(uint32_t) * 4); + { + uint8_t *w = buffer.ptrw(); + uint32_t *fptr = (uint32_t *)w; + fptr[0] = 0; + fptr[1] = 0; + fptr[2] = 0; + fptr[3] = 0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //weights + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + } + + { + Vector<String> skeleton_modes; + skeleton_modes.push_back("\n#define MODE_2D\n"); + skeleton_modes.push_back(""); + + skeleton_shader.shader.initialize(skeleton_modes); + skeleton_shader.version = skeleton_shader.shader.version_create(); + for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) { + skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i); + skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]); + } + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(default_rd_storage_buffer); + uniforms.push_back(u); + } + skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); + } + } +} + +MeshStorage::~MeshStorage() { + //def buffers + for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { + RD::get_singleton()->free(mesh_default_rd_buffers[i]); + } + + skeleton_shader.shader.version_free(skeleton_shader.version); + + RD::get_singleton()->free(default_rd_storage_buffer); + + singleton = nullptr; +} + +/* MESH API */ + +RID MeshStorage::mesh_allocate() { + return mesh_owner.allocate_rid(); +} + +void MeshStorage::mesh_initialize(RID p_rid) { + mesh_owner.initialize_rid(p_rid, Mesh()); +} + +void MeshStorage::mesh_free(RID p_rid) { + mesh_clear(p_rid); + mesh_set_shadow_mesh(p_rid, RID()); + Mesh *mesh = mesh_owner.get_or_null(p_rid); + mesh->dependency.deleted_notify(p_rid); + if (mesh->instances.size()) { + ERR_PRINT("deleting mesh with active instances"); + } + if (mesh->shadow_owners.size()) { + for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + Mesh *shadow_owner = E->get(); + shadow_owner->shadow_mesh = RID(); + shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + } + } + mesh_owner.free(p_rid); +} + +void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) { + ERR_FAIL_COND(p_blend_shape_count < 0); + + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + + ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist + + mesh->blend_shape_count = p_blend_shape_count; +} + +/// Returns stride +void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + + ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES); + +#ifdef DEBUG_ENABLED + //do a validation, to catch errors first + { + uint32_t stride = 0; + uint32_t attrib_stride = 0; + uint32_t skin_stride = 0; + + for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { + if ((p_surface.format & (1 << i))) { + switch (i) { + case RS::ARRAY_VERTEX: { + if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + stride += sizeof(float) * 2; + } else { + stride += sizeof(float) * 3; + } + + } break; + case RS::ARRAY_NORMAL: { + stride += sizeof(int32_t); + + } break; + case RS::ARRAY_TANGENT: { + stride += sizeof(int32_t); + + } break; + case RS::ARRAY_COLOR: { + attrib_stride += sizeof(uint32_t); + } break; + case RS::ARRAY_TEX_UV: { + attrib_stride += sizeof(float) * 2; + + } break; + case RS::ARRAY_TEX_UV2: { + attrib_stride += sizeof(float) * 2; + + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + int idx = i - RS::ARRAY_CUSTOM0; + uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; + uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + attrib_stride += fmtsize[fmt]; + + } break; + case RS::ARRAY_WEIGHTS: + case RS::ARRAY_BONES: { + //uses a separate array + bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS; + skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8); + } break; + } + } + } + + int expected_size = stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + + int bs_expected_size = expected_size * mesh->blend_shape_count; + + ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")"); + + int expected_attrib_size = attrib_stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")"); + + if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) { + expected_size = skin_stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + } + } + +#endif + + Mesh::Surface *s = memnew(Mesh::Surface); + + s->format = p_surface.format; + s->primitive = p_surface.primitive; + + bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); + + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); + s->vertex_buffer_size = p_surface.vertex_data.size(); + + if (p_surface.attribute_data.size()) { + s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); + } + if (p_surface.skin_data.size()) { + s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage); + s->skin_buffer_size = p_surface.skin_data.size(); + } + + s->vertex_count = p_surface.vertex_count; + + if (p_surface.format & RS::ARRAY_FORMAT_BONES) { + mesh->has_bone_weights = true; + } + + if (p_surface.index_count) { + bool is_index_16 = p_surface.vertex_count <= 65536; + + s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); + s->index_count = p_surface.index_count; + s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); + if (p_surface.lods.size()) { + s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); + s->lod_count = p_surface.lods.size(); + + for (int i = 0; i < p_surface.lods.size(); i++) { + uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); + s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); + s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); + s->lods[i].edge_length = p_surface.lods[i].edge_length; + s->lods[i].index_count = indices; + } + } + } + + s->aabb = p_surface.aabb; + s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. + + if (mesh->blend_shape_count > 0) { + s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data); + } + + if (use_as_storage) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(s->vertex_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (s->skin_buffer.is_valid()) { + u.append_id(s->skin_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (s->blend_shape_buffer.is_valid()) { + u.append_id(s->blend_shape_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + + s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE); + } + + if (mesh->surface_count == 0) { + mesh->bone_aabbs = p_surface.bone_aabbs; + mesh->aabb = p_surface.aabb; + } else { + if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) { + // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone + // Each surface may affect different numbers of bones. + mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); + } + for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { + mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); + } + mesh->aabb.merge_with(p_surface.aabb); + } + + s->material = p_surface.material; + + mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); + mesh->surfaces[mesh->surface_count] = s; + mesh->surface_count++; + + for (MeshInstance *mi : mesh->instances) { + _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); + } + + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + + for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + Mesh *shadow_owner = E->get(); + shadow_owner->shadow_mesh = RID(); + shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + } + + mesh->material_cache.clear(); +} + +int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const { + const Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, -1); + return mesh->blend_shape_count; +} + +void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_INDEX((int)p_mode, 2); + + mesh->blend_shape_mode = p_mode; +} + +RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); + return mesh->blend_shape_mode; +} + +void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); +} + +void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null()); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r); +} + +void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null()); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r); +} + +void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + mesh->surfaces[p_surface]->material = p_material; + + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + mesh->material_cache.clear(); +} + +RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RID()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); + + return mesh->surfaces[p_surface]->material; +} + +RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); + + Mesh::Surface &s = *mesh->surfaces[p_surface]; + + RS::SurfaceData sd; + sd.format = s.format; + sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + if (s.attribute_buffer.is_valid()) { + sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); + } + if (s.skin_buffer.is_valid()) { + sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer); + } + sd.vertex_count = s.vertex_count; + sd.index_count = s.index_count; + sd.primitive = s.primitive; + + if (sd.index_count) { + sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); + } + sd.aabb = s.aabb; + for (uint32_t i = 0; i < s.lod_count; i++) { + RS::SurfaceData::LOD lod; + lod.edge_length = s.lods[i].edge_length; + lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); + sd.lods.push_back(lod); + } + + sd.bone_aabbs = s.bone_aabbs; + + if (s.blend_shape_buffer.is_valid()) { + sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer); + } + + return sd; +} + +int MeshStorage::mesh_get_surface_count(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, 0); + return mesh->surface_count; +} + +void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + mesh->custom_aabb = p_aabb; +} + +AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, AABB()); + return mesh->custom_aabb; +} + +AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, AABB()); + + if (mesh->custom_aabb != AABB()) { + return mesh->custom_aabb; + } + + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + if (!skeleton || skeleton->size == 0) { + return mesh->aabb; + } + + AABB aabb; + + for (uint32_t i = 0; i < mesh->surface_count; i++) { + AABB laabb; + if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { + int bs = mesh->surfaces[i]->bone_aabbs.size(); + const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr(); + + int sbs = skeleton->size; + ERR_CONTINUE(bs > sbs); + const float *baseptr = skeleton->data.ptr(); + + bool first = true; + + if (skeleton->use_2d) { + for (int j = 0; j < bs; j++) { + if (skbones[0].size == Vector3()) { + continue; //bone is unused + } + + const float *dataptr = baseptr + j * 8; + + Transform3D mtx; + + mtx.basis.elements[0].x = dataptr[0]; + mtx.basis.elements[1].x = dataptr[1]; + mtx.origin.x = dataptr[3]; + + mtx.basis.elements[0].y = dataptr[4]; + mtx.basis.elements[1].y = dataptr[5]; + mtx.origin.y = dataptr[7]; + + AABB baabb = mtx.xform(skbones[j]); + + if (first) { + laabb = baabb; + first = false; + } else { + laabb.merge_with(baabb); + } + } + } else { + for (int j = 0; j < bs; j++) { + if (skbones[0].size == Vector3()) { + continue; //bone is unused + } + + const float *dataptr = baseptr + j * 12; + + Transform3D mtx; + + mtx.basis.elements[0][0] = dataptr[0]; + mtx.basis.elements[0][1] = dataptr[1]; + mtx.basis.elements[0][2] = dataptr[2]; + mtx.origin.x = dataptr[3]; + mtx.basis.elements[1][0] = dataptr[4]; + mtx.basis.elements[1][1] = dataptr[5]; + mtx.basis.elements[1][2] = dataptr[6]; + mtx.origin.y = dataptr[7]; + mtx.basis.elements[2][0] = dataptr[8]; + mtx.basis.elements[2][1] = dataptr[9]; + mtx.basis.elements[2][2] = dataptr[10]; + mtx.origin.z = dataptr[11]; + + AABB baabb = mtx.xform(skbones[j]); + if (first) { + laabb = baabb; + first = false; + } else { + laabb.merge_with(baabb); + } + } + } + + if (laabb.size == Vector3()) { + laabb = mesh->surfaces[i]->aabb; + } + } else { + laabb = mesh->surfaces[i]->aabb; + } + + if (i == 0) { + aabb = laabb; + } else { + aabb.merge_with(laabb); + } + } + + return aabb; +} + +void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + + Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); + if (shadow_mesh) { + shadow_mesh->shadow_owners.erase(mesh); + } + mesh->shadow_mesh = p_shadow_mesh; + + shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); + + if (shadow_mesh) { + shadow_mesh->shadow_owners.insert(mesh); + } + + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); +} + +void MeshStorage::mesh_clear(RID p_mesh) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + for (uint32_t i = 0; i < mesh->surface_count; i++) { + Mesh::Surface &s = *mesh->surfaces[i]; + RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + if (s.attribute_buffer.is_valid()) { + RD::get_singleton()->free(s.attribute_buffer); + } + if (s.skin_buffer.is_valid()) { + RD::get_singleton()->free(s.skin_buffer); + } + if (s.versions) { + memfree(s.versions); //reallocs, so free with memfree. + } + + if (s.index_buffer.is_valid()) { + RD::get_singleton()->free(s.index_buffer); + } + + if (s.lod_count) { + for (uint32_t j = 0; j < s.lod_count; j++) { + RD::get_singleton()->free(s.lods[j].index_buffer); + } + memdelete_arr(s.lods); + } + + if (s.blend_shape_buffer.is_valid()) { + RD::get_singleton()->free(s.blend_shape_buffer); + } + + memdelete(mesh->surfaces[i]); + } + if (mesh->surfaces) { + memfree(mesh->surfaces); + } + + mesh->surfaces = nullptr; + mesh->surface_count = 0; + mesh->material_cache.clear(); + //clear instance data + for (MeshInstance *mi : mesh->instances) { + _mesh_instance_clear(mi); + } + mesh->has_bone_weights = false; + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + + for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + Mesh *shadow_owner = E->get(); + shadow_owner->shadow_mesh = RID(); + shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + } +} + +bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, false); + + return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); +} + +/* MESH INSTANCE */ + +RID MeshStorage::mesh_instance_create(RID p_base) { + Mesh *mesh = mesh_owner.get_or_null(p_base); + ERR_FAIL_COND_V(!mesh, RID()); + + RID rid = mesh_instance_owner.make_rid(); + MeshInstance *mi = mesh_instance_owner.get_or_null(rid); + + mi->mesh = mesh; + + for (uint32_t i = 0; i < mesh->surface_count; i++) { + _mesh_instance_add_surface(mi, mesh, i); + } + + mi->I = mesh->instances.push_back(mi); + + mi->dirty = true; + + return rid; +} + +void MeshStorage::mesh_instance_free(RID p_rid) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid); + _mesh_instance_clear(mi); + mi->mesh->instances.erase(mi->I); + mi->I = nullptr; + + mesh_instance_owner.free(p_rid); +} + +void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + if (mi->skeleton == p_skeleton) { + return; + } + mi->skeleton = p_skeleton; + mi->skeleton_version = 0; + mi->dirty = true; +} + +void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + ERR_FAIL_COND(!mi); + ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size()); + mi->blend_weights[p_shape] = p_weight; + mi->weights_dirty = true; + //will be eventually updated +} + +void MeshStorage::_mesh_instance_clear(MeshInstance *mi) { + for (uint32_t i = 0; i < mi->surfaces.size(); i++) { + if (mi->surfaces[i].versions) { + for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { + RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); + } + memfree(mi->surfaces[i].versions); + } + if (mi->surfaces[i].vertex_buffer.is_valid()) { + RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); + } + } + mi->surfaces.clear(); + + if (mi->blend_weights_buffer.is_valid()) { + RD::get_singleton()->free(mi->blend_weights_buffer); + } + mi->blend_weights.clear(); + mi->weights_dirty = false; + mi->skeleton_version = 0; +} + +void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) { + if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) { + mi->blend_weights.resize(mesh->blend_shape_count); + for (uint32_t i = 0; i < mi->blend_weights.size(); i++) { + mi->blend_weights[i] = 0; + } + mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array()); + mi->weights_dirty = true; + } + + MeshInstance::Surface s; + if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { + //surface warrants transform + s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(s.vertex_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (mi->blend_weights_buffer.is_valid()) { + u.append_id(mi->blend_weights_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE); + } + + mi->surfaces.push_back(s); + mi->dirty = true; +} + +void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + + bool needs_update = mi->dirty; + + if (mi->weights_dirty && !mi->weight_update_list.in_list()) { + dirty_mesh_instance_weights.add(&mi->weight_update_list); + needs_update = true; + } + + if (mi->array_update_list.in_list()) { + return; + } + + if (!needs_update && mi->skeleton.is_valid()) { + Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); + if (sk && sk->version != mi->skeleton_version) { + needs_update = true; + } + } + + if (needs_update) { + dirty_mesh_instance_arrays.add(&mi->array_update_list); + } +} + +void MeshStorage::update_mesh_instances() { + while (dirty_mesh_instance_weights.first()) { + MeshInstance *mi = dirty_mesh_instance_weights.first()->self(); + + if (mi->blend_weights_buffer.is_valid()) { + RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr()); + } + dirty_mesh_instance_weights.remove(&mi->weight_update_list); + mi->weights_dirty = false; + } + if (dirty_mesh_instance_arrays.first() == nullptr) { + return; //nothing to do + } + + //process skeletons and blend shapes + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + while (dirty_mesh_instance_arrays.first()) { + MeshInstance *mi = dirty_mesh_instance_arrays.first()->self(); + + Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); + + for (uint32_t i = 0; i < mi->surfaces.size(); i++) { + if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) { + continue; + } + + bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE); + if (sk && sk->uniform_set_mi.is_valid()) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON); + } + + SkeletonShader::PushConstant push_constant; + + push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL; + push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT; + push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES); + push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0; + + push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count; + push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; + + push_constant.blend_shape_count = mi->mesh->blend_shape_count; + push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; + push_constant.pad0 = 0; + push_constant.pad1 = 0; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant)); + + //dispatch without barrier, so all is done at the same time + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1); + } + + mi->dirty = false; + if (sk) { + mi->skeleton_version = sk->version; + } + dirty_mesh_instance_arrays.remove(&mi->array_update_list); + } + + RD::get_singleton()->compute_list_end(); +} + +void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) { + Vector<RD::VertexAttribute> attributes; + Vector<RID> buffers; + + uint32_t stride = 0; + uint32_t attribute_stride = 0; + uint32_t skin_stride = 0; + + for (int i = 0; i < RS::ARRAY_INDEX; i++) { + RD::VertexAttribute vd; + RID buffer; + vd.location = i; + + if (!(s->format & (1 << i))) { + // Not supplied by surface, use default value + buffer = mesh_default_rd_buffers[i]; + vd.stride = 0; + switch (i) { + case RS::ARRAY_VERTEX: { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + + } break; + case RS::ARRAY_NORMAL: { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } break; + case RS::ARRAY_TANGENT: { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + case RS::ARRAY_COLOR: { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + + } break; + case RS::ARRAY_TEX_UV: { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + + } break; + case RS::ARRAY_TEX_UV2: { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + case RS::ARRAY_BONES: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + } break; + case RS::ARRAY_WEIGHTS: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + } + } else { + //Supplied, use it + + vd.stride = 1; //mark that it needs a stride set (default uses 0) + + switch (i) { + case RS::ARRAY_VERTEX: { + vd.offset = stride; + + if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + stride += sizeof(float) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + stride += sizeof(float) * 3; + } + + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + + } break; + case RS::ARRAY_NORMAL: { + vd.offset = stride; + + vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + + stride += sizeof(uint32_t); + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + } break; + case RS::ARRAY_TANGENT: { + vd.offset = stride; + + vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + stride += sizeof(uint32_t); + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + } break; + case RS::ARRAY_COLOR: { + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + attribute_stride += sizeof(int8_t) * 4; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_TEX_UV: { + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + buffer = s->attribute_buffer; + + } break; + case RS::ARRAY_TEX_UV2: { + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + vd.offset = attribute_stride; + + int idx = i - RS::ARRAY_CUSTOM0; + uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; + uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; + vd.format = fmtrd[fmt]; + attribute_stride += fmtsize[fmt]; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_BONES: { + vd.offset = skin_stride; + + vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT; + skin_stride += sizeof(int16_t) * 4; + buffer = s->skin_buffer; + } break; + case RS::ARRAY_WEIGHTS: { + vd.offset = skin_stride; + + vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; + skin_stride += sizeof(int16_t) * 4; + buffer = s->skin_buffer; + } break; + } + } + + if (!(p_input_mask & (1 << i))) { + continue; // Shader does not need this, skip it (but computing stride was important anyway) + } + + attributes.push_back(vd); + buffers.push_back(buffer); + } + + //update final stride + for (int i = 0; i < attributes.size(); i++) { + if (attributes[i].stride == 0) { + continue; //default location + } + int loc = attributes[i].location; + + if (loc < RS::ARRAY_COLOR) { + attributes.write[i].stride = stride; + } else if (loc < RS::ARRAY_BONES) { + attributes.write[i].stride = attribute_stride; + } else { + attributes.write[i].stride = skin_stride; + } + } + + v.input_mask = p_input_mask; + v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); + v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); +} + +////////////////// MULTIMESH + +RID MeshStorage::multimesh_allocate() { + return multimesh_owner.allocate_rid(); +} +void MeshStorage::multimesh_initialize(RID p_rid) { + multimesh_owner.initialize_rid(p_rid, MultiMesh()); +} + +void MeshStorage::multimesh_free(RID p_rid) { + _update_dirty_multimeshes(); + multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); + MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid); + multimesh->dependency.deleted_notify(p_rid); + multimesh_owner.free(p_rid); +} + +void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + + if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { + return; + } + + if (multimesh->buffer.is_valid()) { + RD::get_singleton()->free(multimesh->buffer); + multimesh->buffer = RID(); + multimesh->uniform_set_2d = RID(); //cleared by dependency + multimesh->uniform_set_3d = RID(); //cleared by dependency + } + + if (multimesh->data_cache_dirty_regions) { + memdelete_arr(multimesh->data_cache_dirty_regions); + multimesh->data_cache_dirty_regions = nullptr; + multimesh->data_cache_used_dirty_regions = 0; + } + + multimesh->instances = p_instances; + multimesh->xform_format = p_transform_format; + multimesh->uses_colors = p_use_colors; + multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12; + multimesh->uses_custom_data = p_use_custom_data; + multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); + multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); + multimesh->buffer_set = false; + + //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); + multimesh->data_cache = Vector<float>(); + multimesh->aabb = AABB(); + multimesh->aabb_dirty = false; + multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); + + if (multimesh->instances) { + multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); + } + + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH); +} + +int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->instances; +} + +void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + if (multimesh->mesh == p_mesh) { + return; + } + multimesh->mesh = p_mesh; + + if (multimesh->instances == 0) { + return; + } + + if (multimesh->data_cache.size()) { + //we have a data cache, just mark it dirt + _multimesh_mark_all_dirty(multimesh, false, true); + } else if (multimesh->instances) { + //need to re-create AABB unfortunately, calling this has a penalty + if (multimesh->buffer_set) { + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + const uint8_t *r = buffer.ptr(); + const float *data = (const float *)r; + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + } + } + + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); +} + +#define MULTIMESH_DIRTY_REGION_SIZE 512 + +void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { + if (multimesh->data_cache.size() > 0) { + return; //already local + } + ERR_FAIL_COND(multimesh->data_cache.size() > 0); + // this means that the user wants to load/save individual elements, + // for this, the data must reside on CPU, so just copy it there. + multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); + { + float *w = multimesh->data_cache.ptrw(); + + if (multimesh->buffer_set) { + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + { + const uint8_t *r = buffer.ptr(); + memcpy(w, r, buffer.size()); + } + } else { + memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); + } + } + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + multimesh->data_cache_used_dirty_regions = 0; +} + +void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { + uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; +#ifdef DEBUG_ENABLED + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug +#endif + if (!multimesh->data_cache_dirty_regions[region_index]) { + multimesh->data_cache_dirty_regions[region_index] = true; + multimesh->data_cache_used_dirty_regions++; + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { + if (p_data) { + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + if (!multimesh->data_cache_dirty_regions[i]) { + multimesh->data_cache_dirty_regions[i] = true; + multimesh->data_cache_used_dirty_regions++; + } + } + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { + ERR_FAIL_COND(multimesh->mesh.is_null()); + AABB aabb; + AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); + for (int i = 0; i < p_instances; i++) { + const float *data = p_data + multimesh->stride_cache * i; + Transform3D t; + + if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) { + t.basis.elements[0][0] = data[0]; + t.basis.elements[0][1] = data[1]; + t.basis.elements[0][2] = data[2]; + t.origin.x = data[3]; + t.basis.elements[1][0] = data[4]; + t.basis.elements[1][1] = data[5]; + t.basis.elements[1][2] = data[6]; + t.origin.y = data[7]; + t.basis.elements[2][0] = data[8]; + t.basis.elements[2][1] = data[9]; + t.basis.elements[2][2] = data[10]; + t.origin.z = data[11]; + + } else { + t.basis.elements[0].x = data[0]; + t.basis.elements[1].x = data[1]; + t.origin.x = data[3]; + + t.basis.elements[0].y = data[4]; + t.basis.elements[1].y = data[5]; + t.origin.y = data[7]; + } + + if (i == 0) { + aabb = t.xform(mesh_aabb); + } else { + aabb.merge_with(t.xform(mesh_aabb)); + } + } + + multimesh->aabb = aabb; +} + +void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.basis.elements[0][0]; + dataptr[1] = p_transform.basis.elements[0][1]; + dataptr[2] = p_transform.basis.elements[0][2]; + dataptr[3] = p_transform.origin.x; + dataptr[4] = p_transform.basis.elements[1][0]; + dataptr[5] = p_transform.basis.elements[1][1]; + dataptr[6] = p_transform.basis.elements[1][2]; + dataptr[7] = p_transform.origin.y; + dataptr[8] = p_transform.basis.elements[2][0]; + dataptr[9] = p_transform.basis.elements[2][1]; + dataptr[10] = p_transform.basis.elements[2][2]; + dataptr[11] = p_transform.origin.z; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} + +void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.elements[0][0]; + dataptr[1] = p_transform.elements[1][0]; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2][0]; + dataptr[4] = p_transform.elements[0][1]; + dataptr[5] = p_transform.elements[1][1]; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2][1]; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} + +void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(!multimesh->uses_colors); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} + +void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(!multimesh->uses_custom_data); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} + +RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, RID()); + + return multimesh->mesh; +} + +Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform3D()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D()); + ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D()); + + _multimesh_make_local(multimesh); + + Transform3D t; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache; + + t.basis.elements[0][0] = dataptr[0]; + t.basis.elements[0][1] = dataptr[1]; + t.basis.elements[0][2] = dataptr[2]; + t.origin.x = dataptr[3]; + t.basis.elements[1][0] = dataptr[4]; + t.basis.elements[1][1] = dataptr[5]; + t.basis.elements[1][2] = dataptr[6]; + t.origin.y = dataptr[7]; + t.basis.elements[2][0] = dataptr[8]; + t.basis.elements[2][1] = dataptr[9]; + t.basis.elements[2][2] = dataptr[10]; + t.origin.z = dataptr[11]; + } + + return t; +} + +Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform2D()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); + ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D()); + + _multimesh_make_local(multimesh); + + Transform2D t; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache; + + t.elements[0][0] = dataptr[0]; + t.elements[1][0] = dataptr[1]; + t.elements[2][0] = dataptr[3]; + t.elements[0][1] = dataptr[4]; + t.elements[1][1] = dataptr[5]; + t.elements[2][1] = dataptr[7]; + } + + return t; +} + +Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} + +Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} + +void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); + + { + const float *r = p_buffer.ptr(); + RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r); + multimesh->buffer_set = true; + } + + if (multimesh->data_cache.size()) { + //if we have a data cache, just update it + multimesh->data_cache = p_buffer; + { + //clear dirty since nothing will be dirty anymore + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + multimesh->data_cache_used_dirty_regions = 0; + } + + _multimesh_mark_all_dirty(multimesh, false, true); //update AABB + } else if (multimesh->mesh.is_valid()) { + //if we have a mesh set, we need to re-generate the AABB from the new data + const float *data = p_buffer.ptr(); + + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + } +} + +Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Vector<float>()); + if (multimesh->buffer.is_null()) { + return Vector<float>(); + } else if (multimesh->data_cache.size()) { + return multimesh->data_cache; + } else { + //get from memory + + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + Vector<float> ret; + ret.resize(multimesh->instances * multimesh->stride_cache); + { + float *w = ret.ptrw(); + const uint8_t *r = buffer.ptr(); + memcpy(w, r, buffer.size()); + } + + return ret; + } +} + +void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); + if (multimesh->visible_instances == p_visible) { + return; + } + + if (multimesh->data_cache.size()) { + //there is a data cache.. + _multimesh_mark_all_dirty(multimesh, false, true); + } + + multimesh->visible_instances = p_visible; + + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); +} + +int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->visible_instances; +} + +AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, AABB()); + if (multimesh->aabb_dirty) { + const_cast<MeshStorage *>(this)->_update_dirty_multimeshes(); + } + return multimesh->aabb; +} + +void MeshStorage::_update_dirty_multimeshes() { + while (multimesh_dirty_list) { + MultiMesh *multimesh = multimesh_dirty_list; + + if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists + const float *data = multimesh->data_cache.ptr(); + + uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + + if (multimesh->data_cache_used_dirty_regions) { + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); + + if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { + //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much + RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); + } else { + //not that many regions? update them all + for (uint32_t i = 0; i < visible_region_count; i++) { + if (multimesh->data_cache_dirty_regions[i]) { + uint32_t offset = i * region_size; + uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); + uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i; + RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]); + } + } + } + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + + multimesh->data_cache_used_dirty_regions = 0; + } + + if (multimesh->aabb_dirty) { + //aabb is dirty.. + _multimesh_re_create_aabb(multimesh, data, visible_instances); + multimesh->aabb_dirty = false; + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + } + } + + multimesh_dirty_list = multimesh->dirty_list; + + multimesh->dirty_list = nullptr; + multimesh->dirty = false; + } + + multimesh_dirty_list = nullptr; +} + +/* SKELETON API */ + +RID MeshStorage::skeleton_allocate() { + return skeleton_owner.allocate_rid(); +} +void MeshStorage::skeleton_initialize(RID p_rid) { + skeleton_owner.initialize_rid(p_rid, Skeleton()); +} + +void MeshStorage::skeleton_free(RID p_rid) { + _update_dirty_skeletons(); + skeleton_allocate_data(p_rid, 0); + Skeleton *skeleton = skeleton_owner.get_or_null(p_rid); + skeleton->dependency.deleted_notify(p_rid); + skeleton_owner.free(p_rid); +} + +void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) { + if (!skeleton->dirty) { + skeleton->dirty = true; + skeleton->dirty_list = skeleton_dirty_list; + skeleton_dirty_list = skeleton; + } +} + +void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND(!skeleton); + ERR_FAIL_COND(p_bones < 0); + + if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) { + return; + } + + skeleton->size = p_bones; + skeleton->use_2d = p_2d_skeleton; + skeleton->uniform_set_3d = RID(); + + if (skeleton->buffer.is_valid()) { + RD::get_singleton()->free(skeleton->buffer); + skeleton->buffer = RID(); + skeleton->data.clear(); + skeleton->uniform_set_mi = RID(); + } + + if (skeleton->size) { + skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12)); + skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float)); + memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float)); + + _skeleton_make_dirty(skeleton); + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(skeleton->buffer); + uniforms.push_back(u); + } + skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); + } + } + + skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA); +} + +int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND_V(!skeleton, 0); + + return skeleton->size; +} + +void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone, skeleton->size); + ERR_FAIL_COND(skeleton->use_2d); + + float *dataptr = skeleton->data.ptrw() + p_bone * 12; + + dataptr[0] = p_transform.basis.elements[0][0]; + dataptr[1] = p_transform.basis.elements[0][1]; + dataptr[2] = p_transform.basis.elements[0][2]; + dataptr[3] = p_transform.origin.x; + dataptr[4] = p_transform.basis.elements[1][0]; + dataptr[5] = p_transform.basis.elements[1][1]; + dataptr[6] = p_transform.basis.elements[1][2]; + dataptr[7] = p_transform.origin.y; + dataptr[8] = p_transform.basis.elements[2][0]; + dataptr[9] = p_transform.basis.elements[2][1]; + dataptr[10] = p_transform.basis.elements[2][2]; + dataptr[11] = p_transform.origin.z; + + _skeleton_make_dirty(skeleton); +} + +Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND_V(!skeleton, Transform3D()); + ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D()); + ERR_FAIL_COND_V(skeleton->use_2d, Transform3D()); + + const float *dataptr = skeleton->data.ptr() + p_bone * 12; + + Transform3D t; + + t.basis.elements[0][0] = dataptr[0]; + t.basis.elements[0][1] = dataptr[1]; + t.basis.elements[0][2] = dataptr[2]; + t.origin.x = dataptr[3]; + t.basis.elements[1][0] = dataptr[4]; + t.basis.elements[1][1] = dataptr[5]; + t.basis.elements[1][2] = dataptr[6]; + t.origin.y = dataptr[7]; + t.basis.elements[2][0] = dataptr[8]; + t.basis.elements[2][1] = dataptr[9]; + t.basis.elements[2][2] = dataptr[10]; + t.origin.z = dataptr[11]; + + return t; +} + +void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone, skeleton->size); + ERR_FAIL_COND(!skeleton->use_2d); + + float *dataptr = skeleton->data.ptrw() + p_bone * 8; + + dataptr[0] = p_transform.elements[0][0]; + dataptr[1] = p_transform.elements[1][0]; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2][0]; + dataptr[4] = p_transform.elements[0][1]; + dataptr[5] = p_transform.elements[1][1]; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2][1]; + + _skeleton_make_dirty(skeleton); +} + +Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND_V(!skeleton, Transform2D()); + ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); + ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); + + const float *dataptr = skeleton->data.ptr() + p_bone * 8; + + Transform2D t; + t.elements[0][0] = dataptr[0]; + t.elements[1][0] = dataptr[1]; + t.elements[2][0] = dataptr[3]; + t.elements[0][1] = dataptr[4]; + t.elements[1][1] = dataptr[5]; + t.elements[2][1] = dataptr[7]; + + return t; +} + +void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND(!skeleton->use_2d); + + skeleton->base_transform_2d = p_base_transform; +} + +void MeshStorage::_update_dirty_skeletons() { + while (skeleton_dirty_list) { + Skeleton *skeleton = skeleton_dirty_list; + + if (skeleton->size) { + RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr()); + } + + skeleton_dirty_list = skeleton->dirty_list; + + skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES); + + skeleton->version++; + + skeleton->dirty = false; + skeleton->dirty_list = nullptr; + } + + skeleton_dirty_list = nullptr; +} + +void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND(!skeleton); + + p_instance->update_dependency(&skeleton->dependency); +} diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h new file mode 100644 index 0000000000..e8da8ad563 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -0,0 +1,694 @@ +/*************************************************************************/ +/* mesh_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_STORAGE_RD_H +#define MESH_STORAGE_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering/storage/mesh_storage.h" + +namespace RendererRD { + +/* Mesh */ + +enum DefaultRDBuffer { + DEFAULT_RD_BUFFER_VERTEX, + DEFAULT_RD_BUFFER_NORMAL, + DEFAULT_RD_BUFFER_TANGENT, + DEFAULT_RD_BUFFER_COLOR, + DEFAULT_RD_BUFFER_TEX_UV, + DEFAULT_RD_BUFFER_TEX_UV2, + DEFAULT_RD_BUFFER_CUSTOM0, + DEFAULT_RD_BUFFER_CUSTOM1, + DEFAULT_RD_BUFFER_CUSTOM2, + DEFAULT_RD_BUFFER_CUSTOM3, + DEFAULT_RD_BUFFER_BONES, + DEFAULT_RD_BUFFER_WEIGHTS, + DEFAULT_RD_BUFFER_MAX, +}; + +struct MeshInstance; + +struct Mesh { + struct Surface { + RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; + uint32_t format = 0; + + RID vertex_buffer; + RID attribute_buffer; + RID skin_buffer; + uint32_t vertex_count = 0; + uint32_t vertex_buffer_size = 0; + uint32_t skin_buffer_size = 0; + + // A different pipeline needs to be allocated + // depending on the inputs available in the + // material. + // There are never that many geometry/material + // combinations, so a simple array is the most + // cache-efficient structure. + + struct Version { + uint32_t input_mask = 0; + RD::VertexFormatID vertex_format = 0; + RID vertex_array; + }; + + SpinLock version_lock; //needed to access versions + Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + + RID index_buffer; + RID index_array; + uint32_t index_count = 0; + + struct LOD { + float edge_length = 0.0; + uint32_t index_count = 0; + RID index_buffer; + RID index_array; + }; + + LOD *lods = nullptr; + uint32_t lod_count = 0; + + AABB aabb; + + Vector<AABB> bone_aabbs; + + RID blend_shape_buffer; + + RID material; + + uint32_t render_index = 0; + uint64_t render_pass = 0; + + uint32_t multimesh_render_index = 0; + uint64_t multimesh_render_pass = 0; + + uint32_t particles_render_index = 0; + uint64_t particles_render_pass = 0; + + RID uniform_set; + }; + + uint32_t blend_shape_count = 0; + RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; + + Surface **surfaces = nullptr; + uint32_t surface_count = 0; + + Vector<AABB> bone_aabbs; + + bool has_bone_weights = false; + + AABB aabb; + AABB custom_aabb; + + Vector<RID> material_cache; + + List<MeshInstance *> instances; + + RID shadow_mesh; + Set<Mesh *> shadow_owners; + + RendererStorage::Dependency dependency; +}; + +/* Mesh Instance */ + +struct MeshInstance { + Mesh *mesh = nullptr; + RID skeleton; + struct Surface { + RID vertex_buffer; + RID uniform_set; + + Mesh::Surface::Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + }; + LocalVector<Surface> surfaces; + LocalVector<float> blend_weights; + + RID blend_weights_buffer; + List<MeshInstance *>::Element *I = nullptr; //used to erase itself + uint64_t skeleton_version = 0; + bool dirty = false; + bool weights_dirty = false; + SelfList<MeshInstance> weight_update_list; + SelfList<MeshInstance> array_update_list; + MeshInstance() : + weight_update_list(this), array_update_list(this) {} +}; + +/* MultiMesh */ + +struct MultiMesh { + RID mesh; + int instances = 0; + RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; + bool uses_colors = false; + bool uses_custom_data = false; + int visible_instances = -1; + AABB aabb; + bool aabb_dirty = false; + bool buffer_set = false; + uint32_t stride_cache = 0; + uint32_t color_offset_cache = 0; + uint32_t custom_data_offset_cache = 0; + + Vector<float> data_cache; //used if individual setting is used + bool *data_cache_dirty_regions = nullptr; + uint32_t data_cache_used_dirty_regions = 0; + + RID buffer; //storage buffer + RID uniform_set_3d; + RID uniform_set_2d; + + bool dirty = false; + MultiMesh *dirty_list = nullptr; + + RendererStorage::Dependency dependency; +}; + +/* Skeleton */ + +struct SkeletonShader { + struct PushConstant { + uint32_t has_normal; + uint32_t has_tangent; + uint32_t has_skeleton; + uint32_t has_blend_shape; + + uint32_t vertex_count; + uint32_t vertex_stride; + uint32_t skin_stride; + uint32_t skin_weight_offset; + + uint32_t blend_shape_count; + uint32_t normalized_blend_shapes; + uint32_t pad0; + uint32_t pad1; + }; + + enum { + UNIFORM_SET_INSTANCE = 0, + UNIFORM_SET_SURFACE = 1, + UNIFORM_SET_SKELETON = 2, + }; + enum { + SHADER_MODE_2D, + SHADER_MODE_3D, + SHADER_MODE_MAX + }; + + SkeletonShaderRD shader; + RID version; + RID version_shader[SHADER_MODE_MAX]; + RID pipeline[SHADER_MODE_MAX]; + + RID default_skeleton_uniform_set; +}; + +struct Skeleton { + bool use_2d = false; + int size = 0; + Vector<float> data; + RID buffer; + + bool dirty = false; + Skeleton *dirty_list = nullptr; + Transform2D base_transform_2d; + + RID uniform_set_3d; + RID uniform_set_mi; + + uint64_t version = 1; + + RendererStorage::Dependency dependency; +}; + +class MeshStorage : public RendererMeshStorage { +private: + static MeshStorage *singleton; + + RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; + RID default_rd_storage_buffer; + + /* Mesh */ + + mutable RID_Owner<Mesh, true> mesh_owner; + + void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); + + /* Mesh Instance API */ + + void _mesh_instance_clear(MeshInstance *mi); + void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); + + mutable RID_Owner<MeshInstance> mesh_instance_owner; + + SelfList<MeshInstance>::List dirty_mesh_instance_weights; + SelfList<MeshInstance>::List dirty_mesh_instance_arrays; + + /* MultiMesh */ + + mutable RID_Owner<MultiMesh, true> multimesh_owner; + + MultiMesh *multimesh_dirty_list = nullptr; + + _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; + _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); + _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); + _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); + + /* Skeleton */ + + SkeletonShader skeleton_shader; + + mutable RID_Owner<Skeleton, true> skeleton_owner; + + _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton); + + Skeleton *skeleton_dirty_list = nullptr; + +public: + static MeshStorage *get_singleton(); + + MeshStorage(); + virtual ~MeshStorage(); + + RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } + + /* MESH API */ + + Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + + virtual RID mesh_allocate() override; + virtual void mesh_initialize(RID p_mesh) override; + virtual void mesh_free(RID p_rid) override; + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override; + + /// Return stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const override; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override; + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override; + + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override; + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override; + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override; + + virtual int mesh_get_surface_count(RID p_mesh) const override; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const override; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override; + virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override; + + virtual void mesh_clear(RID p_mesh) override; + + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override; + + _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, nullptr); + r_surface_count = mesh->surface_count; + if (r_surface_count == 0) { + return nullptr; + } + if (mesh->material_cache.is_empty()) { + mesh->material_cache.resize(mesh->surface_count); + for (uint32_t i = 0; i < r_surface_count; i++) { + mesh->material_cache.write[i] = mesh->surfaces[i]->material; + } + } + + return mesh->material_cache.ptr(); + } + + _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, nullptr); + ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr); + + return mesh->surfaces[p_surface_index]; + } + + _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RID()); + + return mesh->shadow_mesh; + } + + _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) { + Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface); + return surface->primitive; + } + + _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->lod_count > 0; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->index_count ? s->index_count : s->vertex_count; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + int32_t current_lod = -1; + if (r_index_count) { + *r_index_count = s->index_count; + } + for (uint32_t i = 0; i < s->lod_count; i++) { + float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold; + if (screen_size > p_mesh_lod_threshold) { + break; + } + current_lod = i; + } + if (current_lod == -1) { + return 0; + } else { + if (r_index_count) { + *r_index_count = s->lods[current_lod].index_count; + } + return current_lod + 1; + } + } + + _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + if (p_lod == 0) { + return s->index_array; + } else { + return s->lods[p_lod - 1].index_array; + } + } + + _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + s->version_lock.lock(); + + //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way + + for (uint32_t i = 0; i < s->version_count; i++) { + if (s->versions[i].input_mask != p_input_mask) { + continue; + } + //we have this version, hooray + r_vertex_format = s->versions[i].vertex_format; + r_vertex_array_rd = s->versions[i].vertex_array; + s->version_lock.unlock(); + return; + } + + uint32_t version = s->version_count; + s->version_count++; + s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); + + _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask); + + r_vertex_format = s->versions[version].vertex_format; + r_vertex_array_rd = s->versions[version].vertex_array; + + s->version_lock.unlock(); + } + + _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + ERR_FAIL_COND(!mi); + Mesh *mesh = mi->mesh; + ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); + + MeshInstance::Surface *mis = &mi->surfaces[p_surface_index]; + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + s->version_lock.lock(); + + //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way + + for (uint32_t i = 0; i < mis->version_count; i++) { + if (mis->versions[i].input_mask != p_input_mask) { + continue; + } + //we have this version, hooray + r_vertex_format = mis->versions[i].vertex_format; + r_vertex_array_rd = mis->versions[i].vertex_array; + s->version_lock.unlock(); + return; + } + + uint32_t version = mis->version_count; + mis->version_count++; + mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); + + _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis); + + r_vertex_format = mis->versions[version].vertex_format; + r_vertex_array_rd = mis->versions[version].vertex_array; + + s->version_lock.unlock(); + } + + _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { + ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); + return mesh_default_rd_buffers[p_buffer]; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->render_pass != p_render_pass) { + (*r_index)++; + s->render_pass = p_render_pass; + s->render_index = *r_index; + } + + return s->render_index; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->multimesh_render_pass != p_render_pass) { + (*r_index)++; + s->multimesh_render_pass = p_render_pass; + s->multimesh_render_index = *r_index; + } + + return s->multimesh_render_index; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->particles_render_pass != p_render_pass) { + (*r_index)++; + s->particles_render_pass = p_render_pass; + s->particles_render_index = *r_index; + } + + return s->particles_render_index; + } + + /* MESH INSTANCE API */ + + MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }; + bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }; + + virtual RID mesh_instance_create(RID p_base) override; + virtual void mesh_instance_free(RID p_rid) override; + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override; + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override; + virtual void mesh_instance_check_for_update(RID p_mesh_instance) override; + virtual void update_mesh_instances() override; + + /* MULTIMESH API */ + + MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }; + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + + virtual RID multimesh_allocate() override; + virtual void multimesh_initialize(RID p_multimesh) override; + virtual void multimesh_free(RID p_rid) override; + + virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override; + virtual int multimesh_get_instance_count(RID p_multimesh) const override; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override; + + virtual RID multimesh_get_mesh(RID p_multimesh) const override; + + virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override; + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override; + virtual int multimesh_get_visible_instances(RID p_multimesh) const override; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const override; + + void _update_dirty_multimeshes(); + + _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + return multimesh->xform_format; + } + + _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + return multimesh->uses_colors; + } + + _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + return multimesh->uses_custom_data; + } + + _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + if (multimesh->visible_instances >= 0) { + return multimesh->visible_instances; + } + return multimesh->instances; + } + + _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + if (!multimesh->uniform_set_3d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_3d; + } + + _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + if (!multimesh->uniform_set_2d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_2d; + } + + /* SKELETON API */ + + Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }; + bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }; + + virtual RID skeleton_allocate() override; + virtual void skeleton_initialize(RID p_skeleton) override; + virtual void skeleton_free(RID p_rid) override; + + virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override; + void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform); + virtual int skeleton_get_bone_count(RID p_skeleton) const override; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override; + virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override; + + virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override; + + void _update_dirty_skeletons(); + + _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) { + return skeleton_owner.get_or_null(p_skeleton) != nullptr; + } + + _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND_V(!skeleton, RID()); + ERR_FAIL_COND_V(skeleton->size == 0, RID()); + if (skeleton->use_2d) { + return RID(); + } + if (!skeleton->uniform_set_3d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(skeleton->buffer); + uniforms.push_back(u); + skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return skeleton->uniform_set_3d; + } +}; + +} // namespace RendererRD + +#endif // !MESH_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp new file mode 100644 index 0000000000..a3ca7d3720 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -0,0 +1,1420 @@ +/*************************************************************************/ +/* texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "texture_storage.h" +#include "decal_atlas_storage.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// Texture + +void Texture::cleanup() { + if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) { + //erase this first, as it's a dependency of the one below + RD::get_singleton()->free(rd_texture_srgb); + } + if (RD::get_singleton()->texture_is_valid(rd_texture)) { + RD::get_singleton()->free(rd_texture); + } + if (canvas_texture) { + memdelete(canvas_texture); + } +} + +/////////////////////////////////////////////////////////////////////////// +// TextureStorage + +TextureStorage *TextureStorage::singleton = nullptr; + +TextureStorage *TextureStorage::get_singleton() { + return singleton; +} + +TextureStorage::TextureStorage() { + singleton = this; + + { //create default textures + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 128); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap white array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default 3D + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.depth = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_3D; + + Vector<uint8_t> pv; + pv.resize(64 * 4); + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 1; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } +} + +TextureStorage::~TextureStorage() { + //def textures + for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { + if (default_rd_textures[i].is_valid()) { + RD::get_singleton()->free(default_rd_textures[i]); + } + } + + singleton = nullptr; +} + +bool TextureStorage::can_create_resources_async() const { + return true; +} + +RID TextureStorage::texture_allocate() { + return texture_owner.allocate_rid(); +} + +void TextureStorage::texture_free(RID p_texture) { + Texture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!t); + ERR_FAIL_COND(t->is_render_target); + + t->cleanup(); + + if (t->is_proxy && t->proxy_to.is_valid()) { + Texture *proxy_to = texture_owner.get_or_null(t->proxy_to); + if (proxy_to) { + proxy_to->proxies.erase(p_texture); + } + } + + DecalAtlasStorage::get_singleton()->decal_atlas_remove_texture(p_texture); + + for (int i = 0; i < t->proxies.size(); i++) { + Texture *p = texture_owner.get_or_null(t->proxies[i]); + ERR_CONTINUE(!p); + p->proxy_to = RID(); + p->rd_texture = RID(); + p->rd_texture_srgb = RID(); + } + + texture_owner.free(p_texture); +} + +void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { + TextureToRDFormat ret_format; + Ref<Image> image = _validate_texture_format(p_image, ret_format); + + Texture texture; + + texture.type = Texture::TYPE_2D; + + texture.width = p_image->get_width(); + texture.height = p_image->get_height(); + texture.layers = 1; + texture.mipmaps = p_image->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_image->get_format(); + texture.validated_format = image->get_format(); + + texture.rd_type = RD::TEXTURE_TYPE_2D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<uint8_t> data = image->get_data(); //use image data + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(data); + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { + ERR_FAIL_COND(p_layers.size() == 0); + + ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); + ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0)); + + TextureToRDFormat ret_format; + Vector<Ref<Image>> images; + { + int valid_width = 0; + int valid_height = 0; + bool valid_mipmaps = false; + Image::Format valid_format = Image::FORMAT_MAX; + + for (int i = 0; i < p_layers.size(); i++) { + ERR_FAIL_COND(p_layers[i]->is_empty()); + + if (i == 0) { + valid_width = p_layers[i]->get_width(); + valid_height = p_layers[i]->get_height(); + valid_format = p_layers[i]->get_format(); + valid_mipmaps = p_layers[i]->has_mipmaps(); + } else { + ERR_FAIL_COND(p_layers[i]->get_width() != valid_width); + ERR_FAIL_COND(p_layers[i]->get_height() != valid_height); + ERR_FAIL_COND(p_layers[i]->get_format() != valid_format); + ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps); + } + + images.push_back(_validate_texture_format(p_layers[i], ret_format)); + } + } + + Texture texture; + + texture.type = Texture::TYPE_LAYERED; + texture.layered_type = p_layered_type; + + texture.width = p_layers[0]->get_width(); + texture.height = p_layers[0]->get_height(); + texture.layers = p_layers.size(); + texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_layers[0]->get_format(); + texture.validated_format = images[0]->get_format(); + + switch (p_layered_type) { + case RS::TEXTURE_LAYERED_2D_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + } break; + } + + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = texture.layers; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + for (int i = 0; i < images.size(); i++) { + Vector<uint8_t> data = images[i]->get_data(); //use image data + data_slices.push_back(data); + } + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { + ERR_FAIL_COND(p_data.size() == 0); + + Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + TextureToRDFormat ret_format; + Image::Format validated_format = Image::FORMAT_MAX; + Vector<uint8_t> all_data; + uint32_t mipmap_count = 0; + Vector<Texture::BufferSlice3D> slices; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + TextureToRDFormat f; + images.write[i] = _validate_texture_format(p_data[i], f); + if (i == 0) { + ret_format = f; + validated_format = images[0]->get_format(); + } + + all_data_size += images[i]->get_data().size(); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + Size2i prev_size; + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + + memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); + { + Texture::BufferSlice3D slice; + slice.size.width = images[i]->get_width(); + slice.size.height = images[i]->get_height(); + slice.offset = offset; + slice.buffer_size = s; + slices.push_back(slice); + } + offset += s; + + Size2i img_size(images[i]->get_width(), images[i]->get_height()); + if (img_size != prev_size) { + mipmap_count++; + } + prev_size = img_size; + } + } + + Texture texture; + + texture.type = Texture::TYPE_3D; + texture.width = p_width; + texture.height = p_height; + texture.depth = p_depth; + texture.mipmaps = mipmap_count; + texture.format = p_data[0]->get_format(); + texture.validated_format = validated_format; + + texture.buffer_size_3d = all_data.size(); + texture.buffer_slices_3d = slices; + + texture.rd_type = RD::TEXTURE_TYPE_3D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = texture.depth; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(all_data); //one slice + + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { + Texture *tex = texture_owner.get_or_null(p_base); + ERR_FAIL_COND(!tex); + Texture proxy_tex = *tex; + + proxy_tex.rd_view.format_override = tex->rd_format; + proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + if (proxy_tex.rd_texture_srgb.is_valid()) { + proxy_tex.rd_view.format_override = tex->rd_format_srgb; + proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + } + proxy_tex.proxy_to = p_base; + proxy_tex.is_render_target = false; + proxy_tex.is_proxy = true; + proxy_tex.proxies.clear(); + + texture_owner.initialize_rid(p_texture, proxy_tex); + + tex->proxies.push_back(p_texture); +} + +void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { + ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); + + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->is_render_target); + ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); + ERR_FAIL_COND(p_image->get_format() != tex->format); + + if (tex->type == Texture::TYPE_LAYERED) { + ERR_FAIL_INDEX(p_layer, tex->layers); + } + +#ifdef TOOLS_ENABLED + tex->image_cache_2d.unref(); +#endif + TextureToRDFormat f; + Ref<Image> validated = _validate_texture_format(p_image, f); + + RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data()); +} + +void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { + _texture_2d_update(p_texture, p_image, p_layer, false); +} + +void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_3D); + + Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + Vector<uint8_t> all_data; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + Ref<Image> image = p_data[i]; + if (image->get_format() != tex->validated_format) { + image = image->duplicate(); + image->convert(tex->validated_format); + } + all_data_size += images[i]->get_data().size(); + images.push_back(image); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); + offset += s; + } + } + + RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); +} + +void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(!tex->is_proxy); + Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); + ERR_FAIL_COND(!proxy_to); + ERR_FAIL_COND(proxy_to->is_proxy); + + if (tex->proxy_to.is_valid()) { + //unlink proxy + if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { + RD::get_singleton()->free(tex->rd_texture); + tex->rd_texture = RID(); + } + if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { + RD::get_singleton()->free(tex->rd_texture_srgb); + tex->rd_texture_srgb = RID(); + } + Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); + ERR_FAIL_COND(!prev_tex); + prev_tex->proxies.erase(p_texture); + } + + *tex = *proxy_to; + + tex->proxy_to = p_proxy_to; + tex->is_render_target = false; + tex->is_proxy = true; + tex->proxies.clear(); + proxy_to->proxies.push_back(p_texture); + + tex->rd_view.format_override = tex->rd_format; + tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + if (tex->rd_texture_srgb.is_valid()) { + tex->rd_view.format_override = tex->rd_format_srgb; + tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + } +} + +//these two APIs can be used together or in combination with the others. +void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + texture_2d_initialize(p_texture, image); +} + +void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + Vector<Ref<Image>> images; + if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { + images.push_back(image); + } else { + //cube + for (int i = 0; i < 6; i++) { + images.push_back(image); + } + } + + texture_2d_layered_initialize(p_texture, images, p_layered_type); +} + +void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + Vector<Ref<Image>> images; + //cube + for (int i = 0; i < 4; i++) { + images.push_back(image); + } + + texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); +} + +Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + +#ifdef TOOLS_ENABLED + if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { + return tex->image_cache_2d; + } +#endif + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instantiate(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { + tex->image_cache_2d = image; + } +#endif + + return image; +} + +Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instantiate(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + + return image; +} + +Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); + ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); + + Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + + ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); + + Vector<Ref<Image>> ret; + + for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { + const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; + ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); + ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); + Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); + + Ref<Image> img; + img.instantiate(); + img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); + ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); + if (tex->format != tex->validated_format) { + img->convert(tex->format); + } + + ret.push_back(img); + } + + return ret; +} + +void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy + Texture *by_tex = texture_owner.get_or_null(p_by_texture); + ERR_FAIL_COND(!by_tex); + ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy + + if (tex == by_tex) { + return; + } + + if (tex->rd_texture_srgb.is_valid()) { + RD::get_singleton()->free(tex->rd_texture_srgb); + } + RD::get_singleton()->free(tex->rd_texture); + + if (tex->canvas_texture) { + memdelete(tex->canvas_texture); + tex->canvas_texture = nullptr; + } + + Vector<RID> proxies_to_update = tex->proxies; + Vector<RID> proxies_to_redirect = by_tex->proxies; + + *tex = *by_tex; + + tex->proxies = proxies_to_update; //restore proxies, so they can be updated + + if (tex->canvas_texture) { + tex->canvas_texture->diffuse = p_texture; //update + } + + for (int i = 0; i < proxies_to_update.size(); i++) { + texture_proxy_update(proxies_to_update[i], p_texture); + } + for (int i = 0; i < proxies_to_redirect.size(); i++) { + texture_proxy_update(proxies_to_redirect[i], p_texture); + } + //delete last, so proxies can be updated + texture_owner.free(p_by_texture); + + DecalAtlasStorage::get_singleton()->decal_atlas_mark_dirty_on_texture(p_texture); +} + +void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_2D); + + tex->width_2d = p_width; + tex->height_2d = p_height; +} + +void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->path = p_path; +} + +String TextureStorage::texture_get_path(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, String()); + + return tex->path; +} + +void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_3d_callback_ud = p_userdata; + tex->detect_3d_callback = p_callback; +} + +void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_normal_callback_ud = p_userdata; + tex->detect_normal_callback = p_callback; +} + +void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_roughness_callback_ud = p_userdata; + tex->detect_roughness_callback = p_callback; +} + +void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { +} + +void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { +} + +Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) { + return texture_2d_get_size(p_proxy); +} + +Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { + Ref<Image> image = p_image->duplicate(); + + switch (p_image->get_format()) { + case Image::FORMAT_L8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //luminance + case Image::FORMAT_LA8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; + } break; //luminance-alpha + case Image::FORMAT_R8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RG8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGB8: { + //this format is not mandatory for specification, check if supported first + if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBA8: { + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGBA4444: { + r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGB565: { + r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RF: { + r_format.format = RD::DATA_FORMAT_R32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float + case Image::FORMAT_RGF: { + r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBF: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + image->convert(Image::FORMAT_RGBAF); + } + + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAF: { + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RH: { + r_format.format = RD::DATA_FORMAT_R16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //half float + case Image::FORMAT_RGH: { + r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBH: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->convert(Image::FORMAT_RGBAH); + } + + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAH: { + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RGBE9995: { + r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; +#ifndef _MSC_VER +#warning TODO need to make a function in Image to swap bits for this +#endif + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; + } break; + case Image::FORMAT_DXT1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //s3tc bc1 + case Image::FORMAT_DXT3: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //bc2 + case Image::FORMAT_DXT5: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; //bc3 + case Image::FORMAT_RGTC_R: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGTC_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_BPTC_RGBA: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //btpc bc7 + case Image::FORMAT_BPTC_RGBF: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float bc6h + case Image::FORMAT_BPTC_RGBFU: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //unsigned float bc6hu + case Image::FORMAT_ETC2_R11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //etc2 + case Image::FORMAT_ETC2_R11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //signed: {} break; NOT srgb. + case Image::FORMAT_ETC2_RG11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC2_RG11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC: + case Image::FORMAT_ETC2_RGB8: { + //ETC2 is backwards compatible with ETC1, and all modern platforms support it + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_ETC2_RGBA8: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RGB8A1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_DXT5_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + + default: { + } + } + + return image; +} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h new file mode 100644 index 0000000000..5d8d165a08 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -0,0 +1,230 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_RD_H +#define TEXTURE_STORAGE_RD_H + +#include "canvas_texture_storage.h" +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace RendererRD { + +enum DefaultRDTexture { + DEFAULT_RD_TEXTURE_WHITE, + DEFAULT_RD_TEXTURE_BLACK, + DEFAULT_RD_TEXTURE_NORMAL, + DEFAULT_RD_TEXTURE_ANISO, + DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_3D_BLACK, + DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_MAX +}; + +class Texture { +public: + enum Type { + TYPE_2D, + TYPE_LAYERED, + TYPE_3D + }; + + Type type; + RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; + + RenderingDevice::TextureType rd_type; + RID rd_texture; + RID rd_texture_srgb; + RenderingDevice::DataFormat rd_format; + RenderingDevice::DataFormat rd_format_srgb; + + RD::TextureView rd_view; + + Image::Format format; + Image::Format validated_format; + + int width; + int height; + int depth; + int layers; + int mipmaps; + + int height_2d; + int width_2d; + + struct BufferSlice3D { + Size2i size; + uint32_t offset = 0; + uint32_t buffer_size = 0; + }; + Vector<BufferSlice3D> buffer_slices_3d; + uint32_t buffer_size_3d = 0; + + bool is_render_target; + bool is_proxy; + + Ref<Image> image_cache_2d; + String path; + + RID proxy_to; + Vector<RID> proxies; + + Set<RID> lightmap_users; + + RS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; + + RS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; + + RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; + + CanvasTexture *canvas_texture = nullptr; + + void cleanup(); +}; + +class TextureStorage : public RendererTextureStorage { +private: + static TextureStorage *singleton; + + //textures can be created from threads, so this RID_Owner is thread safe + mutable RID_Owner<Texture, true> texture_owner; + + struct TextureToRDFormat { + RD::DataFormat format; + RD::DataFormat format_srgb; + RD::TextureSwizzle swizzle_r; + RD::TextureSwizzle swizzle_g; + RD::TextureSwizzle swizzle_b; + RD::TextureSwizzle swizzle_a; + TextureToRDFormat() { + format = RD::DATA_FORMAT_MAX; + format_srgb = RD::DATA_FORMAT_MAX; + swizzle_r = RD::TEXTURE_SWIZZLE_R; + swizzle_g = RD::TEXTURE_SWIZZLE_G; + swizzle_b = RD::TEXTURE_SWIZZLE_B; + swizzle_a = RD::TEXTURE_SWIZZLE_A; + } + }; + + Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); + void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false); + +public: + static TextureStorage *get_singleton(); + + RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; + + _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { + return default_rd_textures[p_texture]; + } + + TextureStorage(); + virtual ~TextureStorage(); + + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + + virtual bool can_create_resources_async() const override; + + virtual RID texture_allocate() override; + virtual void texture_free(RID p_rid) override; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; + virtual void texture_3d_placeholder_initialize(RID p_texture) override; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override; + + virtual void texture_set_path(RID p_texture, const String &p_path) override; + virtual String texture_get_path(RID p_texture) const override; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override; + + //internal usage + + _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { + if (p_texture.is_null()) { + return RID(); + } + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + + if (!tex) { + return RID(); + } + return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; + } + + _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { + if (p_texture.is_null()) { + return Size2i(); + } + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + + if (!tex) { + return Size2i(); + } + return Size2i(tex->width_2d, tex->height_2d); + } +}; + +} // namespace RendererRD + +#endif // !_TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp index 5843b9db24..84529ca400 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp @@ -36,7 +36,7 @@ void UniformSetCacheRD::_invalidate(Cache *p_cache) { if (p_cache->prev) { p_cache->prev->next = p_cache->next; } else { - // At begining of table + // At beginning of table uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE; hash_table[table_idx] = p_cache->next; } diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 485cd7ba9d..1304c811f7 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -464,10 +464,10 @@ void RendererSceneCull::instance_initialize(RID p_rid) { } void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) { - bool needs_instance = RSG::storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid()); + bool needs_instance = RSG::mesh_storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid()); if (needs_instance != p_instance->mesh_instance.is_valid()) { if (needs_instance) { - p_instance->mesh_instance = RSG::storage->mesh_instance_create(p_instance->base); + p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base); } else { RSG::storage->free(p_instance->mesh_instance); @@ -488,7 +488,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) { } if (p_instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton); + RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton); } } @@ -890,7 +890,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight); + RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight); } } @@ -900,7 +900,7 @@ void RendererSceneCull::instance_set_surface_override_material(RID p_instance, i if (instance->base_type == RS::INSTANCE_MESH) { //may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case - instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base))); + instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base))); } ERR_FAIL_INDEX(p_surface, instance->materials.size()); @@ -997,7 +997,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) if (p_skeleton.is_valid()) { //update the dependency now, so if cleared, we remove it - RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker); + RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker); } _instance_queue_update(instance, true, true); @@ -1438,7 +1438,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c E->get().value = p_value; if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) { //update directly - RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value); + RSG::material_storage->global_variables_instance_update(p_instance, E->get().index, p_value); } } } @@ -1847,7 +1847,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { if (p_instance->custom_aabb) { new_aabb = *p_instance->custom_aabb; } else { - new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); + new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); } } break; @@ -1856,7 +1856,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { if (p_instance->custom_aabb) { new_aabb = *p_instance->custom_aabb; } else { - new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base); + new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base); } } break; @@ -1887,7 +1887,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { } break; case RenderingServer::INSTANCE_DECAL: { - new_aabb = RSG::storage->decal_get_aabb(p_instance->base); + new_aabb = RSG::decal_atlas_storage->decal_get_aabb(p_instance->base); } break; case RenderingServer::INSTANCE_VOXEL_GI: { @@ -2271,14 +2271,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance); } } shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0); shadow_data.light = light->instance; @@ -2348,14 +2348,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons animated_material_found = true; } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance); } } shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0); shadow_data.light = light->instance; @@ -2412,13 +2412,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance); } } shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0); shadow_data.light = light->instance; @@ -2948,7 +2948,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c //check shadow.. if (light) { - if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->base) && !(RSG::storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->base))) { + if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->base) && !(RSG::storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) { lights_with_shadow.push_back(E); } //add to list @@ -3037,9 +3037,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (scene_cull_result.mesh_instances.size()) { for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) { - RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]); + RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); } } @@ -3473,7 +3473,7 @@ void RendererSceneCull::render_probes() { cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) || - cache->sky_only != RSG::storage->light_directional_is_sky_only(instance->base)) { + cache->sky_mode != RSG::storage->light_directional_get_sky_mode(instance->base)) { cache_dirty = true; } } @@ -3541,7 +3541,7 @@ void RendererSceneCull::render_probes() { cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); - cache->sky_only = RSG::storage->light_directional_is_sky_only(instance->base); + cache->sky_mode = RSG::storage->light_directional_get_sky_mode(instance->base); idx++; } @@ -3627,9 +3627,9 @@ void RendererSceneCull::render_particle_colliders() { } void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { - List<RendererStorage::InstanceShaderParam> plist; - RSG::storage->material_get_instance_shader_parameters(p_material, &plist); - for (const RendererStorage::InstanceShaderParam &E : plist) { + List<RendererMaterialStorage::InstanceShaderParam> plist; + RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist); + for (const RendererMaterialStorage::InstanceShaderParam &E : plist) { StringName name = E.info.name; if (isparams.has(name)) { if (isparams[name].info.type != E.info.type) { @@ -3667,17 +3667,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->material_override.is_valid()) { - RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker); } if (p_instance->material_overlay.is_valid()) { - RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker); } if (p_instance->base_type == RS::INSTANCE_MESH) { //remove materials no longer used and un-own them - int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base); + int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base); p_instance->materials.resize(new_mat_count); _instance_update_mesh_instance(p_instance); @@ -3688,7 +3688,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { RID particle_material = RSG::storage->particles_get_process_material(p_instance->base); if (particle_material.is_valid()) { - RSG::storage->material_update_dependency(particle_material, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker); } } @@ -3704,10 +3704,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->material_override.is_valid()) { - if (!RSG::storage->material_casts_shadows(p_instance->material_override)) { + if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) { can_cast_shadows = false; } - is_animated = RSG::storage->material_is_animated(p_instance->material_override); + is_animated = RSG::material_storage->material_is_animated(p_instance->material_override); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override); } else { if (p_instance->base_type == RS::INSTANCE_MESH) { @@ -3717,22 +3717,22 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { bool cast_shadows = false; for (int i = 0; i < p_instance->materials.size(); i++) { - RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i); + RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i); if (!mat.is_valid()) { cast_shadows = true; } else { - if (RSG::storage->material_casts_shadows(mat)) { + if (RSG::material_storage->material_casts_shadows(mat)) { cast_shadows = true; } - if (RSG::storage->material_is_animated(mat)) { + if (RSG::material_storage->material_is_animated(mat)) { is_animated = true; } _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } } @@ -3742,28 +3742,28 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } } else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) { - RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base); + RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base); if (mesh.is_valid()) { bool cast_shadows = false; - int sc = RSG::storage->mesh_get_surface_count(mesh); + int sc = RSG::mesh_storage->mesh_get_surface_count(mesh); for (int i = 0; i < sc; i++) { - RID mat = RSG::storage->mesh_surface_get_material(mesh, i); + RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i); if (!mat.is_valid()) { cast_shadows = true; } else { - if (RSG::storage->material_casts_shadows(mat)) { + if (RSG::material_storage->material_casts_shadows(mat)) { cast_shadows = true; } - if (RSG::storage->material_is_animated(mat)) { + if (RSG::material_storage->material_is_animated(mat)) { is_animated = true; } _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } } @@ -3784,24 +3784,24 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { continue; } - int sc = RSG::storage->mesh_get_surface_count(mesh); + int sc = RSG::mesh_storage->mesh_get_surface_count(mesh); for (int j = 0; j < sc; j++) { - RID mat = RSG::storage->mesh_surface_get_material(mesh, j); + RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j); if (!mat.is_valid()) { cast_shadows = true; } else { - if (RSG::storage->material_casts_shadows(mat)) { + if (RSG::material_storage->material_casts_shadows(mat)) { cast_shadows = true; } - if (RSG::storage->material_is_animated(mat)) { + if (RSG::material_storage->material_is_animated(mat)) { is_animated = true; } _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } } } @@ -3813,8 +3813,8 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->material_overlay.is_valid()) { - can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay); - is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay); + can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay); + is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay); } @@ -3834,16 +3834,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) { p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0); if (p_instance->instance_allocated_shader_parameters) { - p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self); + p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self); scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset); for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) { if (E.value.value.get_type() != Variant::NIL) { - RSG::storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value); + RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value); } } } else { - RSG::storage->global_variables_instance_free(p_instance->self); + RSG::material_storage->global_variables_instance_free(p_instance->self); p_instance->instance_allocated_shader_parameters_offset = -1; scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1); } @@ -3851,7 +3851,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->skeleton.is_valid()) { - RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker); + RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker); } p_instance->dependency_tracker.update_end(); @@ -3939,7 +3939,7 @@ bool RendererSceneCull::free(RID p_rid) { if (instance->instance_allocated_shader_parameters) { //free the used shader parameters - RSG::storage->global_variables_instance_free(instance->self); + RSG::material_storage->global_variables_instance_free(instance->self); } update_dirty_instances(); //in case something changed this diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 90d290bef9..5f71250ced 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -47,7 +47,7 @@ class RendererSceneCull : public RendererScene { public: - RendererSceneRender *scene_render; + RendererSceneRender *scene_render = nullptr; enum { SDFGI_MAX_CASCADES = 8, @@ -115,7 +115,7 @@ public: /* VISIBILITY NOTIFIER API */ - RendererSceneOcclusionCull *dummy_occlusion_culling; + RendererSceneOcclusionCull *dummy_occlusion_culling = nullptr; /* SCENARIO API */ @@ -273,7 +273,7 @@ public: union { uint64_t instance_data_rid; RendererSceneRender::GeometryInstance *instance_geometry; - InstanceVisibilityNotifierData *visibility_notifier; + InstanceVisibilityNotifierData *visibility_notifier = nullptr; }; Instance *instance = nullptr; int32_t parent_array_index = -1; @@ -365,8 +365,8 @@ public: /* INSTANCING API */ struct InstancePair { - Instance *a; - Instance *b; + Instance *a = nullptr; + Instance *b = nullptr; SelfList<InstancePair> list_a; SelfList<InstancePair> list_b; InstancePair() : @@ -409,7 +409,7 @@ public: bool dynamic_gi : 2; //same above for dynamic objects bool redraw_if_visible : 4; - Instance *lightmap; + Instance *lightmap = nullptr; Rect2 lightmap_uv_scale; int lightmap_slice_index; uint32_t lightmap_cull_index; @@ -455,7 +455,7 @@ public: SelfList<Instance> update_item; - AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? + AABB *custom_aabb = nullptr; // <Zylann> would using aabb directly with a bool be better? float extra_margin; ObjectID object_id; @@ -465,7 +465,7 @@ public: uint64_t version; // changes to this, and changes to base increase version - InstanceBaseData *base_data; + InstanceBaseData *base_data = nullptr; SelfList<InstancePair>::List pairs; uint64_t pair_check; @@ -597,7 +597,7 @@ public: }; struct InstanceReflectionProbeData : public InstanceBaseData { - Instance *owner; + Instance *owner = nullptr; Set<Instance *> geometries; @@ -613,7 +613,7 @@ public: }; struct InstanceDecalData : public InstanceBaseData { - Instance *owner; + Instance *owner = nullptr; RID instance; Set<Instance *> geometries; @@ -656,7 +656,7 @@ public: Set<Instance *> geometries; - Instance *baked_light; + Instance *baked_light = nullptr; RS::LightBakeMode bake_mode; uint32_t max_sdfgi_cascade = 2; @@ -671,7 +671,7 @@ public: }; struct InstanceVoxelGIData : public InstanceBaseData { - Instance *owner; + Instance *owner = nullptr; Set<Instance *> geometries; Set<Instance *> dynamic_geometries; @@ -689,7 +689,7 @@ public: float spot_angle; float spot_attenuation; bool has_shadow; - bool sky_only; + RS::LightDirectionalSkyMode sky_mode; }; Vector<LightCache> light_cache; @@ -1023,7 +1023,7 @@ public: struct VisibilityCullData { uint64_t viewport_mask; - Scenario *scenario; + Scenario *scenario = nullptr; Vector3 camera_position; uint32_t cull_offset; uint32_t cull_count; @@ -1035,12 +1035,12 @@ public: _FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask); struct CullData { - Cull *cull; - Scenario *scenario; + Cull *cull = nullptr; + Scenario *scenario = nullptr; RID shadow_atlas; Transform3D cam_transform; uint32_t visible_layers; - Instance *render_reflection_probe; + Instance *render_reflection_probe = nullptr; const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer; const CameraMatrix *camera_matrix; uint64_t visibility_viewport_mask; diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 5f9c4bb816..0b8734e68c 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -223,7 +223,7 @@ public: struct RenderSDFGIUpdateData { bool update_static = false; uint32_t static_cascade_count; - uint32_t *static_cascade_indices; + uint32_t *static_cascade_indices = nullptr; PagedArray<RID> *static_positional_lights; const Vector<RID> *directional_lights; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index ca3d3a048d..7bbd414465 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -54,7 +54,6 @@ public: struct DependencyTracker; -protected: struct Dependency { void changed_notify(DependencyChangedNotification p_notification); void deleted_notify(const RID &p_rid); @@ -66,7 +65,6 @@ protected: Map<DependencyTracker *, uint32_t> instances; }; -public: struct DependencyTracker { void *userdata = nullptr; typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *); @@ -121,188 +119,6 @@ public: Set<Dependency *> dependencies; }; - virtual bool can_create_resources_async() const = 0; - /* TEXTURE API */ - - virtual RID texture_allocate() = 0; - - virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; - virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; - virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent - - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; - - //these two APIs can be used together or in combination with the others. - virtual void texture_2d_placeholder_initialize(RID p_texture) = 0; - virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0; - virtual void texture_3d_placeholder_initialize(RID p_texture) = 0; - - virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; - - virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; - - virtual void texture_set_path(RID p_texture, const String &p_path) = 0; - virtual String texture_get_path(RID p_texture) const = 0; - - virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - - virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - - /* CANVAS TEXTURE API */ - - virtual RID canvas_texture_allocate() = 0; - virtual void canvas_texture_initialize(RID p_rid) = 0; - - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; - - virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; - virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; - - /* SHADER API */ - - virtual RID shader_allocate() = 0; - virtual void shader_initialize(RID p_rid) = 0; - - virtual void shader_set_code(RID p_shader, const String &p_code) = 0; - virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; - virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; - - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; - - /* COMMON MATERIAL API */ - - virtual RID material_allocate() = 0; - virtual void material_initialize(RID p_rid) = 0; - - virtual void material_set_render_priority(RID p_material, int priority) = 0; - virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; - - virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; - virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; - - virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; - - virtual bool material_is_animated(RID p_material) = 0; - virtual bool material_casts_shadows(RID p_material) = 0; - - struct InstanceShaderParam { - PropertyInfo info; - int index; - Variant default_value; - }; - - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; - - virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0; - - /* MESH API */ - - virtual RID mesh_allocate() = 0; - virtual void mesh_initialize(RID p_rid) = 0; - - virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0; - - /// Returns stride - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; - - virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; - virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - - virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; - - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; - - virtual int mesh_get_surface_count(RID p_mesh) const = 0; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; - virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; - - virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0; - - virtual void mesh_clear(RID p_mesh) = 0; - - virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0; - - /* MESH INSTANCE */ - - virtual RID mesh_instance_create(RID p_base) = 0; - virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0; - virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0; - virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0; - virtual void update_mesh_instances() = 0; - - /* MULTIMESH API */ - - virtual RID multimesh_allocate() = 0; - virtual void multimesh_initialize(RID p_rid) = 0; - - virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; - - virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0; - virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; - virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; - - virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; - - virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; - virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - - virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; - virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; - virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; - - virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; - - /* SKELETON API */ - - virtual RID skeleton_allocate() = 0; - virtual void skeleton_initialize(RID p_rid) = 0; - - virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; - virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; - virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0; - virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; - virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - /* Light API */ virtual RID directional_light_allocate() = 0; @@ -330,8 +146,8 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; virtual bool light_directional_get_blend_splits(RID p_light) const = 0; - virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0; - virtual bool light_directional_is_sky_only(RID p_light) const = 0; + virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0; + virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const = 0; virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; @@ -378,24 +194,6 @@ public: virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0; virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; - virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; - - /* DECAL API */ - - virtual RID decal_allocate() = 0; - virtual void decal_initialize(RID p_rid) = 0; - - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; - virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0; - virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; - virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; - virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0; - virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0; - virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0; - virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0; - virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; - - virtual AABB decal_get_aabb(RID p_decal) const = 0; /* VOXEL GI API */ @@ -562,24 +360,6 @@ public: virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0; virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0; - /* GLOBAL VARIABLES */ - - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; - virtual void global_variable_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_variable_get_list() const = 0; - - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_variable_get(const StringName &p_name) const = 0; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; - - virtual void global_variables_load_settings(bool p_load_textures = true) = 0; - virtual void global_variables_clear() = 0; - - virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; - virtual void global_variables_instance_free(RID p_instance) = 0; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; - /* RENDER TARGET */ enum RenderTargetFlags { diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index b448a15d8e..f492c5e9bd 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -293,7 +293,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. - Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture); + Size2 tsize = RSG::texture_storage->texture_size_with_proxy(cl->texture); tsize *= cl->scale; Vector2 offset = tsize / 2.0; diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 2245d9a216..b6e44e8436 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -129,7 +129,7 @@ public: }; struct CanvasData { - CanvasBase *canvas; + CanvasBase *canvas = nullptr; Transform2D transform; int layer; int sublayer; diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 1880415342..1902b5f74a 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -528,6 +528,7 @@ public: /*********************/ struct AttachmentFormat { + enum { UNUSED_ATTACHMENT = 0xFFFFFFFF }; DataFormat format; TextureSamples samples; uint32_t usage_flags; @@ -729,7 +730,7 @@ public: int binding; // Binding index as specified in shader. private: - // In most cases only one ID is provided per binding, so avoid allocating memory unnecesarily for performance. + // In most cases only one ID is provided per binding, so avoid allocating memory unnecessarily for performance. RID id; // If only one is provided, this is used. Vector<RID> ids; // If multiple ones are provided, this is used instead. @@ -1222,7 +1223,7 @@ public: LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z, }; - virtual int limit_get(Limit p_limit) = 0; + virtual uint64_t limit_get(Limit p_limit) = 0; //methods below not exposed, used by RenderingDeviceRD virtual void prepare_screen_for_drawing() = 0; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index d93aad5d7b..2dab7cb84c 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -398,6 +398,11 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : RendererSceneCull *sr = memnew(RendererSceneCull); RSG::scene = sr; RSG::rasterizer = RendererCompositor::create(); + RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage(); + RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage(); + RSG::material_storage = RSG::rasterizer->get_material_storage(); + RSG::mesh_storage = RSG::rasterizer->get_mesh_storage(); + RSG::texture_storage = RSG::rasterizer->get_texture_storage(); RSG::storage = RSG::rasterizer->get_storage(); RSG::canvas_render = RSG::rasterizer->get_canvas(); sr->set_scene_render(RSG::rasterizer->get_scene()); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 4a8944ccdd..cc1edc728a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -126,54 +126,53 @@ public: #include "servers/server_wrap_mt_common.h" -//from now on, calls forwarded to this singleton -#define ServerName RendererStorage -#define server_name RSG::storage - /* TEXTURE API */ -#define FUNCRIDTEX0(m_type) \ - virtual RID m_type##_create() override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret); \ - } \ - return ret; \ +#define ServerName RendererTextureStorage +#define server_name RSG::texture_storage + +#define FUNCRIDTEX0(m_type) \ + virtual RID m_type##_create() override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret); \ + } \ + return ret; \ } -#define FUNCRIDTEX1(m_type, m_type1) \ - virtual RID m_type##_create(m_type1 p1) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1); \ - } \ - return ret; \ +#define FUNCRIDTEX1(m_type, m_type1) \ + virtual RID m_type##_create(m_type1 p1) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1); \ + } \ + return ret; \ } -#define FUNCRIDTEX2(m_type, m_type1, m_type2) \ - virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1, p2); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2); \ - } \ - return ret; \ +#define FUNCRIDTEX2(m_type, m_type1, m_type2) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2); \ + } \ + return ret; \ } -#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ - virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \ - } \ - return ret; \ +#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \ + } \ + return ret; \ } //these go pass-through, as they can be called from any thread @@ -216,6 +215,12 @@ public: /* SHADER API */ +#undef ServerName +#undef server_name + +#define ServerName RendererMaterialStorage +#define server_name RSG::material_storage + FUNCRIDSPLIT(shader) FUNC2(shader_set_code, RID, const String &) @@ -243,23 +248,32 @@ public: /* MESH API */ +//from now on, calls forwarded to this singleton +#undef ServerName +#undef server_name + +#define ServerName RendererMeshStorage +#define server_name RSG::mesh_storage + virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override { - RID mesh = RSG::storage->mesh_allocate(); + RID mesh = RSG::mesh_storage->mesh_allocate(); + + // TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!! - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { if (Thread::get_caller_id() == server_thread) { command_queue.flush_if_pending(); } - RSG::storage->mesh_initialize(mesh); - RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count); + RSG::mesh_storage->mesh_initialize(mesh); + RSG::mesh_storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { - RSG::storage->mesh_add_surface(mesh, p_surfaces[i]); + RSG::mesh_storage->mesh_add_surface(mesh, p_surfaces[i]); } } else { - command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh); - command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count); + command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_initialize, mesh); + command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { - command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]); + command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_add_surface, mesh, p_surfaces[i]); } } @@ -334,6 +348,11 @@ public: FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &) /* Light API */ +#undef ServerName +#undef server_name + +#define ServerName RendererStorage +#define server_name RSG::storage FUNCRIDSPLIT(directional_light) FUNCRIDSPLIT(omni_light) @@ -354,7 +373,7 @@ public: FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) FUNC2(light_directional_set_blend_splits, RID, bool) - FUNC2(light_directional_set_sky_only, RID, bool) + FUNC2(light_directional_set_sky_mode, RID, LightDirectionalSkyMode) /* PROBE API */ @@ -377,6 +396,12 @@ public: /* DECAL API */ +#undef ServerName +#undef server_name + +#define ServerName RendererDecalAtlasStorage +#define server_name RSG::decal_atlas_storage + FUNCRIDSPLIT(decal) FUNC2(decal_set_extents, RID, const Vector3 &) @@ -391,6 +416,13 @@ public: /* BAKED LIGHT API */ +//from now on, calls forwarded to this singleton +#undef ServerName +#undef server_name + +#define ServerName RendererStorage +#define server_name RSG::storage + FUNCRIDSPLIT(voxel_gi) FUNC8(voxel_gi_allocate_data, RID, const Transform3D &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &) @@ -849,8 +881,8 @@ public: #undef server_name #undef ServerName //from now on, calls forwarded to this singleton -#define ServerName RendererStorage -#define server_name RSG::storage +#define ServerName RendererMaterialStorage +#define server_name RSG::material_storage FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &) FUNC1(global_variable_remove, const StringName &) diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index b8b06b5eea..2be87c27b1 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -32,6 +32,11 @@ bool RenderingServerGlobals::threaded = false; +RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr; +RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr; +RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr; +RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr; +RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr; RendererStorage *RenderingServerGlobals::storage = nullptr; RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; RendererCompositor *RenderingServerGlobals::rasterizer = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index 4351830a5f..40fd638425 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -34,6 +34,11 @@ #include "servers/rendering/renderer_canvas_cull.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_scene.h" +#include "servers/rendering/storage/canvas_texture_storage.h" +#include "servers/rendering/storage/decal_atlas_storage.h" +#include "servers/rendering/storage/material_storage.h" +#include "servers/rendering/storage/mesh_storage.h" +#include "servers/rendering/storage/texture_storage.h" class RendererCanvasCull; class RendererViewport; @@ -43,6 +48,11 @@ class RenderingServerGlobals { public: static bool threaded; + static RendererCanvasTextureStorage *canvas_texture_storage; + static RendererMaterialStorage *material_storage; + static RendererMeshStorage *mesh_storage; + static RendererTextureStorage *texture_storage; + static RendererDecalAtlasStorage *decal_atlas_storage; static RendererStorage *storage; static RendererCanvasRender *canvas_render; static RendererCompositor *rasterizer; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 7683cf20b3..a0769ef106 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2813,7 +2813,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI bool error = false; if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) { - const VariableNode *vn = (VariableNode *)p_func->arguments[arg]; + const VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg]); bool is_const = false; ConstantNode::Value value; @@ -2825,7 +2825,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } } else { if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) { - ConstantNode *cn = (ConstantNode *)p_func->arguments[arg]; + const ConstantNode *cn = static_cast<ConstantNode *>(p_func->arguments[arg]); if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) { int value = cn->values[0].sint; @@ -4132,7 +4132,7 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St bool ShaderLanguage::_check_node_constness(const Node *p_node) const { switch (p_node->type) { case Node::TYPE_OPERATOR: { - OperatorNode *op_node = (OperatorNode *)p_node; + const OperatorNode *op_node = static_cast<const OperatorNode *>(p_node); for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) { if (!_check_node_constness(op_node->arguments[i])) { return false; @@ -4142,13 +4142,13 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const { case Node::TYPE_CONSTANT: break; case Node::TYPE_VARIABLE: { - VariableNode *varn = (VariableNode *)p_node; + const VariableNode *varn = static_cast<const VariableNode *>(p_node); if (!varn->is_const) { return false; } } break; case Node::TYPE_ARRAY: { - ArrayNode *arrn = (ArrayNode *)p_node; + const ArrayNode *arrn = static_cast<const ArrayNode *>(p_node); if (!arrn->is_const) { return false; } @@ -5134,9 +5134,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } else if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_ARRAY; + } call_expression = _parse_and_reduce_expression(p_block, p_function_info); - p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_GLOBAL; + } if (!call_expression) { return nullptr; } @@ -5153,7 +5157,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index_expression->type == Node::TYPE_CONSTANT) { - ConstantNode *cnode = (ConstantNode *)index_expression; + ConstantNode *cnode = static_cast<ConstantNode *>(index_expression); if (cnode) { if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; @@ -5287,9 +5291,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!expr->is_indexed() && expr->get_array_size() > 0) { completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_ARRAY; + } Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info); - p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_GLOBAL; + } if (!call_expression) { return nullptr; } @@ -5587,9 +5595,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons mn->assign_expression = assign_expression; } else if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_ARRAY; + } Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info); - p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_GLOBAL; + } if (!call_expression) { return nullptr; } @@ -5607,7 +5619,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index_expression->type == Node::TYPE_CONSTANT) { - ConstantNode *cnode = (ConstantNode *)index_expression; + ConstantNode *cnode = static_cast<ConstantNode *>(index_expression); if (cnode) { if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; @@ -6690,7 +6702,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } - if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) { _set_error(RTR("Expected a constant expression.")); return ERR_PARSE_ERROR; } @@ -6746,8 +6758,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!n) { return ERR_PARSE_ERROR; } - if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - OperatorNode *op = ((OperatorNode *)n); + if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) { + OperatorNode *op = static_cast<OperatorNode *>(n); for (int i = 1; i < op->arguments.size(); i++) { if (!_check_node_constness(op->arguments[i])) { _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1)); @@ -6791,7 +6803,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } while (tk.type == TK_COMMA); //another variable - p_block->statements.push_back((Node *)vdnode); + p_block->statements.push_back(static_cast<Node *>(vdnode)); } else if (tk.type == TK_CURLY_BRACKET_OPEN) { //a sub block, just because.. BlockNode *block = alloc_node<BlockNode>(); @@ -6913,7 +6925,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } else { Set<int> constants; for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. - ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; + ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]); if (flow) { if (flow->flow_op == FLOW_OP_CASE) { if (flow->expressions[0]->type == Node::TYPE_CONSTANT) { @@ -7483,8 +7495,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int uniforms = 0; int instance_index = 0; #ifdef DEBUG_ENABLED - int uniform_buffer_size = 0; - int max_uniform_buffer_size = 0; + uint64_t uniform_buffer_size = 0; + uint64_t max_uniform_buffer_size = 0; int uniform_buffer_exceeded_line = -1; bool check_device_limit_warnings = false; @@ -8455,7 +8467,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + if (n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) { _set_error(RTR("Expected constant expression.")); return ERR_PARSE_ERROR; } @@ -8511,8 +8523,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (!expr) { return ERR_PARSE_ERROR; } - if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { - OperatorNode *op = ((OperatorNode *)expr); + if (expr->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) { + OperatorNode *op = static_cast<OperatorNode *>(expr); for (int i = 1; i < op->arguments.size(); i++) { if (!_check_node_constness(op->arguments[i])) { _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1)); @@ -8849,7 +8861,7 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper for (int i = p_flow->blocks.size() - 1; i >= 0; i--) { if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) { - BlockNode *last_block = (BlockNode *)p_flow->blocks[i]; + BlockNode *last_block = static_cast<BlockNode *>(p_flow->blocks[i]); if (_find_last_flow_op_in_block(last_block, p_op) == OK) { found = true; break; @@ -8867,7 +8879,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat for (int i = p_block->statements.size() - 1; i >= 0; i--) { if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) { - ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i]; + ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]); if (flow->flow_op == p_op) { found = true; break; @@ -8878,7 +8890,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat } } } else if (p_block->statements[i]->type == Node::TYPE_BLOCK) { - BlockNode *block = (BlockNode *)p_block->statements[i]; + BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]); if (_find_last_flow_op_in_block(block, p_op) == OK) { found = true; break; @@ -9034,7 +9046,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i return OK; } -Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) { clear(); code = p_code; @@ -9053,7 +9065,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_SHADER_TYPE: { for (const String &shader_type : p_info.shader_types) { - ScriptCodeCompletionOption option(shader_type, ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option(shader_type, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); r_options->push_back(option); } return OK; @@ -9073,7 +9085,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (!found) { for (int j = 0; j < info.options.size(); j++) { - ScriptCodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); r_options->push_back(option); } } @@ -9081,7 +9093,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ const String name = String(info.name); if (!shader->render_modes.has(name)) { - ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); r_options->push_back(option); } } @@ -9093,7 +9105,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (shader->structs.has(completion_struct)) { StructNode *node = shader->structs[completion_struct].shader_struct; for (int i = 0; i < node->members.size(); i++) { - ScriptCodeCompletionOption option(node->members[i]->name, ScriptCodeCompletionOption::KIND_MEMBER); + ScriptLanguage::CodeCompletionOption option(node->members[i]->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); r_options->push_back(option); } } @@ -9115,7 +9127,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (found) { continue; } - ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION); + ScriptLanguage::CodeCompletionOption option(E.key, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); r_options->push_back(option); } @@ -9124,7 +9136,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ case COMPLETION_IDENTIFIER: case COMPLETION_FUNCTION_CALL: { bool comp_ident = completion_type == COMPLETION_IDENTIFIER; - Map<String, ScriptCodeCompletionOption::Kind> matches; + Map<String, ScriptLanguage::CodeCompletionKind> matches; StringName skip_function; BlockNode *block = completion_block; @@ -9133,7 +9145,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (comp_ident) { for (const KeyValue<StringName, BlockNode::Variable> &E : block->variables) { if (E.value.line < completion_line) { - matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE); + matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE); } } } @@ -9141,7 +9153,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (block->parent_function) { if (comp_ident) { for (int i = 0; i < block->parent_function->arguments.size(); i++) { - matches.insert(block->parent_function->arguments[i].name, ScriptCodeCompletionOption::KIND_VARIABLE); + matches.insert(block->parent_function->arguments[i].name, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE); } } skip_function = block->parent_function->name; @@ -9152,9 +9164,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (comp_ident) { if (p_info.functions.has("global")) { for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) { - ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; if (E.value.constant) { - kind = ScriptCodeCompletionOption::KIND_CONSTANT; + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; } matches.insert(E.key, kind); } @@ -9162,9 +9174,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (p_info.functions.has("constants")) { for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) { - ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; if (E.value.constant) { - kind = ScriptCodeCompletionOption::KIND_CONSTANT; + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; } matches.insert(E.key, kind); } @@ -9172,22 +9184,22 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (skip_function != StringName() && p_info.functions.has(skip_function)) { for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) { - ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; if (E.value.constant) { - kind = ScriptCodeCompletionOption::KIND_CONSTANT; + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; } matches.insert(E.key, kind); } } for (const KeyValue<StringName, ShaderNode::Constant> &E : shader->constants) { - matches.insert(E.key, ScriptCodeCompletionOption::KIND_CONSTANT); + matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); } for (const KeyValue<StringName, ShaderNode::Varying> &E : shader->varyings) { - matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE); + matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE); } for (const KeyValue<StringName, ShaderNode::Uniform> &E : shader->uniforms) { - matches.insert(E.key, ScriptCodeCompletionOption::KIND_MEMBER); + matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); } } @@ -9195,7 +9207,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (!shader->functions[i].callable || shader->functions[i].name == skip_function) { continue; } - matches.insert(String(shader->functions[i].name), ScriptCodeCompletionOption::KIND_FUNCTION); + matches.insert(String(shader->functions[i].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); } int idx = 0; @@ -9203,7 +9215,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (stages && stages->has(skip_function)) { for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) { - matches.insert(String(E.key), ScriptCodeCompletionOption::KIND_FUNCTION); + matches.insert(String(E.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); } } @@ -9212,7 +9224,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ idx++; continue; } - matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION); + matches.insert(String(builtin_func_defs[idx].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); idx++; } @@ -9226,15 +9238,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ continue; } if (builtin_func_defs[idx].tag == completion_class) { - matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION); + matches.insert(String(builtin_func_defs[idx].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); } idx++; } } - for (const KeyValue<String, ScriptCodeCompletionOption::Kind> &E : matches) { - ScriptCodeCompletionOption option(E.key, E.value); - if (E.value == ScriptCodeCompletionOption::KIND_FUNCTION) { + for (const KeyValue<String, ScriptLanguage::CodeCompletionKind> &E : matches) { + ScriptLanguage::CodeCompletionOption option(E.key, E.value); + if (E.value == ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION) { option.insert_text += "("; } r_options->push_back(option); @@ -9483,18 +9495,18 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } for (int i = 0; i < limit; i++) { - r_options->push_back(ScriptCodeCompletionOption(String::chr(colv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); - r_options->push_back(ScriptCodeCompletionOption(String::chr(coordv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); - r_options->push_back(ScriptCodeCompletionOption(String::chr(coordt[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); + r_options->push_back(ScriptLanguage::CodeCompletionOption(String::chr(colv[i]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT)); + r_options->push_back(ScriptLanguage::CodeCompletionOption(String::chr(coordv[i]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT)); + r_options->push_back(ScriptLanguage::CodeCompletionOption(String::chr(coordt[i]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT)); } } break; case COMPLETION_HINT: { if (completion_base == DataType::TYPE_VEC4) { - ScriptCodeCompletionOption option("hint_color", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option("hint_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); r_options->push_back(option); } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) { - ScriptCodeCompletionOption option("hint_range", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); if (completion_base == DataType::TYPE_INT) { option.insert_text = "hint_range(0, 100, 1)"; @@ -9530,12 +9542,12 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } for (int i = 0; i < options.size(); i++) { - ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option(options[i], ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); r_options->push_back(option); } } if (!completion_base_array) { - ScriptCodeCompletionOption option("instance_index", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption option("instance_index", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); option.insert_text = "instance_index(0)"; r_options->push_back(option); } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index f39b21621d..25ec8760af 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -386,7 +386,7 @@ public: return node; } - Node *nodes; + Node *nodes = nullptr; struct OperatorNode : public Node { DataType return_cache = TYPE_VOID; @@ -615,20 +615,20 @@ public: DataType type; StringName type_str; DataPrecision precision; - ConstantNode *initializer; + ConstantNode *initializer = nullptr; int array_size; }; struct Function { StringName name; - FunctionNode *function; + FunctionNode *function = nullptr; Set<StringName> uses_function; bool callable; }; struct Struct { StringName name; - StructNode *shader_struct; + StructNode *shader_struct = nullptr; }; struct Varying { @@ -715,7 +715,7 @@ public: bool is_op; union { Operator op; - Node *node; + Node *node = nullptr; }; }; @@ -973,7 +973,7 @@ private: Token _make_token(TokenType p_type, const StringName &p_text = StringName()); Token _get_token(); - ShaderNode *shader; + ShaderNode *shader = nullptr; enum IdentifierType { IDENTIFIER_FUNCTION, @@ -1021,7 +1021,7 @@ private: CompletionType completion_type; int completion_line; - BlockNode *completion_block; + BlockNode *completion_block = nullptr; DataType completion_base; bool completion_base_array; SubClassTag completion_class; @@ -1091,7 +1091,7 @@ public: }; Error compile(const String &p_code, const ShaderCompileInfo &p_info); - Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint); + Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint); String get_error_text(); int get_error_line(); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 9ea98dc593..27a69fbc2e 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -86,10 +86,10 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].main_function = true; //builtins - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; @@ -145,10 +145,10 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); @@ -163,9 +163,9 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_ANTIALIASING_EDGE"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_TEXTURE_COORDINATE"] = ShaderLanguage::TYPE_VEC2; - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); @@ -178,7 +178,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SHADOW_ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["BACKLIGHT"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["METALLIC"] = constt(ShaderLanguage::TYPE_FLOAT); @@ -227,7 +226,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); diff --git a/servers/rendering/storage/SCsub b/servers/rendering/storage/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/storage/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/storage/canvas_texture_storage.h b/servers/rendering/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..ad4c67f649 --- /dev/null +++ b/servers/rendering/storage/canvas_texture_storage.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_H +#define CANVAS_TEXTURE_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererCanvasTextureStorage { +public: + virtual ~RendererCanvasTextureStorage(){}; + + virtual RID canvas_texture_allocate() = 0; + virtual void canvas_texture_initialize(RID p_rid) = 0; + virtual void canvas_texture_free(RID p_rid) = 0; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; +}; + +#endif // !CANVAS_TEXTURE_STORAGE_H diff --git a/servers/rendering/storage/decal_atlas_storage.h b/servers/rendering/storage/decal_atlas_storage.h new file mode 100644 index 0000000000..62cd76881b --- /dev/null +++ b/servers/rendering/storage/decal_atlas_storage.h @@ -0,0 +1,60 @@ +/*************************************************************************/ +/* decal_atlas_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DECAL_ATLAS_STORAGE_H +#define DECAL_ATLAS_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererDecalAtlasStorage { +public: + virtual ~RendererDecalAtlasStorage(){}; + + virtual RID decal_allocate() = 0; + virtual void decal_initialize(RID p_rid) = 0; + virtual void decal_free(RID p_rid) = 0; + + virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; + virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0; + virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; + virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; + virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0; + virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0; + virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0; + virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0; + virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; + + virtual AABB decal_get_aabb(RID p_decal) const = 0; + + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; +}; + +#endif // !DECAL_ATLAS_STORAGE_H diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h new file mode 100644 index 0000000000..f0363f129a --- /dev/null +++ b/servers/rendering/storage/material_storage.h @@ -0,0 +1,101 @@ +/*************************************************************************/ +/* material_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MATERIAL_STORAGE_H +#define MATERIAL_STORAGE_H + +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering_server.h" + +class RendererMaterialStorage { +public: + virtual ~RendererMaterialStorage(){}; + + /* GLOBAL VARIABLE API */ + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; + virtual void global_variable_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_variable_get_list() const = 0; + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual Variant global_variable_get(const StringName &p_name) const = 0; + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; + + virtual void global_variables_load_settings(bool p_load_textures = true) = 0; + virtual void global_variables_clear() = 0; + + virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; + virtual void global_variables_instance_free(RID p_instance) = 0; + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; + + /* SHADER API */ + virtual RID shader_allocate() = 0; + virtual void shader_initialize(RID p_rid) = 0; + virtual void shader_free(RID p_rid) = 0; + + virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual String shader_get_code(RID p_shader) const = 0; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; + virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; + + /* MATERIAL API */ + + virtual RID material_allocate() = 0; + virtual void material_initialize(RID p_rid) = 0; + virtual void material_free(RID p_rid) = 0; + + virtual void material_set_render_priority(RID p_material, int priority) = 0; + virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; + + virtual bool material_is_animated(RID p_material) = 0; + virtual bool material_casts_shadows(RID p_material) = 0; + + struct InstanceShaderParam { + PropertyInfo info; + int index; + Variant default_value; + }; + + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; + + virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) = 0; +}; + +#endif // !MATERIAL_STORAGE_H diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h new file mode 100644 index 0000000000..1dac51319c --- /dev/null +++ b/servers/rendering/storage/mesh_storage.h @@ -0,0 +1,136 @@ +/*************************************************************************/ +/* mesh_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_STORAGE_H +#define MESH_STORAGE_H + +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering_server.h" + +class RendererMeshStorage { +public: + virtual ~RendererMeshStorage() {} + + /* MESH API */ + + virtual RID mesh_allocate() = 0; + virtual void mesh_initialize(RID p_rid) = 0; + virtual void mesh_free(RID p_rid) = 0; + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0; + + /// Returns stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; + + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; + + virtual int mesh_get_surface_count(RID p_mesh) const = 0; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; + + virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0; + + virtual void mesh_clear(RID p_mesh) = 0; + + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0; + + /* MESH INSTANCE */ + + virtual RID mesh_instance_create(RID p_base) = 0; + virtual void mesh_instance_free(RID p_rid) = 0; + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0; + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0; + virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0; + virtual void update_mesh_instances() = 0; + + /* MULTIMESH API */ + + virtual RID multimesh_allocate() = 0; + virtual void multimesh_initialize(RID p_rid) = 0; + virtual void multimesh_free(RID p_rid) = 0; + + virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; + + virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; + + virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; + + /* SKELETON API */ + + virtual RID skeleton_allocate() = 0; + virtual void skeleton_initialize(RID p_rid) = 0; + virtual void skeleton_free(RID p_rid) = 0; + + virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; + virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0; + virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + + virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0; +}; + +#endif // !MESH_STORAGE_H diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h new file mode 100644 index 0000000000..bef5e3e146 --- /dev/null +++ b/servers/rendering/storage/texture_storage.h @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_H +#define TEXTURE_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererTextureStorage { +public: + virtual bool can_create_resources_async() const = 0; + + virtual ~RendererTextureStorage(){}; + + virtual RID texture_allocate() = 0; + virtual void texture_free(RID p_rid) = 0; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) = 0; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0; + virtual void texture_3d_placeholder_initialize(RID p_texture) = 0; + + virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; + + virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; + + virtual void texture_set_path(RID p_texture, const String &p_path) = 0; + virtual String texture_get_path(RID p_texture) const = 0; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + + virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; +}; + +#endif // !TEXTURE_STORAGE_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a6992014e8..fa6c3fac68 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -979,7 +979,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Invalid array format for surface."); Vector<uint8_t> blend_shape_data; - uint32_t blend_shape_count = 0; if (p_blend_shapes.size()) { uint32_t bs_format = format & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK; @@ -996,7 +995,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa ERR_FAIL_COND_V_MSG(err2 != OK, ERR_INVALID_DATA, "Invalid blend shape array format for surface."); blend_shape_data.append_array(vertex_array_shape); - blend_shape_count++; } } Vector<SurfaceData::LOD> lods; @@ -1891,7 +1889,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &RenderingServer::light_directional_set_shadow_mode); ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits); - ClassDB::bind_method(D_METHOD("light_directional_set_sky_only", "light", "enable"), &RenderingServer::light_directional_set_sky_only); + ClassDB::bind_method(D_METHOD("light_directional_set_sky_mode", "light", "mode"), &RenderingServer::light_directional_set_sky_mode); ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter); @@ -1937,6 +1935,10 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY); + ClassDB::bind_method(D_METHOD("shadows_quality_set", "quality"), &RenderingServer::shadows_quality_set); ClassDB::bind_method(D_METHOD("directional_shadow_quality_set", "quality"), &RenderingServer::directional_shadow_quality_set); ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size); @@ -2895,8 +2897,7 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/environment/ssao/quality", 2); ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/quality", PropertyInfo(Variant::INT, "rendering/environment/ssao/quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low (Fast),Medium (Average),High (Slow),Ultra (Custom)")); - GLOBAL_DEF("rendering/environment/ssao/half_size", false); - GLOBAL_DEF("rendering/environment/ssao/half_size.mobile", true); + GLOBAL_DEF("rendering/environment/ssao/half_size", true); GLOBAL_DEF("rendering/environment/ssao/adaptive_target", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/adaptive_target", PropertyInfo(Variant::FLOAT, "rendering/environment/ssao/adaptive_target", PROPERTY_HINT_RANGE, "0.0,1.0,0.01")); GLOBAL_DEF("rendering/environment/ssao/blur_passes", 2); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 94d9cb8800..94692ba68d 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -469,9 +469,15 @@ public: LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS, }; + enum LightDirectionalSkyMode { + LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY, + LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY, + LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY, + }; + virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; - virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0; + virtual void light_directional_set_sky_mode(RID p_light, LightDirectionalSkyMode p_mode) = 0; virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0; @@ -1569,6 +1575,7 @@ VARIANT_ENUM_CAST(RenderingServer::LightParam); VARIANT_ENUM_CAST(RenderingServer::LightBakeMode); VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode); VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode); +VARIANT_ENUM_CAST(RenderingServer::LightDirectionalSkyMode); VARIANT_ENUM_CAST(RenderingServer::LightProjectorFilter); VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode); VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeAmbientMode); diff --git a/servers/text/text_server_dummy.h b/servers/text/text_server_dummy.h new file mode 100644 index 0000000000..c603881b7c --- /dev/null +++ b/servers/text/text_server_dummy.h @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* text_server_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXT_SERVER_DUMMY_H +#define TEXT_SERVER_DUMMY_H + +#include "servers/text/text_server_extension.h" + +/*************************************************************************/ + +class TextServerDummy : public TextServerExtension { + GDCLASS(TextServerDummy, TextServerExtension); + _THREAD_SAFE_CLASS_ + +public: + virtual String get_name() const override { + return "Dummy"; + } +}; + +#endif // TEXT_SERVER_DUMMY_H diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 1a10161a5b..c8efacc9c5 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -31,267 +31,269 @@ #include "text_server_extension.h" void TextServerExtension::_bind_methods() { - GDVIRTUAL_BIND(_has_feature, "feature"); - GDVIRTUAL_BIND(_get_name); - GDVIRTUAL_BIND(_get_features); + GDVIRTUAL_BIND(has_feature, "feature"); + GDVIRTUAL_BIND(get_name); + GDVIRTUAL_BIND(get_features); - GDVIRTUAL_BIND(_free, "rid"); - GDVIRTUAL_BIND(_has, "rid"); - GDVIRTUAL_BIND(_load_support_data, "filename"); + GDVIRTUAL_BIND(free_rid, "rid"); + GDVIRTUAL_BIND(has, "rid"); + GDVIRTUAL_BIND(load_support_data, "filename"); - GDVIRTUAL_BIND(_get_support_data_filename); - GDVIRTUAL_BIND(_get_support_data_info); - GDVIRTUAL_BIND(_save_support_data, "filename"); + GDVIRTUAL_BIND(get_support_data_filename); + GDVIRTUAL_BIND(get_support_data_info); + GDVIRTUAL_BIND(save_support_data, "filename"); - GDVIRTUAL_BIND(_is_locale_right_to_left, "locale"); + GDVIRTUAL_BIND(is_locale_right_to_left, "locale"); - GDVIRTUAL_BIND(_name_to_tag, "name"); - GDVIRTUAL_BIND(_tag_to_name, "tag"); + GDVIRTUAL_BIND(name_to_tag, "name"); + GDVIRTUAL_BIND(tag_to_name, "tag"); /* Font interface */ - GDVIRTUAL_BIND(_create_font); + GDVIRTUAL_BIND(create_font); - GDVIRTUAL_BIND(_font_set_data, "font_rid", "data"); - GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size"); + GDVIRTUAL_BIND(font_set_data, "font_rid", "data"); + GDVIRTUAL_BIND(font_set_data_ptr, "font_rid", "data_ptr", "data_size"); - GDVIRTUAL_BIND(_font_set_style, "font_rid", "style"); - GDVIRTUAL_BIND(_font_get_style, "font_rid"); + GDVIRTUAL_BIND(font_set_style, "font_rid", "style"); + GDVIRTUAL_BIND(font_get_style, "font_rid"); - GDVIRTUAL_BIND(_font_set_name, "font_rid", "name"); - GDVIRTUAL_BIND(_font_get_name, "font_rid"); + GDVIRTUAL_BIND(font_set_name, "font_rid", "name"); + GDVIRTUAL_BIND(font_get_name, "font_rid"); - GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style"); - GDVIRTUAL_BIND(_font_get_style_name, "font_rid"); + GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style"); + GDVIRTUAL_BIND(font_get_style_name, "font_rid"); - GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased"); - GDVIRTUAL_BIND(_font_is_antialiased, "font_rid"); + GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased"); + GDVIRTUAL_BIND(font_is_antialiased, "font_rid"); - GDVIRTUAL_BIND(_font_set_multichannel_signed_distance_field, "font_rid", "msdf"); - GDVIRTUAL_BIND(_font_is_multichannel_signed_distance_field, "font_rid"); + GDVIRTUAL_BIND(font_set_multichannel_signed_distance_field, "font_rid", "msdf"); + GDVIRTUAL_BIND(font_is_multichannel_signed_distance_field, "font_rid"); - GDVIRTUAL_BIND(_font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range"); - GDVIRTUAL_BIND(_font_get_msdf_pixel_range, "font_rid"); + GDVIRTUAL_BIND(font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range"); + GDVIRTUAL_BIND(font_get_msdf_pixel_range, "font_rid"); - GDVIRTUAL_BIND(_font_set_msdf_size, "font_rid", "msdf_size"); - GDVIRTUAL_BIND(_font_get_msdf_size, "font_rid"); + GDVIRTUAL_BIND(font_set_msdf_size, "font_rid", "msdf_size"); + GDVIRTUAL_BIND(font_get_msdf_size, "font_rid"); - GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size"); - GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid"); + GDVIRTUAL_BIND(font_set_fixed_size, "font_rid", "fixed_size"); + GDVIRTUAL_BIND(font_get_fixed_size, "font_rid"); - GDVIRTUAL_BIND(_font_set_force_autohinter, "font_rid", "force_autohinter"); - GDVIRTUAL_BIND(_font_is_force_autohinter, "font_rid"); + GDVIRTUAL_BIND(font_set_force_autohinter, "font_rid", "force_autohinter"); + GDVIRTUAL_BIND(font_is_force_autohinter, "font_rid"); - GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting"); - GDVIRTUAL_BIND(_font_get_hinting, "font_rid"); + GDVIRTUAL_BIND(font_set_hinting, "font_rid", "hinting"); + GDVIRTUAL_BIND(font_get_hinting, "font_rid"); - GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning"); - GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid"); + GDVIRTUAL_BIND(font_set_subpixel_positioning, "font_rid", "subpixel_positioning"); + GDVIRTUAL_BIND(font_get_subpixel_positioning, "font_rid"); - GDVIRTUAL_BIND(_font_set_embolden, "font_rid", "strength"); - GDVIRTUAL_BIND(_font_get_embolden, "font_rid"); + GDVIRTUAL_BIND(font_set_embolden, "font_rid", "strength"); + GDVIRTUAL_BIND(font_get_embolden, "font_rid"); - GDVIRTUAL_BIND(_font_set_transform, "font_rid", "transform"); - GDVIRTUAL_BIND(_font_get_transform, "font_rid"); + GDVIRTUAL_BIND(font_set_transform, "font_rid", "transform"); + GDVIRTUAL_BIND(font_get_transform, "font_rid"); - GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates"); - GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid"); + GDVIRTUAL_BIND(font_set_variation_coordinates, "font_rid", "variation_coordinates"); + GDVIRTUAL_BIND(font_get_variation_coordinates, "font_rid"); - GDVIRTUAL_BIND(_font_set_oversampling, "font_rid", "oversampling"); - GDVIRTUAL_BIND(_font_get_oversampling, "font_rid"); + GDVIRTUAL_BIND(font_set_oversampling, "font_rid", "oversampling"); + GDVIRTUAL_BIND(font_get_oversampling, "font_rid"); - GDVIRTUAL_BIND(_font_get_size_cache_list, "font_rid"); - GDVIRTUAL_BIND(_font_clear_size_cache, "font_rid"); - GDVIRTUAL_BIND(_font_remove_size_cache, "font_rid", "size"); + GDVIRTUAL_BIND(font_get_size_cache_list, "font_rid"); + GDVIRTUAL_BIND(font_clear_size_cache, "font_rid"); + GDVIRTUAL_BIND(font_remove_size_cache, "font_rid", "size"); - GDVIRTUAL_BIND(_font_set_ascent, "font_rid", "size", "ascent"); - GDVIRTUAL_BIND(_font_get_ascent, "font_rid", "size"); + GDVIRTUAL_BIND(font_set_ascent, "font_rid", "size", "ascent"); + GDVIRTUAL_BIND(font_get_ascent, "font_rid", "size"); - GDVIRTUAL_BIND(_font_set_descent, "font_rid", "size", "descent"); - GDVIRTUAL_BIND(_font_get_descent, "font_rid", "size"); + GDVIRTUAL_BIND(font_set_descent, "font_rid", "size", "descent"); + GDVIRTUAL_BIND(font_get_descent, "font_rid", "size"); - GDVIRTUAL_BIND(_font_set_underline_position, "font_rid", "size", "underline_position"); - GDVIRTUAL_BIND(_font_get_underline_position, "font_rid", "size"); + GDVIRTUAL_BIND(font_set_underline_position, "font_rid", "size", "underline_position"); + GDVIRTUAL_BIND(font_get_underline_position, "font_rid", "size"); - GDVIRTUAL_BIND(_font_set_underline_thickness, "font_rid", "size", "underline_thickness"); - GDVIRTUAL_BIND(_font_get_underline_thickness, "font_rid", "size"); + GDVIRTUAL_BIND(font_set_underline_thickness, "font_rid", "size", "underline_thickness"); + GDVIRTUAL_BIND(font_get_underline_thickness, "font_rid", "size"); - GDVIRTUAL_BIND(_font_set_scale, "font_rid", "size", "scale"); - GDVIRTUAL_BIND(_font_get_scale, "font_rid", "size"); + GDVIRTUAL_BIND(font_set_scale, "font_rid", "size", "scale"); + GDVIRTUAL_BIND(font_get_scale, "font_rid", "size"); - GDVIRTUAL_BIND(_font_set_spacing, "font_rid", "size", "spacing", "value"); - GDVIRTUAL_BIND(_font_get_spacing, "font_rid", "size", "spacing"); + GDVIRTUAL_BIND(font_set_spacing, "font_rid", "size", "spacing", "value"); + GDVIRTUAL_BIND(font_get_spacing, "font_rid", "size", "spacing"); - GDVIRTUAL_BIND(_font_get_texture_count, "font_rid", "size"); - GDVIRTUAL_BIND(_font_clear_textures, "font_rid", "size"); - GDVIRTUAL_BIND(_font_remove_texture, "font_rid", "size", "texture_index"); + GDVIRTUAL_BIND(font_get_texture_count, "font_rid", "size"); + GDVIRTUAL_BIND(font_clear_textures, "font_rid", "size"); + GDVIRTUAL_BIND(font_remove_texture, "font_rid", "size", "texture_index"); - GDVIRTUAL_BIND(_font_set_texture_image, "font_rid", "size", "texture_index", "image"); - GDVIRTUAL_BIND(_font_get_texture_image, "font_rid", "size", "texture_index"); + GDVIRTUAL_BIND(font_set_texture_image, "font_rid", "size", "texture_index", "image"); + GDVIRTUAL_BIND(font_get_texture_image, "font_rid", "size", "texture_index"); - GDVIRTUAL_BIND(_font_set_texture_offsets, "font_rid", "size", "texture_index", "offset"); - GDVIRTUAL_BIND(_font_get_texture_offsets, "font_rid", "size", "texture_index"); + GDVIRTUAL_BIND(font_set_texture_offsets, "font_rid", "size", "texture_index", "offset"); + GDVIRTUAL_BIND(font_get_texture_offsets, "font_rid", "size", "texture_index"); - GDVIRTUAL_BIND(_font_get_glyph_list, "font_rid", "size"); - GDVIRTUAL_BIND(_font_clear_glyphs, "font_rid", "size"); - GDVIRTUAL_BIND(_font_remove_glyph, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_get_glyph_list, "font_rid", "size"); + GDVIRTUAL_BIND(font_clear_glyphs, "font_rid", "size"); + GDVIRTUAL_BIND(font_remove_glyph, "font_rid", "size", "glyph"); - GDVIRTUAL_BIND(_font_get_glyph_advance, "font_rid", "size", "glyph"); - GDVIRTUAL_BIND(_font_set_glyph_advance, "font_rid", "size", "glyph", "advance"); + GDVIRTUAL_BIND(font_get_glyph_advance, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_set_glyph_advance, "font_rid", "size", "glyph", "advance"); - GDVIRTUAL_BIND(_font_get_glyph_offset, "font_rid", "size", "glyph"); - GDVIRTUAL_BIND(_font_set_glyph_offset, "font_rid", "size", "glyph", "offset"); + GDVIRTUAL_BIND(font_get_glyph_offset, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_set_glyph_offset, "font_rid", "size", "glyph", "offset"); - GDVIRTUAL_BIND(_font_get_glyph_size, "font_rid", "size", "glyph"); - GDVIRTUAL_BIND(_font_set_glyph_size, "font_rid", "size", "glyph", "gl_size"); + GDVIRTUAL_BIND(font_get_glyph_size, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_set_glyph_size, "font_rid", "size", "glyph", "gl_size"); - GDVIRTUAL_BIND(_font_get_glyph_uv_rect, "font_rid", "size", "glyph"); - GDVIRTUAL_BIND(_font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect"); + GDVIRTUAL_BIND(font_get_glyph_uv_rect, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect"); - GDVIRTUAL_BIND(_font_get_glyph_texture_idx, "font_rid", "size", "glyph"); - GDVIRTUAL_BIND(_font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx"); + GDVIRTUAL_BIND(font_get_glyph_texture_idx, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx"); - GDVIRTUAL_BIND(_font_get_glyph_contours, "font_rid", "size", "index"); + GDVIRTUAL_BIND(font_get_glyph_contours, "font_rid", "size", "index"); - GDVIRTUAL_BIND(_font_get_kerning_list, "font_rid", "size"); - GDVIRTUAL_BIND(_font_clear_kerning_map, "font_rid", "size"); - GDVIRTUAL_BIND(_font_remove_kerning, "font_rid", "size", "glyph_pair"); + GDVIRTUAL_BIND(font_get_kerning_list, "font_rid", "size"); + GDVIRTUAL_BIND(font_clear_kerning_map, "font_rid", "size"); + GDVIRTUAL_BIND(font_remove_kerning, "font_rid", "size", "glyph_pair"); - GDVIRTUAL_BIND(_font_set_kerning, "font_rid", "size", "glyph_pair", "kerning"); - GDVIRTUAL_BIND(_font_get_kerning, "font_rid", "size", "glyph_pair"); + GDVIRTUAL_BIND(font_set_kerning, "font_rid", "size", "glyph_pair", "kerning"); + GDVIRTUAL_BIND(font_get_kerning, "font_rid", "size", "glyph_pair"); - GDVIRTUAL_BIND(_font_get_glyph_index, "font_rid", "size", "char", "variation_selector"); + GDVIRTUAL_BIND(font_get_glyph_index, "font_rid", "size", "char", "variation_selector"); - GDVIRTUAL_BIND(_font_has_char, "font_rid", "char"); - GDVIRTUAL_BIND(_font_get_supported_chars, "font_rid"); + GDVIRTUAL_BIND(font_has_char, "font_rid", "char"); + GDVIRTUAL_BIND(font_get_supported_chars, "font_rid"); - GDVIRTUAL_BIND(_font_render_range, "font_rid", "size", "start", "end"); - GDVIRTUAL_BIND(_font_render_glyph, "font_rid", "size", "index"); + GDVIRTUAL_BIND(font_render_range, "font_rid", "size", "start", "end"); + GDVIRTUAL_BIND(font_render_glyph, "font_rid", "size", "index"); - GDVIRTUAL_BIND(_font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color"); - GDVIRTUAL_BIND(_font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color"); + GDVIRTUAL_BIND(font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color"); + GDVIRTUAL_BIND(font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color"); - GDVIRTUAL_BIND(_font_is_language_supported, "font_rid", "language"); - GDVIRTUAL_BIND(_font_set_language_support_override, "font_rid", "language", "supported"); - GDVIRTUAL_BIND(_font_get_language_support_override, "font_rid", "language"); - GDVIRTUAL_BIND(_font_remove_language_support_override, "font_rid", "language"); - GDVIRTUAL_BIND(_font_get_language_support_overrides, "font_rid"); + GDVIRTUAL_BIND(font_is_language_supported, "font_rid", "language"); + GDVIRTUAL_BIND(font_set_language_support_override, "font_rid", "language", "supported"); + GDVIRTUAL_BIND(font_get_language_support_override, "font_rid", "language"); + GDVIRTUAL_BIND(font_remove_language_support_override, "font_rid", "language"); + GDVIRTUAL_BIND(font_get_language_support_overrides, "font_rid"); - GDVIRTUAL_BIND(_font_is_script_supported, "font_rid", "script"); - GDVIRTUAL_BIND(_font_set_script_support_override, "font_rid", "script", "supported"); - GDVIRTUAL_BIND(_font_get_script_support_override, "font_rid", "script"); - GDVIRTUAL_BIND(_font_remove_script_support_override, "font_rid", "script"); - GDVIRTUAL_BIND(_font_get_script_support_overrides, "font_rid"); + GDVIRTUAL_BIND(font_is_script_supported, "font_rid", "script"); + GDVIRTUAL_BIND(font_set_script_support_override, "font_rid", "script", "supported"); + GDVIRTUAL_BIND(font_get_script_support_override, "font_rid", "script"); + GDVIRTUAL_BIND(font_remove_script_support_override, "font_rid", "script"); + GDVIRTUAL_BIND(font_get_script_support_overrides, "font_rid"); - GDVIRTUAL_BIND(_font_set_opentype_feature_overrides, "font_rid", "overrides"); - GDVIRTUAL_BIND(_font_get_opentype_feature_overrides, "font_rid"); + GDVIRTUAL_BIND(font_set_opentype_feature_overrides, "font_rid", "overrides"); + GDVIRTUAL_BIND(font_get_opentype_feature_overrides, "font_rid"); - GDVIRTUAL_BIND(_font_supported_feature_list, "font_rid"); - GDVIRTUAL_BIND(_font_supported_variation_list, "font_rid"); + GDVIRTUAL_BIND(font_supported_feature_list, "font_rid"); + GDVIRTUAL_BIND(font_supported_variation_list, "font_rid"); - GDVIRTUAL_BIND(_font_get_global_oversampling); - GDVIRTUAL_BIND(_font_set_global_oversampling, "oversampling"); + GDVIRTUAL_BIND(font_get_global_oversampling); + GDVIRTUAL_BIND(font_set_global_oversampling, "oversampling"); - GDVIRTUAL_BIND(_get_hex_code_box_size, "size", "index"); - GDVIRTUAL_BIND(_draw_hex_code_box, "canvas", "size", "pos", "index", "color"); + GDVIRTUAL_BIND(get_hex_code_box_size, "size", "index"); + GDVIRTUAL_BIND(draw_hex_code_box, "canvas", "size", "pos", "index", "color"); /* Shaped text buffer interface */ - GDVIRTUAL_BIND(_create_shaped_text, "direction", "orientation"); + GDVIRTUAL_BIND(create_shaped_text, "direction", "orientation"); - GDVIRTUAL_BIND(_shaped_text_clear, "shaped"); + GDVIRTUAL_BIND(shaped_text_clear, "shaped"); - GDVIRTUAL_BIND(_shaped_text_set_direction, "shaped", "direction"); - GDVIRTUAL_BIND(_shaped_text_get_direction, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_inferred_direction, "shaped"); + GDVIRTUAL_BIND(shaped_text_set_direction, "shaped", "direction"); + GDVIRTUAL_BIND(shaped_text_get_direction, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_inferred_direction, "shaped"); - GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override"); + GDVIRTUAL_BIND(shaped_text_set_bidi_override, "shaped", "override"); - GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct"); - GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped"); + GDVIRTUAL_BIND(shaped_text_set_custom_punctuation, "shaped", "punct"); + GDVIRTUAL_BIND(shaped_text_get_custom_punctuation, "shaped"); - GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation"); - GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped"); + GDVIRTUAL_BIND(shaped_text_set_orientation, "shaped", "orientation"); + GDVIRTUAL_BIND(shaped_text_get_orientation, "shaped"); - GDVIRTUAL_BIND(_shaped_text_set_preserve_invalid, "shaped", "enabled"); - GDVIRTUAL_BIND(_shaped_text_get_preserve_invalid, "shaped"); + GDVIRTUAL_BIND(shaped_text_set_preserve_invalid, "shaped", "enabled"); + GDVIRTUAL_BIND(shaped_text_get_preserve_invalid, "shaped"); - GDVIRTUAL_BIND(_shaped_text_set_preserve_control, "shaped", "enabled"); - GDVIRTUAL_BIND(_shaped_text_get_preserve_control, "shaped"); + GDVIRTUAL_BIND(shaped_text_set_preserve_control, "shaped", "enabled"); + GDVIRTUAL_BIND(shaped_text_get_preserve_control, "shaped"); - GDVIRTUAL_BIND(_shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta"); - GDVIRTUAL_BIND(_shaped_text_add_object, "shaped", "key", "size", "inline_align", "length"); - GDVIRTUAL_BIND(_shaped_text_resize_object, "shaped", "key", "size", "inline_align"); + GDVIRTUAL_BIND(shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta"); + GDVIRTUAL_BIND(shaped_text_add_object, "shaped", "key", "size", "inline_align", "length"); + GDVIRTUAL_BIND(shaped_text_resize_object, "shaped", "key", "size", "inline_align"); - GDVIRTUAL_BIND(_shaped_get_span_count, "shaped"); - GDVIRTUAL_BIND(_shaped_get_span_meta, "shaped", "index"); - GDVIRTUAL_BIND(_shaped_set_span_update_font, "shaped", "index", "fonts", "size", "opentype_features"); + GDVIRTUAL_BIND(shaped_get_span_count, "shaped"); + GDVIRTUAL_BIND(shaped_get_span_meta, "shaped", "index"); + GDVIRTUAL_BIND(shaped_set_span_update_font, "shaped", "index", "fonts", "size", "opentype_features"); - GDVIRTUAL_BIND(_shaped_text_substr, "shaped", "start", "length"); - GDVIRTUAL_BIND(_shaped_text_get_parent, "shaped"); + GDVIRTUAL_BIND(shaped_text_substr, "shaped", "start", "length"); + GDVIRTUAL_BIND(shaped_text_get_parent, "shaped"); - GDVIRTUAL_BIND(_shaped_text_fit_to_width, "shaped", "width", "jst_flags"); - GDVIRTUAL_BIND(_shaped_text_tab_align, "shaped", "tab_stops"); + GDVIRTUAL_BIND(shaped_text_fit_to_width, "shaped", "width", "jst_flags"); + GDVIRTUAL_BIND(shaped_text_tab_align, "shaped", "tab_stops"); - GDVIRTUAL_BIND(_shaped_text_shape, "shaped"); - GDVIRTUAL_BIND(_shaped_text_update_breaks, "shaped"); - GDVIRTUAL_BIND(_shaped_text_update_justification_ops, "shaped"); + GDVIRTUAL_BIND(shaped_text_shape, "shaped"); + GDVIRTUAL_BIND(shaped_text_update_breaks, "shaped"); + GDVIRTUAL_BIND(shaped_text_update_justification_ops, "shaped"); - GDVIRTUAL_BIND(_shaped_text_is_ready, "shaped"); + GDVIRTUAL_BIND(shaped_text_is_ready, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped"); - GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_glyph_count, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_glyphs, "shaped"); + GDVIRTUAL_BIND(shaped_text_sort_logical, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_glyph_count, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_range, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_range, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags"); - GDVIRTUAL_BIND(_shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags"); - GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags"); + GDVIRTUAL_BIND(shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags"); + GDVIRTUAL_BIND(shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags"); + GDVIRTUAL_BIND(shaped_text_get_word_breaks, "shaped", "grapheme_flags"); - GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyph_count, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_trim_pos, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_ellipsis_pos, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_ellipsis_glyph_count, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_ellipsis_glyphs, "shaped"); - GDVIRTUAL_BIND(_shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags"); + GDVIRTUAL_BIND(shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags"); - GDVIRTUAL_BIND(_shaped_text_get_objects, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_object_rect, "shaped", "key"); + GDVIRTUAL_BIND(shaped_text_get_objects, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_object_rect, "shaped", "key"); - GDVIRTUAL_BIND(_shaped_text_get_size, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_ascent, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_descent, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_width, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_underline_position, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_underline_thickness, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_size, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_ascent, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_descent, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_width, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_underline_position, "shaped"); + GDVIRTUAL_BIND(shaped_text_get_underline_thickness, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_dominant_direction_in_range, "shaped", "start", "end"); + GDVIRTUAL_BIND(shaped_text_get_dominant_direction_in_range, "shaped", "start", "end"); - GDVIRTUAL_BIND(_shaped_text_get_carets, "shaped", "position", "caret"); - GDVIRTUAL_BIND(_shaped_text_get_selection, "shaped", "start", "end"); + GDVIRTUAL_BIND(shaped_text_get_carets, "shaped", "position", "caret"); + GDVIRTUAL_BIND(shaped_text_get_selection, "shaped", "start", "end"); - GDVIRTUAL_BIND(_shaped_text_hit_test_grapheme, "shaped", "coord"); - GDVIRTUAL_BIND(_shaped_text_hit_test_position, "shaped", "coord"); + GDVIRTUAL_BIND(shaped_text_hit_test_grapheme, "shaped", "coord"); + GDVIRTUAL_BIND(shaped_text_hit_test_position, "shaped", "coord"); - GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color"); - GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color"); + GDVIRTUAL_BIND(shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color"); + GDVIRTUAL_BIND(shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color"); - GDVIRTUAL_BIND(_shaped_text_get_grapheme_bounds, "shaped", "pos"); - GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos"); - GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos"); + GDVIRTUAL_BIND(shaped_text_get_grapheme_bounds, "shaped", "pos"); + GDVIRTUAL_BIND(shaped_text_next_grapheme_pos, "shaped", "pos"); + GDVIRTUAL_BIND(shaped_text_prev_grapheme_pos, "shaped", "pos"); - GDVIRTUAL_BIND(_format_number, "string", "language"); - GDVIRTUAL_BIND(_parse_number, "string", "language"); - GDVIRTUAL_BIND(_percent_sign, "language"); + GDVIRTUAL_BIND(format_number, "string", "language"); + GDVIRTUAL_BIND(parse_number, "string", "language"); + GDVIRTUAL_BIND(percent_sign, "language"); - GDVIRTUAL_BIND(_string_to_upper, "string", "language"); - GDVIRTUAL_BIND(_string_to_lower, "string", "language"); + GDVIRTUAL_BIND(strip_diacritics, "string"); + + GDVIRTUAL_BIND(string_to_upper, "string", "language"); + GDVIRTUAL_BIND(string_to_lower, "string", "language"); } bool TextServerExtension::has_feature(Feature p_feature) const { bool ret; - if (GDVIRTUAL_CALL(_has_feature, p_feature, ret)) { + if (GDVIRTUAL_CALL(has_feature, p_feature, ret)) { return ret; } return false; @@ -299,27 +301,27 @@ bool TextServerExtension::has_feature(Feature p_feature) const { String TextServerExtension::get_name() const { String ret; - if (GDVIRTUAL_CALL(_get_name, ret)) { + if (GDVIRTUAL_CALL(get_name, ret)) { return ret; } return "Unknown"; } -uint32_t TextServerExtension::get_features() const { - uint32_t ret; - if (GDVIRTUAL_CALL(_get_features, ret)) { +int64_t TextServerExtension::get_features() const { + int64_t ret; + if (GDVIRTUAL_CALL(get_features, ret)) { return ret; } return 0; } -void TextServerExtension::free(RID p_rid) { - GDVIRTUAL_CALL(_free, p_rid); +void TextServerExtension::free_rid(const RID &p_rid) { + GDVIRTUAL_CALL(free_rid, p_rid); } -bool TextServerExtension::has(RID p_rid) { +bool TextServerExtension::has(const RID &p_rid) { bool ret; - if (GDVIRTUAL_CALL(_has, p_rid, ret)) { + if (GDVIRTUAL_CALL(has, p_rid, ret)) { return ret; } return false; @@ -327,7 +329,7 @@ bool TextServerExtension::has(RID p_rid) { bool TextServerExtension::load_support_data(const String &p_filename) { bool ret; - if (GDVIRTUAL_CALL(_load_support_data, p_filename, ret)) { + if (GDVIRTUAL_CALL(load_support_data, p_filename, ret)) { return ret; } return false; @@ -335,7 +337,7 @@ bool TextServerExtension::load_support_data(const String &p_filename) { String TextServerExtension::get_support_data_filename() const { String ret; - if (GDVIRTUAL_CALL(_get_support_data_filename, ret)) { + if (GDVIRTUAL_CALL(get_support_data_filename, ret)) { return ret; } return String(); @@ -343,7 +345,7 @@ String TextServerExtension::get_support_data_filename() const { String TextServerExtension::get_support_data_info() const { String ret; - if (GDVIRTUAL_CALL(_get_support_data_info, ret)) { + if (GDVIRTUAL_CALL(get_support_data_info, ret)) { return ret; } return String(); @@ -351,7 +353,7 @@ String TextServerExtension::get_support_data_info() const { bool TextServerExtension::save_support_data(const String &p_filename) const { bool ret; - if (GDVIRTUAL_CALL(_save_support_data, p_filename, ret)) { + if (GDVIRTUAL_CALL(save_support_data, p_filename, ret)) { return ret; } return false; @@ -359,23 +361,23 @@ bool TextServerExtension::save_support_data(const String &p_filename) const { bool TextServerExtension::is_locale_right_to_left(const String &p_locale) const { bool ret; - if (GDVIRTUAL_CALL(_is_locale_right_to_left, p_locale, ret)) { + if (GDVIRTUAL_CALL(is_locale_right_to_left, p_locale, ret)) { return ret; } return false; } -int32_t TextServerExtension::name_to_tag(const String &p_name) const { - int32_t ret; - if (GDVIRTUAL_CALL(_name_to_tag, p_name, ret)) { +int64_t TextServerExtension::name_to_tag(const String &p_name) const { + int64_t ret; + if (GDVIRTUAL_CALL(name_to_tag, p_name, ret)) { return ret; } return 0; } -String TextServerExtension::tag_to_name(int32_t p_tag) const { +String TextServerExtension::tag_to_name(int64_t p_tag) const { String ret; - if (GDVIRTUAL_CALL(_tag_to_name, p_tag, ret)) { + if (GDVIRTUAL_CALL(tag_to_name, p_tag, ret)) { return ret; } return ""; @@ -387,594 +389,594 @@ String TextServerExtension::tag_to_name(int32_t p_tag) const { RID TextServerExtension::create_font() { RID ret; - if (GDVIRTUAL_CALL(_create_font, ret)) { + if (GDVIRTUAL_CALL(create_font, ret)) { return ret; } return RID(); } -void TextServerExtension::font_set_data(RID p_font_rid, const PackedByteArray &p_data) { - GDVIRTUAL_CALL(_font_set_data, p_font_rid, p_data); +void TextServerExtension::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) { + GDVIRTUAL_CALL(font_set_data, p_font_rid, p_data); } -void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) { - GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size); +void TextServerExtension::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) { + GDVIRTUAL_CALL(font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size); } -void TextServerExtension::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) { - GDVIRTUAL_CALL(_font_set_style, p_font_rid, p_style); +void TextServerExtension::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) { + GDVIRTUAL_CALL(font_set_style, p_font_rid, p_style); } -uint32_t /*FontStyle*/ TextServerExtension::font_get_style(RID p_font_rid) const { - uint32_t ret; - if (GDVIRTUAL_CALL(_font_get_style, p_font_rid, ret)) { +int64_t /*FontStyle*/ TextServerExtension::font_get_style(const RID &p_font_rid) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_style, p_font_rid, ret)) { return ret; } return 0; } -void TextServerExtension::font_set_style_name(RID p_font_rid, const String &p_name) { - GDVIRTUAL_CALL(_font_set_style_name, p_font_rid, p_name); +void TextServerExtension::font_set_style_name(const RID &p_font_rid, const String &p_name) { + GDVIRTUAL_CALL(font_set_style_name, p_font_rid, p_name); } -String TextServerExtension::font_get_style_name(RID p_font_rid) const { +String TextServerExtension::font_get_style_name(const RID &p_font_rid) const { String ret; - if (GDVIRTUAL_CALL(_font_get_style_name, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_style_name, p_font_rid, ret)) { return ret; } return String(); } -void TextServerExtension::font_set_name(RID p_font_rid, const String &p_name) { - GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name); +void TextServerExtension::font_set_name(const RID &p_font_rid, const String &p_name) { + GDVIRTUAL_CALL(font_set_name, p_font_rid, p_name); } -String TextServerExtension::font_get_name(RID p_font_rid) const { +String TextServerExtension::font_get_name(const RID &p_font_rid) const { String ret; - if (GDVIRTUAL_CALL(_font_get_name, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_name, p_font_rid, ret)) { return ret; } return String(); } -void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) { - GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased); +void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { + GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased); } -bool TextServerExtension::font_is_antialiased(RID p_font_rid) const { +bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const { bool ret; - if (GDVIRTUAL_CALL(_font_is_antialiased, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) { return ret; } return false; } -void TextServerExtension::font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) { - GDVIRTUAL_CALL(_font_set_multichannel_signed_distance_field, p_font_rid, p_msdf); +void TextServerExtension::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) { + GDVIRTUAL_CALL(font_set_multichannel_signed_distance_field, p_font_rid, p_msdf); } -bool TextServerExtension::font_is_multichannel_signed_distance_field(RID p_font_rid) const { +bool TextServerExtension::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const { bool ret; - if (GDVIRTUAL_CALL(_font_is_multichannel_signed_distance_field, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_is_multichannel_signed_distance_field, p_font_rid, ret)) { return ret; } return false; } -void TextServerExtension::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) { - GDVIRTUAL_CALL(_font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range); +void TextServerExtension::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) { + GDVIRTUAL_CALL(font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range); } -int TextServerExtension::font_get_msdf_pixel_range(RID p_font_rid) const { - int ret; - if (GDVIRTUAL_CALL(_font_get_msdf_pixel_range, p_font_rid, ret)) { +int64_t TextServerExtension::font_get_msdf_pixel_range(const RID &p_font_rid) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_msdf_pixel_range, p_font_rid, ret)) { return ret; } return 0; } -void TextServerExtension::font_set_msdf_size(RID p_font_rid, int p_msdf_size) { - GDVIRTUAL_CALL(_font_set_msdf_size, p_font_rid, p_msdf_size); +void TextServerExtension::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) { + GDVIRTUAL_CALL(font_set_msdf_size, p_font_rid, p_msdf_size); } -int TextServerExtension::font_get_msdf_size(RID p_font_rid) const { - int ret; - if (GDVIRTUAL_CALL(_font_get_msdf_size, p_font_rid, ret)) { +int64_t TextServerExtension::font_get_msdf_size(const RID &p_font_rid) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_msdf_size, p_font_rid, ret)) { return ret; } return 0; } -void TextServerExtension::font_set_fixed_size(RID p_font_rid, int p_fixed_size) { - GDVIRTUAL_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size); +void TextServerExtension::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) { + GDVIRTUAL_CALL(font_set_fixed_size, p_font_rid, p_fixed_size); } -int TextServerExtension::font_get_fixed_size(RID p_font_rid) const { - int ret; - if (GDVIRTUAL_CALL(_font_get_fixed_size, p_font_rid, ret)) { +int64_t TextServerExtension::font_get_fixed_size(const RID &p_font_rid) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_fixed_size, p_font_rid, ret)) { return ret; } return 0; } -void TextServerExtension::font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) { - GDVIRTUAL_CALL(_font_set_force_autohinter, p_font_rid, p_force_autohinter); +void TextServerExtension::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) { + GDVIRTUAL_CALL(font_set_force_autohinter, p_font_rid, p_force_autohinter); } -bool TextServerExtension::font_is_force_autohinter(RID p_font_rid) const { +bool TextServerExtension::font_is_force_autohinter(const RID &p_font_rid) const { bool ret; - if (GDVIRTUAL_CALL(_font_is_force_autohinter, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_is_force_autohinter, p_font_rid, ret)) { return ret; } return false; } -void TextServerExtension::font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) { - GDVIRTUAL_CALL(_font_set_hinting, p_font_rid, p_hinting); +void TextServerExtension::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) { + GDVIRTUAL_CALL(font_set_hinting, p_font_rid, p_hinting); } -TextServer::Hinting TextServerExtension::font_get_hinting(RID p_font_rid) const { +TextServer::Hinting TextServerExtension::font_get_hinting(const RID &p_font_rid) const { TextServer::Hinting ret; - if (GDVIRTUAL_CALL(_font_get_hinting, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_hinting, p_font_rid, ret)) { return (TextServer::Hinting)ret; } return TextServer::Hinting::HINTING_NONE; } -void TextServerExtension::font_set_subpixel_positioning(RID p_font_rid, TextServer::SubpixelPositioning p_subpixel) { - GDVIRTUAL_CALL(_font_set_subpixel_positioning, p_font_rid, p_subpixel); +void TextServerExtension::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) { + GDVIRTUAL_CALL(font_set_subpixel_positioning, p_font_rid, p_subpixel); } -TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioning(RID p_font_rid) const { +TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioning(const RID &p_font_rid) const { TextServer::SubpixelPositioning ret; - if (GDVIRTUAL_CALL(_font_get_subpixel_positioning, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_subpixel_positioning, p_font_rid, ret)) { return (TextServer::SubpixelPositioning)ret; } return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED; } -void TextServerExtension::font_set_embolden(RID p_font_rid, float p_strength) { - GDVIRTUAL_CALL(_font_set_embolden, p_font_rid, p_strength); +void TextServerExtension::font_set_embolden(const RID &p_font_rid, double p_strength) { + GDVIRTUAL_CALL(font_set_embolden, p_font_rid, p_strength); } -float TextServerExtension::font_get_embolden(RID p_font_rid) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_embolden, p_font_rid, ret)) { +double TextServerExtension::font_get_embolden(const RID &p_font_rid) const { + double ret; + if (GDVIRTUAL_CALL(font_get_embolden, p_font_rid, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_transform(RID p_font_rid, Transform2D p_transform) { - GDVIRTUAL_CALL(_font_set_transform, p_font_rid, p_transform); +void TextServerExtension::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) { + GDVIRTUAL_CALL(font_set_transform, p_font_rid, p_transform); } -Transform2D TextServerExtension::font_get_transform(RID p_font_rid) const { +Transform2D TextServerExtension::font_get_transform(const RID &p_font_rid) const { Transform2D ret; - if (GDVIRTUAL_CALL(_font_get_transform, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_transform, p_font_rid, ret)) { return ret; } return Transform2D(); } -void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { - GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates); +void TextServerExtension::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) { + GDVIRTUAL_CALL(font_set_variation_coordinates, p_font_rid, p_variation_coordinates); } -Dictionary TextServerExtension::font_get_variation_coordinates(RID p_font_rid) const { +Dictionary TextServerExtension::font_get_variation_coordinates(const RID &p_font_rid) const { Dictionary ret; - if (GDVIRTUAL_CALL(_font_get_variation_coordinates, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_variation_coordinates, p_font_rid, ret)) { return ret; } return Dictionary(); } -void TextServerExtension::font_set_oversampling(RID p_font_rid, float p_oversampling) { - GDVIRTUAL_CALL(_font_set_oversampling, p_font_rid, p_oversampling); +void TextServerExtension::font_set_oversampling(const RID &p_font_rid, double p_oversampling) { + GDVIRTUAL_CALL(font_set_oversampling, p_font_rid, p_oversampling); } -float TextServerExtension::font_get_oversampling(RID p_font_rid) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_oversampling, p_font_rid, ret)) { +double TextServerExtension::font_get_oversampling(const RID &p_font_rid) const { + double ret; + if (GDVIRTUAL_CALL(font_get_oversampling, p_font_rid, ret)) { return ret; } - return 0.f; + return 0.0; } -Array TextServerExtension::font_get_size_cache_list(RID p_font_rid) const { +Array TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const { Array ret; - if (GDVIRTUAL_CALL(_font_get_size_cache_list, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_size_cache_list, p_font_rid, ret)) { return ret; } return Array(); } -void TextServerExtension::font_clear_size_cache(RID p_font_rid) { - GDVIRTUAL_CALL(_font_clear_size_cache, p_font_rid); +void TextServerExtension::font_clear_size_cache(const RID &p_font_rid) { + GDVIRTUAL_CALL(font_clear_size_cache, p_font_rid); } -void TextServerExtension::font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) { - GDVIRTUAL_CALL(_font_remove_size_cache, p_font_rid, p_size); +void TextServerExtension::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) { + GDVIRTUAL_CALL(font_remove_size_cache, p_font_rid, p_size); } -void TextServerExtension::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) { - GDVIRTUAL_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent); +void TextServerExtension::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) { + GDVIRTUAL_CALL(font_set_ascent, p_font_rid, p_size, p_ascent); } -float TextServerExtension::font_get_ascent(RID p_font_rid, int p_size) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_ascent, p_font_rid, p_size, ret)) { +double TextServerExtension::font_get_ascent(const RID &p_font_rid, int64_t p_size) const { + double ret; + if (GDVIRTUAL_CALL(font_get_ascent, p_font_rid, p_size, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_descent(RID p_font_rid, int p_size, float p_descent) { - GDVIRTUAL_CALL(_font_set_descent, p_font_rid, p_size, p_descent); +void TextServerExtension::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) { + GDVIRTUAL_CALL(font_set_descent, p_font_rid, p_size, p_descent); } -float TextServerExtension::font_get_descent(RID p_font_rid, int p_size) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_descent, p_font_rid, p_size, ret)) { +double TextServerExtension::font_get_descent(const RID &p_font_rid, int64_t p_size) const { + double ret; + if (GDVIRTUAL_CALL(font_get_descent, p_font_rid, p_size, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) { - GDVIRTUAL_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position); +void TextServerExtension::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) { + GDVIRTUAL_CALL(font_set_underline_position, p_font_rid, p_size, p_underline_position); } -float TextServerExtension::font_get_underline_position(RID p_font_rid, int p_size) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_underline_position, p_font_rid, p_size, ret)) { +double TextServerExtension::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const { + double ret; + if (GDVIRTUAL_CALL(font_get_underline_position, p_font_rid, p_size, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) { - GDVIRTUAL_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness); +void TextServerExtension::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) { + GDVIRTUAL_CALL(font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness); } -float TextServerExtension::font_get_underline_thickness(RID p_font_rid, int p_size) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret)) { +double TextServerExtension::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const { + double ret; + if (GDVIRTUAL_CALL(font_get_underline_thickness, p_font_rid, p_size, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_scale(RID p_font_rid, int p_size, float p_scale) { - GDVIRTUAL_CALL(_font_set_scale, p_font_rid, p_size, p_scale); +void TextServerExtension::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) { + GDVIRTUAL_CALL(font_set_scale, p_font_rid, p_size, p_scale); } -float TextServerExtension::font_get_scale(RID p_font_rid, int p_size) const { - float ret; - if (GDVIRTUAL_CALL(_font_get_scale, p_font_rid, p_size, ret)) { +double TextServerExtension::font_get_scale(const RID &p_font_rid, int64_t p_size) const { + double ret; + if (GDVIRTUAL_CALL(font_get_scale, p_font_rid, p_size, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing, int p_value) { - GDVIRTUAL_CALL(_font_set_spacing, p_font_rid, p_size, p_spacing, p_value); +void TextServerExtension::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) { + GDVIRTUAL_CALL(font_set_spacing, p_font_rid, p_size, p_spacing, p_value); } -int TextServerExtension::font_get_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing) const { - int ret; - if (GDVIRTUAL_CALL(_font_get_spacing, p_font_rid, p_size, p_spacing, ret)) { +int64_t TextServerExtension::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_spacing, p_font_rid, p_size, p_spacing, ret)) { return ret; } return 0; } -int TextServerExtension::font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const { - int ret; - if (GDVIRTUAL_CALL(_font_get_texture_count, p_font_rid, p_size, ret)) { +int64_t TextServerExtension::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_texture_count, p_font_rid, p_size, ret)) { return ret; } return 0; } -void TextServerExtension::font_clear_textures(RID p_font_rid, const Vector2i &p_size) { - GDVIRTUAL_CALL(_font_clear_textures, p_font_rid, p_size); +void TextServerExtension::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) { + GDVIRTUAL_CALL(font_clear_textures, p_font_rid, p_size); } -void TextServerExtension::font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) { - GDVIRTUAL_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index); +void TextServerExtension::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) { + GDVIRTUAL_CALL(font_remove_texture, p_font_rid, p_size, p_texture_index); } -void TextServerExtension::font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) { - GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image); +void TextServerExtension::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) { + GDVIRTUAL_CALL(font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image); } -Ref<Image> TextServerExtension::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const { +Ref<Image> TextServerExtension::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const { Ref<Image> ret; - if (GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) { + if (GDVIRTUAL_CALL(font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) { return ret; } return Ref<Image>(); } -void TextServerExtension::font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) { - GDVIRTUAL_CALL(_font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset); +void TextServerExtension::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) { + GDVIRTUAL_CALL(font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset); } -PackedInt32Array TextServerExtension::font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const { +PackedInt32Array TextServerExtension::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const { PackedInt32Array ret; - if (GDVIRTUAL_CALL(_font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) { + if (GDVIRTUAL_CALL(font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) { return ret; } return PackedInt32Array(); } -Array TextServerExtension::font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const { +Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const { Array ret; - if (GDVIRTUAL_CALL(_font_get_glyph_list, p_font_rid, p_size, ret)) { + if (GDVIRTUAL_CALL(font_get_glyph_list, p_font_rid, p_size, ret)) { return ret; } return Array(); } -void TextServerExtension::font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) { - GDVIRTUAL_CALL(_font_clear_glyphs, p_font_rid, p_size); +void TextServerExtension::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) { + GDVIRTUAL_CALL(font_clear_glyphs, p_font_rid, p_size); } -void TextServerExtension::font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) { - GDVIRTUAL_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph); +void TextServerExtension::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) { + GDVIRTUAL_CALL(font_remove_glyph, p_font_rid, p_size, p_glyph); } -Vector2 TextServerExtension::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const { +Vector2 TextServerExtension::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const { Vector2 ret; - if (GDVIRTUAL_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) { + if (GDVIRTUAL_CALL(font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) { return ret; } return Vector2(); } -void TextServerExtension::font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) { - GDVIRTUAL_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance); +void TextServerExtension::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) { + GDVIRTUAL_CALL(font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance); } -Vector2 TextServerExtension::font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { +Vector2 TextServerExtension::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { Vector2 ret; - if (GDVIRTUAL_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) { + if (GDVIRTUAL_CALL(font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) { return ret; } return Vector2(); } -void TextServerExtension::font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) { - GDVIRTUAL_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset); +void TextServerExtension::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) { + GDVIRTUAL_CALL(font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset); } -Vector2 TextServerExtension::font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { +Vector2 TextServerExtension::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { Vector2 ret; - if (GDVIRTUAL_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) { + if (GDVIRTUAL_CALL(font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) { return ret; } return Vector2(); } -void TextServerExtension::font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) { - GDVIRTUAL_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size); +void TextServerExtension::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) { + GDVIRTUAL_CALL(font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size); } -Rect2 TextServerExtension::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { +Rect2 TextServerExtension::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { Rect2 ret; - if (GDVIRTUAL_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) { + if (GDVIRTUAL_CALL(font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) { return ret; } return Rect2(); } -void TextServerExtension::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) { - GDVIRTUAL_CALL(_font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect); +void TextServerExtension::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) { + GDVIRTUAL_CALL(font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect); } -int TextServerExtension::font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { - int ret; - if (GDVIRTUAL_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) { +int64_t TextServerExtension::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) { return ret; } return 0; } -void TextServerExtension::font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) { - GDVIRTUAL_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx); +void TextServerExtension::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) { + GDVIRTUAL_CALL(font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx); } -Dictionary TextServerExtension::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const { +Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const { Dictionary ret; - if (GDVIRTUAL_CALL(_font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) { + if (GDVIRTUAL_CALL(font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) { return ret; } return Dictionary(); } -Array TextServerExtension::font_get_kerning_list(RID p_font_rid, int p_size) const { +Array TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const { Array ret; - if (GDVIRTUAL_CALL(_font_get_kerning_list, p_font_rid, p_size, ret)) { + if (GDVIRTUAL_CALL(font_get_kerning_list, p_font_rid, p_size, ret)) { return ret; } return Array(); } -void TextServerExtension::font_clear_kerning_map(RID p_font_rid, int p_size) { - GDVIRTUAL_CALL(_font_clear_kerning_map, p_font_rid, p_size); +void TextServerExtension::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) { + GDVIRTUAL_CALL(font_clear_kerning_map, p_font_rid, p_size); } -void TextServerExtension::font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) { - GDVIRTUAL_CALL(_font_remove_kerning, p_font_rid, p_size, p_glyph_pair); +void TextServerExtension::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) { + GDVIRTUAL_CALL(font_remove_kerning, p_font_rid, p_size, p_glyph_pair); } -void TextServerExtension::font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) { - GDVIRTUAL_CALL(_font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning); +void TextServerExtension::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) { + GDVIRTUAL_CALL(font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning); } -Vector2 TextServerExtension::font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const { +Vector2 TextServerExtension::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const { Vector2 ret; - if (GDVIRTUAL_CALL(_font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) { + if (GDVIRTUAL_CALL(font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) { return ret; } return Vector2(); } -int32_t TextServerExtension::font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const { - int32_t ret; - if (GDVIRTUAL_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) { +int64_t TextServerExtension::font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const { + int64_t ret; + if (GDVIRTUAL_CALL(font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) { return ret; } return 0; } -bool TextServerExtension::font_has_char(RID p_font_rid, char32_t p_char) const { +bool TextServerExtension::font_has_char(const RID &p_font_rid, int64_t p_char) const { bool ret; - if (GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret)) { + if (GDVIRTUAL_CALL(font_has_char, p_font_rid, p_char, ret)) { return ret; } return false; } -String TextServerExtension::font_get_supported_chars(RID p_font_rid) const { +String TextServerExtension::font_get_supported_chars(const RID &p_font_rid) const { String ret; - if (GDVIRTUAL_CALL(_font_get_supported_chars, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_supported_chars, p_font_rid, ret)) { return ret; } return String(); } -void TextServerExtension::font_render_range(RID p_font_rid, const Vector2i &p_size, char32_t p_start, char32_t p_end) { - GDVIRTUAL_CALL(_font_render_range, p_font_rid, p_size, p_start, p_end); +void TextServerExtension::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) { + GDVIRTUAL_CALL(font_render_range, p_font_rid, p_size, p_start, p_end); } -void TextServerExtension::font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) { - GDVIRTUAL_CALL(_font_render_glyph, p_font_rid, p_size, p_index); +void TextServerExtension::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) { + GDVIRTUAL_CALL(font_render_glyph, p_font_rid, p_size, p_index); } -void TextServerExtension::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const { - GDVIRTUAL_CALL(_font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color); +void TextServerExtension::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { + GDVIRTUAL_CALL(font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color); } -void TextServerExtension::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const { - GDVIRTUAL_CALL(_font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color); +void TextServerExtension::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { + GDVIRTUAL_CALL(font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color); } -bool TextServerExtension::font_is_language_supported(RID p_font_rid, const String &p_language) const { +bool TextServerExtension::font_is_language_supported(const RID &p_font_rid, const String &p_language) const { bool ret; - if (GDVIRTUAL_CALL(_font_is_language_supported, p_font_rid, p_language, ret)) { + if (GDVIRTUAL_CALL(font_is_language_supported, p_font_rid, p_language, ret)) { return ret; } return false; } -void TextServerExtension::font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) { - GDVIRTUAL_CALL(_font_set_language_support_override, p_font_rid, p_language, p_supported); +void TextServerExtension::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) { + GDVIRTUAL_CALL(font_set_language_support_override, p_font_rid, p_language, p_supported); } -bool TextServerExtension::font_get_language_support_override(RID p_font_rid, const String &p_language) { +bool TextServerExtension::font_get_language_support_override(const RID &p_font_rid, const String &p_language) { bool ret; - if (GDVIRTUAL_CALL(_font_get_language_support_override, p_font_rid, p_language, ret)) { + if (GDVIRTUAL_CALL(font_get_language_support_override, p_font_rid, p_language, ret)) { return ret; } return false; } -void TextServerExtension::font_remove_language_support_override(RID p_font_rid, const String &p_language) { - GDVIRTUAL_CALL(_font_remove_language_support_override, p_font_rid, p_language); +void TextServerExtension::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) { + GDVIRTUAL_CALL(font_remove_language_support_override, p_font_rid, p_language); } -Vector<String> TextServerExtension::font_get_language_support_overrides(RID p_font_rid) { - Vector<String> ret; - if (GDVIRTUAL_CALL(_font_get_language_support_overrides, p_font_rid, ret)) { +PackedStringArray TextServerExtension::font_get_language_support_overrides(const RID &p_font_rid) { + PackedStringArray ret; + if (GDVIRTUAL_CALL(font_get_language_support_overrides, p_font_rid, ret)) { return ret; } - return Vector<String>(); + return PackedStringArray(); } -bool TextServerExtension::font_is_script_supported(RID p_font_rid, const String &p_script) const { +bool TextServerExtension::font_is_script_supported(const RID &p_font_rid, const String &p_script) const { bool ret; - if (GDVIRTUAL_CALL(_font_is_script_supported, p_font_rid, p_script, ret)) { + if (GDVIRTUAL_CALL(font_is_script_supported, p_font_rid, p_script, ret)) { return ret; } return false; } -void TextServerExtension::font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) { - GDVIRTUAL_CALL(_font_set_script_support_override, p_font_rid, p_script, p_supported); +void TextServerExtension::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) { + GDVIRTUAL_CALL(font_set_script_support_override, p_font_rid, p_script, p_supported); } -bool TextServerExtension::font_get_script_support_override(RID p_font_rid, const String &p_script) { +bool TextServerExtension::font_get_script_support_override(const RID &p_font_rid, const String &p_script) { bool ret; - if (GDVIRTUAL_CALL(_font_get_script_support_override, p_font_rid, p_script, ret)) { + if (GDVIRTUAL_CALL(font_get_script_support_override, p_font_rid, p_script, ret)) { return ret; } return false; } -void TextServerExtension::font_remove_script_support_override(RID p_font_rid, const String &p_script) { - GDVIRTUAL_CALL(_font_remove_script_support_override, p_font_rid, p_script); +void TextServerExtension::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) { + GDVIRTUAL_CALL(font_remove_script_support_override, p_font_rid, p_script); } -Vector<String> TextServerExtension::font_get_script_support_overrides(RID p_font_rid) { - Vector<String> ret; - if (GDVIRTUAL_CALL(_font_get_script_support_overrides, p_font_rid, ret)) { +PackedStringArray TextServerExtension::font_get_script_support_overrides(const RID &p_font_rid) { + PackedStringArray ret; + if (GDVIRTUAL_CALL(font_get_script_support_overrides, p_font_rid, ret)) { return ret; } - return Vector<String>(); + return PackedStringArray(); } -void TextServerExtension::font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) { - GDVIRTUAL_CALL(_font_set_opentype_feature_overrides, p_font_rid, p_overrides); +void TextServerExtension::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) { + GDVIRTUAL_CALL(font_set_opentype_feature_overrides, p_font_rid, p_overrides); } -Dictionary TextServerExtension::font_get_opentype_feature_overrides(RID p_font_rid) const { +Dictionary TextServerExtension::font_get_opentype_feature_overrides(const RID &p_font_rid) const { Dictionary ret; - if (GDVIRTUAL_CALL(_font_get_opentype_feature_overrides, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_get_opentype_feature_overrides, p_font_rid, ret)) { return ret; } return Dictionary(); } -Dictionary TextServerExtension::font_supported_feature_list(RID p_font_rid) const { +Dictionary TextServerExtension::font_supported_feature_list(const RID &p_font_rid) const { Dictionary ret; - if (GDVIRTUAL_CALL(_font_supported_feature_list, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_supported_feature_list, p_font_rid, ret)) { return ret; } return Dictionary(); } -Dictionary TextServerExtension::font_supported_variation_list(RID p_font_rid) const { +Dictionary TextServerExtension::font_supported_variation_list(const RID &p_font_rid) const { Dictionary ret; - if (GDVIRTUAL_CALL(_font_supported_variation_list, p_font_rid, ret)) { + if (GDVIRTUAL_CALL(font_supported_variation_list, p_font_rid, ret)) { return ret; } return Dictionary(); } -float TextServerExtension::font_get_global_oversampling() const { - float ret; - if (GDVIRTUAL_CALL(_font_get_global_oversampling, ret)) { +double TextServerExtension::font_get_global_oversampling() const { + double ret; + if (GDVIRTUAL_CALL(font_get_global_oversampling, ret)) { return ret; } - return 0.f; + return 0.0; } -void TextServerExtension::font_set_global_oversampling(float p_oversampling) { - GDVIRTUAL_CALL(_font_set_global_oversampling, p_oversampling); +void TextServerExtension::font_set_global_oversampling(double p_oversampling) { + GDVIRTUAL_CALL(font_set_global_oversampling, p_oversampling); } -Vector2 TextServerExtension::get_hex_code_box_size(int p_size, char32_t p_index) const { +Vector2 TextServerExtension::get_hex_code_box_size(int64_t p_size, int64_t p_index) const { Vector2 ret; - if (GDVIRTUAL_CALL(_get_hex_code_box_size, p_size, p_index, ret)) { + if (GDVIRTUAL_CALL(get_hex_code_box_size, p_size, p_index, ret)) { return ret; } return TextServer::get_hex_code_box_size(p_size, p_index); } -void TextServerExtension::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const { - if (!GDVIRTUAL_CALL(_draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) { +void TextServerExtension::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { + if (!GDVIRTUAL_CALL(draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) { TextServer::draw_hex_code_box(p_canvas, p_size, p_pos, p_index, p_color); } } @@ -985,433 +987,425 @@ void TextServerExtension::draw_hex_code_box(RID p_canvas, int p_size, const Vect RID TextServerExtension::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) { RID ret; - if (GDVIRTUAL_CALL(_create_shaped_text, p_direction, p_orientation, ret)) { + if (GDVIRTUAL_CALL(create_shaped_text, p_direction, p_orientation, ret)) { return ret; } return RID(); } -void TextServerExtension::shaped_text_clear(RID p_shaped) { - GDVIRTUAL_CALL(_shaped_text_clear, p_shaped); +void TextServerExtension::shaped_text_clear(const RID &p_shaped) { + GDVIRTUAL_CALL(shaped_text_clear, p_shaped); } -void TextServerExtension::shaped_text_set_direction(RID p_shaped, TextServer::Direction p_direction) { - GDVIRTUAL_CALL(_shaped_text_set_direction, p_shaped, p_direction); +void TextServerExtension::shaped_text_set_direction(const RID &p_shaped, TextServer::Direction p_direction) { + GDVIRTUAL_CALL(shaped_text_set_direction, p_shaped, p_direction); } -TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shaped) const { +TextServer::Direction TextServerExtension::shaped_text_get_direction(const RID &p_shaped) const { TextServer::Direction ret; - if (GDVIRTUAL_CALL(_shaped_text_get_direction, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_direction, p_shaped, ret)) { return (TextServer::Direction)ret; } return TextServer::Direction::DIRECTION_AUTO; } -TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(RID p_shaped) const { +TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(const RID &p_shaped) const { TextServer::Direction ret; - if (GDVIRTUAL_CALL(_shaped_text_get_inferred_direction, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_inferred_direction, p_shaped, ret)) { return (TextServer::Direction)ret; } return TextServer::Direction::DIRECTION_LTR; } -void TextServerExtension::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) { - GDVIRTUAL_CALL(_shaped_text_set_orientation, p_shaped, p_orientation); +void TextServerExtension::shaped_text_set_orientation(const RID &p_shaped, TextServer::Orientation p_orientation) { + GDVIRTUAL_CALL(shaped_text_set_orientation, p_shaped, p_orientation); } -TextServer::Orientation TextServerExtension::shaped_text_get_orientation(RID p_shaped) const { +TextServer::Orientation TextServerExtension::shaped_text_get_orientation(const RID &p_shaped) const { TextServer::Orientation ret; - if (GDVIRTUAL_CALL(_shaped_text_get_orientation, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_orientation, p_shaped, ret)) { return (TextServer::Orientation)ret; } return TextServer::Orientation::ORIENTATION_HORIZONTAL; } -void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) { - GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override); +void TextServerExtension::shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) { + GDVIRTUAL_CALL(shaped_text_set_bidi_override, p_shaped, p_override); } -void TextServerExtension::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) { - GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct); +void TextServerExtension::shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) { + GDVIRTUAL_CALL(shaped_text_set_custom_punctuation, p_shaped, p_punct); } -String TextServerExtension::shaped_text_get_custom_punctuation(RID p_shaped) const { +String TextServerExtension::shaped_text_get_custom_punctuation(const RID &p_shaped) const { String ret; - if (GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_custom_punctuation, p_shaped, ret)) { return ret; } return String(); } -void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) { - GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled); +void TextServerExtension::shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) { + GDVIRTUAL_CALL(shaped_text_set_preserve_invalid, p_shaped, p_enabled); } -bool TextServerExtension::shaped_text_get_preserve_invalid(RID p_shaped) const { +bool TextServerExtension::shaped_text_get_preserve_invalid(const RID &p_shaped) const { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_get_preserve_invalid, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_preserve_invalid, p_shaped, ret)) { return ret; } return false; } -void TextServerExtension::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) { - GDVIRTUAL_CALL(_shaped_text_set_preserve_control, p_shaped, p_enabled); +void TextServerExtension::shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) { + GDVIRTUAL_CALL(shaped_text_set_preserve_control, p_shaped, p_enabled); } -bool TextServerExtension::shaped_text_get_preserve_control(RID p_shaped) const { +bool TextServerExtension::shaped_text_get_preserve_control(const RID &p_shaped) const { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_get_preserve_control, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_preserve_control, p_shaped, ret)) { return ret; } return false; } -bool TextServerExtension::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) { +bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) { bool ret; - Array fonts; - for (int i = 0; i < p_fonts.size(); i++) { - fonts.push_back(p_fonts[i]); - } - if (GDVIRTUAL_CALL(_shaped_text_add_string, p_shaped, p_text, fonts, p_size, p_opentype_features, p_language, p_meta, ret)) { + if (GDVIRTUAL_CALL(shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret)) { return ret; } return false; } -bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) { +bool TextServerExtension::shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length) { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) { + if (GDVIRTUAL_CALL(shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) { return ret; } return false; } -bool TextServerExtension::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) { +bool TextServerExtension::shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align) { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) { + if (GDVIRTUAL_CALL(shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) { return ret; } return false; } -int TextServerExtension::shaped_get_span_count(RID p_shaped) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_get_span_count, p_shaped, ret)) { +int64_t TextServerExtension::shaped_get_span_count(const RID &p_shaped) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_get_span_count, p_shaped, ret)) { return ret; } return 0; } -Variant TextServerExtension::shaped_get_span_meta(RID p_shaped, int p_index) const { +Variant TextServerExtension::shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const { Variant ret; - if (GDVIRTUAL_CALL(_shaped_get_span_meta, p_shaped, p_index, ret)) { + if (GDVIRTUAL_CALL(shaped_get_span_meta, p_shaped, p_index, ret)) { return ret; } return false; } -void TextServerExtension::shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features) { - Array fonts; - for (int i = 0; i < p_fonts.size(); i++) { - fonts.push_back(p_fonts[i]); - } - GDVIRTUAL_CALL(_shaped_set_span_update_font, p_shaped, p_index, fonts, p_size, p_opentype_features); +void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) { + GDVIRTUAL_CALL(shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features); } -RID TextServerExtension::shaped_text_substr(RID p_shaped, int p_start, int p_length) const { +RID TextServerExtension::shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const { RID ret; - if (GDVIRTUAL_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret)) { + if (GDVIRTUAL_CALL(shaped_text_substr, p_shaped, p_start, p_length, ret)) { return ret; } return RID(); } -RID TextServerExtension::shaped_text_get_parent(RID p_shaped) const { +RID TextServerExtension::shaped_text_get_parent(const RID &p_shaped) const { RID ret; - if (GDVIRTUAL_CALL(_shaped_text_get_parent, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_parent, p_shaped, ret)) { return ret; } return RID(); } -float TextServerExtension::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t p_jst_flags) { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) { +double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t p_jst_flags) { + double ret; + if (GDVIRTUAL_CALL(shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) { return ret; } - return 0.f; + return 0.0; } -float TextServerExtension::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_tab_align, p_shaped, p_tab_stops, ret)) { +double TextServerExtension::shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) { + double ret; + if (GDVIRTUAL_CALL(shaped_text_tab_align, p_shaped, p_tab_stops, ret)) { return ret; } - return 0.f; + return 0.0; } -bool TextServerExtension::shaped_text_shape(RID p_shaped) { +bool TextServerExtension::shaped_text_shape(const RID &p_shaped) { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_shape, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_shape, p_shaped, ret)) { return ret; } return false; } -bool TextServerExtension::shaped_text_update_breaks(RID p_shaped) { +bool TextServerExtension::shaped_text_update_breaks(const RID &p_shaped) { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_update_breaks, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_update_breaks, p_shaped, ret)) { return ret; } return false; } -bool TextServerExtension::shaped_text_update_justification_ops(RID p_shaped) { +bool TextServerExtension::shaped_text_update_justification_ops(const RID &p_shaped) { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_update_justification_ops, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_update_justification_ops, p_shaped, ret)) { return ret; } return false; } -bool TextServerExtension::shaped_text_is_ready(RID p_shaped) const { +bool TextServerExtension::shaped_text_is_ready(const RID &p_shaped) const { bool ret; - if (GDVIRTUAL_CALL(_shaped_text_is_ready, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_is_ready, p_shaped, ret)) { return ret; } return false; } -const Glyph *TextServerExtension::shaped_text_get_glyphs(RID p_shaped) const { - GDNativePtr<Glyph> ret; - if (GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, ret)) { +const Glyph *TextServerExtension::shaped_text_get_glyphs(const RID &p_shaped) const { + GDNativeConstPtr<const Glyph> ret; + if (GDVIRTUAL_CALL(shaped_text_get_glyphs, p_shaped, ret)) { return ret; } return nullptr; } -const Glyph *TextServerExtension::shaped_text_sort_logical(RID p_shaped) { - GDNativePtr<Glyph> ret; - if (GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, ret)) { +const Glyph *TextServerExtension::shaped_text_sort_logical(const RID &p_shaped) { + GDNativeConstPtr<const Glyph> ret; + if (GDVIRTUAL_CALL(shaped_text_sort_logical, p_shaped, ret)) { return ret; } return nullptr; } -int TextServerExtension::shaped_text_get_glyph_count(RID p_shaped) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_get_glyph_count, p_shaped, ret)) { +int64_t TextServerExtension::shaped_text_get_glyph_count(const RID &p_shaped) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_get_glyph_count, p_shaped, ret)) { return ret; } return 0; } -Vector2i TextServerExtension::shaped_text_get_range(RID p_shaped) const { +Vector2i TextServerExtension::shaped_text_get_range(const RID &p_shaped) const { Vector2i ret; - if (GDVIRTUAL_CALL(_shaped_text_get_range, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_range, p_shaped, ret)) { return ret; } return Vector2i(); } -PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t p_break_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t p_break_flags) const { PackedInt32Array ret; - if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) { return ret; } return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags); } -PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t p_break_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t p_break_flags) const { PackedInt32Array ret; - if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) { return ret; } return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags); } -PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const { PackedInt32Array ret; - if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) { return ret; } return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags); } -int TextServerExtension::shaped_text_get_trim_pos(RID p_shaped) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_get_trim_pos, p_shaped, ret)) { +int64_t TextServerExtension::shaped_text_get_trim_pos(const RID &p_shaped) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_get_trim_pos, p_shaped, ret)) { return ret; } return -1; } -int TextServerExtension::shaped_text_get_ellipsis_pos(RID p_shaped) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret)) { +int64_t TextServerExtension::shaped_text_get_ellipsis_pos(const RID &p_shaped) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_pos, p_shaped, ret)) { return ret; } return -1; } -const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(RID p_shaped) const { - GDNativePtr<Glyph> ret; - if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret)) { +const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const { + GDNativeConstPtr<const Glyph> ret; + if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_glyphs, p_shaped, ret)) { return ret; } return nullptr; } -int TextServerExtension::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) { +int64_t TextServerExtension::shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) { return ret; } return -1; } -void TextServerExtension::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) { - GDVIRTUAL_CALL(_shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags); +void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) { + GDVIRTUAL_CALL(shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags); } -Array TextServerExtension::shaped_text_get_objects(RID p_shaped) const { +Array TextServerExtension::shaped_text_get_objects(const RID &p_shaped) const { Array ret; - if (GDVIRTUAL_CALL(_shaped_text_get_objects, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_objects, p_shaped, ret)) { return ret; } return Array(); } -Rect2 TextServerExtension::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const { +Rect2 TextServerExtension::shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const { Rect2 ret; - if (GDVIRTUAL_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_object_rect, p_shaped, p_key, ret)) { return ret; } return Rect2(); } -Size2 TextServerExtension::shaped_text_get_size(RID p_shaped) const { +Size2 TextServerExtension::shaped_text_get_size(const RID &p_shaped) const { Size2 ret; - if (GDVIRTUAL_CALL(_shaped_text_get_size, p_shaped, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_size, p_shaped, ret)) { return ret; } return Size2(); } -float TextServerExtension::shaped_text_get_ascent(RID p_shaped) const { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_get_ascent, p_shaped, ret)) { +double TextServerExtension::shaped_text_get_ascent(const RID &p_shaped) const { + double ret; + if (GDVIRTUAL_CALL(shaped_text_get_ascent, p_shaped, ret)) { return ret; } - return 0.f; + return 0.0; } -float TextServerExtension::shaped_text_get_descent(RID p_shaped) const { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_get_descent, p_shaped, ret)) { +double TextServerExtension::shaped_text_get_descent(const RID &p_shaped) const { + double ret; + if (GDVIRTUAL_CALL(shaped_text_get_descent, p_shaped, ret)) { return ret; } - return 0.f; + return 0.0; } -float TextServerExtension::shaped_text_get_width(RID p_shaped) const { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_get_width, p_shaped, ret)) { +double TextServerExtension::shaped_text_get_width(const RID &p_shaped) const { + double ret; + if (GDVIRTUAL_CALL(shaped_text_get_width, p_shaped, ret)) { return ret; } - return 0.f; + return 0.0; } -float TextServerExtension::shaped_text_get_underline_position(RID p_shaped) const { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_get_underline_position, p_shaped, ret)) { +double TextServerExtension::shaped_text_get_underline_position(const RID &p_shaped) const { + double ret; + if (GDVIRTUAL_CALL(shaped_text_get_underline_position, p_shaped, ret)) { return ret; } - return 0.f; + return 0.0; } -float TextServerExtension::shaped_text_get_underline_thickness(RID p_shaped) const { - float ret; - if (GDVIRTUAL_CALL(_shaped_text_get_underline_thickness, p_shaped, ret)) { +double TextServerExtension::shaped_text_get_underline_thickness(const RID &p_shaped) const { + double ret; + if (GDVIRTUAL_CALL(shaped_text_get_underline_thickness, p_shaped, ret)) { return ret; } - return 0.f; + return 0.0; } -TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) { +TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) { return (TextServer::Direction)ret; } return TextServer::shaped_text_get_dominant_direction_in_range(p_shaped, p_start, p_end); } -CaretInfo TextServerExtension::shaped_text_get_carets(RID p_shaped, int p_position) const { +CaretInfo TextServerExtension::shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const { CaretInfo ret; - if (GDVIRTUAL_CALL(_shaped_text_get_carets, p_shaped, p_position, &ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_carets, p_shaped, p_position, &ret)) { return ret; } return TextServer::shaped_text_get_carets(p_shaped, p_position); } -Vector<Vector2> TextServerExtension::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const { +Vector<Vector2> TextServerExtension::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const { Vector<Vector2> ret; - if (GDVIRTUAL_CALL(_shaped_text_get_selection, p_shaped, p_start, p_end, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_selection, p_shaped, p_start, p_end, ret)) { return ret; } return TextServer::shaped_text_get_selection(p_shaped, p_start, p_end); } -int TextServerExtension::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) { +int64_t TextServerExtension::shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) { return ret; } return TextServer::shaped_text_hit_test_grapheme(p_shaped, p_coords); } -int TextServerExtension::shaped_text_hit_test_position(RID p_shaped, float p_coords) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_hit_test_position, p_shaped, p_coords, ret)) { +int64_t TextServerExtension::shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_hit_test_position, p_shaped, p_coords, ret)) { return ret; } return TextServer::shaped_text_hit_test_position(p_shaped, p_coords); } -void TextServerExtension::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const { - if (GDVIRTUAL_CALL(_shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) { +void TextServerExtension::shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, const Color &p_color) const { + if (GDVIRTUAL_CALL(shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) { return; } TextServer::shaped_text_draw(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color); } -void TextServerExtension::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const { - if (GDVIRTUAL_CALL(_shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) { +void TextServerExtension::shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, int64_t p_outline_size, const Color &p_color) const { + if (GDVIRTUAL_CALL(shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) { return; } - shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color); + TextServer::shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color); } -Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const { +Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const { Vector2 ret; - if (GDVIRTUAL_CALL(_shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) { + if (GDVIRTUAL_CALL(shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) { return ret; } return TextServer::shaped_text_get_grapheme_bounds(p_shaped, p_pos); } -int TextServerExtension::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) { +int64_t TextServerExtension::shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) { return ret; } return TextServer::shaped_text_next_grapheme_pos(p_shaped, p_pos); } -int TextServerExtension::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const { - int ret; - if (GDVIRTUAL_CALL(_shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) { +int64_t TextServerExtension::shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const { + int64_t ret; + if (GDVIRTUAL_CALL(shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) { return ret; } return TextServer::shaped_text_prev_grapheme_pos(p_shaped, p_pos); @@ -1419,31 +1413,39 @@ int TextServerExtension::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) String TextServerExtension::format_number(const String &p_string, const String &p_language) const { String ret; - if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) { + if (GDVIRTUAL_CALL(format_number, p_string, p_language, ret)) { return ret; } - return TextServer::format_number(p_string, p_language); + return p_string; } String TextServerExtension::parse_number(const String &p_string, const String &p_language) const { String ret; - if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) { + if (GDVIRTUAL_CALL(parse_number, p_string, p_language, ret)) { return ret; } - return TextServer::parse_number(p_string, p_language); + return p_string; } String TextServerExtension::percent_sign(const String &p_language) const { String ret; - if (GDVIRTUAL_CALL(_percent_sign, p_language, ret)) { + if (GDVIRTUAL_CALL(percent_sign, p_language, ret)) { + return ret; + } + return "%"; +} + +String TextServerExtension::strip_diacritics(const String &p_string) const { + String ret; + if (GDVIRTUAL_CALL(strip_diacritics, p_string, ret)) { return ret; } - return TextServer::percent_sign(p_language); + return TextServer::strip_diacritics(p_string); } String TextServerExtension::string_to_upper(const String &p_string, const String &p_language) const { String ret; - if (GDVIRTUAL_CALL(_string_to_upper, p_string, p_language, ret)) { + if (GDVIRTUAL_CALL(string_to_upper, p_string, p_language, ret)) { return ret; } return p_string; @@ -1451,7 +1453,7 @@ String TextServerExtension::string_to_upper(const String &p_string, const String String TextServerExtension::string_to_lower(const String &p_string, const String &p_language) const { String ret; - if (GDVIRTUAL_CALL(_string_to_lower, p_string, p_language, ret)) { + if (GDVIRTUAL_CALL(string_to_lower, p_string, p_language, ret)) { return ret; } return p_string; diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 7d80467371..c6e7bef4e8 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -48,433 +48,436 @@ protected: public: virtual bool has_feature(Feature p_feature) const override; virtual String get_name() const override; - virtual uint32_t get_features() const override; - GDVIRTUAL1RC(bool, _has_feature, Feature); - GDVIRTUAL0RC(String, _get_name); - GDVIRTUAL0RC(uint32_t, _get_features); + virtual int64_t get_features() const override; + GDVIRTUAL1RC(bool, has_feature, Feature); + GDVIRTUAL0RC(String, get_name); + GDVIRTUAL0RC(int64_t, get_features); - virtual void free(RID p_rid) override; - virtual bool has(RID p_rid) override; + virtual void free_rid(const RID &p_rid) override; + virtual bool has(const RID &p_rid) override; virtual bool load_support_data(const String &p_filename) override; - GDVIRTUAL1(_free, RID); - GDVIRTUAL1R(bool, _has, RID); - GDVIRTUAL1R(bool, _load_support_data, const String &); + GDVIRTUAL1(free_rid, RID); + GDVIRTUAL1R(bool, has, RID); + GDVIRTUAL1R(bool, load_support_data, const String &); virtual String get_support_data_filename() const override; virtual String get_support_data_info() const override; virtual bool save_support_data(const String &p_filename) const override; - GDVIRTUAL0RC(String, _get_support_data_filename); - GDVIRTUAL0RC(String, _get_support_data_info); - GDVIRTUAL1RC(bool, _save_support_data, const String &); + GDVIRTUAL0RC(String, get_support_data_filename); + GDVIRTUAL0RC(String, get_support_data_info); + GDVIRTUAL1RC(bool, save_support_data, const String &); virtual bool is_locale_right_to_left(const String &p_locale) const override; - GDVIRTUAL1RC(bool, _is_locale_right_to_left, const String &); + GDVIRTUAL1RC(bool, is_locale_right_to_left, const String &); - virtual int32_t name_to_tag(const String &p_name) const override; - virtual String tag_to_name(int32_t p_tag) const override; - GDVIRTUAL1RC(int32_t, _name_to_tag, const String &); - GDVIRTUAL1RC(String, _tag_to_name, int32_t); + virtual int64_t name_to_tag(const String &p_name) const override; + virtual String tag_to_name(int64_t p_tag) const override; + GDVIRTUAL1RC(int64_t, name_to_tag, const String &); + GDVIRTUAL1RC(String, tag_to_name, int64_t); /* Font interface */ virtual RID create_font() override; - GDVIRTUAL0R(RID, _create_font); - - virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override; - virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override; - GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &); - GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t); - - virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override; - virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_style, RID, uint32_t); - GDVIRTUAL1RC(uint32_t, _font_get_style, RID); - - virtual void font_set_name(RID p_font_rid, const String &p_name) override; - virtual String font_get_name(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_name, RID, const String &); - GDVIRTUAL1RC(String, _font_get_name, RID); - - virtual void font_set_style_name(RID p_font_rid, const String &p_name) override; - virtual String font_get_style_name(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_style_name, RID, const String &); - GDVIRTUAL1RC(String, _font_get_style_name, RID); - - virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_antialiased, RID, bool); - GDVIRTUAL1RC(bool, _font_is_antialiased, RID); - - virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) override; - virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_multichannel_signed_distance_field, RID, bool); - GDVIRTUAL1RC(bool, _font_is_multichannel_signed_distance_field, RID); - - virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) override; - virtual int font_get_msdf_pixel_range(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_msdf_pixel_range, RID, int); - GDVIRTUAL1RC(int, _font_get_msdf_pixel_range, RID); - - virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) override; - virtual int font_get_msdf_size(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_msdf_size, RID, int); - GDVIRTUAL1RC(int, _font_get_msdf_size, RID); - - virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) override; - virtual int font_get_fixed_size(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_fixed_size, RID, int); - GDVIRTUAL1RC(int, _font_get_fixed_size, RID); - - virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) override; - virtual bool font_is_force_autohinter(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_force_autohinter, RID, bool); - GDVIRTUAL1RC(bool, _font_is_force_autohinter, RID); - - virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) override; - virtual Hinting font_get_hinting(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_hinting, RID, Hinting); - GDVIRTUAL1RC(Hinting, _font_get_hinting, RID); - - virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override; - virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning); - GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID); - - virtual void font_set_embolden(RID p_font_rid, float p_strength) override; - virtual float font_get_embolden(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_embolden, RID, float); - GDVIRTUAL1RC(float, _font_get_embolden, RID); - - virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override; - virtual Transform2D font_get_transform(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_transform, RID, Transform2D); - GDVIRTUAL1RC(Transform2D, _font_get_transform, RID); - - virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; - virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary); - GDVIRTUAL1RC(Dictionary, _font_get_variation_coordinates, RID); - - virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override; - virtual float font_get_oversampling(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_oversampling, RID, float); - GDVIRTUAL1RC(float, _font_get_oversampling, RID); - - virtual Array font_get_size_cache_list(RID p_font_rid) const override; - virtual void font_clear_size_cache(RID p_font_rid) override; - virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override; - GDVIRTUAL1RC(Array, _font_get_size_cache_list, RID); - GDVIRTUAL1(_font_clear_size_cache, RID); - GDVIRTUAL2(_font_remove_size_cache, RID, const Vector2i &); - - virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override; - virtual float font_get_ascent(RID p_font_rid, int p_size) const override; - GDVIRTUAL3(_font_set_ascent, RID, int, float); - GDVIRTUAL2RC(float, _font_get_ascent, RID, int); - - virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override; - virtual float font_get_descent(RID p_font_rid, int p_size) const override; - GDVIRTUAL3(_font_set_descent, RID, int, float); - GDVIRTUAL2RC(float, _font_get_descent, RID, int); - - virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override; - virtual float font_get_underline_position(RID p_font_rid, int p_size) const override; - GDVIRTUAL3(_font_set_underline_position, RID, int, float); - GDVIRTUAL2RC(float, _font_get_underline_position, RID, int); - - virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override; - virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override; - GDVIRTUAL3(_font_set_underline_thickness, RID, int, float); - GDVIRTUAL2RC(float, _font_get_underline_thickness, RID, int); - - virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override; - virtual float font_get_scale(RID p_font_rid, int p_size) const override; - GDVIRTUAL3(_font_set_scale, RID, int, float); - GDVIRTUAL2RC(float, _font_get_scale, RID, int); - - virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override; - virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override; - GDVIRTUAL4(_font_set_spacing, RID, int, SpacingType, int); - GDVIRTUAL3RC(int, _font_get_spacing, RID, int, SpacingType); - - virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const override; - virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) override; - virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) override; - GDVIRTUAL2RC(int, _font_get_texture_count, RID, const Vector2i &); - GDVIRTUAL2(_font_clear_textures, RID, const Vector2i &); - GDVIRTUAL3(_font_remove_texture, RID, const Vector2i &, int); - - virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) override; - virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override; - GDVIRTUAL4(_font_set_texture_image, RID, const Vector2i &, int, const Ref<Image> &); - GDVIRTUAL3RC(Ref<Image>, _font_get_texture_image, RID, const Vector2i &, int); - - virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) override; - virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override; - GDVIRTUAL4(_font_set_texture_offsets, RID, const Vector2i &, int, const PackedInt32Array &); - GDVIRTUAL3RC(PackedInt32Array, _font_get_texture_offsets, RID, const Vector2i &, int); - - virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const override; - virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) override; - virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) override; - GDVIRTUAL2RC(Array, _font_get_glyph_list, RID, const Vector2i &); - GDVIRTUAL2(_font_clear_glyphs, RID, const Vector2i &); - GDVIRTUAL3(_font_remove_glyph, RID, const Vector2i &, int32_t); - - virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const override; - virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) override; - GDVIRTUAL3RC(Vector2, _font_get_glyph_advance, RID, int, int32_t); - GDVIRTUAL4(_font_set_glyph_advance, RID, int, int32_t, const Vector2 &); - - virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; - virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) override; - GDVIRTUAL3RC(Vector2, _font_get_glyph_offset, RID, const Vector2i &, int32_t); - GDVIRTUAL4(_font_set_glyph_offset, RID, const Vector2i &, int32_t, const Vector2 &); - - virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; - virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) override; - GDVIRTUAL3RC(Vector2, _font_get_glyph_size, RID, const Vector2i &, int32_t); - GDVIRTUAL4(_font_set_glyph_size, RID, const Vector2i &, int32_t, const Vector2 &); - - virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; - virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) override; - GDVIRTUAL3RC(Rect2, _font_get_glyph_uv_rect, RID, const Vector2i &, int32_t); - GDVIRTUAL4(_font_set_glyph_uv_rect, RID, const Vector2i &, int32_t, const Rect2 &); - - virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; - virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override; - GDVIRTUAL3RC(int, _font_get_glyph_texture_idx, RID, const Vector2i &, int32_t); - GDVIRTUAL4(_font_set_glyph_texture_idx, RID, const Vector2i &, int32_t, int); - - virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override; - GDVIRTUAL3RC(Dictionary, _font_get_glyph_contours, RID, int, int32_t); - - virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override; - virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override; - virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) override; - GDVIRTUAL2RC(Array, _font_get_kerning_list, RID, int); - GDVIRTUAL2(_font_clear_kerning_map, RID, int); - GDVIRTUAL3(_font_remove_kerning, RID, int, const Vector2i &); - - virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override; - virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const override; - GDVIRTUAL4(_font_set_kerning, RID, int, const Vector2i &, const Vector2 &); - GDVIRTUAL3RC(Vector2, _font_get_kerning, RID, int, const Vector2i &); - - virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector = 0) const override; - GDVIRTUAL4RC(int32_t, _font_get_glyph_index, RID, int, char32_t, char32_t); - - virtual bool font_has_char(RID p_font_rid, char32_t p_char) const override; - virtual String font_get_supported_chars(RID p_font_rid) const override; - GDVIRTUAL2RC(bool, _font_has_char, RID, char32_t); - GDVIRTUAL1RC(String, _font_get_supported_chars, RID); - - virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) override; - virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) override; - GDVIRTUAL4(_font_render_range, RID, const Vector2i &, char32_t, char32_t); - GDVIRTUAL3(_font_render_glyph, RID, const Vector2i &, int32_t); - - virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; - virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; - GDVIRTUAL6C(_font_draw_glyph, RID, RID, int, const Vector2 &, int32_t, const Color &); - GDVIRTUAL7C(_font_draw_glyph_outline, RID, RID, int, int, const Vector2 &, int32_t, const Color &); - - virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const override; - virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) override; - virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) override; - virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) override; - virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) override; - GDVIRTUAL2RC(bool, _font_is_language_supported, RID, const String &); - GDVIRTUAL3(_font_set_language_support_override, RID, const String &, bool); - GDVIRTUAL2R(bool, _font_get_language_support_override, RID, const String &); - GDVIRTUAL2(_font_remove_language_support_override, RID, const String &); - GDVIRTUAL1R(Vector<String>, _font_get_language_support_overrides, RID); - - virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const override; - virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) override; - virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) override; - virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) override; - virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) override; - GDVIRTUAL2RC(bool, _font_is_script_supported, RID, const String &); - GDVIRTUAL3(_font_set_script_support_override, RID, const String &, bool); - GDVIRTUAL2R(bool, _font_get_script_support_override, RID, const String &); - GDVIRTUAL2(_font_remove_script_support_override, RID, const String &); - GDVIRTUAL1R(Vector<String>, _font_get_script_support_overrides, RID); - - virtual void font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) override; - virtual Dictionary font_get_opentype_feature_overrides(RID p_font_rid) const override; - GDVIRTUAL2(_font_set_opentype_feature_overrides, RID, const Dictionary &); - GDVIRTUAL1RC(Dictionary, _font_get_opentype_feature_overrides, RID); - - virtual Dictionary font_supported_feature_list(RID p_font_rid) const override; - virtual Dictionary font_supported_variation_list(RID p_font_rid) const override; - GDVIRTUAL1RC(Dictionary, _font_supported_feature_list, RID); - GDVIRTUAL1RC(Dictionary, _font_supported_variation_list, RID); - - virtual float font_get_global_oversampling() const override; - virtual void font_set_global_oversampling(float p_oversampling) override; - GDVIRTUAL0RC(float, _font_get_global_oversampling); - GDVIRTUAL1(_font_set_global_oversampling, float); - - virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const override; - virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const override; - GDVIRTUAL2RC(Vector2, _get_hex_code_box_size, int, char32_t); - GDVIRTUAL5C(_draw_hex_code_box, RID, int, const Vector2 &, char32_t, const Color &); + GDVIRTUAL0R(RID, create_font); + + virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) override; + virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) override; + GDVIRTUAL2(font_set_data, RID, const PackedByteArray &); + GDVIRTUAL3(font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, int64_t); + + virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override; + virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_style, RID, int64_t); + GDVIRTUAL1RC(int64_t, font_get_style, RID); + + virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; + virtual String font_get_name(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_name, RID, const String &); + GDVIRTUAL1RC(String, font_get_name, RID); + + virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override; + virtual String font_get_style_name(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_style_name, RID, const String &); + GDVIRTUAL1RC(String, font_get_style_name, RID); + + virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; + virtual bool font_is_antialiased(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_antialiased, RID, bool); + GDVIRTUAL1RC(bool, font_is_antialiased, RID); + + virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override; + virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_multichannel_signed_distance_field, RID, bool); + GDVIRTUAL1RC(bool, font_is_multichannel_signed_distance_field, RID); + + virtual void font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) override; + virtual int64_t font_get_msdf_pixel_range(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_msdf_pixel_range, RID, int64_t); + GDVIRTUAL1RC(int64_t, font_get_msdf_pixel_range, RID); + + virtual void font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) override; + virtual int64_t font_get_msdf_size(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_msdf_size, RID, int64_t); + GDVIRTUAL1RC(int64_t, font_get_msdf_size, RID); + + virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) override; + virtual int64_t font_get_fixed_size(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_fixed_size, RID, int64_t); + GDVIRTUAL1RC(int64_t, font_get_fixed_size, RID); + + virtual void font_set_subpixel_positioning(const RID &p_font_rid, SubpixelPositioning p_subpixel) override; + virtual SubpixelPositioning font_get_subpixel_positioning(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_subpixel_positioning, RID, SubpixelPositioning); + GDVIRTUAL1RC(SubpixelPositioning, font_get_subpixel_positioning, RID); + + virtual void font_set_embolden(const RID &p_font_rid, double p_strength) override; + virtual double font_get_embolden(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_embolden, RID, double); + GDVIRTUAL1RC(double, font_get_embolden, RID); + + virtual void font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) override; + virtual Transform2D font_get_transform(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_transform, RID, Transform2D); + GDVIRTUAL1RC(Transform2D, font_get_transform, RID); + + virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) override; + virtual bool font_is_force_autohinter(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_force_autohinter, RID, bool); + GDVIRTUAL1RC(bool, font_is_force_autohinter, RID); + + virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) override; + virtual Hinting font_get_hinting(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_hinting, RID, Hinting); + GDVIRTUAL1RC(Hinting, font_get_hinting, RID); + + virtual void font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) override; + virtual Dictionary font_get_variation_coordinates(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_variation_coordinates, RID, Dictionary); + GDVIRTUAL1RC(Dictionary, font_get_variation_coordinates, RID); + + virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) override; + virtual double font_get_oversampling(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_oversampling, RID, double); + GDVIRTUAL1RC(double, font_get_oversampling, RID); + + virtual Array font_get_size_cache_list(const RID &p_font_rid) const override; + virtual void font_clear_size_cache(const RID &p_font_rid) override; + virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) override; + GDVIRTUAL1RC(Array, font_get_size_cache_list, RID); + GDVIRTUAL1(font_clear_size_cache, RID); + GDVIRTUAL2(font_remove_size_cache, RID, const Vector2i &); + + virtual void font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) override; + virtual double font_get_ascent(const RID &p_font_rid, int64_t p_size) const override; + GDVIRTUAL3(font_set_ascent, RID, int64_t, double); + GDVIRTUAL2RC(double, font_get_ascent, RID, int64_t); + + virtual void font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) override; + virtual double font_get_descent(const RID &p_font_rid, int64_t p_size) const override; + GDVIRTUAL3(font_set_descent, RID, int64_t, double); + GDVIRTUAL2RC(double, font_get_descent, RID, int64_t); + + virtual void font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) override; + virtual double font_get_underline_position(const RID &p_font_rid, int64_t p_size) const override; + GDVIRTUAL3(font_set_underline_position, RID, int64_t, double); + GDVIRTUAL2RC(double, font_get_underline_position, RID, int64_t); + + virtual void font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) override; + virtual double font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const override; + GDVIRTUAL3(font_set_underline_thickness, RID, int64_t, double); + GDVIRTUAL2RC(double, font_get_underline_thickness, RID, int64_t); + + virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override; + virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override; + GDVIRTUAL3(font_set_scale, RID, int64_t, double); + GDVIRTUAL2RC(double, font_get_scale, RID, int64_t); + + virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override; + virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override; + GDVIRTUAL4(font_set_spacing, RID, int64_t, SpacingType, int64_t); + GDVIRTUAL3RC(int64_t, font_get_spacing, RID, int64_t, SpacingType); + + virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override; + virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override; + virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override; + GDVIRTUAL2RC(int64_t, font_get_texture_count, RID, const Vector2i &); + GDVIRTUAL2(font_clear_textures, RID, const Vector2i &); + GDVIRTUAL3(font_remove_texture, RID, const Vector2i &, int64_t); + + virtual void font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) override; + virtual Ref<Image> font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override; + GDVIRTUAL4(font_set_texture_image, RID, const Vector2i &, int64_t, const Ref<Image> &); + GDVIRTUAL3RC(Ref<Image>, font_get_texture_image, RID, const Vector2i &, int64_t); + + virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) override; + virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override; + GDVIRTUAL4(font_set_texture_offsets, RID, const Vector2i &, int64_t, const PackedInt32Array &); + GDVIRTUAL3RC(PackedInt32Array, font_get_texture_offsets, RID, const Vector2i &, int64_t); + + virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override; + virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) override; + virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) override; + GDVIRTUAL2RC(Array, font_get_glyph_list, RID, const Vector2i &); + GDVIRTUAL2(font_clear_glyphs, RID, const Vector2i &); + GDVIRTUAL3(font_remove_glyph, RID, const Vector2i &, int64_t); + + virtual Vector2 font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const override; + virtual void font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) override; + GDVIRTUAL3RC(Vector2, font_get_glyph_advance, RID, int64_t, int64_t); + GDVIRTUAL4(font_set_glyph_advance, RID, int64_t, int64_t, const Vector2 &); + + virtual Vector2 font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual void font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) override; + GDVIRTUAL3RC(Vector2, font_get_glyph_offset, RID, const Vector2i &, int64_t); + GDVIRTUAL4(font_set_glyph_offset, RID, const Vector2i &, int64_t, const Vector2 &); + + virtual Vector2 font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual void font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) override; + GDVIRTUAL3RC(Vector2, font_get_glyph_size, RID, const Vector2i &, int64_t); + GDVIRTUAL4(font_set_glyph_size, RID, const Vector2i &, int64_t, const Vector2 &); + + virtual Rect2 font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual void font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) override; + GDVIRTUAL3RC(Rect2, font_get_glyph_uv_rect, RID, const Vector2i &, int64_t); + GDVIRTUAL4(font_set_glyph_uv_rect, RID, const Vector2i &, int64_t, const Rect2 &); + + virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override; + GDVIRTUAL3RC(int64_t, font_get_glyph_texture_idx, RID, const Vector2i &, int64_t); + GDVIRTUAL4(font_set_glyph_texture_idx, RID, const Vector2i &, int64_t, int64_t); + + virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override; + GDVIRTUAL3RC(Dictionary, font_get_glyph_contours, RID, int64_t, int64_t); + + virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override; + virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) override; + virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) override; + GDVIRTUAL2RC(Array, font_get_kerning_list, RID, int64_t); + GDVIRTUAL2(font_clear_kerning_map, RID, int64_t); + GDVIRTUAL3(font_remove_kerning, RID, int64_t, const Vector2i &); + + virtual void font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override; + virtual Vector2 font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const override; + GDVIRTUAL4(font_set_kerning, RID, int64_t, const Vector2i &, const Vector2 &); + GDVIRTUAL3RC(Vector2, font_get_kerning, RID, int64_t, const Vector2i &); + + virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector = 0) const override; + GDVIRTUAL4RC(int64_t, font_get_glyph_index, RID, int64_t, int64_t, int64_t); + + virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const override; + virtual String font_get_supported_chars(const RID &p_font_rid) const override; + GDVIRTUAL2RC(bool, font_has_char, RID, int64_t); + GDVIRTUAL1RC(String, font_get_supported_chars, RID); + + virtual void font_render_range(const RID &p_font, const Vector2i &p_size, int64_t p_start, int64_t p_end) override; + virtual void font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) override; + GDVIRTUAL4(font_render_range, RID, const Vector2i &, int64_t, int64_t); + GDVIRTUAL3(font_render_glyph, RID, const Vector2i &, int64_t); + + virtual void font_draw_glyph(const RID &p_font, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const override; + virtual void font_draw_glyph_outline(const RID &p_font, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const override; + GDVIRTUAL6C(font_draw_glyph, RID, RID, int64_t, const Vector2 &, int64_t, const Color &); + GDVIRTUAL7C(font_draw_glyph_outline, RID, RID, int64_t, int64_t, const Vector2 &, int64_t, const Color &); + + virtual bool font_is_language_supported(const RID &p_font_rid, const String &p_language) const override; + virtual void font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) override; + virtual bool font_get_language_support_override(const RID &p_font_rid, const String &p_language) override; + virtual void font_remove_language_support_override(const RID &p_font_rid, const String &p_language) override; + virtual PackedStringArray font_get_language_support_overrides(const RID &p_font_rid) override; + GDVIRTUAL2RC(bool, font_is_language_supported, RID, const String &); + GDVIRTUAL3(font_set_language_support_override, RID, const String &, bool); + GDVIRTUAL2R(bool, font_get_language_support_override, RID, const String &); + GDVIRTUAL2(font_remove_language_support_override, RID, const String &); + GDVIRTUAL1R(PackedStringArray, font_get_language_support_overrides, RID); + + virtual bool font_is_script_supported(const RID &p_font_rid, const String &p_script) const override; + virtual void font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) override; + virtual bool font_get_script_support_override(const RID &p_font_rid, const String &p_script) override; + virtual void font_remove_script_support_override(const RID &p_font_rid, const String &p_script) override; + virtual PackedStringArray font_get_script_support_overrides(const RID &p_font_rid) override; + GDVIRTUAL2RC(bool, font_is_script_supported, RID, const String &); + GDVIRTUAL3(font_set_script_support_override, RID, const String &, bool); + GDVIRTUAL2R(bool, font_get_script_support_override, RID, const String &); + GDVIRTUAL2(font_remove_script_support_override, RID, const String &); + GDVIRTUAL1R(PackedStringArray, font_get_script_support_overrides, RID); + + virtual void font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) override; + virtual Dictionary font_get_opentype_feature_overrides(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_opentype_feature_overrides, RID, const Dictionary &); + GDVIRTUAL1RC(Dictionary, font_get_opentype_feature_overrides, RID); + + virtual Dictionary font_supported_feature_list(const RID &p_font_rid) const override; + virtual Dictionary font_supported_variation_list(const RID &p_font_rid) const override; + GDVIRTUAL1RC(Dictionary, font_supported_feature_list, RID); + GDVIRTUAL1RC(Dictionary, font_supported_variation_list, RID); + + virtual double font_get_global_oversampling() const override; + virtual void font_set_global_oversampling(double p_oversampling) override; + GDVIRTUAL0RC(double, font_get_global_oversampling); + GDVIRTUAL1(font_set_global_oversampling, double); + + virtual Vector2 get_hex_code_box_size(int64_t p_size, int64_t p_index) const override; + virtual void draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override; + GDVIRTUAL2RC(Vector2, get_hex_code_box_size, int64_t, int64_t); + GDVIRTUAL5C(draw_hex_code_box, RID, int64_t, const Vector2 &, int64_t, const Color &); /* Shaped text buffer interface */ virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; - GDVIRTUAL2R(RID, _create_shaped_text, Direction, Orientation); - - virtual void shaped_text_clear(RID p_shaped) override; - GDVIRTUAL1(_shaped_text_clear, RID); - - virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override; - virtual Direction shaped_text_get_direction(RID p_shaped) const override; - virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const override; - GDVIRTUAL2(_shaped_text_set_direction, RID, Direction); - GDVIRTUAL1RC(Direction, _shaped_text_get_direction, RID); - GDVIRTUAL1RC(Direction, _shaped_text_get_inferred_direction, RID); - - virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; - GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &); - - virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override; - virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override; - GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String); - GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID); - - virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; - virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; - GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation); - GDVIRTUAL1RC(Orientation, _shaped_text_get_orientation, RID); - - virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) override; - virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const override; - GDVIRTUAL2(_shaped_text_set_preserve_invalid, RID, bool); - GDVIRTUAL1RC(bool, _shaped_text_get_preserve_invalid, RID); - - virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) override; - virtual bool shaped_text_get_preserve_control(RID p_shaped) const override; - GDVIRTUAL2(_shaped_text_set_preserve_control, RID, bool); - GDVIRTUAL1RC(bool, _shaped_text_get_preserve_control, RID); - - virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override; - virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) override; - virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override; - GDVIRTUAL7R(bool, _shaped_text_add_string, RID, const String &, const Array &, int, const Dictionary &, const String &, const Variant &); - GDVIRTUAL5R(bool, _shaped_text_add_object, RID, Variant, const Size2 &, InlineAlignment, int); - GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, Variant, const Size2 &, InlineAlignment); - - virtual int shaped_get_span_count(RID p_shaped) const override; - virtual Variant shaped_get_span_meta(RID p_shaped, int p_index) const override; - virtual void shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary()) override; - GDVIRTUAL1RC(int, _shaped_get_span_count, RID); - GDVIRTUAL2RC(Variant, _shaped_get_span_meta, RID, int); - GDVIRTUAL5(_shaped_set_span_update_font, RID, int, const Array &, int, const Dictionary &); - - virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override; - virtual RID shaped_text_get_parent(RID p_shaped) const override; - GDVIRTUAL3RC(RID, _shaped_text_substr, RID, int, int); - GDVIRTUAL1RC(RID, _shaped_text_get_parent, RID); - - virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; - virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override; - GDVIRTUAL3R(float, _shaped_text_fit_to_width, RID, float, uint16_t); - GDVIRTUAL2R(float, _shaped_text_tab_align, RID, const PackedFloat32Array &); - - virtual bool shaped_text_shape(RID p_shaped) override; - virtual bool shaped_text_update_breaks(RID p_shaped) override; - virtual bool shaped_text_update_justification_ops(RID p_shaped) override; - GDVIRTUAL1R(bool, _shaped_text_shape, RID); - GDVIRTUAL1R(bool, _shaped_text_update_breaks, RID); - GDVIRTUAL1R(bool, _shaped_text_update_justification_ops, RID); - - virtual bool shaped_text_is_ready(RID p_shaped) const override; - GDVIRTUAL1RC(bool, _shaped_text_is_ready, RID); - - virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override; - virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override; - virtual int shaped_text_get_glyph_count(RID p_shaped) const override; - GDVIRTUAL1RC(GDNativePtr<Glyph>, _shaped_text_get_glyphs, RID); - GDVIRTUAL1R(GDNativePtr<Glyph>, _shaped_text_sort_logical, RID); - GDVIRTUAL1RC(int, _shaped_text_get_glyph_count, RID); - - virtual Vector2i shaped_text_get_range(RID p_shaped) const override; - GDVIRTUAL1RC(Vector2i, _shaped_text_get_range, RID); - - virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; - virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; - virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override; - GDVIRTUAL5RC(PackedInt32Array, _shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int, bool, uint16_t); - GDVIRTUAL4RC(PackedInt32Array, _shaped_text_get_line_breaks, RID, float, int, uint16_t); - GDVIRTUAL2RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, int); - - virtual int shaped_text_get_trim_pos(RID p_shaped) const override; - virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override; - virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override; - virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override; - GDVIRTUAL1RC(int, _shaped_text_get_trim_pos, RID); - GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_pos, RID); - GDVIRTUAL1RC(GDNativePtr<Glyph>, _shaped_text_get_ellipsis_glyphs, RID); - GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_glyph_count, RID); - - virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override; - GDVIRTUAL3(_shaped_text_overrun_trim_to_width, RID, float, uint16_t); - - virtual Array shaped_text_get_objects(RID p_shaped) const override; - virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override; - GDVIRTUAL1RC(Array, _shaped_text_get_objects, RID); - GDVIRTUAL2RC(Rect2, _shaped_text_get_object_rect, RID, Variant); - - virtual Size2 shaped_text_get_size(RID p_shaped) const override; - virtual float shaped_text_get_ascent(RID p_shaped) const override; - virtual float shaped_text_get_descent(RID p_shaped) const override; - virtual float shaped_text_get_width(RID p_shaped) const override; - virtual float shaped_text_get_underline_position(RID p_shaped) const override; - virtual float shaped_text_get_underline_thickness(RID p_shaped) const override; - GDVIRTUAL1RC(Size2, _shaped_text_get_size, RID); - GDVIRTUAL1RC(float, _shaped_text_get_ascent, RID); - GDVIRTUAL1RC(float, _shaped_text_get_descent, RID); - GDVIRTUAL1RC(float, _shaped_text_get_width, RID); - GDVIRTUAL1RC(float, _shaped_text_get_underline_position, RID); - GDVIRTUAL1RC(float, _shaped_text_get_underline_thickness, RID); - - virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const override; - GDVIRTUAL3RC(int, _shaped_text_get_dominant_direction_in_range, RID, int, int); - - virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const override; - virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const override; - GDVIRTUAL3C(_shaped_text_get_carets, RID, int, GDNativePtr<CaretInfo>); - GDVIRTUAL3RC(Vector<Vector2>, _shaped_text_get_selection, RID, int, int); - - virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const override; - virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const override; - GDVIRTUAL2RC(int, _shaped_text_hit_test_grapheme, RID, float); - GDVIRTUAL2RC(int, _shaped_text_hit_test_position, RID, float); - - virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const override; - virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override; - GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, float, float, const Color &); - GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, float, float, int, const Color &); - - virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const override; - virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const override; - virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const override; - GDVIRTUAL2RC(Vector2, _shaped_text_get_grapheme_bounds, RID, int); - GDVIRTUAL2RC(int, _shaped_text_next_grapheme_pos, RID, int); - GDVIRTUAL2RC(int, _shaped_text_prev_grapheme_pos, RID, int); + GDVIRTUAL2R(RID, create_shaped_text, Direction, Orientation); + + virtual void shaped_text_clear(const RID &p_shaped) override; + GDVIRTUAL1(shaped_text_clear, RID); + + virtual void shaped_text_set_direction(const RID &p_shaped, Direction p_direction = DIRECTION_AUTO) override; + virtual Direction shaped_text_get_direction(const RID &p_shaped) const override; + virtual Direction shaped_text_get_inferred_direction(const RID &p_shaped) const override; + GDVIRTUAL2(shaped_text_set_direction, RID, Direction); + GDVIRTUAL1RC(Direction, shaped_text_get_direction, RID); + GDVIRTUAL1RC(Direction, shaped_text_get_inferred_direction, RID); + + virtual void shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) override; + GDVIRTUAL2(shaped_text_set_bidi_override, RID, const Array &); + + virtual void shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) override; + virtual String shaped_text_get_custom_punctuation(const RID &p_shaped) const override; + GDVIRTUAL2(shaped_text_set_custom_punctuation, RID, String); + GDVIRTUAL1RC(String, shaped_text_get_custom_punctuation, RID); + + virtual void shaped_text_set_orientation(const RID &p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; + virtual Orientation shaped_text_get_orientation(const RID &p_shaped) const override; + GDVIRTUAL2(shaped_text_set_orientation, RID, Orientation); + GDVIRTUAL1RC(Orientation, shaped_text_get_orientation, RID); + + virtual void shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) override; + virtual bool shaped_text_get_preserve_invalid(const RID &p_shaped) const override; + GDVIRTUAL2(shaped_text_set_preserve_invalid, RID, bool); + GDVIRTUAL1RC(bool, shaped_text_get_preserve_invalid, RID); + + virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override; + virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override; + GDVIRTUAL2(shaped_text_set_preserve_control, RID, bool); + GDVIRTUAL1RC(bool, shaped_text_get_preserve_control, RID); + + virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override; + virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override; + virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override; + GDVIRTUAL7R(bool, shaped_text_add_string, RID, const String &, const Array &, int64_t, const Dictionary &, const String &, const Variant &); + GDVIRTUAL5R(bool, shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t); + GDVIRTUAL4R(bool, shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment); + + virtual int64_t shaped_get_span_count(const RID &p_shaped) const override; + virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const override; + virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) override; + GDVIRTUAL1RC(int64_t, shaped_get_span_count, RID); + GDVIRTUAL2RC(Variant, shaped_get_span_meta, RID, int64_t); + GDVIRTUAL5(shaped_set_span_update_font, RID, int64_t, const Array &, int64_t, const Dictionary &); + + virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override; + virtual RID shaped_text_get_parent(const RID &p_shaped) const override; + GDVIRTUAL3RC(RID, shaped_text_substr, RID, int64_t, int64_t); + GDVIRTUAL1RC(RID, shaped_text_get_parent, RID); + + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override; + GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, int64_t); + GDVIRTUAL2R(double, shaped_text_tab_align, RID, const PackedFloat32Array &); + + virtual bool shaped_text_shape(const RID &p_shaped) override; + virtual bool shaped_text_update_breaks(const RID &p_shaped) override; + virtual bool shaped_text_update_justification_ops(const RID &p_shaped) override; + GDVIRTUAL1R(bool, shaped_text_shape, RID); + GDVIRTUAL1R(bool, shaped_text_update_breaks, RID); + GDVIRTUAL1R(bool, shaped_text_update_justification_ops, RID); + + virtual bool shaped_text_is_ready(const RID &p_shaped) const override; + GDVIRTUAL1RC(bool, shaped_text_is_ready, RID); + + virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const override; + virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) override; + virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const override; + GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_glyphs, RID); + GDVIRTUAL1R(GDNativeConstPtr<const Glyph>, shaped_text_sort_logical, RID); + GDVIRTUAL1RC(int64_t, shaped_text_get_glyph_count, RID); + + virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override; + GDVIRTUAL1RC(Vector2i, shaped_text_get_range, RID); + + virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; + virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; + virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override; + GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, int64_t); + GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, int64_t); + GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, int64_t); + + virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override; + virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override; + virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override; + virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override; + GDVIRTUAL1RC(int64_t, shaped_text_get_trim_pos, RID); + GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_pos, RID); + GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_ellipsis_glyphs, RID); + GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_glyph_count, RID); + + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override; + GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, int64_t); + + virtual Array shaped_text_get_objects(const RID &p_shaped) const override; + virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override; + GDVIRTUAL1RC(Array, shaped_text_get_objects, RID); + GDVIRTUAL2RC(Rect2, shaped_text_get_object_rect, RID, const Variant &); + + virtual Size2 shaped_text_get_size(const RID &p_shaped) const override; + virtual double shaped_text_get_ascent(const RID &p_shaped) const override; + virtual double shaped_text_get_descent(const RID &p_shaped) const override; + virtual double shaped_text_get_width(const RID &p_shaped) const override; + virtual double shaped_text_get_underline_position(const RID &p_shaped) const override; + virtual double shaped_text_get_underline_thickness(const RID &p_shaped) const override; + GDVIRTUAL1RC(Size2, shaped_text_get_size, RID); + GDVIRTUAL1RC(double, shaped_text_get_ascent, RID); + GDVIRTUAL1RC(double, shaped_text_get_descent, RID); + GDVIRTUAL1RC(double, shaped_text_get_width, RID); + GDVIRTUAL1RC(double, shaped_text_get_underline_position, RID); + GDVIRTUAL1RC(double, shaped_text_get_underline_thickness, RID); + + virtual Direction shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const override; + GDVIRTUAL3RC(int64_t, shaped_text_get_dominant_direction_in_range, RID, int64_t, int64_t); + + virtual CaretInfo shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const override; + virtual Vector<Vector2> shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const override; + GDVIRTUAL3C(shaped_text_get_carets, RID, int64_t, GDNativePtr<CaretInfo>); + GDVIRTUAL3RC(Vector<Vector2>, shaped_text_get_selection, RID, int64_t, int64_t); + + virtual int64_t shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const override; + virtual int64_t shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const override; + GDVIRTUAL2RC(int64_t, shaped_text_hit_test_grapheme, RID, double); + GDVIRTUAL2RC(int64_t, shaped_text_hit_test_position, RID, double); + + virtual void shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, const Color &p_color = Color(1, 1, 1)) const override; + virtual void shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, int64_t p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override; + GDVIRTUAL6C(shaped_text_draw, RID, RID, const Vector2 &, double, double, const Color &); + GDVIRTUAL7C(shaped_text_draw_outline, RID, RID, const Vector2 &, double, double, int64_t, const Color &); + + virtual Vector2 shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const override; + virtual int64_t shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const override; + virtual int64_t shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const override; + GDVIRTUAL2RC(Vector2, shaped_text_get_grapheme_bounds, RID, int64_t); + GDVIRTUAL2RC(int64_t, shaped_text_next_grapheme_pos, RID, int64_t); + GDVIRTUAL2RC(int64_t, shaped_text_prev_grapheme_pos, RID, int64_t); virtual String format_number(const String &p_string, const String &p_language = "") const override; virtual String parse_number(const String &p_string, const String &p_language = "") const override; virtual String percent_sign(const String &p_language = "") const override; - GDVIRTUAL2RC(String, _format_number, const String &, const String &); - GDVIRTUAL2RC(String, _parse_number, const String &, const String &); - GDVIRTUAL1RC(String, _percent_sign, const String &); + GDVIRTUAL2RC(String, format_number, const String &, const String &); + GDVIRTUAL2RC(String, parse_number, const String &, const String &); + GDVIRTUAL1RC(String, percent_sign, const String &); + + virtual String strip_diacritics(const String &p_string) const override; + GDVIRTUAL1RC(String, strip_diacritics, const String &); virtual String string_to_upper(const String &p_string, const String &p_language = "") const override; virtual String string_to_lower(const String &p_string, const String &p_language = "") const override; - GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &); - GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &); + GDVIRTUAL2RC(String, string_to_upper, const String &, const String &); + GDVIRTUAL2RC(String, string_to_lower, const String &, const String &); TextServerExtension(); ~TextServerExtension(); diff --git a/servers/text_server.cpp b/servers/text_server.cpp index aaba79c049..2f32e81f06 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -200,7 +200,7 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("tag_to_name", "tag"), &TextServer::tag_to_name); ClassDB::bind_method(D_METHOD("has", "rid"), &TextServer::has); - ClassDB::bind_method(D_METHOD("free_rid", "rid"), &TextServer::free); // shouldn't conflict with Object::free() + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &TextServer::free_rid); /* Font Interface */ @@ -493,13 +493,19 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_AUTO); BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_HALF); BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_QUARTER); + BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE); + BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE); /* Feature */ + BIND_ENUM_CONSTANT(FEATURE_SIMPLE_LAYOUT); BIND_ENUM_CONSTANT(FEATURE_BIDI_LAYOUT); BIND_ENUM_CONSTANT(FEATURE_VERTICAL_LAYOUT); BIND_ENUM_CONSTANT(FEATURE_SHAPING); BIND_ENUM_CONSTANT(FEATURE_KASHIDA_JUSTIFICATION); BIND_ENUM_CONSTANT(FEATURE_BREAK_ITERATORS); + BIND_ENUM_CONSTANT(FEATURE_FONT_BITMAP); + BIND_ENUM_CONSTANT(FEATURE_FONT_DYNAMIC); + BIND_ENUM_CONSTANT(FEATURE_FONT_MSDF); BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM); BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE); BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION); @@ -522,7 +528,7 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH); } -Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const { +Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const { int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)); int sp = MAX(0, w - 1); int sz = MAX(1, Math::round(p_size / 15.f)); @@ -530,7 +536,7 @@ Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const { return Vector2(4 + 3 * w + sp + 1, 15) * sz; } -void TextServer::_draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const { +void TextServer::_draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const { static uint8_t chars[] = { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x77, 0x1F, 0x4E, 0x3D, 0x4F, 0x47, 0x00 }; uint8_t x = chars[p_index]; if (x & (1 << 6)) { @@ -556,7 +562,7 @@ void TextServer::_draw_hex_code_box_number(RID p_canvas, int p_size, const Vecto } } -void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const { +void TextServer::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { if (p_index == 0) { return; } @@ -600,7 +606,7 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po } } -PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t /*TextBreakFlag*/ p_break_flags) const { +PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t /*TextBreakFlag*/ p_break_flags) const { PackedInt32Array lines; ERR_FAIL_COND_V(p_width.is_empty(), lines); @@ -676,13 +682,13 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const return lines; } -PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t /*TextBreakFlag*/ p_break_flags) const { +PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t /*TextBreakFlag*/ p_break_flags) const { PackedInt32Array lines; const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped); const Vector2i &range = shaped_text_get_range(p_shaped); - float width = 0.f; + double width = 0.f; int line_start = MAX(p_start, range.x); int last_safe_break = -1; int word_count = 0; @@ -744,7 +750,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w return lines; } -PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const { +PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const { PackedInt32Array words; const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped); @@ -752,7 +758,7 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_gra int word_start = range.x; - int l_size = shaped_text_get_glyph_count(p_shaped); + const int l_size = shaped_text_get_glyph_count(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); for (int i = 0; i < l_size; i++) { @@ -776,7 +782,7 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_gra return words; } -CaretInfo TextServer::shaped_text_get_carets(RID p_shaped, int p_position) const { +CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const { Vector<Rect2> carets; TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped); @@ -926,7 +932,7 @@ CaretInfo TextServer::shaped_text_get_carets(RID p_shaped, int p_position) const return caret; } -Dictionary TextServer::_shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const { +Dictionary TextServer::_shaped_text_get_carets_wrapper(const RID &p_shaped, int64_t p_position) const { Dictionary ret; CaretInfo caret = shaped_text_get_carets(p_shaped, p_position); @@ -939,7 +945,7 @@ Dictionary TextServer::_shaped_text_get_carets_wrapper(RID p_shaped, int p_posit return ret; } -TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const { +TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const { if (p_start == p_end) { return DIRECTION_AUTO; } @@ -973,7 +979,7 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(RI } } -Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const { +Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const { Vector<Vector2> ranges; if (p_start == p_end) { @@ -1066,9 +1072,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, return ranges; } -int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const { +int64_t TextServer::shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const { // Exact grapheme hit test, return -1 if missed. - float off = 0.0f; + double off = 0.0f; int v_size = shaped_text_get_glyph_count(p_shaped); const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); @@ -1084,7 +1090,7 @@ int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) cons return -1; } -int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) const { +int64_t TextServer::shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const { int v_size = shaped_text_get_glyph_count(p_shaped); const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); @@ -1177,7 +1183,7 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) cons return 0; } -Vector2 TextServer::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const { +Vector2 TextServer::shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const { int v_size = shaped_text_get_glyph_count(p_shaped); const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); @@ -1198,7 +1204,7 @@ Vector2 TextServer::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) con return Vector2(); } -int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const { +int64_t TextServer::shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const { int v_size = shaped_text_get_glyph_count(p_shaped); const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); for (int i = 0; i < v_size; i++) { @@ -1209,7 +1215,7 @@ int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const { return p_pos; } -int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const { +int64_t TextServer::shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const { int v_size = shaped_text_get_glyph_count(p_shaped); const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); for (int i = 0; i < v_size; i++) { @@ -1221,7 +1227,7 @@ int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const { return p_pos; } -void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const { +void TextServer::shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, const Color &p_color) const { TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped); bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped); @@ -1318,7 +1324,7 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p } } -void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const { +void TextServer::shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, int64_t p_outline_size, const Color &p_color) const { TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped); bool rtl = (shaped_text_get_inferred_direction(p_shaped) == DIRECTION_RTL); @@ -1538,7 +1544,7 @@ String TextServer::strip_diacritics(const String &p_string) const { return result; } -Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const { +Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const { Array ret; const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); @@ -1563,7 +1569,7 @@ Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const { return ret; } -Array TextServer::_shaped_text_sort_logical_wrapper(RID p_shaped) { +Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) { Array ret; const Glyph *glyphs = shaped_text_sort_logical(p_shaped); @@ -1588,7 +1594,7 @@ Array TextServer::_shaped_text_sort_logical_wrapper(RID p_shaped) { return ret; } -Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const { +Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const { Array ret; const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped); diff --git a/servers/text_server.h b/servers/text_server.h index 83dc3df56d..365b7ff663 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -102,25 +102,29 @@ public: }; enum SubpixelPositioning { - SUBPIXEL_POSITIONING_DISABLED, - SUBPIXEL_POSITIONING_AUTO, - SUBPIXEL_POSITIONING_ONE_HALF, - SUBPIXEL_POSITIONING_ONE_QUARTER, - }; + SUBPIXEL_POSITIONING_DISABLED = 0, + SUBPIXEL_POSITIONING_AUTO = 1, + SUBPIXEL_POSITIONING_ONE_HALF = 2, + SUBPIXEL_POSITIONING_ONE_QUARTER = 3, - const int SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE = 20; - const int SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE = 16; + SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE = 20, + SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE = 16, + }; enum Feature { - FEATURE_BIDI_LAYOUT = 1 << 0, - FEATURE_VERTICAL_LAYOUT = 1 << 1, - FEATURE_SHAPING = 1 << 2, - FEATURE_KASHIDA_JUSTIFICATION = 1 << 3, - FEATURE_BREAK_ITERATORS = 1 << 4, - FEATURE_FONT_SYSTEM = 1 << 5, - FEATURE_FONT_VARIABLE = 1 << 6, - FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 7, - FEATURE_USE_SUPPORT_DATA = 1 << 8, + FEATURE_SIMPLE_LAYOUT = 1 << 0, + FEATURE_BIDI_LAYOUT = 1 << 1, + FEATURE_VERTICAL_LAYOUT = 1 << 2, + FEATURE_SHAPING = 1 << 3, + FEATURE_KASHIDA_JUSTIFICATION = 1 << 4, + FEATURE_BREAK_ITERATORS = 1 << 5, + FEATURE_FONT_BITMAP = 1 << 6, + FEATURE_FONT_DYNAMIC = 1 << 7, + FEATURE_FONT_MSDF = 1 << 8, + FEATURE_FONT_SYSTEM = 1 << 9, + FEATURE_FONT_VARIABLE = 1 << 10, + FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 11, + FEATURE_USE_SUPPORT_DATA = 1 << 12, }; enum ContourPointTag { @@ -142,62 +146,9 @@ public: FONT_FIXED_WIDTH = 1 << 2, }; - void _draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; + void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; protected: - struct TrimData { - int trim_pos = -1; - int ellipsis_pos = -1; - Vector<Glyph> ellipsis_glyph_buf; - }; - - struct ShapedTextData { - Mutex mutex; - - /* Source data */ - RID parent; // Substring parent ShapedTextData. - - int start = 0; // Substring start offset in the parent string. - int end = 0; // Substring end offset in the parent string. - - String text; - String custom_punct; - TextServer::Direction direction = DIRECTION_LTR; // Desired text direction. - TextServer::Orientation orientation = ORIENTATION_HORIZONTAL; - - struct EmbeddedObject { - int pos = 0; - InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER; - Rect2 rect; - }; - Map<Variant, EmbeddedObject> objects; - - /* Shaped data */ - TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction. - bool valid = false; // String is shaped. - bool line_breaks_valid = false; // Line and word break flags are populated (and virtual zero width spaces inserted). - bool justification_ops_valid = false; // Virtual elongation glyphs are added to the string. - bool sort_valid = false; - bool text_trimmed = false; - - bool preserve_invalid = true; // Draw hex code box instead of missing characters. - bool preserve_control = false; // Draw control characters. - - float ascent = 0.f; // Ascent for horizontal layout, 1/2 of width for vertical. - float descent = 0.f; // Descent for horizontal layout, 1/2 of width for vertical. - float width = 0.f; // Width for horizontal layout, height for vertical. - float width_trimmed = 0.f; - - float upos = 0.f; - float uthk = 0.f; - - TrimData overrun_trim_data; - bool fit_width_minimum_reached = false; - - Vector<Glyph> glyphs; - Vector<Glyph> glyphs_logical; - }; - Map<char32_t, char32_t> diacritics_map; void _diacritics_map_add(const String &p_from, char32_t p_to); void _init_diacritics_map(); @@ -207,10 +158,10 @@ protected: public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; - virtual uint32_t get_features() const = 0; + virtual int64_t get_features() const = 0; - virtual void free(RID p_rid) = 0; - virtual bool has(RID p_rid) = 0; + virtual void free_rid(const RID &p_rid) = 0; + virtual bool has(const RID &p_rid) = 0; virtual bool load_support_data(const String &p_filename) = 0; virtual String get_support_data_filename() const = 0; @@ -219,251 +170,251 @@ public: virtual bool is_locale_right_to_left(const String &p_locale) const = 0; - virtual int32_t name_to_tag(const String &p_name) const { return 0; }; - virtual String tag_to_name(int32_t p_tag) const { return ""; }; + virtual int64_t name_to_tag(const String &p_name) const { return 0; }; + virtual String tag_to_name(int64_t p_tag) const { return ""; }; /* Font interface */ virtual RID create_font() = 0; - virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0; - virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0; + virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) = 0; + virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) = 0; - virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) = 0; - virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const = 0; + virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) = 0; + virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const = 0; - virtual void font_set_name(RID p_font_rid, const String &p_name) = 0; - virtual String font_get_name(RID p_font_rid) const = 0; + virtual void font_set_name(const RID &p_font_rid, const String &p_name) = 0; + virtual String font_get_name(const RID &p_font_rid) const = 0; - virtual void font_set_style_name(RID p_font_rid, const String &p_name) = 0; - virtual String font_get_style_name(RID p_font_rid) const = 0; + virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0; + virtual String font_get_style_name(const RID &p_font_rid) const = 0; - virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0; - virtual bool font_is_antialiased(RID p_font_rid) const = 0; + virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0; + virtual bool font_is_antialiased(const RID &p_font_rid) const = 0; - virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) = 0; - virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const = 0; + virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) = 0; + virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const = 0; - virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) = 0; - virtual int font_get_msdf_pixel_range(RID p_font_rid) const = 0; + virtual void font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) = 0; + virtual int64_t font_get_msdf_pixel_range(const RID &p_font_rid) const = 0; - virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) = 0; - virtual int font_get_msdf_size(RID p_font_rid) const = 0; + virtual void font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) = 0; + virtual int64_t font_get_msdf_size(const RID &p_font_rid) const = 0; - virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) = 0; - virtual int font_get_fixed_size(RID p_font_rid) const = 0; + virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) = 0; + virtual int64_t font_get_fixed_size(const RID &p_font_rid) const = 0; - virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) = 0; - virtual bool font_is_force_autohinter(RID p_font_rid) const = 0; + virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) = 0; + virtual bool font_is_force_autohinter(const RID &p_font_rid) const = 0; - virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) = 0; - virtual Hinting font_get_hinting(RID p_font_rid) const = 0; + virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) = 0; + virtual Hinting font_get_hinting(const RID &p_font_rid) const = 0; - virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0; - virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0; + virtual void font_set_subpixel_positioning(const RID &p_font_rid, SubpixelPositioning p_subpixel) = 0; + virtual SubpixelPositioning font_get_subpixel_positioning(const RID &p_font_rid) const = 0; - virtual void font_set_embolden(RID p_font_rid, float p_strength) = 0; - virtual float font_get_embolden(RID p_font_rid) const = 0; + virtual void font_set_embolden(const RID &p_font_rid, double p_strength) = 0; + virtual double font_get_embolden(const RID &p_font_rid) const = 0; - virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) = 0; - virtual Transform2D font_get_transform(RID p_font_rid) const = 0; + virtual void font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) = 0; + virtual Transform2D font_get_transform(const RID &p_font_rid) const = 0; - virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0; - virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0; + virtual void font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) = 0; + virtual Dictionary font_get_variation_coordinates(const RID &p_font_rid) const = 0; - virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) = 0; - virtual float font_get_oversampling(RID p_font_rid) const = 0; + virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) = 0; + virtual double font_get_oversampling(const RID &p_font_rid) const = 0; - virtual Array font_get_size_cache_list(RID p_font_rid) const = 0; - virtual void font_clear_size_cache(RID p_font_rid) = 0; - virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) = 0; + virtual Array font_get_size_cache_list(const RID &p_font_rid) const = 0; + virtual void font_clear_size_cache(const RID &p_font_rid) = 0; + virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) = 0; - virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) = 0; - virtual float font_get_ascent(RID p_font_rid, int p_size) const = 0; + virtual void font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) = 0; + virtual double font_get_ascent(const RID &p_font_rid, int64_t p_size) const = 0; - virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) = 0; - virtual float font_get_descent(RID p_font_rid, int p_size) const = 0; + virtual void font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) = 0; + virtual double font_get_descent(const RID &p_font_rid, int64_t p_size) const = 0; - virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) = 0; - virtual float font_get_underline_position(RID p_font_rid, int p_size) const = 0; + virtual void font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) = 0; + virtual double font_get_underline_position(const RID &p_font_rid, int64_t p_size) const = 0; - virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) = 0; - virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const = 0; + virtual void font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) = 0; + virtual double font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const = 0; - virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) = 0; - virtual float font_get_scale(RID p_font_rid, int p_size) const = 0; + virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) = 0; + virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const = 0; - virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) = 0; - virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const = 0; + virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) = 0; + virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const = 0; - virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const = 0; - virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) = 0; - virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) = 0; + virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const = 0; + virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) = 0; + virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) = 0; - virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) = 0; - virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0; + virtual void font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) = 0; + virtual Ref<Image> font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const = 0; - virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) = 0; - virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0; + virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) = 0; + virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const = 0; - virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const = 0; - virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) = 0; - virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) = 0; + virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0; + virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) = 0; + virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) = 0; - virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const = 0; - virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) = 0; + virtual Vector2 font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const = 0; + virtual void font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) = 0; - virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; - virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) = 0; + virtual Vector2 font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; + virtual void font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) = 0; - virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; - virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) = 0; + virtual Vector2 font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; + virtual void font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) = 0; - virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; - virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) = 0; + virtual Rect2 font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; + virtual void font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) = 0; - virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; - virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) = 0; + virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; + virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) = 0; - virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const = 0; + virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0; - virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const = 0; - virtual void font_clear_kerning_map(RID p_font_rid, int p_size) = 0; - virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) = 0; + virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0; + virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) = 0; + virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) = 0; - virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) = 0; - virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const = 0; + virtual void font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) = 0; + virtual Vector2 font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const = 0; - virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const = 0; + virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const = 0; - virtual bool font_has_char(RID p_font_rid, char32_t p_char) const = 0; - virtual String font_get_supported_chars(RID p_font_rid) const = 0; + virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const = 0; + virtual String font_get_supported_chars(const RID &p_font_rid) const = 0; - virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) = 0; - virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) = 0; + virtual void font_render_range(const RID &p_font, const Vector2i &p_size, int64_t p_start, int64_t p_end) = 0; + virtual void font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) = 0; - virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; - virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; + virtual void font_draw_glyph(const RID &p_font, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; + virtual void font_draw_glyph_outline(const RID &p_font, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; - virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const = 0; - virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) = 0; - virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) = 0; - virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) = 0; - virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) = 0; + virtual bool font_is_language_supported(const RID &p_font_rid, const String &p_language) const = 0; + virtual void font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) = 0; + virtual bool font_get_language_support_override(const RID &p_font_rid, const String &p_language) = 0; + virtual void font_remove_language_support_override(const RID &p_font_rid, const String &p_language) = 0; + virtual PackedStringArray font_get_language_support_overrides(const RID &p_font_rid) = 0; - virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const = 0; - virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) = 0; - virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) = 0; - virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) = 0; - virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) = 0; + virtual bool font_is_script_supported(const RID &p_font_rid, const String &p_script) const = 0; + virtual void font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) = 0; + virtual bool font_get_script_support_override(const RID &p_font_rid, const String &p_script) = 0; + virtual void font_remove_script_support_override(const RID &p_font_rid, const String &p_script) = 0; + virtual PackedStringArray font_get_script_support_overrides(const RID &p_font_rid) = 0; - virtual void font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) = 0; - virtual Dictionary font_get_opentype_feature_overrides(RID p_font_rid) const = 0; + virtual void font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) = 0; + virtual Dictionary font_get_opentype_feature_overrides(const RID &p_font_rid) const = 0; - virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0; - virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0; + virtual Dictionary font_supported_feature_list(const RID &p_font_rid) const = 0; + virtual Dictionary font_supported_variation_list(const RID &p_font_rid) const = 0; - virtual float font_get_global_oversampling() const = 0; - virtual void font_set_global_oversampling(float p_oversampling) = 0; + virtual double font_get_global_oversampling() const = 0; + virtual void font_set_global_oversampling(double p_oversampling) = 0; - virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const; - virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const; + virtual Vector2 get_hex_code_box_size(int64_t p_size, int64_t p_index) const; + virtual void draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const; /* Shaped text buffer interface */ virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; - virtual void shaped_text_clear(RID p_shaped) = 0; + virtual void shaped_text_clear(const RID &p_shaped) = 0; - virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) = 0; - virtual Direction shaped_text_get_direction(RID p_shaped) const = 0; - virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const = 0; + virtual void shaped_text_set_direction(const RID &p_shaped, Direction p_direction = DIRECTION_AUTO) = 0; + virtual Direction shaped_text_get_direction(const RID &p_shaped) const = 0; + virtual Direction shaped_text_get_inferred_direction(const RID &p_shaped) const = 0; - virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0; + virtual void shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) = 0; - virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) = 0; - virtual String shaped_text_get_custom_punctuation(RID p_shaped) const = 0; + virtual void shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) = 0; + virtual String shaped_text_get_custom_punctuation(const RID &p_shaped) const = 0; - virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; - virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0; + virtual void shaped_text_set_orientation(const RID &p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; + virtual Orientation shaped_text_get_orientation(const RID &p_shaped) const = 0; - virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) = 0; - virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const = 0; + virtual void shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) = 0; + virtual bool shaped_text_get_preserve_invalid(const RID &p_shaped) const = 0; - virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) = 0; - virtual bool shaped_text_get_preserve_control(RID p_shaped) const = 0; + virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) = 0; + virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const = 0; - virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0; - virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) = 0; - virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0; + virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0; + virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) = 0; + virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0; - virtual int shaped_get_span_count(RID p_shaped) const = 0; - virtual Variant shaped_get_span_meta(RID p_shaped, int p_index) const = 0; - virtual void shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary()) = 0; + virtual int64_t shaped_get_span_count(const RID &p_shaped) const = 0; + virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const = 0; + virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) = 0; - virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range. - virtual RID shaped_text_get_parent(RID p_shaped) const = 0; + virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range. + virtual RID shaped_text_get_parent(const RID &p_shaped) const = 0; - virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; - virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) = 0; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; + virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) = 0; - virtual bool shaped_text_shape(RID p_shaped) = 0; - virtual bool shaped_text_update_breaks(RID p_shaped) = 0; - virtual bool shaped_text_update_justification_ops(RID p_shaped) = 0; + virtual bool shaped_text_shape(const RID &p_shaped) = 0; + virtual bool shaped_text_update_breaks(const RID &p_shaped) = 0; + virtual bool shaped_text_update_justification_ops(const RID &p_shaped) = 0; - virtual bool shaped_text_is_ready(RID p_shaped) const = 0; + virtual bool shaped_text_is_ready(const RID &p_shaped) const = 0; - virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const = 0; - Array _shaped_text_get_glyphs_wrapper(RID p_shaped) const; - virtual const Glyph *shaped_text_sort_logical(RID p_shaped) = 0; - Array _shaped_text_sort_logical_wrapper(RID p_shaped); - virtual int shaped_text_get_glyph_count(RID p_shaped) const = 0; + virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const = 0; + Array _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const; + virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) = 0; + Array _shaped_text_sort_logical_wrapper(const RID &p_shaped); + virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const = 0; - virtual Vector2i shaped_text_get_range(RID p_shaped) const = 0; + virtual Vector2i shaped_text_get_range(const RID &p_shaped) const = 0; - virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; + virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; + virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; + virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; - virtual int shaped_text_get_trim_pos(RID p_shaped) const = 0; - virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const = 0; - virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const = 0; - Array _shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const; - virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const = 0; + virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0; + virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0; + virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const = 0; + Array _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const; + virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const = 0; - virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) = 0; + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) = 0; - virtual Array shaped_text_get_objects(RID p_shaped) const = 0; - virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0; + virtual Array shaped_text_get_objects(const RID &p_shaped) const = 0; + virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const = 0; - virtual Size2 shaped_text_get_size(RID p_shaped) const = 0; - virtual float shaped_text_get_ascent(RID p_shaped) const = 0; - virtual float shaped_text_get_descent(RID p_shaped) const = 0; - virtual float shaped_text_get_width(RID p_shaped) const = 0; - virtual float shaped_text_get_underline_position(RID p_shaped) const = 0; - virtual float shaped_text_get_underline_thickness(RID p_shaped) const = 0; + virtual Size2 shaped_text_get_size(const RID &p_shaped) const = 0; + virtual double shaped_text_get_ascent(const RID &p_shaped) const = 0; + virtual double shaped_text_get_descent(const RID &p_shaped) const = 0; + virtual double shaped_text_get_width(const RID &p_shaped) const = 0; + virtual double shaped_text_get_underline_position(const RID &p_shaped) const = 0; + virtual double shaped_text_get_underline_thickness(const RID &p_shaped) const = 0; - virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const; + virtual Direction shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const; - virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const; - Dictionary _shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const; + virtual CaretInfo shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const; + Dictionary _shaped_text_get_carets_wrapper(const RID &p_shaped, int64_t p_position) const; - virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const; + virtual Vector<Vector2> shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const; - virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index. - virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const; // Return caret/selection position. + virtual int64_t shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const; // Return grapheme index. + virtual int64_t shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const; // Return caret/selection position. - virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const; - virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const; - virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const; + virtual Vector2 shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const; + virtual int64_t shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const; + virtual int64_t shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const; // The pen position is always placed on the baseline and moveing left to right. - virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const; - virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const; + virtual void shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, const Color &p_color = Color(1, 1, 1)) const; + virtual void shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, int64_t p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const; // Number conversion. - virtual String format_number(const String &p_string, const String &p_language = "") const { return p_string; }; - virtual String parse_number(const String &p_string, const String &p_language = "") const { return p_string; }; - virtual String percent_sign(const String &p_language = "") const { return "%"; }; + virtual String format_number(const String &p_string, const String &p_language = "") const = 0; + virtual String parse_number(const String &p_string, const String &p_language = "") const = 0; + virtual String percent_sign(const String &p_language = "") const = 0; virtual String strip_diacritics(const String &p_string) const; @@ -507,23 +458,6 @@ struct CaretInfo { TextServer::Direction t_dir; }; -struct GlyphCompare { // For line breaking reordering. - _FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const { - if (l.start == r.start) { - if (l.count == r.count) { - if ((l.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) { - return false; - } else { - return true; - } - } - return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant. - } else { - return l.start < r.start; - } - } -}; - /*************************************************************************/ class TextServerManager : public Object { |