diff options
140 files changed, 2601 insertions, 1320 deletions
diff --git a/core/math/bvh.h b/core/math/bvh.h index a8e3cc7bbe..e686e27445 100644 --- a/core/math/bvh.h +++ b/core/math/bvh.h @@ -46,21 +46,35 @@ // Layer masks are implemented in the renderers as a later step, and light_cull_mask appears to be // implemented in GLES3 but not GLES2. Layer masks are not yet implemented for directional lights. +// In the physics, the pairable_type is based on 1 << p_object->get_type() where: +// TYPE_AREA, +// TYPE_BODY +// and pairable_mask is either 0 if static, or set to all if non static + #include "bvh_tree.h" +#include "core/os/mutex.h" -#define BVHTREE_CLASS BVH_Tree<T, 2, MAX_ITEMS, USE_PAIRS, Bounds, Point> +#define BVHTREE_CLASS BVH_Tree<T, NUM_TREES, 2, MAX_ITEMS, USER_PAIR_TEST_FUNCTION, USER_CULL_TEST_FUNCTION, USE_PAIRS, BOUNDS, POINT> +#define BVH_LOCKED_FUNCTION BVHLockedFunction(&_mutex, BVH_THREAD_SAFE &&_thread_safe); -template <class T, bool USE_PAIRS = false, int MAX_ITEMS = 32, class Bounds = AABB, class Point = Vector3> +template <class T, int NUM_TREES = 1, bool USE_PAIRS = false, int MAX_ITEMS = 32, class USER_PAIR_TEST_FUNCTION = BVH_DummyPairTestFunction<T>, class USER_CULL_TEST_FUNCTION = BVH_DummyCullTestFunction<T>, class BOUNDS = AABB, class POINT = Vector3, bool BVH_THREAD_SAFE = true> class BVH_Manager { public: // note we are using uint32_t instead of BVHHandle, losing type safety, but this // is for compatibility with octree typedef void *(*PairCallback)(void *, uint32_t, T *, int, uint32_t, T *, int); typedef void (*UnpairCallback)(void *, uint32_t, T *, int, uint32_t, T *, int, void *); + typedef void *(*CheckPairCallback)(void *, uint32_t, T *, int, uint32_t, T *, int, void *); + + // allow locally toggling thread safety if the template has been compiled with BVH_THREAD_SAFE + void params_set_thread_safe(bool p_enable) { + _thread_safe = p_enable; + } // these 2 are crucial for fine tuning, and can be applied manually // see the variable declarations for more info. void params_set_node_expansion(real_t p_value) { + BVH_LOCKED_FUNCTION if (p_value >= 0.0) { tree._node_expansion = p_value; tree._auto_node_expansion = false; @@ -70,43 +84,40 @@ public: } void params_set_pairing_expansion(real_t p_value) { - if (p_value >= 0.0) { - tree._pairing_expansion = p_value; - tree._auto_pairing_expansion = false; - } else { - tree._auto_pairing_expansion = true; - } + BVH_LOCKED_FUNCTION + tree.params_set_pairing_expansion(p_value); } void set_pair_callback(PairCallback p_callback, void *p_userdata) { + BVH_LOCKED_FUNCTION pair_callback = p_callback; pair_callback_userdata = p_userdata; } void set_unpair_callback(UnpairCallback p_callback, void *p_userdata) { + BVH_LOCKED_FUNCTION unpair_callback = p_callback; unpair_callback_userdata = p_userdata; } + void set_check_pair_callback(CheckPairCallback p_callback, void *p_userdata) { + BVH_LOCKED_FUNCTION + check_pair_callback = p_callback; + check_pair_callback_userdata = p_userdata; + } + + BVHHandle create(T *p_userdata, bool p_active = true, uint32_t p_tree_id = 0, uint32_t p_tree_collision_mask = 1, const BOUNDS &p_aabb = BOUNDS(), int p_subindex = 0) { + BVH_LOCKED_FUNCTION - BVHHandle create(T *p_userdata, bool p_active, const Bounds &p_aabb = Bounds(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t p_pairable_mask = 1) { // not sure if absolutely necessary to flush collisions here. It will cost performance to, instead // of waiting for update, so only uncomment this if there are bugs. if (USE_PAIRS) { //_check_for_collisions(); } -#ifdef TOOLS_ENABLED - if (!USE_PAIRS) { - if (p_pairable) { - WARN_PRINT_ONCE("creating pairable item in BVH with USE_PAIRS set to false"); - } - } -#endif - - BVHHandle h = tree.item_add(p_userdata, p_active, p_aabb, p_subindex, p_pairable, p_pairable_type, p_pairable_mask); + BVHHandle h = tree.item_add(p_userdata, p_active, p_aabb, p_subindex, p_tree_id, p_tree_collision_mask); if (USE_PAIRS) { // for safety initialize the expanded AABB - Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb; + BOUNDS &expanded_aabb = tree._pairs[h.id()].expanded_aabb; expanded_aabb = p_aabb; expanded_aabb.grow_by(tree._pairing_expansion); @@ -123,12 +134,18 @@ public: //////////////////////////////////////////////////// // wrapper versions that use uint32_t instead of handle // for backward compatibility. Less type safe - void move(uint32_t p_handle, const Bounds &p_aabb) { + void move(uint32_t p_handle, const BOUNDS &p_aabb) { BVHHandle h; h.set(p_handle); move(h, p_aabb); } + void recheck_pairs(uint32_t p_handle) { + BVHHandle h; + h.set(p_handle); + recheck_pairs(h); + } + void erase(uint32_t p_handle) { BVHHandle h; h.set(p_handle); @@ -141,7 +158,7 @@ public: force_collision_check(h); } - bool activate(uint32_t p_handle, const Bounds &p_aabb, bool p_delay_collision_check = false) { + bool activate(uint32_t p_handle, const BOUNDS &p_aabb, bool p_delay_collision_check = false) { BVHHandle h; h.set(p_handle); return activate(h, p_aabb, p_delay_collision_check); @@ -153,16 +170,16 @@ public: return deactivate(h); } - void set_pairable(uint32_t p_handle, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_force_collision_check = true) { + void set_tree(uint32_t p_handle, uint32_t p_tree_id, uint32_t p_tree_collision_mask, bool p_force_collision_check = true) { BVHHandle h; h.set(p_handle); - set_pairable(h, p_pairable, p_pairable_type, p_pairable_mask, p_force_collision_check); + set_tree(h, p_tree_id, p_tree_collision_mask, p_force_collision_check); } - bool is_pairable(uint32_t p_handle) const { + uint32_t get_tree_id(uint32_t p_handle) const { BVHHandle h; h.set(p_handle); - return item_is_pairable(h); + return item_get_tree_id(h); } int get_subindex(uint32_t p_handle) const { BVHHandle h; @@ -178,7 +195,8 @@ public: //////////////////////////////////////////////////// - void move(BVHHandle p_handle, const Bounds &p_aabb) { + void move(BVHHandle p_handle, const BOUNDS &p_aabb) { + BVH_LOCKED_FUNCTION if (tree.item_move(p_handle, p_aabb)) { if (USE_PAIRS) { _add_changed_item(p_handle, p_aabb); @@ -186,7 +204,12 @@ public: } } + void recheck_pairs(BVHHandle p_handle) { + force_collision_check(p_handle); + } + void erase(BVHHandle p_handle) { + BVH_LOCKED_FUNCTION // call unpair and remove all references to the item // before deleting from the tree if (USE_PAIRS) { @@ -200,11 +223,12 @@ public: // use in conjunction with activate if you have deferred the collision check, and // set pairable has never been called. - // (deferred collision checks are a workaround for rendering server for historical reasons) + // (deferred collision checks are a workaround for visual server for historical reasons) void force_collision_check(BVHHandle p_handle) { + BVH_LOCKED_FUNCTION if (USE_PAIRS) { // the aabb should already be up to date in the BVH - Bounds aabb; + BOUNDS aabb; item_get_AABB(p_handle, aabb); // add it as changed even if aabb not different @@ -218,7 +242,8 @@ public: // these should be read as set_visible for render trees, // but generically this makes items add or remove from the // tree internally, to speed things up by ignoring inactive items - bool activate(BVHHandle p_handle, const Bounds &p_aabb, bool p_delay_collision_check = false) { + bool activate(BVHHandle p_handle, const BOUNDS &p_aabb, bool p_delay_collision_check = false) { + BVH_LOCKED_FUNCTION // sending the aabb here prevents the need for the BVH to maintain // a redundant copy of the aabb. // returns success @@ -242,6 +267,7 @@ public: } bool deactivate(BVHHandle p_handle) { + BVH_LOCKED_FUNCTION // returns success if (tree.item_deactivate(p_handle)) { // call unpair and remove all references to the item @@ -258,12 +284,14 @@ public: return false; } - bool get_active(BVHHandle p_handle) const { + bool get_active(BVHHandle p_handle) { + BVH_LOCKED_FUNCTION return tree.item_get_active(p_handle); } // call e.g. once per frame (this does a trickle optimize) void update() { + BVH_LOCKED_FUNCTION tree.update(); _check_for_collisions(); #ifdef BVH_INTEGRITY_CHECKS @@ -273,24 +301,26 @@ public: // this can be called more frequently than per frame if necessary void update_collisions() { + BVH_LOCKED_FUNCTION _check_for_collisions(); } // prefer calling this directly as type safe - void set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_force_collision_check = true) { + void set_tree(const BVHHandle &p_handle, uint32_t p_tree_id, uint32_t p_tree_collision_mask, bool p_force_collision_check = true) { + BVH_LOCKED_FUNCTION // Returns true if the pairing state has changed. - bool state_changed = tree.item_set_pairable(p_handle, p_pairable, p_pairable_type, p_pairable_mask); + bool state_changed = tree.item_set_tree(p_handle, p_tree_id, p_tree_collision_mask); if (USE_PAIRS) { // not sure if absolutely necessary to flush collisions here. It will cost performance to, instead // of waiting for update, so only uncomment this if there are bugs. //_check_for_collisions(); - if ((p_force_collision_check || state_changed) && get_active(p_handle)) { + if ((p_force_collision_check || state_changed) && tree.item_get_active(p_handle)) { // when the pairable state changes, we need to force a collision check because newly pairable // items may be in collision, and unpairable items might move out of collision. // We cannot depend on waiting for the next update, because that may come much later. - Bounds aabb; + BOUNDS aabb; item_get_AABB(p_handle, aabb); // passing false disables the optimization which prevents collision checks if @@ -307,32 +337,33 @@ public: } // cull tests - int cull_aabb(const Bounds &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) { + int cull_aabb(const BOUNDS &p_aabb, T **p_result_array, int p_result_max, const T *p_tester, uint32_t p_tree_collision_mask = 0xFFFFFFFF, int *p_subindex_array = nullptr) { + BVH_LOCKED_FUNCTION typename BVHTREE_CLASS::CullParams params; params.result_count_overall = 0; params.result_max = p_result_max; params.result_array = p_result_array; params.subindex_array = p_subindex_array; - params.mask = p_mask; - params.pairable_type = 0; - params.test_pairable_only = false; + params.tree_collision_mask = p_tree_collision_mask; params.abb.from(p_aabb); + params.tester = p_tester; tree.cull_aabb(params); return params.result_count_overall; } - int cull_segment(const Point &p_from, const Point &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) { + int cull_segment(const POINT &p_from, const POINT &p_to, T **p_result_array, int p_result_max, const T *p_tester, uint32_t p_tree_collision_mask = 0xFFFFFFFF, int *p_subindex_array = nullptr) { + BVH_LOCKED_FUNCTION typename BVHTREE_CLASS::CullParams params; params.result_count_overall = 0; params.result_max = p_result_max; params.result_array = p_result_array; params.subindex_array = p_subindex_array; - params.mask = p_mask; - params.pairable_type = 0; + params.tester = p_tester; + params.tree_collision_mask = p_tree_collision_mask; params.segment.from = p_from; params.segment.to = p_to; @@ -342,15 +373,16 @@ public: return params.result_count_overall; } - int cull_point(const Point &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) { + int cull_point(const POINT &p_point, T **p_result_array, int p_result_max, const T *p_tester, uint32_t p_tree_collision_mask = 0xFFFFFFFF, int *p_subindex_array = nullptr) { + BVH_LOCKED_FUNCTION typename BVHTREE_CLASS::CullParams params; params.result_count_overall = 0; params.result_max = p_result_max; params.result_array = p_result_array; params.subindex_array = p_subindex_array; - params.mask = p_mask; - params.pairable_type = 0; + params.tester = p_tester; + params.tree_collision_mask = p_tree_collision_mask; params.point = p_point; @@ -358,7 +390,8 @@ public: return params.result_count_overall; } - int cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask = 0xFFFFFFFF) { + int cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, const T *p_tester, uint32_t p_tree_collision_mask = 0xFFFFFFFF) { + BVH_LOCKED_FUNCTION if (!p_convex.size()) { return 0; } @@ -373,8 +406,8 @@ public: params.result_max = p_result_max; params.result_array = p_result_array; params.subindex_array = nullptr; - params.mask = p_mask; - params.pairable_type = 0; + params.tester = p_tester; + params.tree_collision_mask = p_tree_collision_mask; params.hull.planes = &p_convex[0]; params.hull.num_planes = p_convex.size(); @@ -394,7 +427,7 @@ private: return; } - Bounds bb; + BOUNDS bb; typename BVHTREE_CLASS::CullParams params; @@ -402,28 +435,23 @@ private: params.result_max = INT_MAX; params.result_array = nullptr; params.subindex_array = nullptr; - params.mask = 0xFFFFFFFF; - params.pairable_type = 0; for (unsigned int n = 0; n < changed_items.size(); n++) { const BVHHandle &h = changed_items[n]; // use the expanded aabb for pairing - const Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb; + const BOUNDS &expanded_aabb = tree._pairs[h.id()].expanded_aabb; BVHABB_CLASS abb; abb.from(expanded_aabb); + tree.item_fill_cullparams(h, params); + // find all the existing paired aabbs that are no longer // paired, and send callbacks _find_leavers(h, abb, p_full_check); uint32_t changed_item_ref_id = h.id(); - // set up the test from this item. - // this includes whether to test the non pairable tree, - // and the item mask. - tree.item_fill_cullparams(h, params); - params.abb = abb; params.result_count_overall = 0; // might not be needed @@ -456,7 +484,7 @@ private: } public: - void item_get_AABB(BVHHandle p_handle, Bounds &r_aabb) { + void item_get_AABB(BVHHandle p_handle, BOUNDS &r_aabb) { BVHABB_CLASS abb; tree.item_get_ABB(p_handle, abb); abb.to(r_aabb); @@ -464,7 +492,7 @@ public: private: // supplemental funcs - bool item_is_pairable(BVHHandle p_handle) const { return _get_extra(p_handle).pairable; } + uint32_t item_get_tree_id(BVHHandle p_handle) const { return _get_extra(p_handle).tree_id; } T *item_get_userdata(BVHHandle p_handle) const { return _get_extra(p_handle).userdata; } int item_get_subindex(BVHHandle p_handle) const { return _get_extra(p_handle).subindex; } @@ -485,12 +513,35 @@ private: void *ud_from = pairs_from.remove_pair_to(p_to); pairs_to.remove_pair_to(p_from); +#ifdef BVH_VERBOSE_PAIRING + print_line("_unpair " + itos(p_from.id()) + " from " + itos(p_to.id())); +#endif + // callback if (unpair_callback) { unpair_callback(pair_callback_userdata, p_from, exa.userdata, exa.subindex, p_to, exb.userdata, exb.subindex, ud_from); } } + void *_recheck_pair(BVHHandle p_from, BVHHandle p_to, void *p_pair_data) { + tree._handle_sort(p_from, p_to); + + typename BVHTREE_CLASS::ItemExtra &exa = tree._extra[p_from.id()]; + typename BVHTREE_CLASS::ItemExtra &exb = tree._extra[p_to.id()]; + + // if the userdata is the same, no collisions should occur + if ((exa.userdata == exb.userdata) && exa.userdata) { + return p_pair_data; + } + + // callback + if (check_pair_callback) { + return check_pair_callback(check_pair_callback_userdata, p_from, exa.userdata, exa.subindex, p_to, exb.userdata, exb.subindex, p_pair_data); + } + + return p_pair_data; + } + // returns true if unpair bool _find_leavers_process_pair(typename BVHTREE_CLASS::ItemPairs &p_pairs_from, const BVHABB_CLASS &p_abb_from, BVHHandle p_from, BVHHandle p_to, bool p_full_check) { BVHABB_CLASS abb_to; @@ -498,8 +549,8 @@ private: // do they overlap? if (p_abb_from.intersects(abb_to)) { - // the full check for pairable / non pairable and mask changes is extra expense - // this need not be done in most cases (for speed) except in the case where set_pairable is called + // the full check for pairable / non pairable (i.e. tree_id and tree_masks) and mask changes is extra expense + // this need not be done in most cases (for speed) except in the case where set_tree is called // where the masks etc of the objects in question may have changed if (!p_full_check) { return false; @@ -507,12 +558,13 @@ private: const typename BVHTREE_CLASS::ItemExtra &exa = _get_extra(p_from); const typename BVHTREE_CLASS::ItemExtra &exb = _get_extra(p_to); - // one of the two must be pairable to still pair - // if neither are pairable, we always unpair - if (exa.pairable || exb.pairable) { + // Checking tree_ids and tree_collision_masks + if (exa.are_item_trees_compatible(exb)) { + bool pair_allowed = USER_PAIR_TEST_FUNCTION::user_pair_check(exa.userdata, exb.userdata); + // the masks must still be compatible to pair - // i.e. if there is a hit between the two, then they should stay paired - if (tree._cull_pairing_mask_test_hit(exa.pairable_mask, exa.pairable_type, exb.pairable_mask, exb.pairable_type)) { + // i.e. if there is a hit between the two and they intersect, then they should stay paired + if (pair_allowed) { return false; } } @@ -550,6 +602,11 @@ private: const typename BVHTREE_CLASS::ItemExtra &exa = _get_extra(p_ha); const typename BVHTREE_CLASS::ItemExtra &exb = _get_extra(p_hb); + // user collision callback + if (!USER_PAIR_TEST_FUNCTION::user_pair_check(exa.userdata, exb.userdata)) { + return; + } + // if the userdata is the same, no collisions should occur if ((exa.userdata == exb.userdata) && exa.userdata) { return; @@ -573,6 +630,10 @@ private: // callback void *callback_userdata = nullptr; +#ifdef BVH_VERBOSE_PAIRING + print_line("_pair " + itos(p_ha.id()) + " to " + itos(p_hb.id())); +#endif + if (pair_callback) { callback_userdata = pair_callback(pair_callback_userdata, p_ha, exa.userdata, exa.subindex, p_hb, exb.userdata, exb.subindex); } @@ -594,6 +655,32 @@ private: } } + // Send pair callbacks again for all existing pairs for the given handle. + void _recheck_pairs(BVHHandle p_handle) { + typename BVHTREE_CLASS::ItemPairs &from = tree._pairs[p_handle.id()]; + + // checking pair for every partner. + for (unsigned int n = 0; n < from.extended_pairs.size(); n++) { + typename BVHTREE_CLASS::ItemPairs::Link &pair = from.extended_pairs[n]; + BVHHandle h_to = pair.handle; + void *new_pair_data = _recheck_pair(p_handle, h_to, pair.userdata); + + if (new_pair_data != pair.userdata) { + pair.userdata = new_pair_data; + + // Update pair data for the second item. + typename BVHTREE_CLASS::ItemPairs &to = tree._pairs[h_to.id()]; + for (unsigned int to_index = 0; to_index < to.extended_pairs.size(); to_index++) { + typename BVHTREE_CLASS::ItemPairs::Link &to_pair = to.extended_pairs[to_index]; + if (to_pair.handle == p_handle) { + to_pair.userdata = new_pair_data; + break; + } + } + } + } + } + private: const typename BVHTREE_CLASS::ItemExtra &_get_extra(BVHHandle p_handle) const { return tree._extra[p_handle.id()]; @@ -607,19 +694,24 @@ private: _tick++; } - void _add_changed_item(BVHHandle p_handle, const Bounds &aabb, bool p_check_aabb = true) { + void _add_changed_item(BVHHandle p_handle, const BOUNDS &aabb, bool p_check_aabb = true) { // Note that non pairable items can pair with pairable, // so all types must be added to the list +#ifdef BVH_EXPAND_LEAF_AABBS + // if using expanded AABB in the leaf, the redundancy check will already have been made + BOUNDS &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb; + item_get_AABB(p_handle, expanded_aabb); +#else // aabb check with expanded aabb. This greatly decreases processing // at the cost of slightly less accurate pairing checks // Note this pairing AABB is separate from the AABB in the actual tree - Bounds &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb; + BOUNDS &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb; // passing p_check_aabb false disables the optimization which prevents collision checks if // the aabb hasn't changed. This is needed where set_pairable has been called, but the position // has not changed. - if (p_check_aabb && expanded_aabb.encloses(aabb)) { + if (p_check_aabb && tree.expanded_aabb_encloses_not_shrink(expanded_aabb, aabb)) { return; } @@ -627,6 +719,7 @@ private: // this tick, because it is vital that the AABB is kept up to date expanded_aabb = aabb; expanded_aabb.grow_by(tree._pairing_expansion); +#endif // this code is to ensure that changed items only appear once on the updated list // collision checking them multiple times is not needed, and repeats the same thing @@ -670,8 +763,10 @@ private: PairCallback pair_callback; UnpairCallback unpair_callback; + CheckPairCallback check_pair_callback; void *pair_callback_userdata; void *unpair_callback_userdata; + void *check_pair_callback_userdata; BVHTREE_CLASS tree; @@ -680,6 +775,38 @@ private: LocalVector<BVHHandle, uint32_t, true> changed_items; uint32_t _tick; + class BVHLockedFunction { + public: + BVHLockedFunction(Mutex *p_mutex, bool p_thread_safe) { + // will be compiled out if not set in template + if (p_thread_safe) { + _mutex = p_mutex; + + if (_mutex->try_lock() != OK) { + WARN_PRINT("Info : multithread BVH access detected (benign)"); + _mutex->lock(); + } + + } else { + _mutex = nullptr; + } + } + ~BVHLockedFunction() { + // will be compiled out if not set in template + if (_mutex) { + _mutex->unlock(); + } + } + + private: + Mutex *_mutex; + }; + + Mutex _mutex; + + // local toggle for turning on and off thread safety in project settings + bool _thread_safe; + public: BVH_Manager() { _tick = 1; // start from 1 so items with 0 indicate never updated @@ -687,6 +814,7 @@ public: unpair_callback = nullptr; pair_callback_userdata = nullptr; unpair_callback_userdata = nullptr; + _thread_safe = BVH_THREAD_SAFE; } }; diff --git a/core/math/bvh_abb.h b/core/math/bvh_abb.h index 009032d34d..8a44f1c4da 100644 --- a/core/math/bvh_abb.h +++ b/core/math/bvh_abb.h @@ -32,7 +32,7 @@ #define BVH_ABB_H // special optimized version of axis aligned bounding box -template <class Bounds = AABB, class Point = Vector3> +template <class BOUNDS = AABB, class POINT = Vector3> struct BVH_ABB { struct ConvexHull { // convex hulls (optional) @@ -43,8 +43,8 @@ struct BVH_ABB { }; struct Segment { - Point from; - Point to; + POINT from; + POINT to; }; enum IntersectResult { @@ -54,47 +54,47 @@ struct BVH_ABB { }; // we store mins with a negative value in order to test them with SIMD - Point min; - Point neg_max; + POINT min; + POINT neg_max; bool operator==(const BVH_ABB &o) const { return (min == o.min) && (neg_max == o.neg_max); } bool operator!=(const BVH_ABB &o) const { return (*this == o) == false; } - void set(const Point &_min, const Point &_max) { + void set(const POINT &_min, const POINT &_max) { min = _min; neg_max = -_max; } // to and from standard AABB - void from(const Bounds &p_aabb) { + void from(const BOUNDS &p_aabb) { min = p_aabb.position; neg_max = -(p_aabb.position + p_aabb.size); } - void to(Bounds &r_aabb) const { + void to(BOUNDS &r_aabb) const { r_aabb.position = min; r_aabb.size = calculate_size(); } void merge(const BVH_ABB &p_o) { - for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) { + for (int axis = 0; axis < POINT::AXIS_COUNT; ++axis) { neg_max[axis] = MIN(neg_max[axis], p_o.neg_max[axis]); min[axis] = MIN(min[axis], p_o.min[axis]); } } - Point calculate_size() const { + POINT calculate_size() const { return -neg_max - min; } - Point calculate_centre() const { - return Point((calculate_size() * 0.5) + min); + POINT calculate_centre() const { + return POINT((calculate_size() * 0.5) + min); } real_t get_proximity_to(const BVH_ABB &p_b) const { - const Point d = (min - neg_max) - (p_b.min - p_b.neg_max); + const POINT d = (min - neg_max) - (p_b.min - p_b.neg_max); real_t proximity = 0.0; - for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) { + for (int axis = 0; axis < POINT::AXIS_COUNT; ++axis) { proximity += Math::abs(d[axis]); } return proximity; @@ -104,7 +104,7 @@ struct BVH_ABB { return (get_proximity_to(p_a) < get_proximity_to(p_b) ? 0 : 1); } - uint32_t find_cutting_planes(const BVH_ABB::ConvexHull &p_hull, uint32_t *p_plane_ids) const { + uint32_t find_cutting_planes(const typename BVH_ABB::ConvexHull &p_hull, uint32_t *p_plane_ids) const { uint32_t count = 0; for (int n = 0; n < p_hull.num_planes; n++) { @@ -162,7 +162,7 @@ struct BVH_ABB { } bool intersects_convex_partial(const ConvexHull &p_hull) const { - Bounds bb; + BOUNDS bb; to(bb); return bb.intersects_convex_shape(p_hull.planes, p_hull.num_planes, p_hull.points, p_hull.num_points); } @@ -182,7 +182,7 @@ struct BVH_ABB { bool is_within_convex(const ConvexHull &p_hull) const { // use half extents routine - Bounds bb; + BOUNDS bb; to(bb); return bb.inside_convex_shape(p_hull.planes, p_hull.num_planes); } @@ -197,12 +197,12 @@ struct BVH_ABB { } bool intersects_segment(const Segment &p_s) const { - Bounds bb; + BOUNDS bb; to(bb); return bb.intersects_segment(p_s.from, p_s.to); } - bool intersects_point(const Point &p_pt) const { + bool intersects_point(const POINT &p_pt) const { if (_any_lessthan(-p_pt, neg_max)) { return false; } @@ -212,6 +212,7 @@ struct BVH_ABB { return true; } + // Very hot in profiling, make sure optimized bool intersects(const BVH_ABB &p_o) const { if (_any_morethan(p_o.min, -neg_max)) { return false; @@ -222,6 +223,17 @@ struct BVH_ABB { return true; } + // for pre-swizzled tester (this object) + bool intersects_swizzled(const BVH_ABB &p_o) const { + if (_any_lessthan(min, p_o.min)) { + return false; + } + if (_any_lessthan(neg_max, p_o.neg_max)) { + return false; + } + return true; + } + bool is_other_within(const BVH_ABB &p_o) const { if (_any_lessthan(p_o.neg_max, neg_max)) { return false; @@ -232,20 +244,20 @@ struct BVH_ABB { return true; } - void grow(const Point &p_change) { + void grow(const POINT &p_change) { neg_max -= p_change; min -= p_change; } void expand(real_t p_change) { - Point change; + POINT change; change.set_all(p_change); grow(change); } // Actually surface area metric. float get_area() const { - Point d = calculate_size(); + POINT d = calculate_size(); return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x); } @@ -254,8 +266,8 @@ struct BVH_ABB { min = neg_max; } - bool _any_morethan(const Point &p_a, const Point &p_b) const { - for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) { + bool _any_morethan(const POINT &p_a, const POINT &p_b) const { + for (int axis = 0; axis < POINT::AXIS_COUNT; ++axis) { if (p_a[axis] > p_b[axis]) { return true; } @@ -263,8 +275,8 @@ struct BVH_ABB { return false; } - bool _any_lessthan(const Point &p_a, const Point &p_b) const { - for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) { + bool _any_lessthan(const POINT &p_a, const POINT &p_b) const { + for (int axis = 0; axis < POINT::AXIS_COUNT; ++axis) { if (p_a[axis] < p_b[axis]) { return true; } diff --git a/core/math/bvh_cull.inc b/core/math/bvh_cull.inc index ab468bfd29..11f50e41e6 100644 --- a/core/math/bvh_cull.inc +++ b/core/math/bvh_cull.inc @@ -9,20 +9,22 @@ struct CullParams { T **result_array; int *subindex_array; - // nobody truly understands how masks are intended to work. - uint32_t mask; - uint32_t pairable_type; + // We now process masks etc in a user template function, + // and these for simplicity assume even for cull tests there is a + // testing object (which has masks etc) for the user cull checks. + // This means for cull tests on their own, the client will usually + // want to create a dummy object, just in order to specify masks etc. + const T *tester; // optional components for different tests - Point point; + POINT point; BVHABB_CLASS abb; typename BVHABB_CLASS::ConvexHull hull; typename BVHABB_CLASS::Segment segment; - // when collision testing, non pairable moving items - // only need to be tested against the pairable tree. - // collisions with other non pairable items are irrelevant. - bool test_pairable_only; + // When collision testing, we can specify which tree ids + // to collide test against with the tree_collision_mask. + uint32_t tree_collision_mask; }; private: @@ -58,11 +60,22 @@ int cull_convex(CullParams &r_params, bool p_translate_hits = true) { _cull_hits.clear(); r_params.result_count = 0; + uint32_t tree_test_mask = 0; + for (int n = 0; n < NUM_TREES; n++) { + tree_test_mask <<= 1; + if (!tree_test_mask) { + tree_test_mask = 1; + } + if (_root_node_id[n] == BVHCommon::INVALID) { continue; } + if (!(r_params.tree_collision_mask & tree_test_mask)) { + continue; + } + _cull_convex_iterative(_root_node_id[n], r_params); } @@ -77,11 +90,22 @@ int cull_segment(CullParams &r_params, bool p_translate_hits = true) { _cull_hits.clear(); r_params.result_count = 0; + uint32_t tree_test_mask = 0; + for (int n = 0; n < NUM_TREES; n++) { + tree_test_mask <<= 1; + if (!tree_test_mask) { + tree_test_mask = 1; + } + if (_root_node_id[n] == BVHCommon::INVALID) { continue; } + if (!(r_params.tree_collision_mask & tree_test_mask)) { + continue; + } + _cull_segment_iterative(_root_node_id[n], r_params); } @@ -96,11 +120,22 @@ int cull_point(CullParams &r_params, bool p_translate_hits = true) { _cull_hits.clear(); r_params.result_count = 0; + uint32_t tree_test_mask = 0; + for (int n = 0; n < NUM_TREES; n++) { + tree_test_mask <<= 1; + if (!tree_test_mask) { + tree_test_mask = 1; + } + if (_root_node_id[n] == BVHCommon::INVALID) { continue; } + if (!(r_params.tree_collision_mask & tree_test_mask)) { + continue; + } + _cull_point_iterative(_root_node_id[n], r_params); } @@ -115,12 +150,20 @@ int cull_aabb(CullParams &r_params, bool p_translate_hits = true) { _cull_hits.clear(); r_params.result_count = 0; + uint32_t tree_test_mask = 0; + for (int n = 0; n < NUM_TREES; n++) { + tree_test_mask <<= 1; + if (!tree_test_mask) { + tree_test_mask = 1; + } + if (_root_node_id[n] == BVHCommon::INVALID) { continue; } - if ((n == 0) && r_params.test_pairable_only) { + // the tree collision mask determines which trees to collide test against + if (!(r_params.tree_collision_mask & tree_test_mask)) { continue; } @@ -142,22 +185,6 @@ bool _cull_hits_full(const CullParams &p) { return (int)_cull_hits.size() >= p.result_max; } -// write this logic once for use in all routines -// double check this as a possible source of bugs in future. -bool _cull_pairing_mask_test_hit(uint32_t p_maskA, uint32_t p_typeA, uint32_t p_maskB, uint32_t p_typeB) const { - // double check this as a possible source of bugs in future. - bool A_match_B = p_maskA & p_typeB; - - if (!A_match_B) { - bool B_match_A = p_maskB & p_typeA; - if (!B_match_A) { - return false; - } - } - - return true; -} - void _cull_hit(uint32_t p_ref_id, CullParams &p) { // take into account masks etc // this would be more efficient to do before plane checks, @@ -165,7 +192,8 @@ void _cull_hit(uint32_t p_ref_id, CullParams &p) { if (USE_PAIRS) { const ItemExtra &ex = _extra[p_ref_id]; - if (!_cull_pairing_mask_test_hit(p.mask, p.pairable_type, ex.pairable_mask, ex.pairable_type)) { + // user supplied function (for e.g. pairable types and pairable masks in the render tree) + if (!USER_CULL_TEST_FUNCTION::user_cull_check(p.tester, ex.userdata)) { return; } } @@ -294,6 +322,7 @@ bool _cull_point_iterative(uint32_t p_node_id, CullParams &r_params) { return true; } +// Note: This is a very hot loop profiling wise. Take care when changing this and profile. bool _cull_aabb_iterative(uint32_t p_node_id, CullParams &r_params, bool p_fully_within = false) { // our function parameters to keep on a stack struct CullAABBParams { @@ -336,16 +365,26 @@ bool _cull_aabb_iterative(uint32_t p_node_id, CullParams &r_params, bool p_fully _cull_hit(child_id, r_params); } } else { - for (int n = 0; n < leaf.num_items; n++) { + // This section is the hottest area in profiling, so + // is optimized highly + // get this into a local register and preconverted to correct type + int leaf_num_items = leaf.num_items; + + BVHABB_CLASS swizzled_tester; + swizzled_tester.min = -r_params.abb.neg_max; + swizzled_tester.neg_max = -r_params.abb.min; + + for (int n = 0; n < leaf_num_items; n++) { const BVHABB_CLASS &aabb = leaf.get_aabb(n); - if (aabb.intersects(r_params.abb)) { + if (swizzled_tester.intersects_swizzled(aabb)) { uint32_t child_id = leaf.get_item_ref_id(n); // register hit _cull_hit(child_id, r_params); } } + } // not fully within } else { if (!cap.fully_within) { diff --git a/core/math/bvh_debug.inc b/core/math/bvh_debug.inc index 896c36ecf1..2e519ceb3d 100644 --- a/core/math/bvh_debug.inc +++ b/core/math/bvh_debug.inc @@ -7,12 +7,12 @@ void _debug_recursive_print_tree(int p_tree_id) const { } String _debug_aabb_to_string(const BVHABB_CLASS &aabb) const { - Point size = aabb.calculate_size(); + POINT size = aabb.calculate_size(); String sz; float vol = 0.0; - for (int i = 0; i < Point::AXES_COUNT; ++i) { + for (int i = 0; i < POINT::AXIS_COUNT; ++i) { sz += "("; sz += itos(aabb.min[i]); sz += " ~ "; diff --git a/core/math/bvh_logic.inc b/core/math/bvh_logic.inc index c65002a9fd..dd3b135bb5 100644 --- a/core/math/bvh_logic.inc +++ b/core/math/bvh_logic.inc @@ -42,9 +42,9 @@ BVHABB_CLASS _logic_abb_merge(const BVHABB_CLASS &a, const BVHABB_CLASS &b) { //-------------------------------------------------------------------------------------------------- /** - * @file q3DynamicAABBTree.h - * @author Randy Gaul - * @date 10/10/2014 + * @file q3DynamicAABBTree.h + * @author Randy Gaul + * @date 10/10/2014 * Copyright (c) 2014 Randy Gaul http://www.randygaul.net * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -75,11 +75,11 @@ int32_t _logic_balance(int32_t iA, uint32_t p_tree_id) { return iA; } - /* A - * / \ - * B C - * / \ / \ - * D E F G + /* A + * / \ + * B C + * / \ / \ + * D E F G */ CRASH_COND(A->num_children != 2); diff --git a/core/math/bvh_misc.inc b/core/math/bvh_misc.inc index 71aa0e4fe0..9b35a1d36d 100644 --- a/core/math/bvh_misc.inc +++ b/core/math/bvh_misc.inc @@ -1,11 +1,7 @@ int _handle_get_tree_id(BVHHandle p_handle) const { if (USE_PAIRS) { - int tree = 0; - if (_extra[p_handle.id()].pairable) { - tree = 1; - } - return tree; + return _extra[p_handle.id()].tree_id; } return 0; } diff --git a/core/math/bvh_pair.inc b/core/math/bvh_pair.inc index a12acec2b6..7b9c7ce6ae 100644 --- a/core/math/bvh_pair.inc +++ b/core/math/bvh_pair.inc @@ -14,10 +14,10 @@ struct ItemPairs { void clear() { num_pairs = 0; extended_pairs.reset(); - expanded_aabb = Bounds(); + expanded_aabb = BOUNDS(); } - Bounds expanded_aabb; + BOUNDS expanded_aabb; // maybe we can just use the number in the vector TODO int32_t num_pairs; @@ -59,4 +59,14 @@ struct ItemPairs { return userdata; } + + // experiment : scale the pairing expansion by the number of pairs. + // when the number of pairs is high, the density is high and a lower collision margin is better. + // when there are few local pairs, a larger margin is more optimal. + real_t scale_expansion_margin(real_t p_margin) const { + real_t x = real_t(num_pairs) * (1.0 / 9.0); + x = MIN(x, 1.0); + x = 1.0 - x; + return p_margin * x; + } }; diff --git a/core/math/bvh_public.inc b/core/math/bvh_public.inc index 2c1e406712..36b0bfeb13 100644 --- a/core/math/bvh_public.inc +++ b/core/math/bvh_public.inc @@ -1,5 +1,5 @@ public: -BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_invisible = false) { +BVHHandle item_add(T *p_userdata, bool p_active, const BOUNDS &p_aabb, int32_t p_subindex, uint32_t p_tree_id, uint32_t p_tree_collision_mask, bool p_invisible = false) { #ifdef BVH_VERBOSE_TREE VERBOSE_PRINT("\nitem_add BEFORE"); _debug_recursive_print_tree(0); @@ -9,6 +9,13 @@ BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p BVHABB_CLASS abb; abb.from(p_aabb); + // NOTE that we do not expand the AABB for the first create even if + // leaf expansion is switched on. This is for two reasons: + // (1) We don't know if this object will move in future, in which case a non-expanded + // bound would be better... + // (2) We don't yet know how many objects will be paired, which is used to modify + // the expansion margin. + // handle to be filled with the new item ref BVHHandle handle; @@ -40,29 +47,17 @@ BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p extra->active_ref_id = _active_refs.size(); _active_refs.push_back(ref_id); - if (USE_PAIRS) { - extra->pairable_mask = p_pairable_mask; - extra->pairable_type = p_pairable_type; - extra->pairable = p_pairable; - } else { - // just for safety, in case this gets queried etc - extra->pairable = 0; - p_pairable = false; - } + extra->tree_id = p_tree_id; + extra->tree_collision_mask = p_tree_collision_mask; // assign to handle to return handle.set_id(ref_id); - uint32_t tree_id = 0; - if (p_pairable) { - tree_id = 1; - } - - create_root_node(tree_id); + create_root_node(p_tree_id); // we must choose where to add to tree if (p_active) { - ref->tnode_id = _logic_choose_item_add_node(_root_node_id[tree_id], abb); + ref->tnode_id = _logic_choose_item_add_node(_root_node_id[p_tree_id], abb); bool refit = _node_add_item(ref->tnode_id, ref_id, abb); @@ -70,7 +65,7 @@ BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p // only need to refit from the parent const TNode &add_node = _nodes[ref->tnode_id]; if (add_node.parent_id != BVHCommon::INVALID) { - refit_upward_and_balance(add_node.parent_id, tree_id); + refit_upward_and_balance(add_node.parent_id, p_tree_id); } } } else { @@ -103,7 +98,7 @@ void _debug_print_refs() { } // returns false if noop -bool item_move(BVHHandle p_handle, const Bounds &p_aabb) { +bool item_move(BVHHandle p_handle, const BOUNDS &p_aabb) { uint32_t ref_id = p_handle.id(); // get the reference @@ -115,10 +110,19 @@ bool item_move(BVHHandle p_handle, const Bounds &p_aabb) { BVHABB_CLASS abb; abb.from(p_aabb); +#ifdef BVH_EXPAND_LEAF_AABBS + if (USE_PAIRS) { + // scale the pairing expansion by the number of pairs. + abb.expand(_pairs[ref_id].scale_expansion_margin(_pairing_expansion)); + } else { + abb.expand(_pairing_expansion); + } +#endif + BVH_ASSERT(ref.tnode_id != BVHCommon::INVALID); TNode &tnode = _nodes[ref.tnode_id]; - // does it fit within the current aabb? + // does it fit within the current leaf aabb? if (tnode.aabb.is_other_within(abb)) { // do nothing .. fast path .. not moved enough to need refit @@ -129,9 +133,24 @@ bool item_move(BVHHandle p_handle, const Bounds &p_aabb) { BVHABB_CLASS &leaf_abb = leaf.get_aabb(ref.item_id); // no change? +#ifdef BVH_EXPAND_LEAF_AABBS + BOUNDS leaf_aabb; + leaf_abb.to(leaf_aabb); + + // This test should pass in a lot of cases, and by returning false we can avoid + // collision pairing checks later, which greatly reduces processing. + if (expanded_aabb_encloses_not_shrink(leaf_aabb, p_aabb)) { + return false; + } +#else if (leaf_abb == abb) { return false; } +#endif + +#ifdef BVH_VERBOSE_MOVES + print_line("item_move " + itos(p_handle.id()) + "(within tnode aabb) : " + _debug_aabb_to_string(abb)); +#endif leaf_abb = abb; _integrity_check_all(); @@ -139,6 +158,10 @@ bool item_move(BVHHandle p_handle, const Bounds &p_aabb) { return true; } +#ifdef BVH_VERBOSE_MOVES + print_line("item_move " + itos(p_handle.id()) + "(outside tnode aabb) : " + _debug_aabb_to_string(abb)); +#endif + uint32_t tree_id = _handle_get_tree_id(p_handle); // remove and reinsert @@ -206,7 +229,7 @@ void item_remove(BVHHandle p_handle) { } // returns success -bool item_activate(BVHHandle p_handle, const Bounds &p_aabb) { +bool item_activate(BVHHandle p_handle, const BOUNDS &p_aabb) { uint32_t ref_id = p_handle.id(); ItemRef &ref = _refs[ref_id]; if (ref.is_active()) { @@ -260,12 +283,14 @@ void item_fill_cullparams(BVHHandle p_handle, CullParams &r_params) const { uint32_t ref_id = p_handle.id(); const ItemExtra &extra = _extra[ref_id]; - // testing from a non pairable item, we only want to test pairable items - r_params.test_pairable_only = extra.pairable == 0; + // which trees does this item want to collide detect against? + r_params.tree_collision_mask = extra.tree_collision_mask; - // we take into account the mask of the item testing from - r_params.mask = extra.pairable_mask; - r_params.pairable_type = extra.pairable_type; + // The testing user defined object is passed to the user defined cull check function + // for masks etc. This is usually a dummy object of type T with masks set. + // However, if not using the cull_check callback (i.e. returning true), you can pass + // a nullptr instead of dummy object, as it will not be used. + r_params.tester = extra.userdata; } bool item_is_pairable(const BVHHandle &p_handle) { @@ -285,7 +310,7 @@ void item_get_ABB(const BVHHandle &p_handle, BVHABB_CLASS &r_abb) { r_abb = leaf.get_aabb(ref.item_id); } -bool item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) { +bool item_set_tree(const BVHHandle &p_handle, uint32_t p_tree_id, uint32_t p_tree_collision_mask) { // change tree? uint32_t ref_id = p_handle.id(); @@ -293,13 +318,15 @@ bool item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pa ItemRef &ref = _refs[ref_id]; bool active = ref.is_active(); - bool pairable_changed = (ex.pairable != 0) != p_pairable; - bool state_changed = pairable_changed || (ex.pairable_type != p_pairable_type) || (ex.pairable_mask != p_pairable_mask); + bool tree_changed = ex.tree_id != p_tree_id; + bool mask_changed = ex.tree_collision_mask != p_tree_collision_mask; + bool state_changed = tree_changed | mask_changed; - ex.pairable_type = p_pairable_type; - ex.pairable_mask = p_pairable_mask; + // Keep an eye on this for bugs of not noticing changes to objects, + // especially when changing client user masks that will not be detected as a change + // in the BVH. You may need to force a collision check in this case with recheck_pairs(). - if (active && pairable_changed) { + if (active && (tree_changed | mask_changed)) { // record abb TNode &tnode = _nodes[ref.tnode_id]; TLeaf &leaf = _node_get_leaf(tnode); @@ -313,7 +340,8 @@ bool item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pa // we must set the pairable AFTER getting the current tree // because the pairable status determines which tree - ex.pairable = p_pairable; + ex.tree_id = p_tree_id; + ex.tree_collision_mask = p_tree_collision_mask; // add to new tree tree_id = _handle_get_tree_id(p_handle); @@ -333,7 +361,8 @@ bool item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pa } } else { // always keep this up to date - ex.pairable = p_pairable; + ex.tree_id = p_tree_id; + ex.tree_collision_mask = p_tree_collision_mask; } return state_changed; @@ -403,7 +432,7 @@ void update() { // if there are no nodes, do nothing, but if there are... if (bound_valid) { - Bounds bb; + BOUNDS bb; world_bound.to(bb); real_t size = bb.get_longest_axis_size(); @@ -421,3 +450,50 @@ void update() { } #endif } + +void params_set_pairing_expansion(real_t p_value) { + if (p_value < 0.0) { +#ifdef BVH_ALLOW_AUTO_EXPANSION + _auto_pairing_expansion = true; +#endif + return; + } +#ifdef BVH_ALLOW_AUTO_EXPANSION + _auto_pairing_expansion = false; +#endif + + _pairing_expansion = p_value; + + // calculate shrinking threshold + const real_t fudge_factor = 1.1; + _aabb_shrinkage_threshold = _pairing_expansion * POINT::AXIS_COUNT * 2.0 * fudge_factor; +} + +// This routine is not just an enclose check, it also checks for special case of shrinkage +bool expanded_aabb_encloses_not_shrink(const BOUNDS &p_expanded_aabb, const BOUNDS &p_aabb) const { + if (!p_expanded_aabb.encloses(p_aabb)) { + return false; + } + + // Check for special case of shrinkage. If the aabb has shrunk + // significantly we want to create a new expanded bound, because + // the previous expanded bound will have diverged significantly. + const POINT &exp_size = p_expanded_aabb.size; + const POINT &new_size = p_aabb.size; + + real_t exp_l = 0.0; + real_t new_l = 0.0; + + for (int i = 0; i < POINT::AXIS_COUNT; ++i) { + exp_l += exp_size[i]; + new_l += new_size[i]; + } + + // is difference above some metric + real_t diff = exp_l - new_l; + if (diff < _aabb_shrinkage_threshold) { + return true; + } + + return false; +} diff --git a/core/math/bvh_split.inc b/core/math/bvh_split.inc index f19ee8a7da..ff07166d4a 100644 --- a/core/math/bvh_split.inc +++ b/core/math/bvh_split.inc @@ -25,16 +25,16 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u return; } - Point centre = full_bound.calculate_centre(); - Point size = full_bound.calculate_size(); + POINT centre = full_bound.calculate_centre(); + POINT size = full_bound.calculate_size(); - int order[Point::AXIS_COUNT]; + int order[POINT::AXIS_COUNT]; order[0] = size.min_axis_index(); - order[Point::AXIS_COUNT - 1] = size.max_axis_index(); + order[POINT::AXIS_COUNT - 1] = size.max_axis_index(); - static_assert(Point::AXIS_COUNT <= 3); - if (Point::AXIS_COUNT == 3) { + static_assert(POINT::AXIS_COUNT <= 3, "BVH POINT::AXIS_COUNT has unexpected size"); + if (POINT::AXIS_COUNT == 3) { order[1] = 3 - (order[0] + order[2]); } @@ -58,7 +58,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u // detect when split on longest axis failed int min_threshold = MAX_ITEMS / 4; - int min_group_size[Point::AXIS_COUNT]; + int min_group_size[POINT::AXIS_COUNT]; min_group_size[0] = MIN(num_a, num_b); if (min_group_size[0] < min_threshold) { // slow but sure .. first move everything back into a @@ -68,7 +68,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u num_b = 0; // now calculate the best split - for (int axis = 1; axis < Point::AXIS_COUNT; axis++) { + for (int axis = 1; axis < POINT::AXIS_COUNT; axis++) { split_axis = order[axis]; int count = 0; @@ -86,7 +86,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u // best axis int best_axis = 0; int best_min = min_group_size[0]; - for (int axis = 1; axis < Point::AXIS_COUNT; axis++) { + for (int axis = 1; axis < POINT::AXIS_COUNT; axis++) { if (min_group_size[axis] > best_min) { best_min = min_group_size[axis]; best_axis = axis; diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc index 1d1e0e6468..b0d9ae3615 100644 --- a/core/math/bvh_structs.inc +++ b/core/math/bvh_structs.inc @@ -14,25 +14,38 @@ struct ItemRef { // extra info kept in separate parallel list to the references, // as this is less used as keeps cache better struct ItemExtra { - uint32_t last_updated_tick; - uint32_t pairable; - uint32_t pairable_mask; - uint32_t pairable_type; + // Before doing user defined pairing checks (especially in the find_leavers function), + // we may want to check that two items have compatible tree ids and tree masks, + // as if they are incompatible they should not pair / collide. + bool are_item_trees_compatible(const ItemExtra &p_other) const { + uint32_t other_type = 1 << p_other.tree_id; + if (tree_collision_mask & other_type) { + return true; + } + uint32_t our_type = 1 << tree_id; + if (p_other.tree_collision_mask & our_type) { + return true; + } + return false; + } + + // There can be multiple user defined trees + uint32_t tree_id; + // Defines which trees this item should collision check against. + // 1 << tree_id, and normally items would collide against there own + // tree (but not always). + uint32_t tree_collision_mask; + + uint32_t last_updated_tick; int32_t subindex; + T *userdata; + // the active reference is a separate list of which references // are active so that we can slowly iterate through it over many frames for // slow optimize. uint32_t active_ref_id; - - T *userdata; -}; - -// this is an item OR a child node depending on whether a leaf node -struct Item { - BVHABB_CLASS aabb; - uint32_t item_ref_id; }; // tree leaf @@ -133,13 +146,13 @@ struct TNode { // instead of using linked list we maintain // item references (for quick lookup) -PooledList<ItemRef, true> _refs; -PooledList<ItemExtra, true> _extra; +PooledList<ItemRef, uint32_t, true> _refs; +PooledList<ItemExtra, uint32_t, true> _extra; PooledList<ItemPairs> _pairs; // these 2 are not in sync .. nodes != leaves! -PooledList<TNode, true> _nodes; -PooledList<TLeaf, true> _leaves; +PooledList<TNode, uint32_t, true> _nodes; +PooledList<TLeaf, uint32_t, true> _leaves; // we can maintain an un-ordered list of which references are active, // in order to do a slow incremental optimize of the tree over each frame. @@ -152,15 +165,11 @@ uint32_t _current_active_ref = 0; // for pairing collision detection LocalVector<uint32_t, uint32_t, true> _cull_hits; -// we now have multiple root nodes, allowing us to store -// more than 1 tree. This can be more efficient, while sharing the same -// common lists -enum { NUM_TREES = 2, -}; - -// Tree 0 - Non pairable -// Tree 1 - Pairable -// This is more efficient because in physics we only need check non pairable against the pairable tree. +// We can now have a user definable number of trees. +// This allows using e.g. a non-pairable and pairable tree, +// which can be more efficient for example, if we only need check non pairable against the pairable tree. +// It also may be more efficient in terms of separating static from dynamic objects, by reducing housekeeping. +// However this is a trade off, as there is a cost of traversing two trees. uint32_t _root_node_id[NUM_TREES]; // these values may need tweaking according to the project @@ -177,4 +186,14 @@ bool _auto_node_expansion = true; // larger values gives more 'sticky' pairing, and is less likely to exhibit tunneling // we can either use auto mode, where the expansion is based on the root node size, or specify manually real_t _pairing_expansion = 0.1; + +#ifdef BVH_ALLOW_AUTO_EXPANSION bool _auto_pairing_expansion = true; +#endif + +// when using an expanded bound, we must detect the condition where a new AABB +// is significantly smaller than the expanded bound, as this is a special case where we +// should override the optimization and create a new expanded bound. +// This threshold is derived from the _pairing_expansion, and should be recalculated +// if _pairing_expansion is changed. +real_t _aabb_shrinkage_threshold = 0.0; diff --git a/core/math/bvh_tree.h b/core/math/bvh_tree.h index c948d83456..da9b307778 100644 --- a/core/math/bvh_tree.h +++ b/core/math/bvh_tree.h @@ -48,12 +48,17 @@ #include "core/templates/pooled_list.h" #include <limits.h> -#define BVHABB_CLASS BVH_ABB<Bounds, Point> +#define BVHABB_CLASS BVH_ABB<BOUNDS, POINT> + +// not sure if this is better yet so making optional +#define BVH_EXPAND_LEAF_AABBS // never do these checks in release #if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED) //#define BVH_VERBOSE //#define BVH_VERBOSE_TREE +//#define BVH_VERBOSE_PAIRING +//#define BVH_VERBOSE_MOVES //#define BVH_VERBOSE_FRAME //#define BVH_CHECKS @@ -148,7 +153,25 @@ public: } }; -template <class T, int MAX_CHILDREN, int MAX_ITEMS, bool USE_PAIRS = false, class Bounds = AABB, class Point = Vector3> +template <class T> +class BVH_DummyPairTestFunction { +public: + static bool user_collision_check(T *p_a, T *p_b) { + // return false if no collision, decided by masks etc + return true; + } +}; + +template <class T> +class BVH_DummyCullTestFunction { +public: + static bool user_cull_check(T *p_a, T *p_b) { + // return false if no collision + return true; + } +}; + +template <class T, int NUM_TREES, int MAX_CHILDREN, int MAX_ITEMS, class USER_PAIR_TEST_FUNCTION = BVH_DummyPairTestFunction<T>, class USER_CULL_TEST_FUNCTION = BVH_DummyCullTestFunction<T>, bool USE_PAIRS = false, class BOUNDS = AABB, class POINT = Vector3> class BVH_Tree { friend class BVH; @@ -165,6 +188,11 @@ public: // (as these ids are stored as negative numbers in the node) uint32_t dummy_leaf_id; _leaves.request(dummy_leaf_id); + + // In many cases you may want to change this default in the client code, + // or expose this value to the user. + // This default may make sense for a typically scaled 3d game, but maybe not for 2d on a pixel scale. + params_set_pairing_expansion(0.1); } private: @@ -234,7 +262,7 @@ private: change_root_node(sibling_id, p_tree_id); // delete the old root node as no longer needed - _nodes.free(p_parent_id); + node_free_node_and_leaf(p_parent_id); } return; @@ -247,7 +275,19 @@ private: } // put the node on the free list to recycle - _nodes.free(p_parent_id); + node_free_node_and_leaf(p_parent_id); + } + + // A node can either be a node, or a node AND a leaf combo. + // Both must be deleted to prevent a leak. + void node_free_node_and_leaf(uint32_t p_node_id) { + TNode &node = _nodes[p_node_id]; + if (node.is_leaf()) { + int leaf_id = node.get_leaf_id(); + _leaves.free(leaf_id); + } + + _nodes.free(p_node_id); } void change_root_node(uint32_t p_new_root_id, uint32_t p_tree_id) { @@ -339,7 +379,7 @@ private: refit_upward(parent_id); // put the node on the free list to recycle - _nodes.free(owner_node_id); + node_free_node_and_leaf(owner_node_id); } // else if no parent, it is the root node. Do not delete diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h index 5bc723787f..b9067e2edd 100644 --- a/core/templates/paged_allocator.h +++ b/core/templates/paged_allocator.h @@ -86,10 +86,10 @@ public: } p_mem->~T(); available_pool[allocs_available >> page_shift][allocs_available & page_mask] = p_mem; + allocs_available++; if (thread_safe) { spin_lock.unlock(); } - allocs_available++; } void reset(bool p_allow_unfreed = false) { diff --git a/core/templates/pooled_list.h b/core/templates/pooled_list.h index 360fda81f8..f13156b292 100644 --- a/core/templates/pooled_list.h +++ b/core/templates/pooled_list.h @@ -28,16 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef POOLED_LIST_H -#define POOLED_LIST_H - -#include "core/templates/local_vector.h" +#pragma once // Simple template to provide a pool with O(1) allocate and free. // The freelist could alternatively be a linked list placed within the unused elements // to use less memory, however a separate freelist is probably more cache friendly. -// -// NOTE: Take great care when using this with non POD types. The construction and destruction + +// NOTE : Take great care when using this with non POD types. The construction and destruction // is done in the LocalVector, NOT as part of the pool. So requesting a new item does not guarantee // a constructor is run, and free does not guarantee a destructor. // You should generally handle clearing @@ -45,33 +42,60 @@ // This is by design for fastest use in the BVH. If you want a more general pool // that does call constructors / destructors on request / free, this should probably be // a separate template. -template <class T, bool force_trivial = false> + +// The zero_on_first_request feature is optional and is useful for e.g. pools of handles, +// which may use a ref count which we want to be initialized to zero the first time a handle is created, +// but left alone on subsequent allocations (as will typically be incremented). + +// Note that there is no function to compact the pool - this would +// invalidate any existing pool IDs held externally. +// Compaction can be done but would rely on a more complex method +// of preferentially giving out lower IDs in the freelist first. + +#include "core/templates/local_vector.h" + +template <class T, class U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false> class PooledList { - LocalVector<T, uint32_t, force_trivial> list; - LocalVector<uint32_t, uint32_t, true> freelist; + LocalVector<T, U, force_trivial> list; + LocalVector<U, U, true> freelist; // not all list members are necessarily used - int _used_size; + U _used_size; public: PooledList() { _used_size = 0; } - int estimate_memory_use() const { - return (list.size() * sizeof(T)) + (freelist.size() * sizeof(uint32_t)); + // Use with care, in most cases you should make sure to + // free all elements first (i.e. _used_size would be zero), + // although it could also be used without this as an optimization + // in some cases. + void clear() { + list.clear(); + freelist.clear(); + _used_size = 0; + } + + uint64_t estimate_memory_use() const { + return ((uint64_t)list.size() * sizeof(T)) + ((uint64_t)freelist.size() * sizeof(U)); } - const T &operator[](uint32_t p_index) const { + const T &operator[](U p_index) const { return list[p_index]; } - T &operator[](uint32_t p_index) { + T &operator[](U p_index) { return list[p_index]; } - int size() const { return _used_size; } + // To be explicit in a pool there is a distinction + // between the number of elements that are currently + // in use, and the number of elements that have been reserved. + // Using size() would be vague. + U used_size() const { return _used_size; } + U reserved_size() const { return list.size(); } - T *request(uint32_t &r_id) { + T *request(U &r_id) { _used_size++; if (freelist.size()) { @@ -79,19 +103,106 @@ public: int new_size = freelist.size() - 1; r_id = freelist[new_size]; freelist.resize(new_size); + return &list[r_id]; } r_id = list.size(); list.resize(r_id + 1); + + static_assert((!zero_on_first_request) || (__is_pod(T)), "zero_on_first_request requires trivial type"); + if (zero_on_first_request && __is_pod(T)) { + list[r_id] = {}; + } + return &list[r_id]; } - void free(const uint32_t &p_id) { + void free(const U &p_id) { // should not be on free list already - CRASH_COND(p_id >= list.size()); + ERR_FAIL_UNSIGNED_INDEX(p_id, list.size()); freelist.push_back(p_id); + ERR_FAIL_COND_MSG(!_used_size, "_used_size has become out of sync, have you double freed an item?"); _used_size--; } }; -#endif // POOLED_LIST_H +// a pooled list which automatically keeps a list of the active members +template <class T, class U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false> +class TrackedPooledList { +public: + U pool_used_size() const { return _pool.used_size(); } + U pool_reserved_size() const { return _pool.reserved_size(); } + U active_size() const { return _active_list.size(); } + + // use with care, see the earlier notes in the PooledList clear() + void clear() { + _pool.clear(); + _active_list.clear(); + _active_map.clear(); + } + + U get_active_id(U p_index) const { + return _active_list[p_index]; + } + + const T &get_active(U p_index) const { + return _pool[get_active_id(p_index)]; + } + + T &get_active(U p_index) { + return _pool[get_active_id(p_index)]; + } + + const T &operator[](U p_index) const { + return _pool[p_index]; + } + T &operator[](U p_index) { + return _pool[p_index]; + } + + T *request(U &r_id) { + T *item = _pool.request(r_id); + + // add to the active list + U active_list_id = _active_list.size(); + _active_list.push_back(r_id); + + // expand the active map (this should be in sync with the pool list + if (_pool.used_size() > _active_map.size()) { + _active_map.resize(_pool.used_size()); + } + + // store in the active map + _active_map[r_id] = active_list_id; + + return item; + } + + void free(const U &p_id) { + _pool.free(p_id); + + // remove from the active list. + U list_id = _active_map[p_id]; + + // zero the _active map to detect bugs (only in debug?) + _active_map[p_id] = -1; + + _active_list.remove_unordered(list_id); + + // keep the replacement in sync with the correct list Id + if (list_id < _active_list.size()) { + // which pool id has been replaced in the active list + U replacement_id = _active_list[list_id]; + + // keep that replacements map up to date with the new position + _active_map[replacement_id] = list_id; + } + } + + const LocalVector<U, U> &get_active_list() const { return _active_list; } + +private: + PooledList<T, U, force_trivial, zero_on_first_request> _pool; + LocalVector<U, U> _active_map; + LocalVector<U, U> _active_list; +}; diff --git a/doc/classes/CompressedCubemap.xml b/doc/classes/CompressedCubemap.xml new file mode 100644 index 0000000000..fbb0879fdc --- /dev/null +++ b/doc/classes/CompressedCubemap.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CompressedCubemap" inherits="CompressedTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/CompressedCubemapArray.xml b/doc/classes/CompressedCubemapArray.xml new file mode 100644 index 0000000000..ff096cea47 --- /dev/null +++ b/doc/classes/CompressedCubemapArray.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CompressedCubemapArray" inherits="CompressedTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/StreamTexture2D.xml b/doc/classes/CompressedTexture2D.xml index b18105cc29..c99fcf2280 100644 --- a/doc/classes/StreamTexture2D.xml +++ b/doc/classes/CompressedTexture2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="CompressedTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> A [code].stex[/code] texture. </brief_description> @@ -19,7 +19,7 @@ </methods> <members> <member name="load_path" type="String" setter="load" getter="get_load_path" default=""""> - The StreamTexture's file path to a [code].stex[/code] file. + The CompressedTexture's file path to a [code].stex[/code] file. </member> </members> </class> diff --git a/doc/classes/CompressedTexture2DArray.xml b/doc/classes/CompressedTexture2DArray.xml new file mode 100644 index 0000000000..0c751759af --- /dev/null +++ b/doc/classes/CompressedTexture2DArray.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CompressedTexture2DArray" inherits="CompressedTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/StreamTexture3D.xml b/doc/classes/CompressedTexture3D.xml index c0b783369f..de7a93d788 100644 --- a/doc/classes/StreamTexture3D.xml +++ b/doc/classes/CompressedTexture3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamTexture3D" inherits="Texture3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="CompressedTexture3D" inherits="Texture3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> </brief_description> <description> diff --git a/doc/classes/StreamTextureLayered.xml b/doc/classes/CompressedTextureLayered.xml index 8ed36ff54c..03bea84ba4 100644 --- a/doc/classes/StreamTextureLayered.xml +++ b/doc/classes/CompressedTextureLayered.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamTextureLayered" inherits="TextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="CompressedTextureLayered" inherits="TextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> </brief_description> <description> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 81472c09ee..ac2250ab6d 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -70,6 +70,13 @@ [/codeblocks] </description> </method> + <method name="check_changed_settings_in_group" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="setting_prefix" type="String" /> + <description> + Checks if any settings with the prefix [code]setting_prefix[/code] exist in the set of changed settings. See also [method get_changed_settings]. + </description> + </method> <method name="erase"> <return type="void" /> <argument index="0" name="property" type="String" /> @@ -77,6 +84,12 @@ Erases the setting whose name is specified by [code]property[/code]. </description> </method> + <method name="get_changed_settings" qualifiers="const"> + <return type="Array" /> + <description> + Gets an array of the settings which have been changed since the last save. Note that internally [code]changed_settings[/code] is cleared after a successful save, so generally the most appropriate place to use this method is when processing [constant NOTIFICATION_EDITOR_SETTINGS_CHANGED] + </description> + </method> <method name="get_favorites" qualifiers="const"> <return type="PackedStringArray" /> <description> @@ -118,6 +131,13 @@ Returns [code]true[/code] if the setting specified by [code]name[/code] exists, [code]false[/code] otherwise. </description> </method> + <method name="mark_setting_changed"> + <return type="void" /> + <argument index="0" name="setting" type="String" /> + <description> + Marks the passed editor setting as being changed, see [method get_changed_settings]. Only settings which exist (see [method has_setting]) will be accepted. + </description> + </method> <method name="property_can_revert"> <return type="bool" /> <argument index="0" name="name" type="String" /> diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml index d35dacfcde..aecb4fc4b6 100644 --- a/doc/classes/ImageTexture.xml +++ b/doc/classes/ImageTexture.xml @@ -18,7 +18,7 @@ var texture = load("res://icon.png") $Sprite2D.texture = texture [/codeblock] - This is because images have to be imported as a [StreamTexture2D] first to be loaded with [method @GDScript.load]. If you'd still like to load an image file just like any other [Resource], import it as an [Image] resource instead, and then load it normally using the [method @GDScript.load] method. + This is because images have to be imported as a [CompressedTexture2D] first to be loaded with [method @GDScript.load]. If you'd still like to load an image file just like any other [Resource], import it as an [Image] resource instead, and then load it normally using the [method @GDScript.load] method. [b]Note:[/b] The image can be retrieved from an imported texture using the [method Texture2D.get_image] method, which returns a copy of the image: [codeblock] var texture = load("res://icon.png") diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index 1a1a7f8333..821fc1ae95 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -82,7 +82,7 @@ Returns [code]true[/code] if the scene file has nodes. </description> </method> - <method name="get_state"> + <method name="get_state" qualifiers="const"> <return type="SceneState" /> <description> Returns the [code]SceneState[/code] representing the scene file contents. diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index 1ce21d96e1..e05853e816 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -114,7 +114,7 @@ True if the interaction with particle attractors is enabled. </member> <member name="collision_bounce" type="float" setter="set_collision_bounce" getter="get_collision_bounce" default="0.0"> - Collision bouncyness. + Collision bounciness. </member> <member name="collision_enabled" type="bool" setter="set_collision_enabled" getter="is_collision_enabled" default="false"> True if collisions are enabled for this particle system. diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index c516aec809..983a05800f 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -6,7 +6,7 @@ <description> Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They are queried automatically via the [ResourceLoader] singleton, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoaders are registered in the engine. Extending this class allows you to define your own loader. Be sure to respect the documented return types and values. You should give it a global class name with [code]class_name[/code] for it to be registered. Like built-in ResourceFormatLoaders, it will be called automatically when loading resources of its handled type(s). You may also implement a [ResourceFormatSaver]. - [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([StreamTexture2D]) first, so they can be loaded with better efficiency on the graphics card. + [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card. </description> <tutorials> </tutorials> diff --git a/doc/classes/StreamCubemap.xml b/doc/classes/StreamCubemap.xml deleted file mode 100644 index 61ab28ad41..0000000000 --- a/doc/classes/StreamCubemap.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamCubemap" inherits="StreamTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> -</class> diff --git a/doc/classes/StreamCubemapArray.xml b/doc/classes/StreamCubemapArray.xml deleted file mode 100644 index 98e10d9a47..0000000000 --- a/doc/classes/StreamCubemapArray.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamCubemapArray" inherits="StreamTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> -</class> diff --git a/doc/classes/StreamTexture2DArray.xml b/doc/classes/StreamTexture2DArray.xml deleted file mode 100644 index e78a23416c..0000000000 --- a/doc/classes/StreamTexture2DArray.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamTexture2DArray" inherits="StreamTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> -</class> diff --git a/doc/classes/TabBar.xml b/doc/classes/TabBar.xml index 41e1e255ae..6ddcc2044d 100644 --- a/doc/classes/TabBar.xml +++ b/doc/classes/TabBar.xml @@ -106,12 +106,6 @@ Returns the title of the tab at index [code]tab_idx[/code]. </description> </method> - <method name="get_tabs_rearrange_group" qualifiers="const"> - <return type="int" /> - <description> - Returns the [TabBar]'s rearrange group ID. - </description> - </method> <method name="is_tab_disabled" qualifiers="const"> <return type="bool" /> <argument index="0" name="tab_idx" type="int" /> @@ -206,13 +200,6 @@ Sets a [code]title[/code] for the tab at index [code]tab_idx[/code]. </description> </method> - <method name="set_tabs_rearrange_group"> - <return type="void" /> - <argument index="0" name="group_id" type="int" /> - <description> - Defines the rearrange group ID. Choose for each [TabBar] the same value to dragging tabs between [TabBar]. Enable drag with [member drag_to_rearrange_enabled]. - </description> - </method> </methods> <members> <member name="clip_tabs" type="bool" setter="set_clip_tabs" getter="get_clip_tabs" default="true"> @@ -242,6 +229,10 @@ <member name="tab_count" type="int" setter="set_tab_count" getter="get_tab_count" default="0"> The number of tabs currently in the bar. </member> + <member name="tabs_rearrange_group" type="int" setter="set_tabs_rearrange_group" getter="get_tabs_rearrange_group" default="-1"> + [TabBar]s with the same rearrange group ID will allow dragging the tabs between them. Enable drag with [member drag_to_rearrange_enabled]. + Setting this to [code]-1[/code] will disable rearranging between [TabBar]s. + </member> </members> <signals> <signal name="active_tab_rearranged"> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index 3f4ec81c95..3ff4dffe65 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -71,12 +71,6 @@ Returns the title of the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node, but this can be overridden with [method set_tab_title]. </description> </method> - <method name="get_tabs_rearrange_group" qualifiers="const"> - <return type="int" /> - <description> - Returns the [TabContainer] rearrange group id. - </description> - </method> <method name="is_tab_disabled" qualifiers="const"> <return type="bool" /> <argument index="0" name="tab_idx" type="int" /> @@ -130,13 +124,6 @@ Sets a custom title for the tab at index [code]tab_idx[/code] (tab titles default to the name of the indexed child node). Set it to blank to make it the child's name again. </description> </method> - <method name="set_tabs_rearrange_group"> - <return type="void" /> - <argument index="0" name="group_id" type="int" /> - <description> - Defines rearrange group id, choose for each [TabContainer] the same value to enable tab drag between [TabContainer]. Enable drag with [member drag_to_rearrange_enabled]. - </description> - </method> </methods> <members> <member name="all_tabs_in_front" type="bool" setter="set_all_tabs_in_front" getter="is_all_tabs_in_front" default="false"> @@ -154,6 +141,10 @@ <member name="tab_alignment" type="int" setter="set_tab_alignment" getter="get_tab_alignment" enum="TabBar.AlignmentMode" default="1"> Sets the position at which tabs will be placed. See [enum TabBar.AlignmentMode] for details. </member> + <member name="tabs_rearrange_group" type="int" setter="set_tabs_rearrange_group" getter="get_tabs_rearrange_group" default="-1"> + [TabContainer]s with the same rearrange group ID will allow dragging the tabs between them. Enable drag with [member drag_to_rearrange_enabled]. + Setting this to [code]-1[/code] will disable rearranging between [TabContainer]s. + </member> <member name="tabs_visible" type="bool" setter="set_tabs_visible" getter="are_tabs_visible" default="true"> If [code]true[/code], tabs are visible. If [code]false[/code], tabs' content and titles are hidden. </member> diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index 975be428d8..ebe25ed55e 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -21,7 +21,7 @@ <return type="void" /> <argument index="0" name="time_sec" type="float" default="-1" /> <description> - Starts the timer. Sets [code]wait_time[/code] to [code]time_sec[/code] if [code]time_sec > 0[/code]. This also resets the remaining time to [code]wait_time[/code]. + Starts the timer. Sets [member wait_time] to [code]time_sec[/code] if [code]time_sec > 0[/code]. This also resets the remaining time to [member wait_time]. [b]Note:[/b] This method will not resume a paused timer. See [member paused]. </description> </method> diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 9cc505cff1..b86b5f1579 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -5632,18 +5632,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, switch (uniform.uniform_type) { case UNIFORM_TYPE_SAMPLER: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!sampler, RID(), "Sampler (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid sampler."); VkDescriptorImageInfo img_info; @@ -5655,31 +5655,31 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: { - if (uniform.ids.size() != set_uniform.length * 2) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j += 2) { - VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]); + for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) { + VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0)); ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler."); - Texture *texture = texture_owner.get_or_null(uniform.ids[j + 1]); + Texture *texture = texture_owner.get_or_null(uniform.get_id(j + 1)); ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(), @@ -5692,7 +5692,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) { UniformSet::AttachableTexture attachable_texture; attachable_texture.bind = set_uniform.binding; - attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1]; + attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j + 1); attachable_textures.push_back(attachable_texture); } @@ -5711,28 +5711,28 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size() / 2; + write.descriptorCount = uniform.get_id_count() / 2; write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size() / 2; + type_size = uniform.get_id_count() / 2; } break; case UNIFORM_TYPE_TEXTURE: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(), @@ -5745,7 +5745,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) { UniformSet::AttachableTexture attachable_texture; attachable_texture.bind = set_uniform.binding; - attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j]; + attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j); attachable_textures.push_back(attachable_texture); } @@ -5765,27 +5765,27 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_IMAGE: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!texture, RID(), "Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); @@ -5813,29 +5813,29 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_TEXTURE_BUFFER: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorBufferInfo> buffer_info; Vector<VkBufferView> buffer_view; - for (int j = 0; j < uniform.ids.size(); j++) { - TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!buffer, RID(), "Texture Buffer (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture buffer."); buffer_info.push_back(buffer->buffer.buffer_info); @@ -5843,21 +5843,21 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; write.pImageInfo = nullptr; write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr(); write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr(); - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: { - if (uniform.ids.size() != set_uniform.length * 2) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } @@ -5865,11 +5865,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, Vector<VkDescriptorBufferInfo> buffer_info; Vector<VkBufferView> buffer_view; - for (int j = 0; j < uniform.ids.size(); j += 2) { - VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]); + for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) { + VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0)); ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler."); - TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j + 1]); + TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j + 1)); VkDescriptorImageInfo img_info; img_info.sampler = *sampler; @@ -5885,23 +5885,23 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size() / 2; + write.descriptorCount = uniform.get_id_count() / 2; write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr(); write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr(); - type_size = uniform.ids.size() / 2; + type_size = uniform.get_id_count() / 2; } break; case UNIFORM_TYPE_IMAGE_BUFFER: { //todo } break; case UNIFORM_TYPE_UNIFORM_BUFFER: { - ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(), - "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided)."); + ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(), + "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided)."); - Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.ids[0]); + Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.get_id(0)); ERR_FAIL_COND_V_MSG(!buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid."); ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(), @@ -5916,15 +5916,15 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } break; case UNIFORM_TYPE_STORAGE_BUFFER: { - ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(), - "Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided)."); + ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(), + "Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided)."); Buffer *buffer = nullptr; - if (storage_buffer_owner.owns(uniform.ids[0])) { - buffer = storage_buffer_owner.get_or_null(uniform.ids[0]); - } else if (vertex_buffer_owner.owns(uniform.ids[0])) { - buffer = vertex_buffer_owner.get_or_null(uniform.ids[0]); + if (storage_buffer_owner.owns(uniform.get_id(0))) { + buffer = storage_buffer_owner.get_or_null(uniform.get_id(0)); + } else if (vertex_buffer_owner.owns(uniform.get_id(0))) { + buffer = vertex_buffer_owner.get_or_null(uniform.get_id(0)); ERR_FAIL_COND_V_MSG(!(buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), RID(), "Vertex buffer supplied (binding: " + itos(uniform.binding) + ") was not created with storage flag."); } @@ -5944,18 +5944,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, case UNIFORM_TYPE_INPUT_ATTACHMENT: { ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for compute shader (this is not allowed)."); - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!texture, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); @@ -5978,13 +5978,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; default: { } @@ -6034,10 +6034,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, _add_dependency(id, p_shader); for (uint32_t i = 0; i < uniform_count; i++) { const Uniform &uniform = uniforms[i]; - int id_count = uniform.ids.size(); - const RID *ids = uniform.ids.ptr(); + int id_count = uniform.get_id_count(); for (int j = 0; j < id_count; j++) { - _add_dependency(id, ids[j]); + _add_dependency(id, uniform.get_id(j)); } } diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index c8c8c7d891..0dbe230699 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -946,7 +946,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } if (menu->get_item_count()) { - menu->set_as_minsize(); + menu->reset_size(); menu->set_position(popup_pos); menu->popup(); } diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 53f585d06b..3970fca3b5 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2748,7 +2748,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), TTR("Discrete"), MENU_CALL_MODE_DISCRETE); menu->add_icon_item(get_theme_icon(SNAME("TrackTrigger"), SNAME("EditorIcons")), TTR("Trigger"), MENU_CALL_MODE_TRIGGER); menu->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), TTR("Capture"), MENU_CALL_MODE_CAPTURE); - menu->set_as_minsize(); + menu->reset_size(); Vector2 popup_pos = get_screen_position() + update_mode_rect.position + Vector2(0, update_mode_rect.size.height); menu->set_position(popup_pos); @@ -2766,7 +2766,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), TTR("Nearest"), MENU_INTERPOLATION_NEAREST); menu->add_icon_item(get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), TTR("Linear"), MENU_INTERPOLATION_LINEAR); menu->add_icon_item(get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), TTR("Cubic"), MENU_INTERPOLATION_CUBIC); - menu->set_as_minsize(); + menu->reset_size(); Vector2 popup_pos = get_screen_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height); menu->set_position(popup_pos); @@ -2783,7 +2783,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->clear(); menu->add_icon_item(get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons")), TTR("Clamp Loop Interp"), MENU_LOOP_CLAMP); menu->add_icon_item(get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")), TTR("Wrap Loop Interp"), MENU_LOOP_WRAP); - menu->set_as_minsize(); + menu->reset_size(); Vector2 popup_pos = get_screen_position() + loop_wrap_rect.position + Vector2(0, loop_wrap_rect.size.height); menu->set_position(popup_pos); @@ -2885,7 +2885,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_separator(); menu->add_icon_item(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete Key(s)"), MENU_KEY_DELETE); } - menu->set_as_minsize(); + menu->reset_size(); menu->set_position(get_screen_position() + get_local_mouse_position()); menu->popup(); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 9685ff4b70..b64b48b4ee 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -92,6 +92,12 @@ void EditorAudioBus::_notification(int p_what) { audio_value_preview_label->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"))); audio_value_preview_label->add_theme_color_override("font_shadow_color", get_theme_color(SNAME("font_shadow_color"), SNAME("TooltipLabel"))); audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); + + for (int i = 0; i < effect_options->get_item_count(); i++) { + String class_name = effect_options->get_item_metadata(i); + Ref<Texture> icon = EditorNode::get_singleton()->get_class_icon(class_name); + effect_options->set_item_icon(i, icon); + } } break; case NOTIFICATION_READY: { @@ -917,11 +923,9 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { continue; } - Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(E); String name = E.operator String().replace("AudioEffect", ""); effect_options->add_item(name); effect_options->set_item_metadata(effect_options->get_item_count() - 1, E); - effect_options->set_item_icon(effect_options->get_item_count() - 1, icon); } bus_options = memnew(MenuButton); @@ -1328,7 +1332,7 @@ EditorAudioBuses::EditorAudioBuses() { List<String> ext; ResourceLoader::get_recognized_extensions_for_type("AudioBusLayout", &ext); for (const String &E : ext) { - file_dialog->add_filter("*." + E + "; Audio Bus Layout"); + file_dialog->add_filter(vformat("*.%s; %s", E, TTR("Audio Bus Layout"))); } add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &EditorAudioBuses::_file_dialog_callback)); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 295b477080..1afd59e99c 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -542,7 +542,7 @@ void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String & filters.push_back(f); } - DirAccess *da = DirAccess::open("res://"); + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); ERR_FAIL_NULL(da); _edit_files_with_filter(da, filters, r_list, exclude); memdelete(da); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 675ef808e1..a83379dca4 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -691,15 +691,11 @@ void EditorProperty::unhandled_key_input(const Ref<InputEvent> &p_event) { } const Color *EditorProperty::_get_property_colors() { - const Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); - const float saturation = base.get_s() * 0.75; - const float value = base.get_v(); - static Color c[4]; - c[0].set_hsv(0.0 / 3.0 + 0.05, saturation, value); - c[1].set_hsv(1.0 / 3.0 + 0.05, saturation, value); - c[2].set_hsv(2.0 / 3.0 + 0.05, saturation, value); - c[3].set_hsv(1.5 / 3.0 + 0.05, saturation, value); + c[0] = get_theme_color(SNAME("property_color_x"), SNAME("Editor")); + c[1] = get_theme_color(SNAME("property_color_y"), SNAME("Editor")); + c[2] = get_theme_color(SNAME("property_color_z"), SNAME("Editor")); + c[3] = get_theme_color(SNAME("property_color_w"), SNAME("Editor")); return c; } @@ -3514,7 +3510,9 @@ void EditorInspector::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { _update_inspector_bg(); - update_tree(); + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/inspector")) { + update_tree(); + } } break; } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index ddb9c93f04..33864df7d3 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -701,22 +701,29 @@ void EditorNode::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); - theme = create_custom_theme(theme_base->get_theme()); - theme_base->set_theme(theme); - gui_base->set_theme(theme); + bool theme_changed = + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") || + EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme"); - gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles"))); - scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles"))); - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); - scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); - scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); + if (theme_changed) { + theme = create_custom_theme(theme_base->get_theme()); + + theme_base->set_theme(theme); + gui_base->set_theme(theme); - file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); - project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); - debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); - settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); - help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); + gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles"))); + scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); + scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); + + file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); + project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); + debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); + settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); + help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); + } if (EDITOR_GET("interface/scene_tabs/resize_if_many_tabs")) { scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE); @@ -725,7 +732,7 @@ void EditorNode::_notification(int p_what) { } _update_scene_tabs(); - recent_scenes->set_as_minsize(); + recent_scenes->reset_size(); // debugger area if (EditorDebuggerNode::get_singleton()->is_visible()) { @@ -3784,7 +3791,7 @@ void EditorNode::_update_recent_scenes() { recent_scenes->add_separator(); recent_scenes->add_shortcut(ED_SHORTCUT("editor/clear_recent", TTR("Clear Recent Scenes"))); - recent_scenes->set_as_minsize(); + recent_scenes->reset_size(); } void EditorNode::_quick_opened() { @@ -5425,7 +5432,7 @@ void EditorNode::remove_tool_menu_item(const String &p_name) { memdelete(n); } tool_menu->remove_item(i); - tool_menu->set_as_minsize(); + tool_menu->reset_size(); return; } } @@ -6204,7 +6211,7 @@ EditorNode::EditorNode() { dock_vb->add_child(dock_float); - dock_select_popup->set_as_minsize(); + dock_select_popup->reset_size(); dock_select_rect_over = -1; dock_popup_selected = -1; for (int i = 0; i < DOCK_SLOT_MAX; i++) { diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 68a3fabe1e..d93d495ff6 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1185,7 +1185,7 @@ void EditorPropertyLayers::_button_pressed() { } Rect2 gp = button->get_screen_rect(); - layers->set_as_minsize(); + layers->reset_size(); Vector2 popup_pos = gp.position - Vector2(layers->get_contents_minimum_size().x, 0); layers->set_position(popup_pos); layers->popup(); @@ -1626,7 +1626,7 @@ void EditorPropertyVector2::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 2; i++) { - spin[i]->set_custom_label_color(true, colors[i]); + spin[i]->add_theme_color_override("label_color", colors[i]); } } break; } @@ -1720,7 +1720,7 @@ void EditorPropertyRect2::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { - spin[i]->set_custom_label_color(true, colors[i % 2]); + spin[i]->add_theme_color_override("label_color", colors[i % 2]); } } break; } @@ -1849,7 +1849,7 @@ void EditorPropertyVector3::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 3; i++) { - spin[i]->set_custom_label_color(true, colors[i]); + spin[i]->add_theme_color_override("label_color", colors[i]); } } break; } @@ -1939,7 +1939,7 @@ void EditorPropertyVector2i::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 2; i++) { - spin[i]->set_custom_label_color(true, colors[i]); + spin[i]->add_theme_color_override("label_color", colors[i]); } } break; } @@ -2033,7 +2033,7 @@ void EditorPropertyRect2i::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { - spin[i]->set_custom_label_color(true, colors[i % 2]); + spin[i]->add_theme_color_override("label_color", colors[i % 2]); } } break; } @@ -2135,7 +2135,7 @@ void EditorPropertyVector3i::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 3; i++) { - spin[i]->set_custom_label_color(true, colors[i]); + spin[i]->add_theme_color_override("label_color", colors[i]); } } break; } @@ -2228,7 +2228,7 @@ void EditorPropertyPlane::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { - spin[i]->set_custom_label_color(true, colors[i]); + spin[i]->add_theme_color_override("label_color", colors[i]); } } break; } @@ -2322,7 +2322,7 @@ void EditorPropertyQuaternion::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { - spin[i]->set_custom_label_color(true, colors[i]); + spin[i]->add_theme_color_override("label_color", colors[i]); } } break; } @@ -2419,7 +2419,7 @@ void EditorPropertyAABB::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 6; i++) { - spin[i]->set_custom_label_color(true, colors[i % 3]); + spin[i]->add_theme_color_override("label_color", colors[i % 3]); } } break; } @@ -2505,9 +2505,9 @@ void EditorPropertyTransform2D::_notification(int p_what) { for (int i = 0; i < 6; i++) { // For Transform2D, use the 4th color (cyan) for the origin vector. if (i % 3 == 2) { - spin[i]->set_custom_label_color(true, colors[3]); + spin[i]->add_theme_color_override("label_color", colors[3]); } else { - spin[i]->set_custom_label_color(true, colors[i % 3]); + spin[i]->add_theme_color_override("label_color", colors[i % 3]); } } } break; @@ -2599,7 +2599,7 @@ void EditorPropertyBasis::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 9; i++) { - spin[i]->set_custom_label_color(true, colors[i % 3]); + spin[i]->add_theme_color_override("label_color", colors[i % 3]); } } break; } @@ -2696,7 +2696,7 @@ void EditorPropertyTransform3D::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 12; i++) { - spin[i]->set_custom_label_color(true, colors[i % 4]); + spin[i]->add_theme_color_override("label_color", colors[i % 4]); } } break; } diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 61261af608..d354be9af5 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -175,7 +175,7 @@ void EditorPropertyArray::_change_type(Object *p_button, int p_index) { Button *button = Object::cast_to<Button>(p_button); changing_type_index = p_index; Rect2 rect = button->get_screen_rect(); - change_type->set_as_minsize(); + change_type->reset_size(); change_type->set_position(rect.get_end() - Vector2(change_type->get_contents_minimum_size().x, 0)); change_type->popup(); } @@ -751,7 +751,7 @@ void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) { Button *button = Object::cast_to<Button>(p_button); Rect2 rect = button->get_screen_rect(); - change_type->set_as_minsize(); + change_type->reset_size(); change_type->set_position(rect.get_end() - Vector2(change_type->get_contents_minimum_size().x, 0)); change_type->popup(); changing_type_index = p_index; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 2f14667fc0..a7b2a4cfa6 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -149,7 +149,7 @@ void EditorResourcePicker::_update_menu() { _update_menu_items(); Rect2 gt = edit_button->get_screen_rect(); - edit_menu->set_as_minsize(); + edit_menu->reset_size(); int ms = edit_menu->get_contents_minimum_size().width; Vector2 popup_pos = gt.get_end() - Vector2(ms, 0); edit_menu->set_position(popup_pos); @@ -337,7 +337,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { // Ensure that the FileSystem dock is visible. TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(file_system_dock->get_index()); + tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock)); } break; default: { @@ -476,7 +476,7 @@ void EditorResourcePicker::_button_input(const Ref<InputEvent> &p_event) { _update_menu_items(); Vector2 pos = get_screen_position() + mb->get_position(); - edit_menu->set_as_minsize(); + edit_menu->reset_size(); edit_menu->set_position(pos); edit_menu->popup(); } @@ -905,7 +905,12 @@ void EditorScriptPicker::set_create_options(Object *p_menu_node) { } menu_node->add_icon_item(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons")), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); - menu_node->add_icon_item(get_theme_icon(SNAME("ScriptExtend"), SNAME("EditorIcons")), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); + if (script_owner) { + Ref<Script> script = script_owner->get_script(); + if (script.is_valid()) { + menu_node->add_icon_item(get_theme_icon(SNAME("ScriptExtend"), SNAME("EditorIcons")), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); + } + } menu_node->add_separator(); } diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 6bd11fcdd6..0135b33bca 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -63,6 +63,7 @@ bool EditorSettings::_set(const StringName &p_name, const Variant &p_value) { bool changed = _set_only(p_name, p_value); if (changed) { + changed_settings.insert(p_name); emit_signal(SNAME("settings_changed")); } return true; @@ -941,10 +942,34 @@ void EditorSettings::save() { if (err != OK) { ERR_PRINT("Error saving editor settings to " + singleton->config_file_path); } else { + singleton->changed_settings.clear(); print_verbose("EditorSettings: Save OK!"); } } +Array EditorSettings::get_changed_settings() const { + Array arr; + for (const String &setting : changed_settings) { + arr.push_back(setting); + } + + return arr; +} + +bool EditorSettings::check_changed_settings_in_group(const String &p_setting_prefix) const { + for (const String &setting : changed_settings) { + if (setting.begins_with(p_setting_prefix)) { + return true; + } + } + + return false; +} + +void EditorSettings::mark_setting_changed(const String &p_setting) { + changed_settings.insert(p_setting); +} + void EditorSettings::destroy() { if (!singleton.ptr()) { return; @@ -1621,6 +1646,10 @@ void EditorSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("set_builtin_action_override", "name", "actions_list"), &EditorSettings::set_builtin_action_override); + ClassDB::bind_method(D_METHOD("check_changed_settings_in_group", "setting_prefix"), &EditorSettings::check_changed_settings_in_group); + ClassDB::bind_method(D_METHOD("get_changed_settings"), &EditorSettings::get_changed_settings); + ClassDB::bind_method(D_METHOD("mark_setting_changed", "setting"), &EditorSettings::mark_setting_changed); + ADD_SIGNAL(MethodInfo("settings_changed")); BIND_CONSTANT(NOTIFICATION_EDITOR_SETTINGS_CHANGED); diff --git a/editor/editor_settings.h b/editor/editor_settings.h index f0fec3acc7..65723a24f8 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -77,6 +77,8 @@ private: static Ref<EditorSettings> singleton; + Set<String> changed_settings; + HashMap<String, PropertyInfo> hints; HashMap<String, VariantContainer> props; int last_order; @@ -140,6 +142,9 @@ public: bool property_can_revert(const String &p_setting); Variant property_get_revert(const String &p_setting); void add_property_hint(const PropertyInfo &p_hint); + Array get_changed_settings() const; + bool check_changed_settings_in_group(const String &p_setting_prefix) const; + void mark_setting_changed(const String &p_setting); void set_resource_clipboard(const Ref<Resource> &p_resource) { clipboard = p_resource; } Ref<Resource> get_resource_clipboard() const { return clipboard; } diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index 75bba64e2e..8ecdcfff65 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -134,9 +134,13 @@ void EditorSettingsDialog::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { _update_icons(); - // Update theme colors. - inspector->update_category_list(); - _update_shortcuts(); + + bool update_shortcuts_tab = + EditorSettings::get_singleton()->check_changed_settings_in_group("shortcuts") || + EditorSettings::get_singleton()->check_changed_settings_in_group("builtin_action_overrides"); + if (update_shortcuts_tab) { + _update_shortcuts(); + } } break; } } @@ -215,6 +219,8 @@ void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Ar Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(p_name); undo_redo->create_action(TTR("Edit Built-in Action") + " '" + p_name + "'"); + undo_redo->add_do_method(EditorSettings::get_singleton(), "mark_setting_changed", "builtin_action_overrides"); + undo_redo->add_undo_method(EditorSettings::get_singleton(), "mark_setting_changed", "builtin_action_overrides"); undo_redo->add_do_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, p_events); undo_redo->add_undo_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, old_input_array); undo_redo->add_do_method(this, "_settings_changed"); @@ -230,6 +236,8 @@ void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const A undo_redo->create_action(TTR("Edit Shortcut") + " '" + p_path + "'"); undo_redo->add_do_method(current_sc.ptr(), "set_events", p_events); undo_redo->add_undo_method(current_sc.ptr(), "set_events", current_sc->get_events()); + undo_redo->add_do_method(EditorSettings::get_singleton(), "mark_setting_changed", "shortcuts"); + undo_redo->add_undo_method(EditorSettings::get_singleton(), "mark_setting_changed", "shortcuts"); undo_redo->add_do_method(this, "_update_shortcuts"); undo_redo->add_undo_method(this, "_update_shortcuts"); undo_redo->add_do_method(this, "_settings_changed"); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index a4a9e691a0..509a316ef3 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -300,12 +300,7 @@ void EditorSpinSlider::_draw_spin_slider() { int vofs = (size.height - font->get_height(font_size)) / 2 + font->get_ascent(font_size); Color fc = get_theme_color(is_read_only() ? SNAME("font_uneditable_color") : SNAME("font_color"), SNAME("LineEdit")); - Color lc; - if (use_custom_label_color) { - lc = custom_label_color; - } else { - lc = fc; - } + Color lc = get_theme_color(is_read_only() ? SNAME("read_only_label_color") : SNAME("label_color")); if (flat && !label.is_empty()) { Color label_bg_color = get_theme_color(SNAME("dark_color_3"), SNAME("Editor")); @@ -605,11 +600,6 @@ bool EditorSpinSlider::is_flat() const { return flat; } -void EditorSpinSlider::set_custom_label_color(bool p_use_custom_label_color, Color p_custom_label_color) { - use_custom_label_color = p_use_custom_label_color; - custom_label_color = p_custom_label_color; -} - void EditorSpinSlider::_focus_entered() { _ensure_input_popup(); Rect2 gr = get_screen_rect(); @@ -689,5 +679,4 @@ EditorSpinSlider::EditorSpinSlider() { value_input_just_closed = false; hide_slider = false; read_only = false; - use_custom_label_color = false; } diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h index 7e3f2051ac..4e52980804 100644 --- a/editor/editor_spin_slider.h +++ b/editor/editor_spin_slider.h @@ -76,9 +76,6 @@ class EditorSpinSlider : public Range { bool hide_slider; bool flat; - bool use_custom_label_color; - Color custom_label_color; - void _evaluate_input_text(); void _update_value_input_stylebox(); @@ -112,8 +109,6 @@ public: void set_flat(bool p_enable); bool is_flat() const; - void set_custom_label_color(bool p_use_custom_label_color, Color p_custom_label_color); - void setup_and_show() { _focus_entered(); } LineEdit *get_line_edit(); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index cdf51dda20..a79ced39a3 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -435,7 +435,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7); const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9); - Color icon_hover_color = Color(1, 1, 1) * (dark_theme ? 1.15 : 1.45); + const Color icon_normal_color = Color(1, 1, 1); + Color icon_hover_color = icon_normal_color * (dark_theme ? 1.15 : 1.45); icon_hover_color.a = 1.0; Color icon_focus_color = icon_hover_color; // Make the pressed icon color overbright because icons are not completely white on a dark theme. @@ -466,6 +467,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("axis_y_color", "Editor", Color(0.53, 0.84, 0.01)); theme->set_color("axis_z_color", "Editor", Color(0.16, 0.55, 0.96)); + const float prop_color_saturation = accent_color.get_s() * 0.75; + const float prop_color_value = accent_color.get_v(); + + theme->set_color("property_color_x", "Editor", Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + theme->set_color("property_color_y", "Editor", Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + theme->set_color("property_color_z", "Editor", Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + theme->set_color("property_color_w", "Editor", Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + theme->set_color("font_color", "Editor", font_color); theme->set_color("highlighted_font_color", "Editor", font_hover_color); theme->set_color("disabled_font_color", "Editor", font_disabled_color); @@ -688,6 +697,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_focus_color", "Button", font_focus_color); theme->set_color("font_pressed_color", "Button", accent_color); theme->set_color("font_disabled_color", "Button", font_disabled_color); + theme->set_color("icon_normal_color", "Button", icon_normal_color); theme->set_color("icon_hover_color", "Button", icon_hover_color); theme->set_color("icon_focus_color", "Button", icon_focus_color); theme->set_color("icon_pressed_color", "Button", icon_pressed_color); @@ -866,6 +876,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("sub_inspector_property_color", "Editor", dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)); theme->set_constant("sub_inspector_font_offset", "Editor", 4 * EDSCALE); + // EditorSpinSlider. + theme->set_color("label_color", "EditorSpinSlider", font_color); + theme->set_color("read_only_label_color", "EditorSpinSlider", font_readonly_color); + Ref<StyleBoxFlat> style_property_bg = style_default->duplicate(); style_property_bg->set_bg_color(highlight_color); style_property_bg->set_border_width_all(0); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 3cad600002..0a8d35aff1 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -645,7 +645,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ // To support custom Android builds, we install the Java source code and buildsystem // from android_source.zip to the project's res://android folder. - DirAccessRef da = DirAccess::open("res://"); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); // Make res://android dir (if it does not exist). diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b41123c0dd..e8a2a46dd2 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -396,12 +396,25 @@ void FileSystemDock::_notification(int p_what) { } } else if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) { tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM | Tree::DROP_MODE_INBETWEEN); + } else if ((String(dd["type"]) == "nodes")) { + holding_branch = true; + TreeItem *item = tree->get_next_selected(tree->get_root()); + while (item) { + tree_items_selected_on_drag_begin.push_back(item); + item = tree->get_next_selected(item); + } + list_items_selected_on_drag_begin = files->get_selected_items(); } } } break; case NOTIFICATION_DRAG_END: { tree->set_drop_mode_flags(0); + + if (holding_branch) { + holding_branch = false; + _reselect_items_selected_on_drag_begin(true); + } } break; case NOTIFICATION_THEME_CHANGED: { @@ -512,7 +525,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa if (target_path.ends_with("/")) { target_path = target_path.substr(0, target_path.length() - 1); } - DirAccess *dirAccess = DirAccess::open("res://"); + DirAccess *dirAccess = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (dirAccess->file_exists(p_path)) { path = target_path; } else if (dirAccess->dir_exists(p_path)) { @@ -2647,8 +2660,79 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { call_deferred(SNAME("_update_import_dock")); } +void FileSystemDock::_tree_mouse_exited() { + if (holding_branch) { + _reselect_items_selected_on_drag_begin(); + } +} + +void FileSystemDock::_reselect_items_selected_on_drag_begin(bool reset) { + TreeItem *selected_item = tree->get_next_selected(tree->get_root()); + if (selected_item) { + selected_item->deselect(0); + } + if (!tree_items_selected_on_drag_begin.is_empty()) { + bool reselected = false; + for (TreeItem *item : tree_items_selected_on_drag_begin) { + if (item->get_tree()) { + item->select(0); + reselected = true; + } + } + + if (reset) { + tree_items_selected_on_drag_begin.clear(); + } + + if (!reselected) { + // If couldn't reselect the items selected on drag begin, select the "res://" item. + tree->get_root()->get_child(1)->select(0); + } + } + + files->deselect_all(); + if (!list_items_selected_on_drag_begin.is_empty()) { + for (const int idx : list_items_selected_on_drag_begin) { + files->select(idx, false); + } + + if (reset) { + list_items_selected_on_drag_begin.clear(); + } + } +} + void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> key = p_event; + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + TreeItem *item = tree->get_item_at_position(mm->get_position()); + if (item && holding_branch) { + String fpath = item->get_metadata(0); + while (!fpath.ends_with("/") && fpath != "res://" && item->get_parent()) { // Find the parent folder tree item. + item = item->get_parent(); + fpath = item->get_metadata(0); + } + + TreeItem *deselect_item = tree->get_next_selected(tree->get_root()); + while (deselect_item) { + deselect_item->deselect(0); + deselect_item = tree->get_next_selected(deselect_item); + } + item->select(0); + + if (display_mode == DisplayMode::DISPLAY_MODE_SPLIT) { + files->deselect_all(); + // Try to select the corresponding file list item. + const int files_item_idx = files->find_metadata(fpath); + if (files_item_idx != -1) { + files->select(files_item_idx); + } + } + } + } + if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { _tree_rmb_option(FILE_DUPLICATE); @@ -2669,6 +2753,43 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { } void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && holding_branch) { + const int item_idx = files->get_item_at_position(mm->get_position()); + if (item_idx != -1) { + files->deselect_all(); + String fpath = files->get_item_metadata(item_idx); + if (fpath.ends_with("/") || fpath == "res://") { + files->select(item_idx); + } + + TreeItem *deselect_item = tree->get_next_selected(tree->get_root()); + while (deselect_item) { + deselect_item->deselect(0); + deselect_item = tree->get_next_selected(deselect_item); + } + + // Try to select the corresponding tree item. + TreeItem *tree_item = tree->get_item_with_text(files->get_item_text(item_idx)); + if (tree_item) { + tree_item->select(0); + } else { + // Find parent folder. + fpath = fpath.substr(0, fpath.rfind("/") + 1); + if (fpath.size() > String("res://").size()) { + fpath = fpath.left(fpath.size() - 2); // Remove last '/'. + const int slash_idx = fpath.rfind("/"); + fpath = fpath.substr(slash_idx + 1, fpath.size() - slash_idx - 1); + } + + tree_item = tree->get_item_with_text(fpath); + if (tree_item) { + tree_item->select(0); + } + } + } + } + Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { @@ -2932,6 +3053,7 @@ FileSystemDock::FileSystemDock() { tree->connect("empty_rmb", callable_mp(this, &FileSystemDock::_tree_rmb_empty)); tree->connect("nothing_selected", callable_mp(this, &FileSystemDock::_tree_empty_selected)); tree->connect("gui_input", callable_mp(this, &FileSystemDock::_tree_gui_input)); + tree->connect("mouse_exited", callable_mp(this, &FileSystemDock::_tree_mouse_exited)); file_list_vb = memnew(VBoxContainer); file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 21c50beeb2..d457c6acd4 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -185,6 +185,13 @@ private: ItemList *files; bool import_dock_needs_update; + bool holding_branch = false; + Vector<TreeItem *> tree_items_selected_on_drag_begin; + PackedInt32Array list_items_selected_on_drag_begin; + + void _tree_mouse_exited(); + void _reselect_items_selected_on_drag_begin(bool reset = false); + Ref<Texture2D> _get_tree_item_icon(bool p_is_valid, String p_file_type); bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path = false); Vector<String> _compute_uncollapsed_paths(); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index ebfb0b32fb..f0a2d7d553 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -767,7 +767,6 @@ bool DynamicFontImportSettings::_char_update(int32_t p_char) { selected_chars.insert(p_char); return true; } - label_glyphs->set_text(TTR("Preloaded glyphs: ") + itos(selected_glyphs.size())); } void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) { diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 7071042818..d9dd273ed4 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -104,16 +104,16 @@ String ResourceImporterLayeredTexture::get_save_extension() const { String ResourceImporterLayeredTexture::get_resource_type() const { switch (mode) { case MODE_CUBEMAP: { - return "StreamCubemap"; + return "CompressedCubemap"; } break; case MODE_2D_ARRAY: { - return "StreamTexture2DArray"; + return "CompressedTexture2DArray"; } break; case MODE_CUBEMAP_ARRAY: { - return "StreamCubemapArray"; + return "CompressedCubemapArray"; } break; case MODE_3D: { - return "StreamTexture3D"; + return "CompressedTexture3D"; } break; } ERR_FAIL_V(String()); @@ -263,7 +263,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons f->store_8('T'); f->store_8('L'); - f->store_32(StreamTextureLayered::FORMAT_VERSION); + f->store_32(CompressedTextureLayered::FORMAT_VERSION); f->store_32(p_images.size()); // For 2d layers or 3d depth. f->store_32(mode); f->store_32(0); diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index edd981c63d..58e5c47d8d 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -35,7 +35,7 @@ #include "core/io/resource_importer.h" #include "core/object/ref_counted.h" -class StreamTexture2D; +class CompressedTexture2D; class LayeredTextureImport : public RefCounted { GDCLASS(LayeredTextureImport, RefCounted); diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 35a20e85c1..1561fc788c 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -37,7 +37,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" -void ResourceImporterTexture::_texture_reimport_roughness(const Ref<StreamTexture2D> &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { +void ResourceImporterTexture::_texture_reimport_roughness(const Ref<CompressedTexture2D> &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { ERR_FAIL_COND(p_tex.is_null()); MutexLock lock(singleton->mutex); @@ -53,7 +53,7 @@ void ResourceImporterTexture::_texture_reimport_roughness(const Ref<StreamTextur singleton->make_flags[path].normal_path_for_roughness = p_normal_path; } -void ResourceImporterTexture::_texture_reimport_3d(const Ref<StreamTexture2D> &p_tex) { +void ResourceImporterTexture::_texture_reimport_3d(const Ref<CompressedTexture2D> &p_tex) { ERR_FAIL_COND(p_tex.is_null()); MutexLock lock(singleton->mutex); @@ -67,7 +67,7 @@ void ResourceImporterTexture::_texture_reimport_3d(const Ref<StreamTexture2D> &p singleton->make_flags[path].flags |= MAKE_3D_FLAG; } -void ResourceImporterTexture::_texture_reimport_normal(const Ref<StreamTexture2D> &p_tex) { +void ResourceImporterTexture::_texture_reimport_normal(const Ref<CompressedTexture2D> &p_tex) { ERR_FAIL_COND(p_tex.is_null()); MutexLock lock(singleton->mutex); @@ -153,11 +153,11 @@ void ResourceImporterTexture::get_recognized_extensions(List<String> *p_extensio } String ResourceImporterTexture::get_save_extension() const { - return "stex"; + return "ctex"; } String ResourceImporterTexture::get_resource_type() const { - return "StreamTexture2D"; + return "CompressedTexture2D"; } bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { @@ -231,7 +231,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") || !Image::_webp_mem_loader_func; // WebP module disabled. bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit - f->store_32(use_webp ? StreamTexture2D::DATA_FORMAT_WEBP : StreamTexture2D::DATA_FORMAT_PNG); + f->store_32(use_webp ? CompressedTexture2D::DATA_FORMAT_WEBP : CompressedTexture2D::DATA_FORMAT_PNG); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -253,7 +253,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image } break; case COMPRESS_LOSSY: { - f->store_32(StreamTexture2D::DATA_FORMAT_WEBP); + f->store_32(CompressedTexture2D::DATA_FORMAT_WEBP); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -273,7 +273,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image image->compress_from_channels(p_compress_format, p_channels, p_lossy_quality); - f->store_32(StreamTexture2D::DATA_FORMAT_IMAGE); + f->store_32(CompressedTexture2D::DATA_FORMAT_IMAGE); f->store_16(image->get_width()); f->store_16(image->get_height()); f->store_32(image->get_mipmap_count()); @@ -285,7 +285,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image f->store_buffer(r, dl); } break; case COMPRESS_VRAM_UNCOMPRESSED: { - f->store_32(StreamTexture2D::DATA_FORMAT_IMAGE); + f->store_32(CompressedTexture2D::DATA_FORMAT_IMAGE); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -299,7 +299,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image } break; case COMPRESS_BASIS_UNIVERSAL: { - f->store_32(StreamTexture2D::DATA_FORMAT_BASIS_UNIVERSAL); + f->store_32(CompressedTexture2D::DATA_FORMAT_BASIS_UNIVERSAL); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -326,26 +326,26 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String f->store_8('2'); //godot streamable texture 2D //format version - f->store_32(StreamTexture2D::FORMAT_VERSION); + f->store_32(CompressedTexture2D::FORMAT_VERSION); //texture may be resized later, so original size must be saved first f->store_32(p_image->get_width()); f->store_32(p_image->get_height()); uint32_t flags = 0; if (p_streamable) { - flags |= StreamTexture2D::FORMAT_BIT_STREAM; + flags |= CompressedTexture2D::FORMAT_BIT_STREAM; } if (p_mipmaps) { - flags |= StreamTexture2D::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit + flags |= CompressedTexture2D::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit } if (p_detect_3d) { - flags |= StreamTexture2D::FORMAT_BIT_DETECT_3D; + flags |= CompressedTexture2D::FORMAT_BIT_DETECT_3D; } if (p_detect_roughness) { - flags |= StreamTexture2D::FORMAT_BIT_DETECT_ROUGNESS; + flags |= CompressedTexture2D::FORMAT_BIT_DETECT_ROUGNESS; } if (p_detect_normal) { - flags |= StreamTexture2D::FORMAT_BIT_DETECT_NORMAL; + flags |= CompressedTexture2D::FORMAT_BIT_DETECT_NORMAL; } f->store_32(flags); @@ -540,19 +540,19 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String if (!bptc_ldr && can_s3tc && is_ldr) { image_compress_mode = Image::COMPRESS_S3TC; } - _save_stex(image, p_save_path + ".s3tc.stex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("s3tc"); formats_imported.push_back("s3tc"); } if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2")) { - _save_stex(image, p_save_path + ".etc2.stex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("etc2"); formats_imported.push_back("etc2"); } if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc")) { - _save_stex(image, p_save_path + ".etc.stex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("etc"); formats_imported.push_back("etc"); } @@ -562,7 +562,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } } else { //import normally - _save_stex(image, p_save_path + ".stex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); } if (r_metadata) { @@ -638,9 +638,9 @@ ResourceImporterTexture *ResourceImporterTexture::singleton = nullptr; ResourceImporterTexture::ResourceImporterTexture() { singleton = this; - StreamTexture2D::request_3d_callback = _texture_reimport_3d; - StreamTexture2D::request_roughness_callback = _texture_reimport_roughness; - StreamTexture2D::request_normal_callback = _texture_reimport_normal; + CompressedTexture2D::request_3d_callback = _texture_reimport_3d; + CompressedTexture2D::request_roughness_callback = _texture_reimport_roughness; + CompressedTexture2D::request_normal_callback = _texture_reimport_normal; } ResourceImporterTexture::~ResourceImporterTexture() { diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index ea2318fb33..bd43eaef58 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -37,7 +37,7 @@ #include "scene/resources/texture.h" #include "servers/rendering_server.h" -class StreamTexture2D; +class CompressedTexture2D; class ResourceImporterTexture : public ResourceImporter { GDCLASS(ResourceImporterTexture, ResourceImporter); @@ -67,9 +67,9 @@ protected: Map<StringName, MakeInfo> make_flags; - static void _texture_reimport_roughness(const Ref<StreamTexture2D> &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); - static void _texture_reimport_3d(const Ref<StreamTexture2D> &p_tex); - static void _texture_reimport_normal(const Ref<StreamTexture2D> &p_tex); + static void _texture_reimport_roughness(const Ref<CompressedTexture2D> &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); + static void _texture_reimport_3d(const Ref<CompressedTexture2D> &p_tex); + static void _texture_reimport_normal(const Ref<CompressedTexture2D> &p_tex); static ResourceImporterTexture *singleton; static const char *compression_formats[]; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 4e06253041..f500268ad3 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -1269,8 +1269,8 @@ SceneImportSettings::SceneImportSettings() { item_save_path = memnew(EditorFileDialog); item_save_path->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); - item_save_path->add_filter("*.tres;Text Resource"); - item_save_path->add_filter("*.res;Binary Resource"); + item_save_path->add_filter("*.tres; " + TTR("Text Resource")); + item_save_path->add_filter("*.res; " + TTR("Binary Resource")); add_child(item_save_path); item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed)); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 48ea3013f7..d5e7c312d9 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -117,7 +117,7 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { if (name_edit->get_text().is_empty()) { is_valid = false; name_validation->set_texture(invalid_icon); - name_validation->set_tooltip(TTR("Plugin name cannot not be blank.")); + name_validation->set_tooltip(TTR("Plugin name cannot be blank.")); } if (script_edit->get_text().get_extension() != ext) { is_valid = false; @@ -127,7 +127,7 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { if (script_edit->get_text().get_basename().is_empty()) { is_valid = false; script_validation->set_texture(invalid_icon); - script_validation->set_tooltip(TTR("Script name cannot not be blank.")); + script_validation->set_tooltip(TTR("Script name cannot be blank.")); } if (subfolder_edit->get_text().is_empty()) { is_valid = false; diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index ad126d28f6..dd166ccd1d 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -547,6 +547,7 @@ void AnimationPlayerEditor::_animation_name_edited() { Ref<Animation> anim = player->get_animation(current); Ref<Animation> new_anim = _animation_clone(anim); + new_anim->set_name(new_name); undo_redo->create_action(TTR("Duplicate Animation")); undo_redo->add_do_method(player, "add_animation", new_name, new_anim); diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp index affe10a01d..643a470425 100644 --- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp @@ -152,7 +152,7 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_sdf_save_path_and_bake(const Strin } config->set_value("remap", "importer", "3d_texture"); - config->set_value("remap", "type", "StreamTexture3D"); + config->set_value("remap", "type", "CompressedTexture3D"); if (!config->has_section_key("params", "compress/mode")) { config->set_value("params", "compress/mode", 3); //user may want another compression, so leave it be } diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp index 5992e52162..aef97f059a 100644 --- a/editor/plugins/lightmap_gi_editor_plugin.cpp +++ b/editor/plugins/lightmap_gi_editor_plugin.cpp @@ -138,7 +138,7 @@ LightmapGIEditorPlugin::LightmapGIEditorPlugin() { file_dialog = memnew(EditorFileDialog); file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); - file_dialog->add_filter("*.lmbake ; LightMap Bake"); + file_dialog->add_filter("*.lmbake ; " + TTR("LightMap Bake")); file_dialog->set_title(TTR("Select lightmap bake file:")); file_dialog->connect("file_selected", callable_mp(this, &LightmapGIEditorPlugin::_bake_select_file)); bake->add_child(file_dialog); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 002c879cdc..17c6457444 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2037,14 +2037,16 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (ED_IS_SHORTCUT("spatial_editor/cancel_transform", p_event) && _edit.mode != TRANSFORM_NONE) { cancel_transform(); } - if (ED_IS_SHORTCUT("spatial_editor/instant_translate", p_event)) { - begin_transform(TRANSFORM_TRANSLATE, true); - } - if (ED_IS_SHORTCUT("spatial_editor/instant_rotate", p_event)) { - begin_transform(TRANSFORM_ROTATE, true); - } - if (ED_IS_SHORTCUT("spatial_editor/instant_scale", p_event)) { - begin_transform(TRANSFORM_SCALE, true); + if (!is_freelook_active()) { + if (ED_IS_SHORTCUT("spatial_editor/instant_translate", p_event)) { + begin_transform(TRANSFORM_TRANSLATE, true); + } + if (ED_IS_SHORTCUT("spatial_editor/instant_rotate", p_event)) { + begin_transform(TRANSFORM_ROTATE, true); + } + if (ED_IS_SHORTCUT("spatial_editor/instant_scale", p_event)) { + begin_transform(TRANSFORM_SCALE, true); + } } // Freelook doesn't work in orthogonal mode. @@ -6920,19 +6922,19 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { } void Node3DEditor::_update_theme() { - tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons"))); - tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons"))); - - tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))); - tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); - tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons"))); + tool_button[TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons"))); + tool_button[TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons"))); + tool_button[TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons"))); + tool_button[TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons"))); + + tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))); + tool_option_button[TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons"))); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons"))); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons"))); diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp index f8e6054848..9cd428a2d4 100644 --- a/editor/plugins/ot_features_plugin.cpp +++ b/editor/plugins/ot_features_plugin.cpp @@ -53,7 +53,7 @@ void OpenTypeFeaturesEditor::_notification(int p_what) { button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); button->set_size(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))->get_size()); - spin->set_custom_label_color(true, base); + spin->add_theme_color_override("label_color", base); } break; } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a4a2919034..43467a6c41 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -682,7 +682,7 @@ void ScriptEditor::_update_recent_scripts() { recent_scripts->add_shortcut(ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Files"))); recent_scripts->set_item_disabled(recent_scripts->get_item_id(recent_scripts->get_item_count() - 1), rc.is_empty()); - recent_scripts->set_as_minsize(); + recent_scripts->reset_size(); } void ScriptEditor::_open_recent_script(int p_idx) { @@ -810,7 +810,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { } if (idx >= 0) { if (history_pos >= 0) { - idx = history[history_pos].control->get_index(); + idx = tab_container->get_tab_idx_from_control(history[history_pos].control); } tab_container->set_current_tab(idx); } else { @@ -1429,7 +1429,7 @@ void ScriptEditor::_menu_option(int p_option) { file_system_dock->navigate_to_path(path); // Ensure that the FileSystem dock is visible. TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(file_system_dock->get_index()); + tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock)); } } break; case CLOSE_DOCS: { @@ -1635,7 +1635,7 @@ void ScriptEditor::_notification(int p_what) { filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))); - recent_scripts->set_as_minsize(); + recent_scripts->reset_size(); if (is_inside_tree()) { _update_script_colors(); @@ -3376,7 +3376,7 @@ void ScriptEditor::_update_history_pos(int p_new_pos) { } history_pos = p_new_pos; - tab_container->set_current_tab(history[history_pos].control->get_index()); + tab_container->set_current_tab(tab_container->get_tab_idx_from_control(history[history_pos].control)); n = history[history_pos].control; diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index 17fe4fdc50..a7c06ada5c 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -64,8 +64,8 @@ void TexturePreview::_update_metadata_label_text() { String format; if (Object::cast_to<ImageTexture>(*texture)) { format = Image::get_format_name(Object::cast_to<ImageTexture>(*texture)->get_format()); - } else if (Object::cast_to<StreamTexture2D>(*texture)) { - format = Image::get_format_name(Object::cast_to<StreamTexture2D>(*texture)->get_format()); + } else if (Object::cast_to<CompressedTexture2D>(*texture)) { + format = Image::get_format_name(Object::cast_to<CompressedTexture2D>(*texture)->get_format()); } else { format = texture->get_class(); } @@ -110,7 +110,7 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) { } bool EditorInspectorPluginTexture::can_handle(Object *p_object) { - return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<StreamTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr; + return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<CompressedTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr; } void EditorInspectorPluginTexture::parse_begin(Object *p_object) { diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 74e3372730..d313b98a7f 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -2077,7 +2077,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito List<String> ext; ResourceLoader::get_recognized_extensions_for_type("Theme", &ext); for (const String &E : ext) { - import_another_theme_dialog->add_filter("*." + E + "; Theme Resource"); + import_another_theme_dialog->add_filter(vformat("*.%s; %s", E, TTR("Theme Resource"))); } import_another_file_hb->add_child(import_another_theme_dialog); import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk)); @@ -3664,7 +3664,7 @@ ThemeEditor::ThemeEditor() { List<String> ext; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &ext); for (const String &E : ext) { - preview_scene_dialog->add_filter("*." + E + "; Scene"); + preview_scene_dialog->add_filter(vformat("*.%s; %s", E, TTR("Scene"))); } main_hs->add_child(preview_scene_dialog); preview_scene_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_preview_scene_dialog_cbk)); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index e9fee8709d..172259c714 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4977,6 +4977,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("VertexId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -4990,6 +4994,9 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo"), { "albedo" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); @@ -5000,6 +5007,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Metallic", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness"), { "roughness" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ShadowAttenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_attenuation"), { "shadow_attenuation" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular"), { "specular" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); @@ -5009,9 +5017,11 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Canvas", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "canvas"), { "canvas" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("InstanceId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Screen", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "screen"), { "screen" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("VertexId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), { "world" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("AtLightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 1a111bcbfc..17db955cc7 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -883,7 +883,8 @@ void ProjectExportDialog::_export_project() { List<String> extension_list = platform->get_binary_extensions(current); for (int i = 0; i < extension_list.size(); i++) { - export_project->add_filter("*." + extension_list[i] + " ; " + platform->get_name() + " Export"); + // TRANSLATORS: This is the name of a project export file format. %s will be replaced by the platform name. + export_project->add_filter(vformat("*.%s; %s", extension_list[i], vformat(TTR("%s Export"), platform->get_name()))); } if (!current->get_export_path().is_empty()) { diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 4d708dc7e0..7059509e72 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -63,7 +63,7 @@ void ProjectSettingsEditor::queue_save() { } void ProjectSettingsEditor::set_plugins_page() { - tab_container->set_current_tab(plugin_settings->get_index()); + tab_container->set_current_tab(tab_container->get_tab_idx_from_control(plugin_settings)); } void ProjectSettingsEditor::update_plugins() { diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index cd65ee7ae6..0282504c70 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -228,7 +228,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { file_system_dock->navigate_to_path(r->get_path()); // Ensure that the FileSystem dock is visible. TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(file_system_dock->get_index()); + tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock)); } break; default: { if (p_which >= CONVERT_BASE_ID) { diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index ba65828ac1..c6a8a928db 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -135,7 +135,8 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i set_selected(n); - NodeDock::get_singleton()->get_parent()->call("set_current_tab", NodeDock::get_singleton()->get_index()); + TabContainer *tab_container = Object::cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); + NodeDock::get_singleton()->get_parent()->call("set_current_tab", tab_container->get_tab_idx_from_control(NodeDock::get_singleton())); NodeDock::get_singleton()->show_connections(); } else if (p_id == BUTTON_GROUPS) { @@ -144,7 +145,8 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i set_selected(n); - NodeDock::get_singleton()->get_parent()->call("set_current_tab", NodeDock::get_singleton()->get_index()); + TabContainer *tab_container = Object::cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); + NodeDock::get_singleton()->get_parent()->call("set_current_tab", tab_container->get_tab_idx_from_control(NodeDock::get_singleton())); NodeDock::get_singleton()->show_groups(); } } diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 3ff8b2b91a..547fd1cfd5 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1139,7 +1139,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * #endif // TOOLS_ENABLED } - if (p_function->identifier->name == "_init") { + if (p_function->identifier->name == GDScriptLanguage::get_singleton()->strings._init) { // Constructor. GDScriptParser::DataType return_type = parser->current_class->get_datatype(); return_type.is_meta_type = false; @@ -1153,6 +1153,57 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * } else { GDScriptParser::DataType return_type = resolve_datatype(p_function->return_type); p_function->set_datatype(return_type); + +#ifdef DEBUG_ENABLED + // Check if the function signature matches the parent. If not it's an error since it breaks polymorphism. + // Not for the constructor which can vary in signature. + GDScriptParser::DataType base_type = parser->current_class->base_type; + GDScriptParser::DataType parent_return_type; + List<GDScriptParser::DataType> parameters_types; + int default_par_count = 0; + bool is_static = false; + bool is_vararg = false; + if (get_function_signature(p_function, false, base_type, p_function->identifier->name, parent_return_type, parameters_types, default_par_count, is_static, is_vararg)) { + bool valid = p_function->is_static == is_static; + valid = valid && parent_return_type == p_function->get_datatype(); + + int par_count_diff = p_function->parameters.size() - parameters_types.size(); + valid = valid && par_count_diff >= 0; + valid = valid && p_function->default_arg_values.size() >= default_par_count + par_count_diff; + + int i = 0; + for (const GDScriptParser::DataType &par_type : parameters_types) { + valid = valid && par_type == p_function->parameters[i++]->get_datatype(); + } + + if (!valid) { + // Compute parent signature as a string to show in the error message. + String parent_signature = parent_return_type.is_hard_type() ? parent_return_type.to_string() : "Variant"; + if (parent_signature == "null") { + parent_signature = "void"; + } + parent_signature += " " + p_function->identifier->name.operator String() + "("; + int j = 0; + for (const GDScriptParser::DataType &par_type : parameters_types) { + if (j > 0) { + parent_signature += ", "; + } + String parameter = par_type.to_string(); + if (parameter == "null") { + parameter = "Variant"; + } + parent_signature += parameter; + if (j == parameters_types.size() - default_par_count) { + parent_signature += " = default"; + } + + j++; + } + parent_signature += ")"; + push_error(vformat(R"(The function signature doesn't match the parent. Parent signature is "%s".)", parent_signature), p_function); + } + } +#endif } parser->current_function = previous_function; @@ -2416,7 +2467,9 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a GDScriptParser::DataType return_type; List<GDScriptParser::DataType> par_types; - if (get_function_signature(p_call, base_type, p_call->function_name, return_type, par_types, default_arg_count, is_static, is_vararg)) { + bool is_constructor = (base_type.is_meta_type || (p_call->callee && p_call->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_call->function_name == SNAME("new"); + + if (get_function_signature(p_call, is_constructor, base_type, p_call->function_name, return_type, par_types, default_arg_count, is_static, is_vararg)) { // If the function require typed arrays we must make literals be typed. for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) { int index = E.key; @@ -3576,7 +3629,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo return result; } -bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source, GDScriptParser::DataType p_base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) { +bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bool p_is_constructor, GDScriptParser::DataType p_base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) { r_static = false; r_vararg = false; r_default_arg_count = 0; @@ -3616,8 +3669,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source return false; } - bool is_constructor = (p_base_type.is_meta_type || (p_source->callee && p_source->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_function == StaticCString::create("new"); - if (is_constructor) { + if (p_is_constructor) { function_name = "_init"; r_static = true; } @@ -3638,7 +3690,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source } if (found_function != nullptr) { - r_static = is_constructor || found_function->is_static; + r_static = p_is_constructor || found_function->is_static; for (int i = 0; i < found_function->parameters.size(); i++) { r_par_types.push_back(found_function->parameters[i]->get_datatype()); if (found_function->parameters[i]->default_value != nullptr) { @@ -3664,7 +3716,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source } // If the base is a script, it might be trying to access members of the Script class itself. - if (p_base_type.is_meta_type && !is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) { + if (p_base_type.is_meta_type && !p_is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) { MethodInfo info; StringName script_class = p_base_type.kind == GDScriptParser::DataType::SCRIPT ? p_base_type.script_type->get_class_name() : StringName(GDScript::get_class_static()); @@ -3684,7 +3736,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source } #endif - if (is_constructor) { + if (p_is_constructor) { // Native types always have a default constructor. r_return_type = p_base_type; r_return_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 2697a6ec2b..7b8883e1d3 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -105,7 +105,7 @@ class GDScriptAnalyzer { GDScriptParser::DataType type_from_metatype(const GDScriptParser::DataType &p_meta_type) const; GDScriptParser::DataType type_from_property(const PropertyInfo &p_property) const; GDScriptParser::DataType make_global_class_meta_type(const StringName &p_class_name, const GDScriptParser::Node *p_source); - bool get_function_signature(GDScriptParser::CallNode *p_source, GDScriptParser::DataType base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg); + bool get_function_signature(GDScriptParser::Node *p_source, bool p_is_constructor, GDScriptParser::DataType base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg); bool function_signature_from_info(const MethodInfo &p_info, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg); bool validate_call_arg(const List<GDScriptParser::DataType> &p_par_types, int p_default_args_count, bool p_is_vararg, const GDScriptParser::CallNode *p_call); bool validate_call_arg(const MethodInfo &p_method, const GDScriptParser::CallNode *p_call); diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.gd new file mode 100644 index 0000000000..435711fcaf --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int) -> int: + return 0 + +class Child extends Parent: + func my_function() -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out new file mode 100644 index 0000000000..3baeb17066 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.gd new file mode 100644 index 0000000000..2bd392e8f8 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int) -> int: + return 0 + +class Child extends Parent: + func my_function(_pary1: int, _par2: int) -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out new file mode 100644 index 0000000000..3baeb17066 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.gd new file mode 100644 index 0000000000..49ec82ce2d --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int = 0) -> int: + return 0 + +class Child extends Parent: + func my_function(_par1: int) -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out new file mode 100644 index 0000000000..665c229339 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int = default)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.gd new file mode 100644 index 0000000000..4a17a7831f --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int) -> int: + return 0 + +class Child extends Parent: + func my_function(_par1: Vector2) -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out new file mode 100644 index 0000000000..3baeb17066 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.gd new file mode 100644 index 0000000000..b205ec96ef --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function() -> int: + return 0 + +class Child extends Parent: + func my_function() -> Vector2: + return Vector2() diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out new file mode 100644 index 0000000000..5b22739a93 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function()". diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.gd b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.gd new file mode 100644 index 0000000000..d678f3acfc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.gd @@ -0,0 +1,17 @@ +func test(): + var instance := Parent.new() + var result := instance.my_function(1) + print(result) + assert(result == 1) + instance = Child.new() + result = instance.my_function(2) + print(result) + assert(result == 0) + +class Parent: + func my_function(par1: int) -> int: + return par1 + +class Child extends Parent: + func my_function(_par1: int, par2: int = 0) -> int: + return par2 diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.out b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.out new file mode 100644 index 0000000000..fc5315a501 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.out @@ -0,0 +1,3 @@ +GDTEST_OK +1 +0 diff --git a/modules/gdscript/tests/scripts/parser/features/class_inheritance_access.gd b/modules/gdscript/tests/scripts/parser/features/class_inheritance_access.gd new file mode 100644 index 0000000000..eb392672eb --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class_inheritance_access.gd @@ -0,0 +1,40 @@ +# Test access visibility of parent elements in nested class architectures. +class Parent: + const parent_const := 1 + + var parent_variable := 2 + + signal parent_signal + + var parent_attribute: int: + get: + return 3 + + func parent_func(): + return 4 + + class Nested: + const nested_const := 5 + + +class Child extends Parent: + func child_test(): + print(parent_const) + print(self.parent_const) + print(parent_variable) + print(self.parent_variable) + print(parent_signal.get_name()) + print(self.parent_signal.get_name()) + print(parent_attribute) + print(self.parent_attribute) + print(parent_func.get_method()) + print(self.parent_func.get_method()) + print(parent_func()) + print(self.parent_func()) + print(Nested.nested_const) + print(self.Nested.nested_const) + print(Parent.Nested.nested_const) + + +func test(): + Child.new().child_test() diff --git a/modules/gdscript/tests/scripts/parser/features/class_inheritance_access.out b/modules/gdscript/tests/scripts/parser/features/class_inheritance_access.out new file mode 100644 index 0000000000..09e87bccfa --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class_inheritance_access.out @@ -0,0 +1,16 @@ +GDTEST_OK +1 +1 +2 +2 +parent_signal +parent_signal +3 +3 +parent_func +parent_func +4 +4 +5 +5 +5 diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 11715040c2..a4b3bfdbd0 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -618,14 +618,14 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(dest_light_tex); + u.append_id(dest_light_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.ids.push_back(source_light_tex); + u.append_id(source_light_tex); uniforms.push_back(u); } } @@ -856,70 +856,70 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(vertex_buffer); + u.append_id(vertex_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(triangle_buffer); + u.append_id(triangle_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; - u.ids.push_back(triangle_cell_indices_buffer); + u.append_id(triangle_cell_indices_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 4; - u.ids.push_back(lights_buffer); + u.append_id(lights_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 5; - u.ids.push_back(seams_buffer); + u.append_id(seams_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 6; - u.ids.push_back(probe_positions_buffer); + u.append_id(probe_positions_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 7; - u.ids.push_back(grid_texture); + u.append_id(grid_texture); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 8; - u.ids.push_back(albedo_array_tex); + u.append_id(albedo_array_tex); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(emission_array_tex); + u.append_id(emission_array_tex); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; - u.ids.push_back(sampler); + u.append_id(sampler); base_uniforms.push_back(u); } } @@ -1057,14 +1057,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(position_tex); + u.append_id(position_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(unocclude_tex); //will be unused + u.append_id(unocclude_tex); //will be unused uniforms.push_back(u); } } @@ -1097,42 +1097,42 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(light_source_tex); + u.append_id(light_source_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.ids.push_back(light_dest_tex); //will be unused + u.append_id(light_dest_tex); //will be unused uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.ids.push_back(position_tex); + u.append_id(position_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 3; - u.ids.push_back(normal_tex); + u.append_id(normal_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; - u.ids.push_back(light_accum_tex); + u.append_id(light_accum_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; - u.ids.push_back(light_primary_dynamic_tex); + u.append_id(light_primary_dynamic_tex); uniforms.push_back(u); } } @@ -1176,57 +1176,57 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(light_dest_tex); + u.append_id(light_dest_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.ids.push_back(light_source_tex); + u.append_id(light_source_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.ids.push_back(position_tex); + u.append_id(position_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 3; - u.ids.push_back(normal_tex); + u.append_id(normal_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; - u.ids.push_back(light_accum_tex); + u.append_id(light_accum_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; - u.ids.push_back(unocclude_tex); //reuse unocclude tex + u.append_id(unocclude_tex); //reuse unocclude tex uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 6; - u.ids.push_back(light_environment_tex); + u.append_id(light_environment_tex); uniforms.push_back(u); } } RID secondary_uniform_set[2]; secondary_uniform_set[0] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1); - uniforms.write[0].ids.write[0] = light_source_tex; - uniforms.write[1].ids.write[0] = light_dest_tex; + uniforms.write[0].set_id(0, light_source_tex); + uniforms.write[1].set_id(0, light_dest_tex); secondary_uniform_set[1] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1); switch (p_quality) { @@ -1332,28 +1332,28 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(light_probe_buffer); + u.append_id(light_probe_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.ids.push_back(light_dest_tex); + u.append_id(light_dest_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.ids.push_back(light_primary_dynamic_tex); + u.append_id(light_primary_dynamic_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 3; - u.ids.push_back(light_environment_tex); + u.append_id(light_environment_tex); uniforms.push_back(u); } } @@ -1531,7 +1531,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.ids.push_back(light_accum_tex2); + u.append_id(light_accum_tex2); uniforms.push_back(u); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 8679f28132..ee218cb1f8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -81,6 +81,15 @@ namespace Godot } } + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y) + { + x = this.x; + y = this.y; + } + internal void Normalize() { real_t lengthsq = LengthSquared(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 9b51de5c8c..412a885daa 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -82,6 +82,15 @@ namespace Godot } /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y) + { + x = this.x; + y = this.y; + } + + /// <summary> /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 1e60fb9523..45e5287610 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -96,6 +96,16 @@ namespace Godot } } + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y, out real_t z) + { + x = this.x; + y = this.y; + z = this.z; + } + internal void Normalize() { real_t lengthsq = LengthSquared(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index eb06d2b87e..abfd2ae720 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -97,6 +97,16 @@ namespace Godot } /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y, out int z) + { + x = this.x; + y = this.y; + z = this.z; + } + + /// <summary> /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 2c431028b0..ca6a45cb83 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -543,7 +543,7 @@ bool EditorExportPlatformAndroid::_should_compress_asset(const String &p_path, c ".webp", // Same reasoning as .png ".cfb", // Don't let small config files slow-down startup ".scn", // Binary scenes are usually already compressed - ".stex", // Streamable textures are usually already compressed + ".ctex", // Streamable textures are usually already compressed // Trailer for easier processing nullptr }; diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp index 594495375a..a76ff042b2 100644 --- a/platform/uwp/export/export_plugin.cpp +++ b/platform/uwp/export/export_plugin.cpp @@ -98,13 +98,13 @@ void EditorExportPlatformUWP::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_flipped"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "images/background_color"), "transparent")); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/store_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square44x44_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square71x71_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square150x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square310x310_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/wide310x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/splash_screen", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/store_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square44x44_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square71x71_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square150x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square310x310_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/wide310x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/splash_screen", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_square150x150"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_wide310x150"), false)); @@ -201,37 +201,37 @@ bool EditorExportPlatformUWP::can_export(const Ref<EditorExportPreset> &p_preset err += TTR("Invalid background color.") + "\n"; } - if (!p_preset->get("images/store_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/store_logo"))), 50, 50)) { + if (!p_preset->get("images/store_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/store_logo"))), 50, 50)) { valid = false; err += TTR("Invalid Store Logo image dimensions (should be 50x50).") + "\n"; } - if (!p_preset->get("images/square44x44_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/square44x44_logo"))), 44, 44)) { + if (!p_preset->get("images/square44x44_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square44x44_logo"))), 44, 44)) { valid = false; err += TTR("Invalid square 44x44 logo image dimensions (should be 44x44).") + "\n"; } - if (!p_preset->get("images/square71x71_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/square71x71_logo"))), 71, 71)) { + if (!p_preset->get("images/square71x71_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square71x71_logo"))), 71, 71)) { valid = false; err += TTR("Invalid square 71x71 logo image dimensions (should be 71x71).") + "\n"; } - if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/square150x150_logo"))), 150, 150)) { + if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square150x150_logo"))), 150, 150)) { valid = false; err += TTR("Invalid square 150x150 logo image dimensions (should be 150x150).") + "\n"; } - if (!p_preset->get("images/square310x310_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/square310x310_logo"))), 310, 310)) { + if (!p_preset->get("images/square310x310_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square310x310_logo"))), 310, 310)) { valid = false; err += TTR("Invalid square 310x310 logo image dimensions (should be 310x310).") + "\n"; } - if (!p_preset->get("images/wide310x150_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/wide310x150_logo"))), 310, 150)) { + if (!p_preset->get("images/wide310x150_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/wide310x150_logo"))), 310, 150)) { valid = false; err += TTR("Invalid wide 310x150 logo image dimensions (should be 310x150).") + "\n"; } - if (!p_preset->get("images/splash_screen").is_zero() && !_valid_image((Object::cast_to<StreamTexture2D>((Object *)p_preset->get("images/splash_screen"))), 620, 300)) { + if (!p_preset->get("images/splash_screen").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/splash_screen"))), 620, 300)) { valid = false; err += TTR("Invalid splash screen image dimensions (should be 620x300).") + "\n"; } diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h index 4c2d25e533..bf89b10ffa 100644 --- a/platform/uwp/export/export_plugin.h +++ b/platform/uwp/export/export_plugin.h @@ -191,7 +191,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform { return false; } - bool _valid_image(const StreamTexture2D *p_image, int p_width, int p_height) const { + bool _valid_image(const CompressedTexture2D *p_image, int p_width, int p_height) const { if (!p_image) { return false; } @@ -311,22 +311,22 @@ class EditorExportPlatformUWP : public EditorExportPlatform { Vector<uint8_t> _get_image_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) { Vector<uint8_t> data; - StreamTexture2D *texture = nullptr; + CompressedTexture2D *texture = nullptr; if (p_path.find("StoreLogo") != -1) { - texture = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/store_logo"))); + texture = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/store_logo"))); } else if (p_path.find("Square44x44Logo") != -1) { - texture = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square44x44_logo"))); + texture = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square44x44_logo"))); } else if (p_path.find("Square71x71Logo") != -1) { - texture = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square71x71_logo"))); + texture = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square71x71_logo"))); } else if (p_path.find("Square150x150Logo") != -1) { - texture = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square150x150_logo"))); + texture = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square150x150_logo"))); } else if (p_path.find("Square310x310Logo") != -1) { - texture = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square310x310_logo"))); + texture = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square310x310_logo"))); } else if (p_path.find("Wide310x150Logo") != -1) { - texture = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/wide310x150_logo"))); + texture = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/wide310x150_logo"))); } else if (p_path.find("SplashScreen") != -1) { - texture = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/splash_screen"))); + texture = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/splash_screen"))); } else { ERR_PRINT("Unable to load logo"); } @@ -393,7 +393,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform { ".webp", // Same reasoning as .png ".cfb", // Don't let small config files slow-down startup ".scn", // Binary scenes are usually already compressed - ".stex", // Streamable textures are usually already compressed + ".ctex", // Streamable textures are usually already compressed // Trailer for easier processing nullptr }; diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 68d2b91fad..07f41c0bf9 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -982,7 +982,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa } config->set_value("remap", "importer", "2d_array_texture"); - config->set_value("remap", "type", "StreamTexture2DArray"); + config->set_value("remap", "type", "CompressedTexture2DArray"); if (!config->has_section_key("params", "compress/mode")) { config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index aa4391e9f1..9f32ac223c 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -1304,7 +1304,7 @@ void ColorPickerButton::pressed() { Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); - popup->set_as_minsize(); + popup->reset_size(); picker->_update_presets(); Rect2i usable_rect = popup->get_usable_parent_rect(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 46f60c92d9..3c712a89bb 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -250,42 +250,41 @@ Transform2D Control::_get_internal_transform() const { bool Control::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; - // Prefixes "custom_*" are supported for compatibility with 3.x. - if (!name.begins_with("theme_override") && !name.begins_with("custom")) { + if (!name.begins_with("theme_override")) { return false; } if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) { - if (name.begins_with("theme_override_icons/") || name.begins_with("custom_icons/")) { + if (name.begins_with("theme_override_icons/")) { String dname = name.get_slicec('/', 1); if (data.icon_override.has(dname)) { data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } data.icon_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - } else if (name.begins_with("theme_override_styles/") || name.begins_with("custom_styles/")) { + } else if (name.begins_with("theme_override_styles/")) { String dname = name.get_slicec('/', 1); if (data.style_override.has(dname)) { data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } data.style_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - } else if (name.begins_with("theme_override_fonts/") || name.begins_with("custom_fonts/")) { + } else if (name.begins_with("theme_override_fonts/")) { String dname = name.get_slicec('/', 1); if (data.font_override.has(dname)) { data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } data.font_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - } else if (name.begins_with("theme_override_font_sizes/") || name.begins_with("custom_font_sizes/")) { + } else if (name.begins_with("theme_override_font_sizes/")) { String dname = name.get_slicec('/', 1); data.font_size_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - } else if (name.begins_with("theme_override_colors/") || name.begins_with("custom_colors/")) { + } else if (name.begins_with("theme_override_colors/")) { String dname = name.get_slicec('/', 1); data.color_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - } else if (name.begins_with("theme_override_constants/") || name.begins_with("custom_constants/")) { + } else if (name.begins_with("theme_override_constants/")) { String dname = name.get_slicec('/', 1); data.constant_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); @@ -294,22 +293,22 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { } } else { - if (name.begins_with("theme_override_icons/") || name.begins_with("custom_icons/")) { + if (name.begins_with("theme_override_icons/")) { String dname = name.get_slicec('/', 1); add_theme_icon_override(dname, p_value); - } else if (name.begins_with("theme_override_styles/") || name.begins_with("custom_styles/")) { + } else if (name.begins_with("theme_override_styles/")) { String dname = name.get_slicec('/', 1); add_theme_style_override(dname, p_value); - } else if (name.begins_with("theme_override_fonts/") || name.begins_with("custom_fonts/")) { + } else if (name.begins_with("theme_override_fonts/")) { String dname = name.get_slicec('/', 1); add_theme_font_override(dname, p_value); - } else if (name.begins_with("theme_override_font_sizes/") || name.begins_with("custom_font_sizes/")) { + } else if (name.begins_with("theme_override_font_sizes/")) { String dname = name.get_slicec('/', 1); add_theme_font_size_override(dname, p_value); - } else if (name.begins_with("theme_override_colors/") || name.begins_with("custom_colors/")) { + } else if (name.begins_with("theme_override_colors/")) { String dname = name.get_slicec('/', 1); add_theme_color_override(dname, p_value); - } else if (name.begins_with("theme_override_constants/") || name.begins_with("custom_constants/")) { + } else if (name.begins_with("theme_override_constants/")) { String dname = name.get_slicec('/', 1); add_theme_constant_override(dname, p_value); } else { diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 24b91cd16a..b9e3e7814e 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -111,10 +111,6 @@ void Popup::_close_pressed() { call_deferred(SNAME("hide")); } -void Popup::set_as_minsize() { - set_size(get_contents_minimum_size()); -} - void Popup::_bind_methods() { ADD_SIGNAL(MethodInfo("popup_hide")); } diff --git a/scene/gui/popup.h b/scene/gui/popup.h index a3c56c9ff1..c45f4ddc24 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -58,8 +58,6 @@ protected: static void _bind_methods(); public: - void set_as_minsize(); - Popup(); ~Popup(); }; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index af2edfa090..840c3d5c31 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -186,7 +186,7 @@ void PopupMenu::_activate_submenu(int p_over) { float scroll_offset = control->get_position().y; - submenu_popup->set_as_minsize(); // Shrink the popup size to its contents. + submenu_popup->reset_size(); // Shrink the popup size to its contents. Size2 submenu_size = submenu_popup->get_size(); Point2 submenu_pos; diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 0e088a44e5..a11248ec6b 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -1541,6 +1541,7 @@ void TabBar::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_to_selected"), "set_scroll_to_selected", "get_scroll_to_selected"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_with_rmb"), "set_select_with_rmb", "get_select_with_rmb"); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 9953637e4f..102fe18502 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -138,6 +138,13 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) { void TabContainer::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + // If some nodes happen to be renamed outside the tree, the tab names need to be updated manually. + if (get_tab_count() > 0) { + _refresh_tab_names(); + } + } break; + case NOTIFICATION_READY: case NOTIFICATION_RESIZED: { _update_margins(); @@ -394,7 +401,10 @@ void TabContainer::_drop_data_fw(const Point2 &p_point, const Variant &p_data, C } move_child(get_tab_control(tab_from_id), get_tab_control(hover_now)->get_index(false)); - set_current_tab(hover_now); + if (!is_tab_disabled(hover_now)) { + set_current_tab(hover_now); + } + } else if (get_tabs_rearrange_group() != -1) { // Drag and drop between TabContainers. Node *from_node = get_node(from_path); @@ -409,8 +419,9 @@ void TabContainer::_drop_data_fw(const Point2 &p_point, const Variant &p_data, C } move_child(moving_tabc, get_tab_control(hover_now)->get_index(false)); - - set_current_tab(hover_now); + if (!is_tab_disabled(hover_now)) { + set_current_tab(hover_now); + } } } } @@ -430,12 +441,11 @@ void TabContainer::_on_tab_selected(int p_tab) { emit_signal(SNAME("tab_selected"), p_tab); } -void TabContainer::_child_renamed_callback() { +void TabContainer::_refresh_tab_names() { Vector<Control *> controls = _get_tab_controls(); for (int i = 0; i < controls.size(); i++) { if (!controls[i]->has_meta("_tab_name") && String(controls[i]->get_name()) != get_tab_title(i)) { tab_bar->set_tab_title(i, controls[i]->get_name()); - return; } } } @@ -457,7 +467,7 @@ void TabContainer::add_child_notify(Node *p_child) { _update_margins(); - p_child->connect("renamed", callable_mp(this, &TabContainer::_child_renamed_callback)); + p_child->connect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names)); // TabBar won't emit the "tab_changed" signal when not inside the tree. if (!is_inside_tree()) { @@ -508,7 +518,7 @@ void TabContainer::remove_child_notify(Node *p_child) { if (p_child->has_meta("_tab_name")) { p_child->remove_meta("_tab_name"); } - p_child->disconnect("renamed", callable_mp(this, &TabContainer::_child_renamed_callback)); + p_child->disconnect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names)); // TabBar won't emit the "tab_changed" signal when not inside the tree. if (!is_inside_tree()) { @@ -635,6 +645,11 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) { tab_bar->set_tab_title(p_tab, p_title); child->set_meta("_tab_name", p_title); } + + _update_margins(); + if (!get_clip_tabs()) { + update_minimum_size(); + } } String TabContainer::get_tab_title(int p_tab) const { @@ -643,6 +658,9 @@ String TabContainer::get_tab_title(int p_tab) const { void TabContainer::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) { tab_bar->set_tab_icon(p_tab, p_icon); + + _update_margins(); + _repaint(); } Ref<Texture2D> TabContainer::get_tab_icon(int p_tab) const { @@ -651,6 +669,11 @@ Ref<Texture2D> TabContainer::get_tab_icon(int p_tab) const { void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) { tab_bar->set_tab_disabled(p_tab, p_disabled); + + _update_margins(); + if (!get_clip_tabs()) { + update_minimum_size(); + } } bool TabContainer::is_tab_disabled(int p_tab) const { @@ -663,6 +686,11 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) { tab_bar->set_tab_hidden(p_tab, p_hidden); child->hide(); + + _update_margins(); + if (!get_clip_tabs()) { + update_minimum_size(); + } } bool TabContainer::is_tab_hidden(int p_tab) const { @@ -735,7 +763,9 @@ void TabContainer::set_popup(Node *p_popup) { if (had_popup != bool(popup)) { update(); _update_margins(); - update_minimum_size(); + if (!get_clip_tabs()) { + update_minimum_size(); + } } } @@ -838,6 +868,7 @@ void TabContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "all_tabs_in_front"), "set_all_tabs_in_front", "is_all_tabs_in_front"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hidden_tabs_for_min_size"), "set_use_hidden_tabs_for_min_size", "get_use_hidden_tabs_for_min_size"); } diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 1322f08206..c54934b37b 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -51,6 +51,7 @@ class TabContainer : public Container { Vector<Control *> _get_tab_controls() const; void _on_theme_changed(); void _repaint(); + void _refresh_tab_names(); void _update_margins(); void _on_mouse_exited(); void _on_tab_changed(int p_tab); @@ -61,7 +62,6 @@ class TabContainer : public Container { void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control); protected: - void _child_renamed_callback(); virtual void gui_input(const Ref<InputEvent> &p_event) override; void _notification(int p_what); virtual void add_child_notify(Node *p_child) override; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 69e7472cf2..d1e8b477a6 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -486,7 +486,7 @@ bool SceneTree::process(double p_time) { } E->get()->set_time_left(time_left); - if (time_left < 0) { + if (time_left <= 0) { E->get()->emit_signal(SNAME("timeout")); timers.erase(E); } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index ccac3c6c68..0b66ff004b 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -260,9 +260,9 @@ static Ref<ResourceFormatSaverText> resource_saver_text; static Ref<ResourceFormatLoaderText> resource_loader_text; -static Ref<ResourceFormatLoaderStreamTexture2D> resource_loader_stream_texture; -static Ref<ResourceFormatLoaderStreamTextureLayered> resource_loader_texture_layered; -static Ref<ResourceFormatLoaderStreamTexture3D> resource_loader_texture_3d; +static Ref<ResourceFormatLoaderCompressedTexture2D> resource_loader_stream_texture; +static Ref<ResourceFormatLoaderCompressedTextureLayered> resource_loader_texture_layered; +static Ref<ResourceFormatLoaderCompressedTexture3D> resource_loader_texture_3d; static Ref<ResourceFormatSaverShader> resource_saver_shader; static Ref<ResourceFormatLoaderShader> resource_loader_shader; @@ -808,7 +808,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(Texture); GDREGISTER_VIRTUAL_CLASS(Texture2D); GDREGISTER_CLASS(Sky); - GDREGISTER_CLASS(StreamTexture2D); + GDREGISTER_CLASS(CompressedTexture2D); GDREGISTER_CLASS(ImageTexture); GDREGISTER_CLASS(AtlasTexture); GDREGISTER_CLASS(MeshTexture); @@ -823,14 +823,14 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(ImageTextureLayered); GDREGISTER_VIRTUAL_CLASS(Texture3D); GDREGISTER_CLASS(ImageTexture3D); - GDREGISTER_CLASS(StreamTexture3D); + GDREGISTER_CLASS(CompressedTexture3D); GDREGISTER_CLASS(Cubemap); GDREGISTER_CLASS(CubemapArray); GDREGISTER_CLASS(Texture2DArray); - GDREGISTER_VIRTUAL_CLASS(StreamTextureLayered); - GDREGISTER_CLASS(StreamCubemap); - GDREGISTER_CLASS(StreamCubemapArray); - GDREGISTER_CLASS(StreamTexture2DArray); + GDREGISTER_VIRTUAL_CLASS(CompressedTextureLayered); + GDREGISTER_CLASS(CompressedCubemap); + GDREGISTER_CLASS(CompressedCubemapArray); + GDREGISTER_CLASS(CompressedTexture2DArray); GDREGISTER_CLASS(Animation); GDREGISTER_CLASS(FontData); @@ -1016,7 +1016,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("SpringArm", "SpringArm3D"); ClassDB::add_compatibility_class("Sprite", "Sprite2D"); ClassDB::add_compatibility_class("StaticBody", "StaticBody3D"); - ClassDB::add_compatibility_class("StreamTexture", "StreamTexture2D"); + ClassDB::add_compatibility_class("CompressedTexture", "CompressedTexture2D"); ClassDB::add_compatibility_class("TextureProgress", "TextureProgressBar"); ClassDB::add_compatibility_class("VehicleBody", "VehicleBody3D"); ClassDB::add_compatibility_class("VehicleWheel", "VehicleWheel3D"); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 9d388d465d..2f1ac7a83a 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -1653,7 +1653,7 @@ void PackedScene::recreate_state() { #endif } -Ref<SceneState> PackedScene::get_state() { +Ref<SceneState> PackedScene::get_state() const { return state; } diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 81b38840d9..96222937d0 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -228,7 +228,7 @@ public: virtual void set_last_modified_time(uint64_t p_time) override { state->set_last_modified_time(p_time); } #endif - Ref<SceneState> get_state(); + Ref<SceneState> get_state() const; PackedScene(); }; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 0ee0e4b33e..1ab1d81355 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -293,7 +293,7 @@ ImageTexture::~ImageTexture() { ////////////////////////////////////////// -Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit) { +Ref<Image> CompressedTexture2D::load_image_from_file(FileAccess *f, int p_size_limit) { uint32_t data_format = f->get_32(); uint32_t w = f->get_16(); uint32_t h = f->get_16(); @@ -426,7 +426,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit return Ref<Image>(); } -void StreamTexture2D::set_path(const String &p_path, bool p_take_over) { +void CompressedTexture2D::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); } @@ -434,36 +434,36 @@ void StreamTexture2D::set_path(const String &p_path, bool p_take_over) { Resource::set_path(p_path, p_take_over); } -void StreamTexture2D::_requested_3d(void *p_ud) { - StreamTexture2D *st = (StreamTexture2D *)p_ud; - Ref<StreamTexture2D> stex(st); +void CompressedTexture2D::_requested_3d(void *p_ud) { + CompressedTexture2D *st = (CompressedTexture2D *)p_ud; + Ref<CompressedTexture2D> stex(st); ERR_FAIL_COND(!request_3d_callback); request_3d_callback(stex); } -void StreamTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { - StreamTexture2D *st = (StreamTexture2D *)p_ud; - Ref<StreamTexture2D> stex(st); +void CompressedTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { + CompressedTexture2D *st = (CompressedTexture2D *)p_ud; + Ref<CompressedTexture2D> stex(st); ERR_FAIL_COND(!request_roughness_callback); request_roughness_callback(stex, p_normal_path, p_roughness_channel); } -void StreamTexture2D::_requested_normal(void *p_ud) { - StreamTexture2D *st = (StreamTexture2D *)p_ud; - Ref<StreamTexture2D> stex(st); +void CompressedTexture2D::_requested_normal(void *p_ud) { + CompressedTexture2D *st = (CompressedTexture2D *)p_ud; + Ref<CompressedTexture2D> stex(st); ERR_FAIL_COND(!request_normal_callback); request_normal_callback(stex); } -StreamTexture2D::TextureFormatRequestCallback StreamTexture2D::request_3d_callback = nullptr; -StreamTexture2D::TextureFormatRoughnessRequestCallback StreamTexture2D::request_roughness_callback = nullptr; -StreamTexture2D::TextureFormatRequestCallback StreamTexture2D::request_normal_callback = nullptr; +CompressedTexture2D::TextureFormatRequestCallback CompressedTexture2D::request_3d_callback = nullptr; +CompressedTexture2D::TextureFormatRoughnessRequestCallback CompressedTexture2D::request_roughness_callback = nullptr; +CompressedTexture2D::TextureFormatRequestCallback CompressedTexture2D::request_normal_callback = nullptr; -Image::Format StreamTexture2D::get_format() const { +Image::Format CompressedTexture2D::get_format() const { return format; } -Error StreamTexture2D::_load_data(const String &p_path, int &r_width, int &r_height, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { +Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r_height, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { alpha_cache.unref(); ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER); @@ -523,7 +523,7 @@ Error StreamTexture2D::_load_data(const String &p_path, int &r_width, int &r_hei return OK; } -Error StreamTexture2D::load(const String &p_path) { +Error CompressedTexture2D::load(const String &p_path) { int lw, lh; Ref<Image> image; image.instantiate(); @@ -590,51 +590,51 @@ Error StreamTexture2D::load(const String &p_path) { return OK; } -String StreamTexture2D::get_load_path() const { +String CompressedTexture2D::get_load_path() const { return path_to_file; } -int StreamTexture2D::get_width() const { +int CompressedTexture2D::get_width() const { return w; } -int StreamTexture2D::get_height() const { +int CompressedTexture2D::get_height() const { return h; } -RID StreamTexture2D::get_rid() const { +RID CompressedTexture2D::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_2d_placeholder_create(); } return texture; } -void StreamTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { +void CompressedTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { if ((w | h) == 0) { return; } RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose); } -void StreamTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { +void CompressedTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { if ((w | h) == 0) { return; } RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose); } -void StreamTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { +void CompressedTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { if ((w | h) == 0) { return; } RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, p_clip_uv); } -bool StreamTexture2D::has_alpha() const { +bool CompressedTexture2D::has_alpha() const { return false; } -Ref<Image> StreamTexture2D::get_image() const { +Ref<Image> CompressedTexture2D::get_image() const { if (texture.is_valid()) { return RS::get_singleton()->texture_2d_get(texture); } else { @@ -642,7 +642,7 @@ Ref<Image> StreamTexture2D::get_image() const { } } -bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { +bool CompressedTexture2D::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { Ref<Image> img = get_image(); if (img.is_valid()) { @@ -676,7 +676,7 @@ bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { return true; } -void StreamTexture2D::reload_from_file() { +void CompressedTexture2D::reload_from_file() { String path = get_path(); if (!path.is_resource_file()) { return; @@ -691,26 +691,26 @@ void StreamTexture2D::reload_from_file() { load(path); } -void StreamTexture2D::_validate_property(PropertyInfo &property) const { +void CompressedTexture2D::_validate_property(PropertyInfo &property) const { } -void StreamTexture2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture2D::load); - ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture2D::get_load_path); +void CompressedTexture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &CompressedTexture2D::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &CompressedTexture2D::get_load_path); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.ctex"), "load", "get_load_path"); } -StreamTexture2D::StreamTexture2D() {} +CompressedTexture2D::CompressedTexture2D() {} -StreamTexture2D::~StreamTexture2D() { +CompressedTexture2D::~CompressedTexture2D() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } } -RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref<StreamTexture2D> st; +RES ResourceFormatLoaderCompressedTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref<CompressedTexture2D> st; st.instantiate(); Error err = st->load(p_path); if (r_error) { @@ -723,17 +723,17 @@ RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String return st; } -void ResourceFormatLoaderStreamTexture2D::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("stex"); +void ResourceFormatLoaderCompressedTexture2D::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("ctex"); } -bool ResourceFormatLoaderStreamTexture2D::handles_type(const String &p_type) const { - return p_type == "StreamTexture2D"; +bool ResourceFormatLoaderCompressedTexture2D::handles_type(const String &p_type) const { + return p_type == "CompressedTexture2D"; } -String ResourceFormatLoaderStreamTexture2D::get_resource_type(const String &p_path) const { - if (p_path.get_extension().to_lower() == "stex") { - return "StreamTexture2D"; +String ResourceFormatLoaderCompressedTexture2D::get_resource_type(const String &p_path) const { + if (p_path.get_extension().to_lower() == "ctex") { + return "CompressedTexture2D"; } return ""; } @@ -846,7 +846,7 @@ ImageTexture3D::~ImageTexture3D() { //////////////////////////////////////////// -void StreamTexture3D::set_path(const String &p_path, bool p_take_over) { +void CompressedTexture3D::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); } @@ -854,11 +854,11 @@ void StreamTexture3D::set_path(const String &p_path, bool p_take_over) { Resource::set_path(p_path, p_take_over); } -Image::Format StreamTexture3D::get_format() const { +Image::Format CompressedTexture3D::get_format() const { return format; } -Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) { +Error CompressedTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) { FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path)); @@ -887,7 +887,7 @@ Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_da r_data.clear(); for (int i = 0; i < (r_depth + mipmaps); i++) { - Ref<Image> image = StreamTexture2D::load_image_from_file(f, 0); + Ref<Image> image = CompressedTexture2D::load_image_from_file(f, 0); ERR_FAIL_COND_V(image.is_null() || image->is_empty(), ERR_CANT_OPEN); if (i == 0) { r_format = image->get_format(); @@ -900,7 +900,7 @@ Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_da return OK; } -Error StreamTexture3D::load(const String &p_path) { +Error CompressedTexture3D::load(const String &p_path) { Vector<Ref<Image>> data; int tw, th, td; @@ -937,34 +937,34 @@ Error StreamTexture3D::load(const String &p_path) { return OK; } -String StreamTexture3D::get_load_path() const { +String CompressedTexture3D::get_load_path() const { return path_to_file; } -int StreamTexture3D::get_width() const { +int CompressedTexture3D::get_width() const { return w; } -int StreamTexture3D::get_height() const { +int CompressedTexture3D::get_height() const { return h; } -int StreamTexture3D::get_depth() const { +int CompressedTexture3D::get_depth() const { return d; } -bool StreamTexture3D::has_mipmaps() const { +bool CompressedTexture3D::has_mipmaps() const { return mipmaps; } -RID StreamTexture3D::get_rid() const { +RID CompressedTexture3D::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_3d_placeholder_create(); } return texture; } -Vector<Ref<Image>> StreamTexture3D::get_data() const { +Vector<Ref<Image>> CompressedTexture3D::get_data() const { if (texture.is_valid()) { return RS::get_singleton()->texture_3d_get(texture); } else { @@ -972,7 +972,7 @@ Vector<Ref<Image>> StreamTexture3D::get_data() const { } } -void StreamTexture3D::reload_from_file() { +void CompressedTexture3D::reload_from_file() { String path = get_path(); if (!path.is_resource_file()) { return; @@ -987,19 +987,19 @@ void StreamTexture3D::reload_from_file() { load(path); } -void StreamTexture3D::_validate_property(PropertyInfo &property) const { +void CompressedTexture3D::_validate_property(PropertyInfo &property) const { } -void StreamTexture3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture3D::load); - ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture3D::get_load_path); +void CompressedTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &CompressedTexture3D::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &CompressedTexture3D::get_load_path); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.ctex"), "load", "get_load_path"); } -StreamTexture3D::StreamTexture3D() {} +CompressedTexture3D::CompressedTexture3D() {} -StreamTexture3D::~StreamTexture3D() { +CompressedTexture3D::~CompressedTexture3D() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } @@ -1007,8 +1007,8 @@ StreamTexture3D::~StreamTexture3D() { ///////////////////////////// -RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref<StreamTexture3D> st; +RES ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref<CompressedTexture3D> st; st.instantiate(); Error err = st->load(p_path); if (r_error) { @@ -1021,17 +1021,17 @@ RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String return st; } -void ResourceFormatLoaderStreamTexture3D::get_recognized_extensions(List<String> *p_extensions) const { +void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("stex3d"); } -bool ResourceFormatLoaderStreamTexture3D::handles_type(const String &p_type) const { - return p_type == "StreamTexture3D"; +bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const { + return p_type == "CompressedTexture3D"; } -String ResourceFormatLoaderStreamTexture3D::get_resource_type(const String &p_path) const { +String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const { if (p_path.get_extension().to_lower() == "stex3d") { - return "StreamTexture3D"; + return "CompressedTexture3D"; } return ""; } @@ -2599,7 +2599,7 @@ ImageTextureLayered::~ImageTextureLayered() { /////////////////////////////////////////// -void StreamTextureLayered::set_path(const String &p_path, bool p_take_over) { +void CompressedTextureLayered::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); } @@ -2607,11 +2607,11 @@ void StreamTextureLayered::set_path(const String &p_path, bool p_take_over) { Resource::set_path(p_path, p_take_over); } -Image::Format StreamTextureLayered::get_format() const { +Image::Format CompressedTextureLayered::get_format() const { return format; } -Error StreamTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> &images, int &mipmap_limit, int p_size_limit) { +Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> &images, int &mipmap_limit, int p_size_limit) { ERR_FAIL_COND_V(images.size() != 0, ERR_INVALID_PARAMETER); FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); @@ -2647,7 +2647,7 @@ Error StreamTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> images.resize(layer_count); for (uint32_t i = 0; i < layer_count; i++) { - Ref<Image> image = StreamTexture2D::load_image_from_file(f, p_size_limit); + Ref<Image> image = CompressedTexture2D::load_image_from_file(f, p_size_limit); ERR_FAIL_COND_V(image.is_null() || image->is_empty(), ERR_CANT_OPEN); images.write[i] = image; } @@ -2655,7 +2655,7 @@ Error StreamTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> return OK; } -Error StreamTextureLayered::load(const String &p_path) { +Error CompressedTextureLayered::load(const String &p_path) { Vector<Ref<Image>> images; int mipmap_limit; @@ -2690,38 +2690,38 @@ Error StreamTextureLayered::load(const String &p_path) { return OK; } -String StreamTextureLayered::get_load_path() const { +String CompressedTextureLayered::get_load_path() const { return path_to_file; } -int StreamTextureLayered::get_width() const { +int CompressedTextureLayered::get_width() const { return w; } -int StreamTextureLayered::get_height() const { +int CompressedTextureLayered::get_height() const { return h; } -int StreamTextureLayered::get_layers() const { +int CompressedTextureLayered::get_layers() const { return layers; } -bool StreamTextureLayered::has_mipmaps() const { +bool CompressedTextureLayered::has_mipmaps() const { return mipmaps; } -TextureLayered::LayeredType StreamTextureLayered::get_layered_type() const { +TextureLayered::LayeredType CompressedTextureLayered::get_layered_type() const { return layered_type; } -RID StreamTextureLayered::get_rid() const { +RID CompressedTextureLayered::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_2d_layered_placeholder_create(RS::TextureLayeredType(layered_type)); } return texture; } -Ref<Image> StreamTextureLayered::get_layer_data(int p_layer) const { +Ref<Image> CompressedTextureLayered::get_layer_data(int p_layer) const { if (texture.is_valid()) { return RS::get_singleton()->texture_2d_layer_get(texture, p_layer); } else { @@ -2729,7 +2729,7 @@ Ref<Image> StreamTextureLayered::get_layer_data(int p_layer) const { } } -void StreamTextureLayered::reload_from_file() { +void CompressedTextureLayered::reload_from_file() { String path = get_path(); if (!path.is_resource_file()) { return; @@ -2744,21 +2744,21 @@ void StreamTextureLayered::reload_from_file() { load(path); } -void StreamTextureLayered::_validate_property(PropertyInfo &property) const { +void CompressedTextureLayered::_validate_property(PropertyInfo &property) const { } -void StreamTextureLayered::_bind_methods() { - ClassDB::bind_method(D_METHOD("load", "path"), &StreamTextureLayered::load); - ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTextureLayered::get_load_path); +void CompressedTextureLayered::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &CompressedTextureLayered::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &CompressedTextureLayered::get_load_path); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.ctex"), "load", "get_load_path"); } -StreamTextureLayered::StreamTextureLayered(LayeredType p_type) { +CompressedTextureLayered::CompressedTextureLayered(LayeredType p_type) { layered_type = p_type; } -StreamTextureLayered::~StreamTextureLayered() { +CompressedTextureLayered::~CompressedTextureLayered() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } @@ -2766,18 +2766,18 @@ StreamTextureLayered::~StreamTextureLayered() { ///////////////////////////////////////////////// -RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref<StreamTextureLayered> st; +RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref<CompressedTextureLayered> st; if (p_path.get_extension().to_lower() == "stexarray") { - Ref<StreamTexture2DArray> s; + Ref<CompressedTexture2DArray> s; s.instantiate(); st = s; } else if (p_path.get_extension().to_lower() == "scube") { - Ref<StreamCubemap> s; + Ref<CompressedCubemap> s; s.instantiate(); st = s; } else if (p_path.get_extension().to_lower() == "scubearray") { - Ref<StreamCubemapArray> s; + Ref<CompressedCubemapArray> s; s.instantiate(); st = s; } else { @@ -2797,25 +2797,25 @@ RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const S return st; } -void ResourceFormatLoaderStreamTextureLayered::get_recognized_extensions(List<String> *p_extensions) const { +void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("stexarray"); p_extensions->push_back("scube"); p_extensions->push_back("scubearray"); } -bool ResourceFormatLoaderStreamTextureLayered::handles_type(const String &p_type) const { - return p_type == "StreamTexture2DArray" || p_type == "StreamCubemap" || p_type == "StreamCubemapArray"; +bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const { + return p_type == "CompressedTexture2DArray" || p_type == "CompressedCubemap" || p_type == "CompressedCubemapArray"; } -String ResourceFormatLoaderStreamTextureLayered::get_resource_type(const String &p_path) const { +String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const { if (p_path.get_extension().to_lower() == "stexarray") { - return "StreamTexture2DArray"; + return "CompressedTexture2DArray"; } if (p_path.get_extension().to_lower() == "scube") { - return "StreamCubemap"; + return "CompressedCubemap"; } if (p_path.get_extension().to_lower() == "scubearray") { - return "StreamCubemapArray"; + return "CompressedCubemapArray"; } return ""; } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 8075497c42..a3c147610d 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -128,8 +128,8 @@ public: ~ImageTexture(); }; -class StreamTexture2D : public Texture2D { - GDCLASS(StreamTexture2D, Texture2D); +class CompressedTexture2D : public Texture2D { + GDCLASS(CompressedTexture2D, Texture2D); public: enum DataFormat { @@ -174,8 +174,8 @@ protected: public: static Ref<Image> load_image_from_file(FileAccess *p_file, int p_size_limit); - typedef void (*TextureFormatRequestCallback)(const Ref<StreamTexture2D> &); - typedef void (*TextureFormatRoughnessRequestCallback)(const Ref<StreamTexture2D> &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); + typedef void (*TextureFormatRequestCallback)(const Ref<CompressedTexture2D> &); + typedef void (*TextureFormatRoughnessRequestCallback)(const Ref<CompressedTexture2D> &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); static TextureFormatRequestCallback request_3d_callback; static TextureFormatRoughnessRequestCallback request_roughness_callback; @@ -200,11 +200,11 @@ public: virtual Ref<Image> get_image() const override; - StreamTexture2D(); - ~StreamTexture2D(); + CompressedTexture2D(); + ~CompressedTexture2D(); }; -class ResourceFormatLoaderStreamTexture2D : public ResourceFormatLoader { +class ResourceFormatLoaderCompressedTexture2D : public ResourceFormatLoader { public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -380,8 +380,8 @@ public: ImageTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} }; -class StreamTextureLayered : public TextureLayered { - GDCLASS(StreamTextureLayered, TextureLayered); +class CompressedTextureLayered : public TextureLayered { + GDCLASS(CompressedTextureLayered, TextureLayered); public: enum DataFormat { @@ -433,34 +433,34 @@ public: virtual Ref<Image> get_layer_data(int p_layer) const override; - StreamTextureLayered(LayeredType p_layered_type); - ~StreamTextureLayered(); + CompressedTextureLayered(LayeredType p_layered_type); + ~CompressedTextureLayered(); }; -class StreamTexture2DArray : public StreamTextureLayered { - GDCLASS(StreamTexture2DArray, StreamTextureLayered) +class CompressedTexture2DArray : public CompressedTextureLayered { + GDCLASS(CompressedTexture2DArray, CompressedTextureLayered) public: - StreamTexture2DArray() : - StreamTextureLayered(LAYERED_TYPE_2D_ARRAY) {} + CompressedTexture2DArray() : + CompressedTextureLayered(LAYERED_TYPE_2D_ARRAY) {} }; -class StreamCubemap : public StreamTextureLayered { - GDCLASS(StreamCubemap, StreamTextureLayered); +class CompressedCubemap : public CompressedTextureLayered { + GDCLASS(CompressedCubemap, CompressedTextureLayered); public: - StreamCubemap() : - StreamTextureLayered(LAYERED_TYPE_CUBEMAP) {} + CompressedCubemap() : + CompressedTextureLayered(LAYERED_TYPE_CUBEMAP) {} }; -class StreamCubemapArray : public StreamTextureLayered { - GDCLASS(StreamCubemapArray, StreamTextureLayered); +class CompressedCubemapArray : public CompressedTextureLayered { + GDCLASS(CompressedCubemapArray, CompressedTextureLayered); public: - StreamCubemapArray() : - StreamTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} + CompressedCubemapArray() : + CompressedTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} }; -class ResourceFormatLoaderStreamTextureLayered : public ResourceFormatLoader { +class ResourceFormatLoaderCompressedTextureLayered : public ResourceFormatLoader { public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -520,8 +520,8 @@ public: ~ImageTexture3D(); }; -class StreamTexture3D : public Texture3D { - GDCLASS(StreamTexture3D, Texture3D); +class CompressedTexture3D : public Texture3D { + GDCLASS(CompressedTexture3D, Texture3D); public: enum DataFormat { @@ -571,11 +571,11 @@ public: virtual Vector<Ref<Image>> get_data() const override; - StreamTexture3D(); - ~StreamTexture3D(); + CompressedTexture3D(); + ~CompressedTexture3D(); }; -class ResourceFormatLoaderStreamTexture3D : public ResourceFormatLoader { +class ResourceFormatLoaderCompressedTexture3D : public ResourceFormatLoader { public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index d58ef0c6fb..03b768e869 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -2517,6 +2517,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Node3D, Vertex { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" }, @@ -2538,6 +2539,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, // Node3D, Fragment { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, @@ -2564,6 +2568,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_roughness_texture", "NORMAL_ROUGHNESS_TEXTURE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "depth_texture", "DEPTH_TEXTURE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, // Node3D, Light { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, @@ -2574,6 +2581,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_color", "LIGHT_COLOR" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "attenuation", "ATTENUATION" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "shadow_attenuation", "SHADOW_ATTENUATION" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "albedo", "ALBEDO" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "diffuse", "DIFFUSE_LIGHT" }, @@ -2605,6 +2613,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" }, // Canvas Item, Fragment { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, @@ -3334,6 +3344,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" }, //////////////////////////////////////////////////////////////////////// // Node3D, Fragment. @@ -3345,6 +3356,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular", "SPECULAR" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "emission", "EMISSION" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao", "AO" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" }, @@ -3360,7 +3372,10 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_scissor_threshold", "ALPHA_SCISSOR_THRESHOLD" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_hash_scale", "ALPHA_HASH_SCALE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_aa_edge", "ALPHA_ANTIALIASING_EDGE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "alpha_uv", "ALPHA_TEXTURE_COORDINATE" }, + //////////////////////////////////////////////////////////////////////// // Node3D, Light. //////////////////////////////////////////////////////////////////////// @@ -3484,7 +3499,7 @@ bool VisualShaderNodeOutput::is_port_separator(int p_index) const { } if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) { String name = get_input_port_name(p_index); - return bool(name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold"); + return bool(name == "Ao" || name == "Normal" || name == "Rim" || name == "Clearcoat" || name == "Anisotropy" || name == "Subsurf Scatter" || name == "Alpha Scissor Threshold"); } return false; } diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp index 5a96dae8ca..06f035a506 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp @@ -32,7 +32,9 @@ #include "godot_collision_object_2d.h" GodotBroadPhase2D::ID GodotBroadPhase2DBVH::create(GodotCollisionObject2D *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) { - ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care? + 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); + ID oid = bvh.create(p_object, true, tree_id, tree_collision_mask, p_aabb, p_subindex); // Pair everything, don't care? return oid + 1; } @@ -41,8 +43,9 @@ void GodotBroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) { } void GodotBroadPhase2DBVH::set_static(ID p_id, bool p_static) { - GodotCollisionObject2D *it = bvh.get(p_id - 1); - bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care? + 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) { @@ -56,7 +59,8 @@ GodotCollisionObject2D *GodotBroadPhase2DBVH::get_object(ID p_id) const { } bool GodotBroadPhase2DBVH::is_static(ID p_id) const { - return !bvh.is_pairable(p_id - 1); + uint32_t tree_id = bvh.get_tree_id(p_id - 1); + return tree_id == 0; } int GodotBroadPhase2DBVH::get_subindex(ID p_id) const { @@ -64,11 +68,11 @@ int GodotBroadPhase2DBVH::get_subindex(ID p_id) const { } int GodotBroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) { - return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); + return bvh.cull_segment(p_from, p_to, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices); } int GodotBroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) { - return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); + return bvh.cull_aabb(p_aabb, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices); } 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) { diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h index d77e0574eb..b11ad0e75e 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.h +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h @@ -38,7 +38,34 @@ #include "core/math/vector2.h" class GodotBroadPhase2DBVH : public GodotBroadPhase2D { - BVH_Manager<GodotCollisionObject2D, true, 128, Rect2, Vector2> bvh; + template <class T> + class UserPairTestFunction { + public: + static bool user_pair_check(const T *p_a, const T *p_b) { + // return false if no collision, decided by masks etc + return p_a->interacts_with(p_b); + } + }; + + template <class T> + class UserCullTestFunction { + public: + static bool user_cull_check(const T *p_a, const T *p_b) { + return true; + } + }; + + enum Tree { + TREE_STATIC = 0, + TREE_DYNAMIC = 1, + }; + + enum TreeFlag { + TREE_FLAG_STATIC = 1 << TREE_STATIC, + TREE_FLAG_DYNAMIC = 1 << TREE_DYNAMIC, + }; + + BVH_Manager<GodotCollisionObject2D, 2, true, 128, UserPairTestFunction<GodotCollisionObject2D>, UserCullTestFunction<GodotCollisionObject2D>, Rect2, Vector2> bvh; static void *_pair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int); static void _unpair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int, void *); diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h index 1e9baad8d9..19d6e91561 100644 --- a/servers/physics_2d/godot_collision_object_2d.h +++ b/servers/physics_2d/godot_collision_object_2d.h @@ -180,7 +180,7 @@ public: return p_other->collision_layer & collision_mask; } - _FORCE_INLINE_ bool interacts_with(GodotCollisionObject2D *p_other) const { + _FORCE_INLINE_ bool interacts_with(const GodotCollisionObject2D *p_other) const { return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; } diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 68dac67d21..04b8d3c741 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -995,11 +995,8 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: return collided; } +// Assumes a valid collision pair, this should have been checked beforehand in the BVH or octree. void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self) { - if (!A->interacts_with(B)) { - return nullptr; - } - GodotCollisionObject2D::Type type_A = A->get_type(); GodotCollisionObject2D::Type type_B = B->get_type(); if (type_A > type_B) { diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp index 9a6b96c411..ecdf74fd41 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp @@ -33,7 +33,9 @@ #include "godot_collision_object_3d.h" GodotBroadPhase3DBVH::ID GodotBroadPhase3DBVH::create(GodotCollisionObject3D *p_object, int p_subindex, const AABB &p_aabb, bool p_static) { - ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care? + 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); + ID oid = bvh.create(p_object, true, tree_id, tree_collision_mask, p_aabb, p_subindex); // Pair everything, don't care? return oid + 1; } @@ -42,8 +44,9 @@ void GodotBroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) { } void GodotBroadPhase3DBVH::set_static(ID p_id, bool p_static) { - GodotCollisionObject3D *it = bvh.get(p_id - 1); - bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care? + 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) { @@ -57,7 +60,8 @@ GodotCollisionObject3D *GodotBroadPhase3DBVH::get_object(ID p_id) const { } bool GodotBroadPhase3DBVH::is_static(ID p_id) const { - return !bvh.is_pairable(p_id - 1); + uint32_t tree_id = bvh.get_tree_id(p_id - 1); + return tree_id == 0; } int GodotBroadPhase3DBVH::get_subindex(ID p_id) const { @@ -65,15 +69,15 @@ int GodotBroadPhase3DBVH::get_subindex(ID p_id) const { } int GodotBroadPhase3DBVH::cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) { - return bvh.cull_point(p_point, p_results, p_max_results, p_result_indices); + return bvh.cull_point(p_point, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices); } int GodotBroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) { - return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); + return bvh.cull_segment(p_from, p_to, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices); } int GodotBroadPhase3DBVH::cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) { - return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); + return bvh.cull_aabb(p_aabb, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices); } 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) { diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h index 7138019a9c..7660030195 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.h +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h @@ -36,7 +36,34 @@ #include "core/math/bvh.h" class GodotBroadPhase3DBVH : public GodotBroadPhase3D { - BVH_Manager<GodotCollisionObject3D, true, 128> bvh; + template <class T> + class UserPairTestFunction { + public: + static bool user_pair_check(const T *p_a, const T *p_b) { + // return false if no collision, decided by masks etc + return p_a->interacts_with(p_b); + } + }; + + template <class T> + class UserCullTestFunction { + public: + static bool user_cull_check(const T *p_a, const T *p_b) { + return true; + } + }; + + enum Tree { + TREE_STATIC = 0, + TREE_DYNAMIC = 1, + }; + + enum TreeFlag { + TREE_FLAG_STATIC = 1 << TREE_STATIC, + TREE_FLAG_DYNAMIC = 1 << TREE_DYNAMIC, + }; + + BVH_Manager<GodotCollisionObject3D, 2, true, 128, UserPairTestFunction<GodotCollisionObject3D>, UserCullTestFunction<GodotCollisionObject3D>> bvh; static void *_pair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int); static void _unpair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int, void *); diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h index 0178838a25..515b945564 100644 --- a/servers/physics_3d/godot_collision_object_3d.h +++ b/servers/physics_3d/godot_collision_object_3d.h @@ -169,7 +169,7 @@ public: return p_other->collision_layer & collision_mask; } - _FORCE_INLINE_ bool interacts_with(GodotCollisionObject3D *p_other) const { + _FORCE_INLINE_ bool interacts_with(const GodotCollisionObject3D *p_other) const { return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; } diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 2490a2f506..e28b6da0d9 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1007,11 +1007,8 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D:: return collided; } +// Assumes a valid collision pair, this should have been checked beforehand in the BVH or octree. void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self) { - if (!A->interacts_with(B)) { - return nullptr; - } - GodotCollisionObject3D::Type type_A = A->get_type(); GodotCollisionObject3D::Type type_B = B->get_type(); if (type_A > type_B) { diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 418d2bc42e..a96f873088 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -66,7 +66,7 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas } } - RENDER_TIMESTAMP("Render Canvas Items"); + RENDER_TIMESTAMP("Render CanvasItems"); bool sdf_flag; RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, sdf_flag); @@ -338,7 +338,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 } void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) { - RENDER_TIMESTAMP(">Render Canvas"); + RENDER_TIMESTAMP("> Render Canvas"); sdf_used = false; snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel; @@ -384,7 +384,7 @@ void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, co } } - RENDER_TIMESTAMP("<End Render Canvas"); + RENDER_TIMESTAMP("< Render Canvas"); } bool RendererCanvasCull::was_sdf_used() { diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 6ad3556969..24108b3a59 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -287,21 +287,21 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 1; - u.ids.push_back(state_uniform); + u.append_id(state_uniform); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(element_buffer); + u.append_id(element_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; - u.ids.push_back(cluster_render_buffer); + u.append_id(cluster_render_buffer); uniforms.push_back(u); } @@ -314,14 +314,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(cluster_render_buffer); + u.append_id(cluster_render_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(cluster_buffer); + u.append_id(cluster_buffer); uniforms.push_back(u); } @@ -329,7 +329,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; - u.ids.push_back(element_buffer); + u.append_id(element_buffer); uniforms.push_back(u); } @@ -342,14 +342,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(cluster_buffer); + u.append_id(cluster_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(p_color_buffer); + u.append_id(p_color_buffer); uniforms.push_back(u); } @@ -357,14 +357,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 3; - u.ids.push_back(p_depth_buffer); + u.append_id(p_depth_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 4; - u.ids.push_back(p_depth_buffer_sampler); + u.append_id(p_depth_buffer_sampler); uniforms.push_back(u); } @@ -398,7 +398,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa } void ClusterBuilderRD::bake_cluster() { - RENDER_TIMESTAMP(">Bake Cluster"); + RENDER_TIMESTAMP("> Bake 3D Cluster"); RD::get_singleton()->draw_command_begin_label("Bake Light Cluster"); @@ -429,7 +429,7 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); - RENDER_TIMESTAMP("Render Elements"); + RENDER_TIMESTAMP("Render 3D Cluster Elements"); //render elements { @@ -466,7 +466,7 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE); } //store elements - RENDER_TIMESTAMP("Pack Elements"); + RENDER_TIMESTAMP("Pack 3D Cluster Elements"); { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -492,7 +492,7 @@ void ClusterBuilderRD::bake_cluster() { } else { RD::get_singleton()->barrier(RD::BARRIER_MASK_TRANSFER, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); } - RENDER_TIMESTAMP("<Bake Cluster"); + RENDER_TIMESTAMP("< Bake 3D Cluster"); RD::get_singleton()->draw_command_end_label(); } diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index fe3863fec7..a5a9dae0b9 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -60,7 +60,7 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(p_image); + u.append_id(p_image); uniforms.push_back(u); //any thing with the same configuration (one texture in binding 0 for set 0), is good RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1); @@ -82,7 +82,7 @@ RID EffectsRD::_get_uniform_set_for_input(RID p_texture) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT; u.binding = 0; - u.ids.push_back(p_texture); + u.append_id(p_texture); uniforms.push_back(u); // This is specific to our subpass shader RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, TONEMAP_MODE_SUBPASS), 0); @@ -104,8 +104,8 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture); + u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.append_id(p_texture); uniforms.push_back(u); // anything with the same configuration (one texture in binding 0 for set 0), is good RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0); @@ -132,16 +132,16 @@ RID EffectsRD::_get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2 RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture1); + u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.append_id(p_texture1); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 1; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture2); + u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.append_id(p_texture2); uniforms.push_back(u); } // anything with the same configuration (one texture in binding 0 for set 0), is good @@ -164,8 +164,8 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture); + u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.append_id(p_texture); uniforms.push_back(u); //any thing with the same configuration (one texture in binding 0 for set 0), is good RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0); @@ -191,8 +191,8 @@ RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(p_sampler); - u.ids.push_back(p_texture); + u.append_id(p_sampler); + u.append_id(p_texture); uniforms.push_back(u); //any thing with the same configuration (one texture in binding 0 for set 0), is good RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0); @@ -219,16 +219,16 @@ RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture1); + u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.append_id(p_texture1); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 1; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture2); + u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.append_id(p_texture2); uniforms.push_back(u); } //any thing with the same configuration (one texture in binding 0 for set 0), is good @@ -256,14 +256,14 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(p_texture1); + u.append_id(p_texture1); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(p_texture2); + u.append_id(p_texture2); uniforms.push_back(u); } //any thing with the same configuration (one texture in binding 0 for set 0), is good @@ -1389,28 +1389,28 @@ void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(p_depth_mipmaps[depth_index + 1]); + u.append_id(p_depth_mipmaps[depth_index + 1]); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(p_depth_mipmaps[depth_index + 2]); + u.append_id(p_depth_mipmaps[depth_index + 2]); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(p_depth_mipmaps[depth_index + 3]); + u.append_id(p_depth_mipmaps[depth_index + 3]); uniforms.push_back(u); } if (use_full_mips) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; - u.ids.push_back(p_depth_mipmaps[4]); + u.append_id(p_depth_mipmaps[4]); uniforms.push_back(u); } ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2); @@ -1537,22 +1537,22 @@ void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(default_sampler); - u.ids.push_back(p_depth_mipmaps_texture); + u.append_id(default_sampler); + u.append_id(p_depth_mipmaps_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(p_normal_buffer); + u.append_id(p_normal_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 2; - u.ids.push_back(ss_effects.gather_constants_buffer); + u.append_id(ss_effects.gather_constants_buffer); uniforms.push_back(u); } r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0); @@ -1564,22 +1564,22 @@ void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(p_ao_pong); + u.append_id(p_ao_pong); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 1; - u.ids.push_back(default_sampler); - u.ids.push_back(p_importance_map); + u.append_id(default_sampler); + u.append_id(p_importance_map); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(ssao.importance_map_load_counter); + u.append_id(ssao.importance_map_load_counter); uniforms.push_back(u); } r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); @@ -1811,15 +1811,15 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(default_mipmap_sampler); - u.ids.push_back(p_diffuse); + u.append_id(default_mipmap_sampler); + u.append_id(p_diffuse); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 1; - u.ids.push_back(ssil.projection_uniform_buffer); + u.append_id(ssil.projection_uniform_buffer); uniforms.push_back(u); } r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3); @@ -1831,22 +1831,22 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(default_sampler); - u.ids.push_back(p_depth_mipmaps_texture); + u.append_id(default_sampler); + u.append_id(p_depth_mipmaps_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(p_normal_buffer); + u.append_id(p_normal_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 2; - u.ids.push_back(ss_effects.gather_constants_buffer); + u.append_id(ss_effects.gather_constants_buffer); uniforms.push_back(u); } r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0); @@ -1858,22 +1858,22 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; - u.ids.push_back(p_ssil_pong); + u.append_id(p_ssil_pong); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 1; - u.ids.push_back(default_sampler); - u.ids.push_back(p_importance_map); + u.append_id(default_sampler); + u.append_id(p_importance_map); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(ssil.importance_map_load_counter); + u.append_id(ssil.importance_map_load_counter); uniforms.push_back(u); } r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1); @@ -2131,7 +2131,7 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = i; - u.ids.push_back(p_dest_cubemap[i]); + u.append_id(p_dest_cubemap[i]); uniforms.push_back(u); } if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { @@ -2651,7 +2651,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(ssao.importance_map_load_counter); + u.append_id(ssao.importance_map_load_counter); uniforms.push_back(u); } ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2); @@ -2766,7 +2766,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(filter.coefficient_buffer); + u.append_id(filter.coefficient_buffer); uniforms.push_back(u); } filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); @@ -2784,7 +2784,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(filter.coefficient_buffer); + u.append_id(filter.coefficient_buffer); uniforms.push_back(u); } filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); @@ -2921,7 +2921,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(ssil.importance_map_load_counter); + u.append_id(ssil.importance_map_load_counter); uniforms.push_back(u); } ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2); 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 d113fcd4f0..6b500260ef 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,7 @@ #include "render_forward_clustered.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" @@ -824,7 +825,6 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat if (p_index >= (int)scene_state.uniform_buffers.size()) { uint32_t from = scene_state.uniform_buffers.size(); scene_state.uniform_buffers.resize(p_index + 1); - render_pass_uniform_sets.resize(p_index + 1); for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) { scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); } @@ -1417,7 +1417,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_voxelgi); if (needs_pre_resolve) { - RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (parallel)"); + RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (Parallel)"); } else { RENDER_TIMESTAMP("Render Depth Pre-Pass"); } @@ -1444,8 +1444,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - RENDER_TIMESTAMP("Resolve Depth Pre-Pass"); - RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass"); + RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)"); + RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)"); if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) { if (needs_pre_resolve) { RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE); @@ -1562,15 +1562,15 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_separate_specular) { if (using_sss) { - RENDER_TIMESTAMP("Sub Surface Scattering"); - RD::get_singleton()->draw_command_begin_label("Process Sub Surface Scattering"); + RENDER_TIMESTAMP("Sub-Surface Scattering"); + RD::get_singleton()->draw_command_begin_label("Process Sub-Surface Scattering"); _process_sss(p_render_data->render_buffers, p_render_data->cam_projection); RD::get_singleton()->draw_command_end_label(); } if (using_ssr) { - RENDER_TIMESTAMP("Screen Space Reflection"); - RD::get_singleton()->draw_command_begin_label("Process Screen Space Reflections"); + 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); RD::get_singleton()->draw_command_end_label(); } else { @@ -1590,9 +1590,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _render_buffers_copy_depth_texture(p_render_data); } - RENDER_TIMESTAMP("Render Transparent Pass"); + RENDER_TIMESTAMP("Render 3D Transparent Pass"); - RD::get_singleton()->draw_command_begin_label("Render Transparent Pass"); + RD::get_singleton()->draw_command_begin_label("Render 3D Transparent Pass"); rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true); @@ -1618,7 +1618,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Copy framebuffer for SSIL"); if (using_ssil) { - RENDER_TIMESTAMP("Copy Final Framebuffer"); + RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL)"); _copy_framebuffer_to_ssil(p_render_data->render_buffers); } RD::get_singleton()->draw_command_end_label(); @@ -1731,7 +1731,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { } void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { - RENDER_TIMESTAMP("Setup Render Collider Heightfield"); + RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -1769,9 +1769,9 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con } void RenderForwardClustered::_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) { - RENDER_TIMESTAMP("Setup Rendering Material"); + RENDER_TIMESTAMP("Setup Rendering 3D Material"); - RD::get_singleton()->draw_command_begin_label("Render Material"); + RD::get_singleton()->draw_command_begin_label("Render 3D Material"); RenderDataRD render_data; render_data.cam_projection = p_cam_projection; @@ -1795,7 +1795,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); - RENDER_TIMESTAMP("Render Material"); + 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); @@ -1841,7 +1841,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); - RENDER_TIMESTAMP("Render Material"); + 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); @@ -1991,11 +1991,9 @@ void RenderForwardClustered::_update_render_base_uniform_set() { Vector<RD::Uniform> uniforms; { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 1; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -2008,6 +2006,9 @@ void RenderForwardClustered::_update_render_base_uniform_set() { ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); + uniforms.push_back(u); } @@ -2015,7 +2016,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(scene_shader.shadow_sampler); + u.append_id(scene_shader.shadow_sampler); uniforms.push_back(u); } @@ -2042,7 +2043,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { } break; } - u.ids.push_back(sampler); + u.append_id(sampler); uniforms.push_back(u); } @@ -2069,7 +2070,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { } break; } - u.ids.push_back(sampler); + u.append_id(sampler); uniforms.push_back(u); } @@ -2077,14 +2078,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_omni_light_buffer()); + u.append_id(get_omni_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_spot_light_buffer()); + u.append_id(get_spot_light_buffer()); uniforms.push_back(u); } @@ -2092,28 +2093,28 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_reflection_probe_buffer()); + u.append_id(get_reflection_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(get_directional_light_buffer()); + u.append_id(get_directional_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.lightmap_buffer); + u.append_id(scene_state.lightmap_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.lightmap_capture_buffer); + u.append_id(scene_state.lightmap_capture_buffer); uniforms.push_back(u); } { @@ -2121,7 +2122,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture(); - u.ids.push_back(decal_atlas); + u.append_id(decal_atlas); uniforms.push_back(u); } { @@ -2129,14 +2130,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() { u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture_srgb(); - u.ids.push_back(decal_atlas); + u.append_id(decal_atlas); uniforms.push_back(u); } { RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_decal_buffer()); + u.append_id(get_decal_buffer()); uniforms.push_back(u); } @@ -2144,7 +2145,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.ids.push_back(storage->global_variables_get_storage_buffer()); + u.append_id(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -2152,7 +2153,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 15; - u.ids.push_back(sdfgi_get_ubo()); + u.append_id(sdfgi_get_ubo()); uniforms.push_back(u); } @@ -2161,9 +2162,6 @@ 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) { - //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()); - 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); @@ -2177,7 +2175,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.uniform_buffers[p_index]); + u.append_id(scene_state.uniform_buffers[p_index]); uniforms.push_back(u); } { @@ -2188,7 +2186,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (instance_buffer == RID()) { instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used } - u.ids.push_back(instance_buffer); + u.append_id(instance_buffer); uniforms.push_back(u); } { @@ -2201,7 +2199,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(radiance_texture); + u.append_id(radiance_texture); uniforms.push_back(u); } @@ -2211,9 +2209,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (ref_texture.is_valid()) { - u.ids.push_back(ref_texture); + u.append_id(ref_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -2229,7 +2227,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (!texture.is_valid()) { texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } { @@ -2237,9 +2235,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { - u.ids.push_back(directional_shadow_get_texture()); + u.append_id(directional_shadow_get_texture()); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -2247,16 +2245,16 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.resize(scene_state.max_lightmaps); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::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); - u.ids.write[i] = rd_texture; + u.append_id(rd_texture); } else { - u.ids.write[i] = default_tex; + u.append_id(default_tex); } } @@ -2266,7 +2264,6 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; 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); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { @@ -2274,9 +2271,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (!tex.is_valid()) { tex = default_tex; } - u.ids.write[i] = tex; + u.append_id(tex); } else { - u.ids.write[i] = default_tex; + u.append_id(default_tex); } } @@ -2288,7 +2285,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID cb = (p_render_data && p_render_data->cluster_buffer.is_valid()) ? p_render_data->cluster_buffer : scene_shader.default_vec4_xform_buffer; - u.ids.push_back(cb); + u.append_id(cb); uniforms.push_back(u); } @@ -2298,7 +2295,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } { @@ -2307,7 +2304,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -2317,7 +2314,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -2327,7 +2324,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -2337,7 +2334,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -2347,7 +2344,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } { @@ -2360,7 +2357,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } else { t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } - u.ids.push_back(t); + u.append_id(t); uniforms.push_back(u); } { @@ -2368,9 +2365,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 16; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { - u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); + u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -2378,7 +2375,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 17; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer()); + u.append_id(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer()); uniforms.push_back(u); } { @@ -2394,7 +2391,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } else { vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); } - u.ids.push_back(vfog); + u.append_id(vfog); uniforms.push_back(u); } { @@ -2403,42 +2400,29 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } } - if (p_index >= (int)render_pass_uniform_sets.size()) { - render_pass_uniform_sets.resize(p_index + 1); - } - - if (render_pass_uniform_sets[p_index].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[p_index])) { - RD::get_singleton()->free(render_pass_uniform_sets[p_index]); - } - - render_pass_uniform_sets[p_index] = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET); - return render_pass_uniform_sets[p_index]; + return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms); } 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) { - if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { - RD::get_singleton()->free(sdfgi_pass_uniform_set); - } - Vector<RD::Uniform> uniforms; { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.uniform_buffers[0]); + u.append_id(scene_state.uniform_buffers[0]); uniforms.push_back(u); } { RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.instance_buffer[RENDER_LIST_SECONDARY]); + u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]); uniforms.push_back(u); } { @@ -2447,7 +2431,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(radiance_texture); + u.append_id(radiance_texture); uniforms.push_back(u); } @@ -2457,7 +2441,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(ref_texture); + u.append_id(ref_texture); uniforms.push_back(u); } @@ -2467,7 +2451,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -2477,7 +2461,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -2486,10 +2470,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.resize(scene_state.max_lightmaps); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { - u.ids.write[i] = default_tex; + u.append_id(default_tex); } uniforms.push_back(u); @@ -2500,10 +2484,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; 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); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { - u.ids.write[i] = default_tex; + u.append_id(default_tex); } uniforms.push_back(u); @@ -2514,7 +2498,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID cb = scene_shader.default_vec4_xform_buffer; - u.ids.push_back(cb); + u.append_id(cb); uniforms.push_back(u); } @@ -2524,33 +2508,32 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.ids.push_back(p_albedo_texture); + u.append_id(p_albedo_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.ids.push_back(p_emission_texture); + u.append_id(p_emission_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; - u.ids.push_back(p_emission_aniso_texture); + u.append_id(p_emission_aniso_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 12; - u.ids.push_back(p_geom_facing_texture); + u.append_id(p_geom_facing_texture); uniforms.push_back(u); } - sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET); - return sdfgi_pass_uniform_set; + return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET, uniforms); } RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { @@ -3218,17 +3201,6 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) : RenderForwardClustered::~RenderForwardClustered() { directional_shadow_atlas_set_size(0); - //clear base uniform set if still valid - for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) { - if (render_pass_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[i])) { - RD::get_singleton()->free(render_pass_uniform_sets[i]); - } - } - - if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { - RD::get_singleton()->free(sdfgi_pass_uniform_set); - } - { for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) { RD::get_singleton()->free(scene_state.uniform_buffers[i]); 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 f858887bd0..dd5c719352 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -121,8 +121,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb); RID render_base_uniform_set; - LocalVector<RID> render_pass_uniform_sets; - RID sdfgi_pass_uniform_set; uint64_t lightmap_texture_array_version = 0xFFFFFFFF; 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 24be451e78..b4def4e11c 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 @@ -751,7 +751,7 @@ void fragment() { Vector<RD::Uniform> uniforms; RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(default_vec4_xform_buffer); + u.append_id(default_vec4_xform_buffer); u.binding = 0; uniforms.push_back(u); 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 a623af7533..957b490664 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -306,7 +306,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.uniform_buffers[p_index]); + u.append_id(scene_state.uniform_buffers[p_index]); uniforms.push_back(u); } @@ -320,7 +320,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(radiance_texture); + u.append_id(radiance_texture); uniforms.push_back(u); } @@ -330,9 +330,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (ref_texture.is_valid()) { - u.ids.push_back(ref_texture); + u.append_id(ref_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -348,7 +348,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (!texture.is_valid()) { texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } { @@ -356,9 +356,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { - u.ids.push_back(directional_shadow_get_texture()); + u.append_id(directional_shadow_get_texture()); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -368,16 +368,16 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.resize(scene_state.max_lightmaps); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::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); - u.ids.write[i] = rd_texture; + u.append_id(rd_texture); } else { - u.ids.write[i] = default_tex; + u.append_id(default_tex); } } @@ -411,7 +411,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer; - u.ids.push_back(cb); + u.append_id(cb); uniforms.push_back(u); } */ @@ -422,7 +422,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } { @@ -431,7 +431,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ 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); - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } @@ -653,9 +653,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (draw_sky || draw_sky_fog_only) { // !BAS! @TODO See if we can limit doing some things double and maybe even move this into _pre_opaque_render // and change Forward Clustered in the same way as we have here (but without using subpasses) - RENDER_TIMESTAMP("Setup Sky resolution buffers"); + RENDER_TIMESTAMP("Setup Sky Resolution Buffers"); - RD::get_singleton()->draw_command_begin_label("Setup Sky resolution buffers"); + RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers"); if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; @@ -972,9 +972,9 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { /* */ void RenderForwardMobile::_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) { - RENDER_TIMESTAMP("Setup Rendering Material"); + RENDER_TIMESTAMP("Setup Rendering 3D Material"); - RD::get_singleton()->draw_command_begin_label("Render Material"); + RD::get_singleton()->draw_command_begin_label("Render 3D Material"); _update_render_base_uniform_set(); @@ -997,7 +997,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); - RENDER_TIMESTAMP("Render Material"); + 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, rp_uniform_set, 0); @@ -1039,7 +1039,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); - RENDER_TIMESTAMP("Render Material"); + 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, rp_uniform_set, true, false); @@ -1089,7 +1089,7 @@ void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_ } void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { - RENDER_TIMESTAMP("Setup Render Collider Heightfield"); + RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -1145,11 +1145,9 @@ void RenderForwardMobile::_update_render_base_uniform_set() { Vector<RD::Uniform> uniforms; { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 1; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -1162,6 +1160,9 @@ void RenderForwardMobile::_update_render_base_uniform_set() { ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); + uniforms.push_back(u); } @@ -1169,7 +1170,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(scene_shader.shadow_sampler); + u.append_id(scene_shader.shadow_sampler); uniforms.push_back(u); } @@ -1196,7 +1197,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { } break; } - u.ids.push_back(sampler); + u.append_id(sampler); uniforms.push_back(u); } @@ -1223,7 +1224,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { } break; } - u.ids.push_back(sampler); + u.append_id(sampler); uniforms.push_back(u); } @@ -1231,14 +1232,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_omni_light_buffer()); + u.append_id(get_omni_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_spot_light_buffer()); + u.append_id(get_spot_light_buffer()); uniforms.push_back(u); } @@ -1246,28 +1247,28 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_reflection_probe_buffer()); + u.append_id(get_reflection_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(get_directional_light_buffer()); + u.append_id(get_directional_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.lightmap_buffer); + u.append_id(scene_state.lightmap_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.lightmap_capture_buffer); + u.append_id(scene_state.lightmap_capture_buffer); uniforms.push_back(u); } { @@ -1275,7 +1276,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture(); - u.ids.push_back(decal_atlas); + u.append_id(decal_atlas); uniforms.push_back(u); } { @@ -1283,14 +1284,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() { u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture_srgb(); - u.ids.push_back(decal_atlas); + u.append_id(decal_atlas); uniforms.push_back(u); } { RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(get_decal_buffer()); + u.append_id(get_decal_buffer()); uniforms.push_back(u); } @@ -1298,7 +1299,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.ids.push_back(storage->global_variables_get_storage_buffer()); + u.append_id(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } 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 34b2fa9440..4dc56e8970 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 @@ -734,7 +734,7 @@ void fragment() { Vector<RD::Uniform> uniforms; RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(default_vec4_xform_buffer); + u.append_id(default_vec4_xform_buffer); u.binding = 0; uniforms.push_back(u); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 0f3daef371..38234cf0e7 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -931,7 +931,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 1; - u.ids.push_back(state.canvas_state_buffer); + u.append_id(state.canvas_state_buffer); uniforms.push_back(u); } @@ -939,7 +939,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 2; - u.ids.push_back(state.lights_uniform_buffer); + u.append_id(state.lights_uniform_buffer); uniforms.push_back(u); } @@ -947,7 +947,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.ids.push_back(storage->decal_atlas_get_texture()); + u.append_id(storage->decal_atlas_get_texture()); uniforms.push_back(u); } @@ -955,7 +955,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 = 4; - u.ids.push_back(state.shadow_texture); + u.append_id(state.shadow_texture); uniforms.push_back(u); } @@ -963,7 +963,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 5; - u.ids.push_back(state.shadow_sampler); + u.append_id(state.shadow_sampler); uniforms.push_back(u); } @@ -980,7 +980,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } } - u.ids.push_back(screen); + u.append_id(screen); uniforms.push_back(u); } @@ -989,17 +989,15 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 7; RID sdf = storage->render_target_get_sdf_texture(p_to_render_target); - u.ids.push_back(sdf); + u.append_id(sdf); uniforms.push_back(u); } { //needs samplers for the material (uses custom textures) create them - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 8; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -1012,6 +1010,9 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 8, ids); + uniforms.push_back(u); } @@ -1019,7 +1020,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.ids.push_back(storage->global_variables_get_storage_buffer()); + u.append_id(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -2567,7 +2568,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(storage->get_default_rd_storage_buffer()); + u.append_id(storage->get_default_rd_storage_buffer()); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 606527ed24..e8978e7dca 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -56,8 +56,8 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(blit.sampler); - u.ids.push_back(rd_texture); + u.append_id(blit.sampler); + u.append_id(rd_texture); uniforms.push_back(u); RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0); @@ -175,8 +175,8 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(blit.sampler); - u.ids.push_back(rd_texture); + u.append_id(blit.sampler); + u.append_id(rd_texture); uniforms.push_back(u); uset = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0); } @@ -241,6 +241,8 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RendererCompositorRD *RendererCompositorRD::singleton = nullptr; RendererCompositorRD::RendererCompositorRD() { + uniform_set_cache = memnew(UniformSetCacheRD); + { String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path(); if (shader_cache_dir.is_empty()) { @@ -301,5 +303,6 @@ RendererCompositorRD::RendererCompositorRD() { } RendererCompositorRD::~RendererCompositorRD() { + memdelete(uniform_set_cache); ShaderRD::set_shader_cache_dir(String()); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 9a992d5819..e526b95677 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -39,9 +39,11 @@ #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/uniform_set_cache_rd.h" class RendererCompositorRD : public RendererCompositor { protected: + UniformSetCacheRD *uniform_set_cache; RendererCanvasRenderRD *canvas; RendererStorageRD *storage; RendererSceneRenderRD *scene; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 1a84bafbd0..8f0e1d36db 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -221,14 +221,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1 + u.append_id(render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1 uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_albedo); + u.append_id(render_albedo); uniforms.push_back(u); } { @@ -236,7 +236,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; for (int j = 0; j < 8; j++) { - u.ids.push_back(render_occlusion[j]); + u.append_id(render_occlusion[j]); } uniforms.push_back(u); } @@ -244,21 +244,21 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; - u.ids.push_back(render_emission); + u.append_id(render_emission); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; - u.ids.push_back(render_emission_aniso); + u.append_id(render_emission_aniso); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 6; - u.ids.push_back(render_geom_facing); + u.append_id(render_geom_facing); uniforms.push_back(u); } @@ -266,28 +266,28 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 7; - u.ids.push_back(cascade.sdf_tex); + u.append_id(cascade.sdf_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; - u.ids.push_back(occlusion_data); + u.append_id(occlusion_data); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 10; - u.ids.push_back(cascade.solid_cell_dispatch_buffer); + u.append_id(cascade.solid_cell_dispatch_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 11; - u.ids.push_back(cascade.solid_cell_buffer); + u.append_id(cascade.solid_cell_buffer); uniforms.push_back(u); } @@ -300,42 +300,42 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_albedo); + u.append_id(render_albedo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_geom_facing); + u.append_id(render_geom_facing); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; - u.ids.push_back(render_emission); + u.append_id(render_emission); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; - u.ids.push_back(render_emission_aniso); + u.append_id(render_emission_aniso); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 5; - u.ids.push_back(cascade.solid_cell_dispatch_buffer); + u.append_id(cascade.solid_cell_dispatch_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 6; - u.ids.push_back(cascade.solid_cell_buffer); + u.append_id(cascade.solid_cell_buffer); uniforms.push_back(u); } @@ -348,7 +348,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; for (int j = 0; j < 8; j++) { - u.ids.push_back(render_occlusion[j]); + u.append_id(render_occlusion[j]); } uniforms.push_back(u); } @@ -356,7 +356,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(occlusion_data); + u.append_id(occlusion_data); uniforms.push_back(u); } @@ -375,9 +375,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < cascades.size()) { - u.ids.push_back(cascades[j].sdf_tex); + u.append_id(cascades[j].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -386,70 +386,70 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(cascade.solid_cell_dispatch_buffer); + u.append_id(cascade.solid_cell_dispatch_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(cascade.solid_cell_buffer); + u.append_id(cascade.solid_cell_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.ids.push_back(cascade.light_data); + u.append_id(cascade.light_data); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.ids.push_back(cascade.light_aniso_0_tex); + u.append_id(cascade.light_aniso_0_tex); uniforms.push_back(u); } { RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.ids.push_back(cascade.light_aniso_1_tex); + u.append_id(cascade.light_aniso_1_tex); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(cascades_ubo); + u.append_id(cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(cascade.lights_buffer); + u.append_id(cascade.lights_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(lightprobe_texture); + u.append_id(lightprobe_texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(occlusion_texture); + u.append_id(occlusion_texture); uniforms.push_back(u); } @@ -463,14 +463,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_albedo); + u.append_id(render_albedo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_sdf[0]); + u.append_id(render_sdf[0]); uniforms.push_back(u); } @@ -483,14 +483,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_albedo); + u.append_id(render_albedo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_sdf_half[0]); + u.append_id(render_sdf_half[0]); uniforms.push_back(u); } @@ -504,19 +504,22 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_sdf[0]); + u.append_id(render_sdf[0]); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_sdf[1]); + u.append_id(render_sdf[1]); uniforms.push_back(u); } jump_flood_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0); - SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]); + RID aux0 = uniforms.write[0].get_id(0); + RID aux1 = uniforms.write[1].get_id(0); + uniforms.write[0].set_id(0, aux1); + uniforms.write[1].set_id(0, aux0); jump_flood_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0); } //jump flood half uniform set @@ -526,19 +529,22 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_sdf_half[0]); + u.append_id(render_sdf_half[0]); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_sdf_half[1]); + u.append_id(render_sdf_half[1]); uniforms.push_back(u); } jump_flood_half_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0); - SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]); + RID aux0 = uniforms.write[0].get_id(0); + RID aux1 = uniforms.write[1].get_id(0); + uniforms.write[0].set_id(0, aux1); + uniforms.write[1].set_id(0, aux0); jump_flood_half_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0); } @@ -549,21 +555,21 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_albedo); + u.append_id(render_albedo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size + u.append_id(render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; - u.ids.push_back(render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass + u.append_id(render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass uniforms.push_back(u); } @@ -578,7 +584,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(render_albedo); + u.append_id(render_albedo); uniforms.push_back(u); } { @@ -586,7 +592,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; for (int i = 0; i < 8; i++) { - u.ids.push_back(render_occlusion[i]); + u.append_id(render_occlusion[i]); } uniforms.push_back(u); } @@ -594,7 +600,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; - u.ids.push_back(render_geom_facing); + u.append_id(render_geom_facing); uniforms.push_back(u); } @@ -612,9 +618,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < cascades.size()) { - u.ids.push_back(cascades[j].sdf_tex); + u.append_id(cascades[j].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -625,9 +631,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < cascades.size()) { - u.ids.push_back(cascades[j].light_tex); + u.append_id(cascades[j].light_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -638,9 +644,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < cascades.size()) { - u.ids.push_back(cascades[j].light_aniso_0_tex); + u.append_id(cascades[j].light_aniso_0_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -651,9 +657,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < cascades.size()) { - u.ids.push_back(cascades[j].light_aniso_1_tex); + u.append_id(cascades[j].light_aniso_1_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -662,7 +668,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 6; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -670,14 +676,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 7; - u.ids.push_back(cascades_ubo); + u.append_id(cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; - u.ids.push_back(lightprobe_data); + u.append_id(lightprobe_data); uniforms.push_back(u); } @@ -685,14 +691,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.ids.push_back(cascades[i].lightprobe_history_tex); + u.append_id(cascades[i].lightprobe_history_tex); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.ids.push_back(cascades[i].lightprobe_average_tex); + u.append_id(cascades[i].lightprobe_average_tex); uniforms.push_back(u); } @@ -700,14 +706,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; - u.ids.push_back(lightprobe_history_scroll); + u.append_id(lightprobe_history_scroll); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 12; - u.ids.push_back(lightprobe_average_scroll); + u.append_id(lightprobe_average_scroll); uniforms.push_back(u); } { @@ -723,14 +729,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V } else { parent_average = cascades[i - 1].lightprobe_average_tex; //to use something, but it won't be used } - u.ids.push_back(parent_average); + u.append_id(parent_average); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 14; - u.ids.push_back(ambient_texture); + u.append_id(ambient_texture); uniforms.push_back(u); } @@ -934,7 +940,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.ids.push_back(p_sky->radiance); + u.append_id(p_sky->radiance); uniforms.push_back(u); } @@ -942,7 +948,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 1; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -1002,7 +1008,7 @@ void RendererSceneGIRD::SDFGI::store_probes() { push_constant.y_mult = y_mult; // Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces - RENDER_TIMESTAMP("Average Probes"); + RENDER_TIMESTAMP("Average SDFGI Probes"); RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE]); @@ -1110,9 +1116,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < cascades.size()) { - u.ids.push_back(cascades[i].sdf_tex); + u.append_id(cascades[i].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1123,9 +1129,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < cascades.size()) { - u.ids.push_back(cascades[i].light_tex); + u.append_id(cascades[i].light_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1136,9 +1142,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < cascades.size()) { - u.ids.push_back(cascades[i].light_aniso_0_tex); + u.append_id(cascades[i].light_aniso_0_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1149,9 +1155,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < cascades.size()) { - u.ids.push_back(cascades[i].light_aniso_1_tex); + u.append_id(cascades[i].light_aniso_1_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1160,35 +1166,35 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(occlusion_texture); + u.append_id(occlusion_texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(cascades_ubo); + u.append_id(cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.ids.push_back(p_texture); + u.append_id(p_texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(lightprobe_texture); + u.append_id(lightprobe_texture); uniforms.push_back(u); } debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0); @@ -1273,28 +1279,28 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(cascades_ubo); + u.append_id(cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(lightprobe_texture); + u.append_id(lightprobe_texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(occlusion_texture); + u.append_id(occlusion_texture); uniforms.push_back(u); } @@ -1555,14 +1561,14 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, if (cascade_next != cascade) { RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade"); - RENDER_TIMESTAMP(">SDFGI Update SDF"); + RENDER_TIMESTAMP("> SDFGI Update SDF"); //done rendering! must update SDF //clear dispatch indirect data SDFGIShader::PreprocessPushConstant push_constant; memset(&push_constant, 0, sizeof(SDFGIShader::PreprocessPushConstant)); - RENDER_TIMESTAMP("Scroll SDF"); + RENDER_TIMESTAMP("SDFGI Scroll SDF"); //scroll if (cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) { @@ -1701,7 +1707,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, push_constant.half_size = true; { - RENDER_TIMESTAMP("SDFGI Jump Flood (Half Size)"); + RENDER_TIMESTAMP("SDFGI Jump Flood (Half-Size)"); uint32_t s = cascade_half_size; @@ -1723,7 +1729,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, } } - RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half Size)"); + RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half-Size)"); //continue with optimized jump flood for smaller reads RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]); @@ -1759,7 +1765,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, } else { //full size jumpflood - RENDER_TIMESTAMP("SDFGI Jump Flood"); + RENDER_TIMESTAMP("SDFGI Jump Flood (Full-Size)"); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_initialize_uniform_set, 0); @@ -1790,7 +1796,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, } } - RENDER_TIMESTAMP("SDFGI Jump Flood Optimized"); + RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Full-Size)"); //continue with optimized jump flood for smaller reads RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]); @@ -1882,7 +1888,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, //finalize render and update sdf #endif - RENDER_TIMESTAMP("<SDFGI Update SDF"); + RENDER_TIMESTAMP("< SDFGI Update SDF"); RD::get_singleton()->draw_command_end_label(); } } @@ -1891,7 +1897,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... - RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lighs"); + RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights"); update_cascades(); @@ -2073,14 +2079,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(storage->voxel_gi_get_octree_buffer(probe)); + u.append_id(storage->voxel_gi_get_octree_buffer(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(storage->voxel_gi_get_data_buffer(probe)); + u.append_id(storage->voxel_gi_get_data_buffer(probe)); uniforms.push_back(u); } @@ -2088,21 +2094,21 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 4; - u.ids.push_back(write_buffer); + u.append_id(write_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe)); + u.append_id(storage->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -2113,7 +2119,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 3; - u.ids.push_back(gi->voxel_gi_lights_uniform); + u.append_id(gi->voxel_gi_lights_uniform); copy_uniforms.push_back(u); } @@ -2125,7 +2131,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; - u.ids.push_back(texture); + u.append_id(texture); copy_uniforms.push_back(u); } mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0); @@ -2138,7 +2144,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; - u.ids.push_back(mipmap.texture); + u.append_id(mipmap.texture); uniforms.push_back(u); } @@ -2213,7 +2219,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 3; - u.ids.push_back(gi->voxel_gi_lights_uniform); + u.append_id(gi->voxel_gi_lights_uniform); uniforms.push_back(u); } @@ -2221,56 +2227,56 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; - u.ids.push_back(dmap.albedo); + u.append_id(dmap.albedo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 6; - u.ids.push_back(dmap.normal); + u.append_id(dmap.normal); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 7; - u.ids.push_back(dmap.orm); + u.append_id(dmap.orm); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 8; - u.ids.push_back(dmap.fb_depth); + u.append_id(dmap.fb_depth); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe)); + u.append_id(storage->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; - u.ids.push_back(dmap.texture); + u.append_id(dmap.texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 12; - u.ids.push_back(dmap.depth); + u.append_id(dmap.depth); uniforms.push_back(u); } @@ -2286,14 +2292,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; - u.ids.push_back(dynamic_maps[dynamic_maps.size() - 1].texture); + u.append_id(dynamic_maps[dynamic_maps.size() - 1].texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 6; - u.ids.push_back(dynamic_maps[dynamic_maps.size() - 1].depth); + u.append_id(dynamic_maps[dynamic_maps.size() - 1].depth); uniforms.push_back(u); } @@ -2302,14 +2308,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 7; - u.ids.push_back(dmap.texture); + u.append_id(dmap.texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; - u.ids.push_back(dmap.depth); + u.append_id(dmap.depth); uniforms.push_back(u); } } @@ -2318,14 +2324,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe)); + u.append_id(storage->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -2334,7 +2340,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; - u.ids.push_back(mipmaps[dmap.mipmap].texture); + u.append_id(mipmaps[dmap.mipmap].texture); uniforms.push_back(u); } } @@ -2747,21 +2753,21 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(storage->voxel_gi_get_data_buffer(probe)); + u.append_id(storage->voxel_gi_get_data_buffer(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.ids.push_back(texture); + u.append_id(texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 3; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -2918,14 +2924,14 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 1; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -3178,9 +3184,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex); + u.append_id(rb->sdfgi->cascades[j].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3191,9 +3197,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.ids.push_back(rb->sdfgi->cascades[j].light_tex); + u.append_id(rb->sdfgi->cascades[j].light_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3204,9 +3210,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_0_tex); + u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3217,9 +3223,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_1_tex); + u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3229,9 +3235,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; if (rb->sdfgi) { - u.ids.push_back(rb->sdfgi->occlusion_texture); + u.append_id(rb->sdfgi->occlusion_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3239,14 +3245,14 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 6; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 7; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } @@ -3254,7 +3260,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.ids.push_back(rb->ambient_buffer); + u.append_id(rb->ambient_buffer); uniforms.push_back(u); } @@ -3262,7 +3268,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.ids.push_back(rb->reflection_buffer); + u.append_id(rb->reflection_buffer); uniforms.push_back(u); } @@ -3271,9 +3277,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 11; if (rb->sdfgi) { - u.ids.push_back(rb->sdfgi->lightprobe_texture); + u.append_id(rb->sdfgi->lightprobe_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3281,14 +3287,14 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; - u.ids.push_back(rb->depth_texture); + u.append_id(rb->depth_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 13; - u.ids.push_back(p_normal_roughness_buffer); + u.append_id(p_normal_roughness_buffer); uniforms.push_back(u); } { @@ -3296,21 +3302,21 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ 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); - u.ids.push_back(buffer); + u.append_id(buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 15; - u.ids.push_back(sdfgi_ubo); + u.append_id(sdfgi_ubo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 16; - u.ids.push_back(rb->gi.voxel_gi_buffer); + u.append_id(rb->gi.voxel_gi_buffer); uniforms.push_back(u); } { @@ -3318,7 +3324,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 17; for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { - u.ids.push_back(rb->gi.voxel_gi_textures[i]); + u.append_id(rb->gi.voxel_gi_textures[i]); } uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 8814822cda..0fa9f6ee7f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -4119,7 +4119,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e return; } - RENDER_TIMESTAMP(">Volumetric Fog"); + RENDER_TIMESTAMP("> Volumetric Fog"); RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) { @@ -4181,7 +4181,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(rb->volumetric_fog->fog_map); + u.append_id(rb->volumetric_fog->fog_map); uniforms.push_back(u); } @@ -4191,7 +4191,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (p_fog_volumes.size() > 0) { RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); - RENDER_TIMESTAMP("Render Fog Volumes"); + RENDER_TIMESTAMP("Render FogVolumes"); VolumetricFogShader::VolumeUBO params; @@ -4246,7 +4246,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 1; - u.ids.push_back(rb->volumetric_fog->emissive_map); + u.append_id(rb->volumetric_fog->emissive_map); uniforms.push_back(u); } @@ -4254,7 +4254,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 2; - u.ids.push_back(volumetric_fog.volume_ubo); + u.append_id(volumetric_fog.volume_ubo); uniforms.push_back(u); } @@ -4266,7 +4266,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 3; - u.ids.push_back(rb->volumetric_fog->density_map); + u.append_id(rb->volumetric_fog->density_map); uniforms.push_back(u); } @@ -4278,7 +4278,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 4; - u.ids.push_back(rb->volumetric_fog->light_map); + u.append_id(rb->volumetric_fog->light_map); uniforms.push_back(u); } @@ -4399,9 +4399,9 @@ 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.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); } else { - u.ids.push_back(shadow_atlas->depth); + u.append_id(shadow_atlas->depth); } uniforms.push_back(u); @@ -4413,9 +4413,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; if (directional_shadow.depth.is_valid()) { - u.ids.push_back(directional_shadow.depth); + u.append_id(directional_shadow.depth); } else { - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -4425,7 +4425,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; - u.ids.push_back(get_omni_light_buffer()); + u.append_id(get_omni_light_buffer()); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4433,7 +4433,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 4; - u.ids.push_back(get_spot_light_buffer()); + u.append_id(get_spot_light_buffer()); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4442,7 +4442,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 5; - u.ids.push_back(get_directional_light_buffer()); + u.append_id(get_directional_light_buffer()); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4451,7 +4451,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 6; - u.ids.push_back(rb->cluster_builder->get_cluster_buffer()); + u.append_id(rb->cluster_builder->get_cluster_buffer()); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4460,7 +4460,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 7; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4469,7 +4469,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; - u.ids.push_back(rb->volumetric_fog->light_density_map); + u.append_id(rb->volumetric_fog->light_density_map); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4478,7 +4478,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.ids.push_back(rb->volumetric_fog->fog_map); + u.append_id(rb->volumetric_fog->fog_map); uniforms.push_back(u); } @@ -4486,7 +4486,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.ids.push_back(rb->volumetric_fog->prev_light_density_map); + u.append_id(rb->volumetric_fog->prev_light_density_map); copy_uniforms.push_back(u); } @@ -4494,7 +4494,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; - u.ids.push_back(shadow_sampler); + u.append_id(shadow_sampler); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4503,7 +4503,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 11; - u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers)); + u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers)); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4513,7 +4513,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) { - u.ids.push_back(rb->gi.voxel_gi_textures[i]); + u.append_id(rb->gi.voxel_gi_textures[i]); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -4522,7 +4522,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 13; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4530,7 +4530,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 14; - u.ids.push_back(volumetric_fog.params_ubo); + u.append_id(volumetric_fog.params_ubo); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -4538,7 +4538,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 = 15; - u.ids.push_back(rb->volumetric_fog->prev_light_density_map); + u.append_id(rb->volumetric_fog->prev_light_density_map); uniforms.push_back(u); } { @@ -4549,7 +4549,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 16; - u.ids.push_back(rb->volumetric_fog->density_map); + u.append_id(rb->volumetric_fog->density_map); uniforms.push_back(u); } { @@ -4560,7 +4560,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 17; - u.ids.push_back(rb->volumetric_fog->light_map); + u.append_id(rb->volumetric_fog->light_map); uniforms.push_back(u); } @@ -4572,7 +4572,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 18; - u.ids.push_back(rb->volumetric_fog->emissive_map); + u.append_id(rb->volumetric_fog->emissive_map); uniforms.push_back(u); } @@ -4582,7 +4582,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e 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 sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID(); - u.ids.push_back(sky_texture.is_valid() ? sky_texture : radiance_texture); + u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); uniforms.push_back(u); } @@ -4590,7 +4590,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); - SWAP(uniforms.write[7].ids.write[0], uniforms.write[8].ids.write[0]); + RID aux7 = uniforms.write[7].get_id(0); + RID aux8 = uniforms.write[8].get_id(0); + + uniforms.write[7].set_id(0, aux8); + uniforms.write[8].set_id(0, aux7); rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0); } @@ -4605,7 +4609,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; - u.ids.push_back(gi.sdfgi_ubo); + u.append_id(gi.sdfgi_ubo); uniforms.push_back(u); } @@ -4613,7 +4617,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 = 1; - u.ids.push_back(rb->sdfgi->ambient_texture); + u.append_id(rb->sdfgi->ambient_texture); uniforms.push_back(u); } @@ -4621,7 +4625,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 = 2; - u.ids.push_back(rb->sdfgi->occlusion_texture); + u.append_id(rb->sdfgi->occlusion_texture); uniforms.push_back(u); } @@ -4785,7 +4789,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); - RENDER_TIMESTAMP("<Volumetric Fog"); + RENDER_TIMESTAMP("< Volumetric Fog"); RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_command_end_label(); @@ -4874,7 +4878,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool bool render_gi = p_render_data->render_buffers.is_valid() && p_use_gi; if (render_shadows && render_gi) { - RENDER_TIMESTAMP("Render GI + Render Shadows (parallel)"); + RENDER_TIMESTAMP("Render GI + Render Shadows (Parallel)"); } else if (render_shadows) { RENDER_TIMESTAMP("Render Shadows"); } else if (render_gi) { @@ -5754,11 +5758,9 @@ void fog() { Vector<RD::Uniform> uniforms; { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 1; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -5771,6 +5773,8 @@ void fog() { ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); uniforms.push_back(u); } @@ -5778,7 +5782,7 @@ void fog() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(storage->global_variables_get_storage_buffer()); + u.append_id(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index b44ae6cf8d..d39fe306f4 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -630,9 +630,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { - u.ids.push_back(radiance); + u.append_id(radiance); } else { - u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -642,15 +642,15 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu u.binding = 1; // half res if (half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(reflection.layers[0].views[1]); + u.append_id(reflection.layers[0].views[1]); } else { - u.ids.push_back(half_res_pass); + u.append_id(half_res_pass); } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -661,15 +661,15 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu u.binding = 2; // quarter res if (quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(reflection.layers[0].views[2]); + u.append_id(reflection.layers[0].views[2]); } else { - u.ids.push_back(quarter_res_pass); + u.append_id(quarter_res_pass); } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -918,11 +918,9 @@ void sky() { Vector<RD::Uniform> uniforms; { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 0; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -935,6 +933,9 @@ void sky() { ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids); + uniforms.push_back(u); } @@ -942,7 +943,7 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(storage->global_variables_get_storage_buffer()); + u.append_id(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -950,7 +951,7 @@ void sky() { RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(sky_scene_state.uniform_buffer); + u.append_id(sky_scene_state.uniform_buffer); uniforms.push_back(u); } @@ -958,7 +959,7 @@ void sky() { RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(sky_scene_state.directional_light_buffer); + u.append_id(sky_scene_state.directional_light_buffer); uniforms.push_back(u); } @@ -972,7 +973,7 @@ void sky() { u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - u.ids.push_back(vfog); + u.append_id(vfog); uniforms.push_back(u); } @@ -1005,21 +1006,21 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 35aa0f1f31..edf2113c2a 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1320,10 +1320,10 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas t = texture_owner.get_or_null(ct->diffuse); if (!t) { - u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); ct->size_cache = Size2i(1, 1); } else { - u.ids.push_back(t->rd_texture); + u.append_id(t->rd_texture); ct->size_cache = Size2i(t->width_2d, t->height_2d); } uniforms.push_back(u); @@ -1335,10 +1335,10 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas t = texture_owner.get_or_null(ct->normal_map); if (!t) { - u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); + u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); ct->use_normal_cache = false; } else { - u.ids.push_back(t->rd_texture); + u.append_id(t->rd_texture); ct->use_normal_cache = true; } uniforms.push_back(u); @@ -1350,10 +1350,10 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas t = texture_owner.get_or_null(ct->specular); if (!t) { - u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); ct->use_specular_cache = false; } else { - u.ids.push_back(t->rd_texture); + u.append_id(t->rd_texture); ct->use_specular_cache = true; } uniforms.push_back(u); @@ -1362,7 +1362,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 3; - u.ids.push_back(sampler_rd_get_default(filter, repeat)); + u.append_id(sampler_rd_get_default(filter, repeat)); uniforms.push_back(u); } @@ -2933,7 +2933,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; - u.ids.push_back(uniform_buffer); + u.append_id(uniform_buffer); uniforms.push_back(u); } @@ -2946,10 +2946,10 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St u.binding = 1 + k; if (array_size > 0) { for (int j = 0; j < array_size; j++) { - u.ids.push_back(textures[k++]); + u.append_id(textures[k++]); } } else { - u.ids.push_back(textures[k++]); + u.append_id(textures[k++]); } uniforms.push_back(u); } @@ -3155,7 +3155,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(s->vertex_buffer); + u.append_id(s->vertex_buffer); uniforms.push_back(u); } { @@ -3163,9 +3163,9 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; if (s->skin_buffer.is_valid()) { - u.ids.push_back(s->skin_buffer); + u.append_id(s->skin_buffer); } else { - u.ids.push_back(default_rd_storage_buffer); + u.append_id(default_rd_storage_buffer); } uniforms.push_back(u); } @@ -3174,9 +3174,9 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; if (s->blend_shape_buffer.is_valid()) { - u.ids.push_back(s->blend_shape_buffer); + u.append_id(s->blend_shape_buffer); } else { - u.ids.push_back(default_rd_storage_buffer); + u.append_id(default_rd_storage_buffer); } uniforms.push_back(u); } @@ -3618,7 +3618,7 @@ void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(s.vertex_buffer); + u.append_id(s.vertex_buffer); uniforms.push_back(u); } { @@ -3626,9 +3626,9 @@ void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; if (mi->blend_weights_buffer.is_valid()) { - u.ids.push_back(mi->blend_weights_buffer); + u.append_id(mi->blend_weights_buffer); } else { - u.ids.push_back(default_rd_storage_buffer); + u.append_id(default_rd_storage_buffer); } uniforms.push_back(u); } @@ -4953,14 +4953,14 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(p_particles->frame_params_buffer); + u.append_id(p_particles->frame_params_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(p_particles->particle_buffer); + u.append_id(p_particles->particle_buffer); uniforms.push_back(u); } @@ -4969,9 +4969,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; if (p_particles->emission_storage_buffer.is_valid()) { - u.ids.push_back(p_particles->emission_storage_buffer); + u.append_id(p_particles->emission_storage_buffer); } else { - u.ids.push_back(default_rd_storage_buffer); + u.append_id(default_rd_storage_buffer); } uniforms.push_back(u); } @@ -4984,9 +4984,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer _particles_allocate_emission_buffer(sub_emitter); } - u.ids.push_back(sub_emitter->emission_storage_buffer); + u.append_id(sub_emitter->emission_storage_buffer); } else { - u.ids.push_back(default_rd_storage_buffer); + u.append_id(default_rd_storage_buffer); } uniforms.push_back(u); } @@ -5257,7 +5257,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (rd_tex == RID()) { rd_tex = default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE]; } - u.ids.push_back(rd_tex); + u.append_id(rd_tex); } uniforms.push_back(u); } @@ -5266,9 +5266,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; if (collision_heightmap_texture.is_valid()) { - u.ids.push_back(collision_heightmap_texture); + u.append_id(collision_heightmap_texture); } else { - u.ids.push_back(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]); + u.append_id(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]); } uniforms.push_back(u); } @@ -5402,7 +5402,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(particles->particles_sort_buffer); + u.append_id(particles->particles_sort_buffer); uniforms.push_back(u); } @@ -5522,14 +5522,14 @@ void RendererStorageRD::_particles_update_buffers(Particles *particles) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(particles->particle_buffer); + u.append_id(particles->particle_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(particles->particle_instance_buffer); + u.append_id(particles->particle_instance_buffer); uniforms.push_back(u); } @@ -5627,9 +5627,9 @@ void RendererStorageRD::update_particles() { u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; if (particles->trail_bind_pose_buffer.is_valid()) { - u.ids.push_back(particles->trail_bind_pose_buffer); + u.append_id(particles->trail_bind_pose_buffer); } else { - u.ids.push_back(default_rd_storage_buffer); + u.append_id(default_rd_storage_buffer); } uniforms.push_back(u); } @@ -6315,7 +6315,7 @@ void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(skeleton->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); @@ -7146,21 +7146,21 @@ void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(voxel_gi->octree_buffer); + u.append_id(voxel_gi->octree_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(voxel_gi->data_buffer); + u.append_id(voxel_gi->data_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; - u.ids.push_back(shared_tex); + u.append_id(shared_tex); uniforms.push_back(u); } @@ -8008,33 +8008,36 @@ void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; - u.ids.push_back(rt->sdf_buffer_write); + u.append_id(rt->sdf_buffer_write); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; - u.ids.push_back(rt->sdf_buffer_read); + u.append_id(rt->sdf_buffer_read); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; - u.ids.push_back(rt->sdf_buffer_process[0]); + u.append_id(rt->sdf_buffer_process[0]); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; - u.ids.push_back(rt->sdf_buffer_process[1]); + u.append_id(rt->sdf_buffer_process[1]); uniforms.push_back(u); } rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0); - SWAP(uniforms.write[2].ids.write[0], uniforms.write[3].ids.write[0]); + RID aux2 = uniforms.write[2].get_id(0); + RID aux3 = uniforms.write[3].get_id(0); + uniforms.write[2].set_id(0, aux3); + uniforms.write[3].set_id(0, aux2); rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0); } } @@ -10074,11 +10077,9 @@ void process() { Vector<RD::Uniform> uniforms; { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 1; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); ids_ptr[0] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[1] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); ids_ptr[2] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -10091,6 +10092,8 @@ void process() { ids_ptr[9] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[10] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); ids_ptr[11] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); uniforms.push_back(u); } @@ -10098,7 +10101,7 @@ void process() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(global_variables_get_storage_buffer()); + u.append_id(global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -10167,7 +10170,7 @@ void process() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(default_rd_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); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index cb35c2bf65..95aa547a02 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -1765,7 +1765,7 @@ public: RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(multimesh->buffer); + u.append_id(multimesh->buffer); uniforms.push_back(u); multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); } @@ -1780,7 +1780,7 @@ public: RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(multimesh->buffer); + u.append_id(multimesh->buffer); uniforms.push_back(u); multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); } @@ -1818,7 +1818,7 @@ public: RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(skeleton->buffer); + u.append_id(skeleton->buffer); uniforms.push_back(u); skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); } @@ -2276,7 +2276,7 @@ public: RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.ids.push_back(particles->particle_instance_buffer); + u.append_id(particles->particle_instance_buffer); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp new file mode 100644 index 0000000000..5843b9db24 --- /dev/null +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* uniform_set_cache_rd.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 "uniform_set_cache_rd.h" + +UniformSetCacheRD *UniformSetCacheRD::singleton = nullptr; + +void UniformSetCacheRD::_invalidate(Cache *p_cache) { + if (p_cache->prev) { + p_cache->prev->next = p_cache->next; + } else { + // At begining of table + uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE; + hash_table[table_idx] = p_cache->next; + } + + if (p_cache->next) { + p_cache->next->prev = p_cache->prev; + } + + cache_allocator.free(p_cache); + cache_instances_used--; +} +void UniformSetCacheRD::_uniform_set_invalidation_callback(void *p_userdata) { + singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata)); +} + +UniformSetCacheRD::UniformSetCacheRD() { + ERR_FAIL_COND(singleton != nullptr); + singleton = this; +} + +UniformSetCacheRD::~UniformSetCacheRD() { + if (cache_instances_used > 0) { + ERR_PRINT("At exit: " + itos(cache_instances_used) + " uniform set cache instance(s) still in use."); + } +} diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h new file mode 100644 index 0000000000..e49cf4dafa --- /dev/null +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h @@ -0,0 +1,221 @@ +/*************************************************************************/ +/* uniform_set_cache_rd.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 UNIFORM_SET_CACHE_H +#define UNIFORM_SET_CACHE_H + +#include "core/templates/local_vector.h" +#include "core/templates/paged_allocator.h" +#include "servers/rendering/rendering_device.h" + +class UniformSetCacheRD : public Object { + GDCLASS(UniformSetCacheRD, Object) + + struct Cache { + Cache *prev = nullptr; + Cache *next = nullptr; + uint32_t hash = 0; + RID shader; + uint32_t set = 0; + RID cache; + LocalVector<RD::Uniform> uniforms; + }; + + PagedAllocator<Cache> cache_allocator; + + enum { + HASH_TABLE_SIZE = 16381 // Prime + }; + + Cache *hash_table[HASH_TABLE_SIZE] = {}; + + static _FORCE_INLINE_ uint32_t _hash_uniform(const RD::Uniform &u, uint32_t h) { + h = hash_djb2_one_32(u.uniform_type, h); + h = hash_djb2_one_32(u.binding, h); + uint32_t rsize = u.get_id_count(); + for (uint32_t j = 0; j < rsize; j++) { + h = hash_djb2_one_64(u.get_id(j).get_id(), h); + } + return h; + } + + static _FORCE_INLINE_ bool _compare_uniform(const RD::Uniform &a, const RD::Uniform &b) { + if (a.binding != b.binding) { + return false; + } + if (a.uniform_type != b.uniform_type) { + return false; + } + uint32_t rsize = a.get_id_count(); + if (rsize != b.get_id_count()) { + return false; + } + for (uint32_t j = 0; j < rsize; j++) { + if (a.get_id(j) != b.get_id(j)) { + return false; + } + } + return true; + } + + _FORCE_INLINE_ uint32_t _hash_args(uint32_t h, const RD::Uniform &arg) { + return _hash_uniform(arg, h); + } + + template <typename... Args> + uint32_t _hash_args(uint32_t h, const RD::Uniform &arg, Args... args) { + h = _hash_uniform(arg, h); + return _hash_args(h, args...); + } + + _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RD::Uniform> &uniforms, const RD::Uniform &arg) { + return _compare_uniform(uniforms[idx], arg); + } + + template <typename... Args> + _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RD::Uniform> &uniforms, const RD::Uniform &arg, Args... args) { + if (!_compare_uniform(uniforms[idx], arg)) { + return false; + } + return _compare_args(idx + 1, uniforms, args...); + } + + _FORCE_INLINE_ void _create_args(Vector<RD::Uniform> &uniforms, const RD::Uniform &arg) { + uniforms.push_back(arg); + } + + template <typename... Args> + _FORCE_INLINE_ void _create_args(Vector<RD::Uniform> &uniforms, const RD::Uniform &arg, Args... args) { + uniforms.push_back(arg); + _create_args(uniforms, args...); + } + + static UniformSetCacheRD *singleton; + + uint32_t cache_instances_used = 0; + + void _invalidate(Cache *p_cache); + static void _uniform_set_invalidation_callback(void *p_userdata); + + RID _allocate_from_uniforms(RID p_shader, uint32_t p_set, uint32_t p_hash, uint32_t p_table_idx, const Vector<RD::Uniform> &p_uniforms) { + RID rid = RD::get_singleton()->uniform_set_create(p_uniforms, p_shader, p_set); + ERR_FAIL_COND_V(rid.is_null(), rid); + + Cache *c = cache_allocator.alloc(); + c->hash = p_hash; + c->set = p_set; + c->shader = p_shader; + c->cache = rid; + c->uniforms.resize(p_uniforms.size()); + for (uint32_t i = 0; i < c->uniforms.size(); i++) { + c->uniforms[i] = p_uniforms[i]; + } + c->prev = nullptr; + c->next = hash_table[p_table_idx]; + if (hash_table[p_table_idx]) { + hash_table[p_table_idx]->prev = c; + } + hash_table[p_table_idx] = c; + + RD::get_singleton()->uniform_set_set_invalidation_callback(rid, _uniform_set_invalidation_callback, c); + + cache_instances_used++; + + return rid; + } + +public: + template <typename... Args> + RID get_cache(RID p_shader, uint32_t p_set, Args... args) { + uint32_t h = hash_djb2_one_64(p_shader.get_id()); + h = hash_djb2_one_32(p_set, h); + h = _hash_args(h, args...); + + uint32_t table_idx = h % HASH_TABLE_SIZE; + { + const Cache *c = hash_table[table_idx]; + + while (c) { + if (c->hash == h && c->set == p_set && c->shader == p_shader && _compare_args(0, c->uniforms, args...)) { + return c->cache; + } + c = c->next; + } + } + + // Not in cache, create: + + Vector<RD::Uniform> uniforms; + _create_args(uniforms, args...); + + return _allocate_from_uniforms(p_shader, p_set, h, table_idx, uniforms); + } + + template <typename... Args> + RID get_cache_vec(RID p_shader, uint32_t p_set, const Vector<RD::Uniform> &p_uniforms) { + uint32_t h = hash_djb2_one_64(p_shader.get_id()); + h = hash_djb2_one_32(p_set, h); + for (int i = 0; i < p_uniforms.size(); i++) { + h = _hash_uniform(p_uniforms[i], h); + } + + uint32_t table_idx = h % HASH_TABLE_SIZE; + { + const Cache *c = hash_table[table_idx]; + + while (c) { + if (c->hash == h && c->set == p_set && c->shader == p_shader) { + bool all_ok = true; + for (int i = 0; i < p_uniforms.size(); i++) { + if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) { + all_ok = false; + break; + } + } + + if (all_ok) { + return c->cache; + } + } + c = c->next; + } + } + + // Not in cache, create: + return _allocate_from_uniforms(p_shader, p_set, h, table_idx, p_uniforms); + } + + static UniformSetCacheRD *get_singleton() { return singleton; } + + UniformSetCacheRD(); + ~UniformSetCacheRD(); +}; + +#endif // UNIFORMSETCACHE_H diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 5bdc7ce600..485cd7ba9d 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2039,7 +2039,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in cull.shadows[p_shadow_index].light_instance = light->instance; for (int i = 0; i < splits; i++) { - RENDER_TIMESTAMP("Culling Directional Light split" + itos(i)); + RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i)); // setup a camera matrix for that range! CameraMatrix camera_matrix; @@ -2227,7 +2227,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } for (int i = 0; i < 2; i++) { //using this one ensures that raster deferred will have it - RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i)); + RENDER_TIMESTAMP("Cull OmniLight3D Shadow Paraboloid, Half " + itos(i)); real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); @@ -2295,7 +2295,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons cm.set_perspective(90, 1, radius * 0.005f, radius); for (int i = 0; i < 6; i++) { - RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i)); + RENDER_TIMESTAMP("Cull OmniLight3D Shadow Cube, Side " + itos(i)); //using this one ensures that raster deferred will have it static const Vector3 view_normals[6] = { @@ -2368,7 +2368,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } break; case RS::LIGHT_SPOT: { - RENDER_TIMESTAMP("Culling Spot Light"); + RENDER_TIMESTAMP("Cull SpotLight3D Shadow"); if (max_shadows_used + 1 > MAX_UPDATE_SHADOWS) { return true; @@ -2508,7 +2508,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ RID environment = _render_get_environment(p_camera, p_scenario); - RENDER_TIMESTAMP("Update occlusion buffer") + RENDER_TIMESTAMP("Update Occlusion Buffer") // For now just cull on the first camera RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool); @@ -2890,7 +2890,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not) } - RENDER_TIMESTAMP("Visibility Dependencies"); + RENDER_TIMESTAMP("Update Visibility Dependencies"); if (scenario->instance_visibility.get_bin_count() > 0) { if (!scenario->viewport_visibility_masks.has(p_viewport)) { @@ -2918,7 +2918,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - RENDER_TIMESTAMP("Culling"); + RENDER_TIMESTAMP("Cull 3D Scene"); //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_ortogonal); @@ -3155,9 +3155,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) { //must redraw! - RENDER_TIMESTAMP(">Rendering Light " + itos(i)); + RENDER_TIMESTAMP("> Render Light3D " + itos(i)); light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); - RENDER_TIMESTAMP("<Rendering Light " + itos(i)); + RENDER_TIMESTAMP("< Render Light3D " + itos(i)); } else { light->shadow_dirty = redraw; } @@ -3217,7 +3217,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c occluders_tex = RSG::viewport->viewport_get_occluder_debug_texture(p_viewport); } - RENDER_TIMESTAMP("Render Scene "); + RENDER_TIMESTAMP("Render 3D Scene"); scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info); for (uint32_t i = 0; i < max_shadows_used; i++) { @@ -3263,7 +3263,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, } else { environment = scenario->fallback_environment; } - RENDER_TIMESTAMP("Render Empty Scene "); + RENDER_TIMESTAMP("Render Empty 3D Scene"); RendererSceneRender::CameraData camera_data; camera_data.set_camera(Transform3D(), CameraMatrix(), true, false); @@ -3337,7 +3337,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int environment = scenario->fallback_environment; } - RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step)); + RENDER_TIMESTAMP("Render ReflectionProbe, Step " + itos(p_step)); RendererSceneRender::CameraData camera_data; camera_data.set_camera(xform, cm, false, false); @@ -3345,7 +3345,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int } else { //do roughness postprocess step until it believes it's done - RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step)); + RENDER_TIMESTAMP("Post-Process ReflectionProbe, Step " + itos(p_step)); return scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); } @@ -3398,7 +3398,7 @@ void RendererSceneCull::render_probes() { SelfList<InstanceVoxelGIData> *voxel_gi = voxel_gi_update_list.first(); if (voxel_gi) { - RENDER_TIMESTAMP("Render GI Probes"); + RENDER_TIMESTAMP("Render VoxelGI"); } while (voxel_gi) { diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 69c017a1c8..b448a15d8e 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -145,7 +145,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { } void RendererViewport::_draw_3d(Viewport *p_viewport) { - RENDER_TIMESTAMP(">Begin Rendering 3D Scene"); + RENDER_TIMESTAMP("> Render 3D Scene"); Ref<XRInterface> xr_interface; if (p_viewport->use_xr && XRServer::get_singleton() != nullptr) { @@ -170,7 +170,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) { float screen_mesh_lod_threshold = p_viewport->mesh_lod_threshold / float(p_viewport->size.width); RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, screen_mesh_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info); - RENDER_TIMESTAMP("<End Rendering 3D Scene"); + RENDER_TIMESTAMP("< Render 3D Scene"); } void RendererViewport::_draw_viewport(Viewport *p_viewport) { @@ -281,7 +281,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { int shadow_count = 0; int directional_light_count = 0; - RENDER_TIMESTAMP("Cull Canvas Lights"); + RENDER_TIMESTAMP("Cull 2D Lights"); for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); @@ -355,8 +355,8 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::LightOccluderInstance *occluders = nullptr; - RENDER_TIMESTAMP(">Render 2D Shadows"); - RENDER_TIMESTAMP("Cull Occluders"); + RENDER_TIMESTAMP("> Render PointLight2D Shadows"); + RENDER_TIMESTAMP("Cull LightOccluder2Ds"); //make list of occluders for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) { @@ -378,13 +378,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::Light *light = lights_with_shadow; while (light) { - RENDER_TIMESTAMP("Render Shadow"); + RENDER_TIMESTAMP("Render PointLight2D Shadow"); RSG::canvas_render->light_update_shadow(light->light_internal, shadow_count++, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders); light = light->shadows_next_ptr; } - RENDER_TIMESTAMP("<End rendering 2D Shadows"); + RENDER_TIMESTAMP("< Render PointLight2D Shadows"); } if (directional_lights_with_shadow) { @@ -436,7 +436,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::LightOccluderInstance *occluders = nullptr; - RENDER_TIMESTAMP(">Render Directional 2D Shadows"); + RENDER_TIMESTAMP("> Render DirectionalLight2D Shadows"); //make list of occluders int occ_cullded = 0; @@ -467,7 +467,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { light = light->shadows_next_ptr; } - RENDER_TIMESTAMP("<Render Directional 2D Shadows"); + RENDER_TIMESTAMP("< Render DirectionalLight2D Shadows"); } if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) { @@ -566,7 +566,7 @@ void RendererViewport::draw_viewports() { Map<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list; //draw viewports - RENDER_TIMESTAMP(">Render Viewports"); + RENDER_TIMESTAMP("> Render Viewports"); //determine what is visible draw_viewports_pass++; @@ -641,7 +641,7 @@ void RendererViewport::draw_viewports() { continue; //should not draw } - RENDER_TIMESTAMP(">Rendering Viewport " + itos(i)); + RENDER_TIMESTAMP("> Render Viewport " + itos(i)); RSG::storage->render_target_set_as_unused(vp->render_target); if (vp->use_xr && xr_interface.is_valid()) { @@ -699,7 +699,7 @@ void RendererViewport::draw_viewports() { vp->update_mode = RS::VIEWPORT_UPDATE_DISABLED; } - RENDER_TIMESTAMP("<Rendering Viewport " + itos(i)); + RENDER_TIMESTAMP("< Render Viewport " + itos(i)); objects_drawn += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME]; vertices_drawn += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME]; @@ -711,7 +711,7 @@ void RendererViewport::draw_viewports() { total_vertices_drawn = vertices_drawn; total_draw_calls_used = draw_calls_used; - RENDER_TIMESTAMP("<Render Viewports"); + RENDER_TIMESTAMP("< Render Viewports"); //this needs to be called to make screen swapping more efficient RSG::rasterizer->prepare_for_blitting_render_targets(); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 49d89bcadc..1880415342 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -726,16 +726,65 @@ public: struct Uniform { UniformType uniform_type; - int binding; //binding index as specified in shader + int binding; // Binding index as specified in shader. - //for single items, provide one ID, for - //multiple items (declared as arrays in shader), - //provide more - //for sampler with texture, supply two IDs for each. - //accepted IDs are: Sampler, Texture, Uniform Buffer and Texture Buffer - Vector<RID> ids; + private: + // In most cases only one ID is provided per binding, so avoid allocating memory unnecesarily for performance. + RID id; // If only one is provided, this is used. + Vector<RID> ids; // If multiple ones are provided, this is used instead. - Uniform() { + public: + _FORCE_INLINE_ uint32_t get_id_count() const { + return (id.is_valid() ? 1 : ids.size()); + } + + _FORCE_INLINE_ RID get_id(uint32_t p_idx) const { + if (id.is_valid()) { + ERR_FAIL_COND_V(p_idx != 0, RID()); + return id; + } else { + return ids[p_idx]; + } + } + _FORCE_INLINE_ void set_id(uint32_t p_idx, RID p_id) { + if (id.is_valid()) { + ERR_FAIL_COND(p_idx != 0); + id = p_id; + } else { + ids.write[p_idx] = p_id; + } + } + + _FORCE_INLINE_ void append_id(RID p_id) { + if (ids.is_empty()) { + if (id == RID()) { + id = p_id; + } else { + ids.push_back(id); + ids.push_back(p_id); + id = RID(); + } + } else { + ids.push_back(p_id); + } + } + + _FORCE_INLINE_ void clear_ids() { + id = RID(); + ids.clear(); + } + + _FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, RID p_id) { + uniform_type = p_type; + binding = p_binding; + id = p_id; + } + _FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, const Vector<RID> &p_ids) { + uniform_type = p_type; + binding = p_binding; + ids = p_ids; + } + _FORCE_INLINE_ Uniform() { uniform_type = UNIFORM_TYPE_IMAGE; binding = 0; } diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index b07857364b..ee5bf8b891 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -441,23 +441,23 @@ public: RD_SETGET(RD::UniformType, uniform_type) RD_SETGET(int32_t, binding) - void add_id(const RID &p_id) { base.ids.push_back(p_id); } - void clear_ids() { base.ids.clear(); } + void add_id(const RID &p_id) { base.append_id(p_id); } + void clear_ids() { base.clear_ids(); } Array get_ids() const { Array ids; - for (int i = 0; i < base.ids.size(); i++) { - ids.push_back(base.ids[i]); + for (uint32_t i = 0; i < base.get_id_count(); i++) { + ids.push_back(base.get_id(i)); } return ids; } protected: void _set_ids(const Array &p_ids) { - base.ids.clear(); + base.clear_ids(); for (int i = 0; i < p_ids.size(); i++) { RID id = p_ids[i]; ERR_FAIL_COND(id.is_null()); - base.ids.push_back(id); + base.append_id(id); } } static void _bind_methods() { diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 37cc6599b1..e84c0f05cc 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -752,15 +752,19 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_gra for (int i = 0; i < l_size; i++) { if (l_gl[i].count > 0) { if ((l_gl[i].flags & p_grapheme_flags) != 0) { - words.push_back(word_start); - words.push_back(l_gl[i].start); + if (word_start != l_gl[i].start) { + words.push_back(word_start); + words.push_back(l_gl[i].start); + } word_start = l_gl[i].end; } } } if (l_size > 0) { - words.push_back(word_start); - words.push_back(range.y); + if (word_start != range.y) { + words.push_back(word_start); + words.push_back(range.y); + } } return words; |