diff options
Diffstat (limited to 'servers')
91 files changed, 6782 insertions, 6118 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 1ba0afd8a1..635e4601c7 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -54,7 +54,7 @@ Error AudioDriverDummy::init() { }; void AudioDriverDummy::thread_func(void *p_udata) { - AudioDriverDummy *ad = (AudioDriverDummy *)p_udata; + AudioDriverDummy *ad = static_cast<AudioDriverDummy *>(p_udata); uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000; diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 6324e2f5d3..68b523e086 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -40,7 +40,7 @@ class AudioDriverDummy : public AudioDriver { Thread thread; Mutex mutex; - int32_t *samples_in; + int32_t *samples_in = nullptr; static void thread_func(void *p_udata); diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h index 9e55662d0a..1ec1abd4d5 100644 --- a/servers/audio/audio_filter_sw.h +++ b/servers/audio/audio_filter_sw.h @@ -57,7 +57,7 @@ public: class Processor { // simple filter processor - AudioFilterSW *filter; + AudioFilterSW *filter = nullptr; Coeffs coeffs; float ha1, ha2, hb1, hb2; //history Coeffs incr_coeffs; diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h index 3fbe684c3e..81ac6332e2 100644 --- a/servers/audio/audio_rb_resampler.h +++ b/servers/audio/audio_rb_resampler.h @@ -55,8 +55,8 @@ struct AudioRBResampler { MIX_FRAC_MASK = MIX_FRAC_LEN - 1, }; - float *read_buf; - float *rb; + float *read_buf = nullptr; + float *rb = nullptr; template <int C> uint32_t _resample(AudioFrame *p_dest, int p_todo, int32_t p_increment); diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp index 0069f6ad85..d68522e5b9 100644 --- a/servers/audio/effects/audio_effect_record.cpp +++ b/servers/audio/effects/audio_effect_record.cpp @@ -62,7 +62,7 @@ void AudioEffectRecordInstance::_update_buffer() { } void AudioEffectRecordInstance::_update(void *userdata) { - AudioEffectRecordInstance *ins = (AudioEffectRecordInstance *)userdata; + AudioEffectRecordInstance *ins = static_cast<AudioEffectRecordInstance *>(userdata); ins->_update_buffer(); } diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h index 8b8b7b47a0..1f93d1cf9f 100644 --- a/servers/audio/effects/audio_effect_stereo_enhance.h +++ b/servers/audio/effects/audio_effect_stereo_enhance.h @@ -44,7 +44,7 @@ class AudioEffectStereoEnhanceInstance : public AudioEffectInstance { MAX_DELAY_MS = 50 }; - float *delay_ringbuff; + float *delay_ringbuff = nullptr; unsigned int ringbuff_pos; unsigned int ringbuff_mask; diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h index 51288262b3..2ce4b95fcf 100644 --- a/servers/audio/effects/audio_stream_generator.h +++ b/servers/audio/effects/audio_stream_generator.h @@ -65,7 +65,7 @@ class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled { int skips; bool active; float mixed; - AudioStreamGenerator *generator; + AudioStreamGenerator *generator = nullptr; protected: virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override; diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h index ff59ab8d82..de25e8c52b 100644 --- a/servers/audio/effects/reverb.h +++ b/servers/audio/effects/reverb.h @@ -75,7 +75,7 @@ private: Comb comb[MAX_COMBS]; AllPass allpass[MAX_ALLPASS]; - float *input_buffer; + float *input_buffer = nullptr; float *echo_buffer = nullptr; int echo_buffer_size; int echo_buffer_pos; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 9d83e5cacc..777bebcf60 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1343,6 +1343,7 @@ void AudioServer::init_channels_and_buffers() { for (int j = 0; j < channel_count; j++) { buses.write[i]->channels.write[j].buffer.resize(buffer_size); } + _update_bus_effects(i); } } diff --git a/servers/audio_server.h b/servers/audio_server.h index 0c150427f2..5563d60e4a 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -284,7 +284,7 @@ private: struct CallbackItem { AudioCallback callback; - void *userdata; + void *userdata = nullptr; }; SafeList<CallbackItem *> update_callback_list; diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index 41a7746183..ce6bed41c9 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -45,7 +45,7 @@ protected: static void _bind_methods(); public: - // The warning is valid, but unavoidable. If the function is not overriden it will error anyway. + // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. EXBIND0RC(Vector3, get_total_gravity) EXBIND0RC(real_t, get_total_angular_damp) @@ -193,7 +193,7 @@ typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult; struct PhysicsServer3DExtensionStateCallback { - void *instance; + void *instance = nullptr; void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state); }; @@ -208,7 +208,7 @@ protected: static void _bind_methods(); public: - // The warning is valid, but unavoidable. If the function is not overriden it will error anyway. + // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. EXBIND0R(RID, world_boundary_shape_create) EXBIND0R(RID, separation_ray_shape_create) diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index 6e8078909b..dadd9747b1 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -96,7 +96,7 @@ class GodotArea2D : public GodotCollisionObject2D { Set<GodotConstraint2D *> constraints; - virtual void _shapes_changed(); + virtual void _shapes_changed() override; void _queue_monitor_update(); void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode); @@ -151,7 +151,7 @@ public: void set_transform(const Transform2D &p_transform); - void set_space(GodotSpace2D *p_space); + void set_space(GodotSpace2D *p_space) override; void call_queries(); diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 1335a19126..4b87a69d5c 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -103,7 +103,7 @@ class GodotBody2D : public GodotCollisionObject2D { bool can_sleep = true; bool first_time_kinematic = false; void _mass_properties_changed(); - virtual void _shapes_changed(); + virtual void _shapes_changed() override; Transform2D new_transform; List<Pair<GodotConstraint2D *, int>> constraint_list; @@ -302,7 +302,7 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; } _FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } - void set_space(GodotSpace2D *p_space); + void set_space(GodotSpace2D *p_space) override; void update_mass_properties(); void reset_mass_properties(); diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp index 2bf1e5a1d4..6e76697a1b 100644 --- a/servers/physics_2d/godot_body_pair_2d.cpp +++ b/servers/physics_2d/godot_body_pair_2d.cpp @@ -39,7 +39,7 @@ #define MAX_BIAS_ROTATION (Math_PI / 8) void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) { - GodotBodyPair2D *self = (GodotBodyPair2D *)p_self; + GodotBodyPair2D *self = static_cast<GodotBodyPair2D *>(p_self); self->_contact_added_callback(p_point_A, p_point_B); } diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp index 2cc60fc765..c545fec113 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp @@ -82,7 +82,7 @@ int GodotBroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D } void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B) { - GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self); + GodotBroadPhase2DBVH *bpo = static_cast<GodotBroadPhase2DBVH *>(self); if (!bpo->pair_callback) { return nullptr; } @@ -91,7 +91,7 @@ void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollis } void GodotBroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B, void *pairdata) { - GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self); + GodotBroadPhase2DBVH *bpo = static_cast<GodotBroadPhase2DBVH *>(self); if (!bpo->unpair_callback) { return; } diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h index b11ad0e75e..512111f948 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.h +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h @@ -77,22 +77,22 @@ class GodotBroadPhase2DBVH : public GodotBroadPhase2D { public: // 0 is an invalid ID - virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false); - virtual void move(ID p_id, const Rect2 &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); + virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) override; + virtual void move(ID p_id, const Rect2 &p_aabb) override; + virtual void set_static(ID p_id, bool p_static) override; + virtual void remove(ID p_id) override; - virtual GodotCollisionObject2D *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; + virtual GodotCollisionObject2D *get_object(ID p_id) const override; + virtual bool is_static(ID p_id) const override; + virtual int get_subindex(ID p_id) const override; - virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) override; + virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) override; - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) override; + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) override; - virtual void update(); + virtual void update() override; static GodotBroadPhase2D *_create(); GodotBroadPhase2DBVH(); diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h index 19d6e91561..1a683a7b0f 100644 --- a/servers/physics_2d/godot_collision_object_2d.h +++ b/servers/physics_2d/godot_collision_object_2d.h @@ -104,7 +104,7 @@ public: _FORCE_INLINE_ void set_canvas_instance_id(const ObjectID &p_canvas_instance_id) { canvas_instance_id = p_canvas_instance_id; } _FORCE_INLINE_ ObjectID get_canvas_instance_id() const { return canvas_instance_id; } - void _shape_changed(); + void _shape_changed() override; _FORCE_INLINE_ Type get_type() const { return type; } void add_shape(GodotShape2D *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); @@ -166,7 +166,7 @@ public: } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } - void remove_shape(GodotShape2D *p_shape); + void remove_shape(GodotShape2D *p_shape) override; void remove_shape(int p_index); virtual void set_space(GodotSpace2D *p_space) = 0; diff --git a/servers/physics_2d/godot_collision_solver_2d.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp index 263d6d939f..383c6a915c 100644 --- a/servers/physics_2d/godot_collision_solver_2d.cpp +++ b/servers/physics_2d/godot_collision_solver_2d.cpp @@ -150,7 +150,7 @@ struct _ConcaveCollisionInfo2D { }; bool GodotCollisionSolver2D::concave_callback(void *p_userdata, GodotShape2D *p_convex) { - _ConcaveCollisionInfo2D &cinfo = *(_ConcaveCollisionInfo2D *)(p_userdata); + _ConcaveCollisionInfo2D &cinfo = *(static_cast<_ConcaveCollisionInfo2D *>(p_userdata)); cinfo.aabb_tests++; bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, cinfo.motion_A, p_convex, *cinfo.transform_B, cinfo.motion_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, cinfo.sep_axis, cinfo.margin_A, cinfo.margin_B); diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index a9b499c6b5..650a95c914 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -144,7 +144,7 @@ real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const { } void GodotPhysicsServer2D::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { - CollCbkData *cbk = (CollCbkData *)p_userdata; + CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata); if (cbk->max == 0) { return; @@ -1212,7 +1212,7 @@ void GodotPhysicsServer2D::free(RID p_rid) { GodotSpace2D *space = space_owner.get_or_null(p_rid); while (space->get_objects().size()) { - GodotCollisionObject2D *co = (GodotCollisionObject2D *)space->get_objects().front()->get(); + GodotCollisionObject2D *co = static_cast<GodotCollisionObject2D *>(space->get_objects().front()->get()); co->set_space(nullptr); } @@ -1251,7 +1251,7 @@ void GodotPhysicsServer2D::step(real_t p_step) { active_objects = 0; collision_pairs = 0; for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { - stepper->step((GodotSpace2D *)E->get(), p_step); + stepper->step(const_cast<GodotSpace2D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); collision_pairs += E->get()->get_collision_pairs(); @@ -1272,7 +1272,7 @@ void GodotPhysicsServer2D::flush_queries() { uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { - GodotSpace2D *space = (GodotSpace2D *)E->get(); + GodotSpace2D *space = const_cast<GodotSpace2D *>(E->get()); space->call_queries(); } diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp index b5dbb8a2dd..6c020f9e72 100644 --- a/servers/physics_2d/godot_shape_2d.cpp +++ b/servers/physics_2d/godot_shape_2d.cpp @@ -37,7 +37,7 @@ void GodotShape2D::configure(const Rect2 &p_aabb) { aabb = p_aabb; configured = true; for (const KeyValue<GodotShapeOwner2D *, int> &E : owners) { - GodotShapeOwner2D *co = (GodotShapeOwner2D *)E.key; + GodotShapeOwner2D *co = const_cast<GodotShapeOwner2D *>(E.key); co->_shape_changed(); } } diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 99c0566fb1..63e3af1395 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -403,7 +403,7 @@ struct _RestCallbackData2D { }; static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { - _RestCallbackData2D *rd = (_RestCallbackData2D *)p_userdata; + _RestCallbackData2D *rd = static_cast<_RestCallbackData2D *>(p_userdata); Vector2 contact_rel = p_point_B - p_point_A; real_t len = contact_rel.length(); @@ -1005,7 +1005,7 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A SWAP(type_A, type_B); } - GodotSpace2D *self = (GodotSpace2D *)p_self; + GodotSpace2D *self = static_cast<GodotSpace2D *>(p_self); self->collision_pairs++; if (type_A == GodotCollisionObject2D::TYPE_AREA) { @@ -1021,7 +1021,7 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A } } else { - GodotBodyPair2D *b = memnew(GodotBodyPair2D((GodotBody2D *)A, p_subindex_A, (GodotBody2D *)B, p_subindex_B)); + GodotBodyPair2D *b = memnew(GodotBodyPair2D(static_cast<GodotBody2D *>(A), p_subindex_A, static_cast<GodotBody2D *>(B), p_subindex_B)); return b; } diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 866c415440..fd72038be3 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -47,7 +47,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D } for (const Pair<GodotConstraint2D *, int> &E : p_body->get_constraint_list()) { - GodotConstraint2D *constraint = (GodotConstraint2D *)E.first; + GodotConstraint2D *constraint = const_cast<GodotConstraint2D *>(E.first); if (constraint->get_island_step() == _step) { continue; // Already processed. } diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index ce64fc802a..d15f8ec0a6 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -102,7 +102,7 @@ class GodotArea3D : public GodotCollisionObject3D { Set<GodotConstraint3D *> constraints; - virtual void _shapes_changed(); + virtual void _shapes_changed() override; void _queue_monitor_update(); void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode); @@ -172,7 +172,7 @@ public: void set_transform(const Transform3D &p_transform); - void set_space(GodotSpace3D *p_space); + void set_space(GodotSpace3D *p_space) override; void call_queries(); diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h index c416477204..64b43a3b51 100644 --- a/servers/physics_3d/godot_area_pair_3d.h +++ b/servers/physics_3d/godot_area_pair_3d.h @@ -37,8 +37,8 @@ #include "godot_soft_body_3d.h" class GodotAreaPair3D : public GodotConstraint3D { - GodotBody3D *body; - GodotArea3D *area; + GodotBody3D *body = nullptr; + GodotArea3D *area = nullptr; int body_shape; int area_shape; bool colliding = false; @@ -55,8 +55,8 @@ public: }; class GodotArea2Pair3D : public GodotConstraint3D { - GodotArea3D *area_a; - GodotArea3D *area_b; + GodotArea3D *area_a = nullptr; + GodotArea3D *area_b = nullptr; int shape_a; int shape_b; bool colliding_a = false; @@ -76,8 +76,8 @@ public: }; class GodotAreaSoftBodyPair3D : public GodotConstraint3D { - GodotSoftBody3D *soft_body; - GodotArea3D *area; + GodotSoftBody3D *soft_body = nullptr; + GodotArea3D *area = nullptr; int soft_body_shape; int area_shape; bool colliding = false; diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 1906e8aab1..c0c847d920 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -109,7 +109,7 @@ class GodotBody3D : public GodotCollisionObject3D { bool first_time_kinematic = false; void _mass_properties_changed(); - virtual void _shapes_changed(); + virtual void _shapes_changed() override; Transform3D new_transform; Map<GodotConstraint3D *, int> constraint_map; @@ -301,7 +301,7 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; } _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; } - void set_space(GodotSpace3D *p_space); + void set_space(GodotSpace3D *p_space) override; void update_mass_properties(); void reset_mass_properties(); diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index 89d5d59161..eebbe0196d 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -39,7 +39,7 @@ #define MAX_BIAS_ROTATION (Math_PI / 8) void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - GodotBodyPair3D *pair = (GodotBodyPair3D *)p_userdata; + GodotBodyPair3D *pair = static_cast<GodotBodyPair3D *>(p_userdata); pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } @@ -562,7 +562,7 @@ GodotBodyPair3D::~GodotBodyPair3D() { } void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - GodotBodySoftBodyPair3D *pair = (GodotBodySoftBodyPair3D *)p_userdata; + GodotBodySoftBodyPair3D *pair = static_cast<GodotBodySoftBodyPair3D *>(p_userdata); pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp index b34f9d214f..435c1e8aec 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp @@ -87,7 +87,7 @@ int GodotBroadPhase3DBVH::cull_aabb(const AABB &p_aabb, GodotCollisionObject3D * } void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B) { - GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self); + GodotBroadPhase3DBVH *bpo = static_cast<GodotBroadPhase3DBVH *>(self); if (!bpo->pair_callback) { return nullptr; } @@ -96,7 +96,7 @@ void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollis } void GodotBroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B, void *pairdata) { - GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self); + GodotBroadPhase3DBVH *bpo = static_cast<GodotBroadPhase3DBVH *>(self); if (!bpo->unpair_callback) { return; } diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h index 7660030195..ae5a18d955 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.h +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h @@ -75,23 +75,23 @@ class GodotBroadPhase3DBVH : public GodotBroadPhase3D { public: // 0 is an invalid ID - virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false); - virtual void move(ID p_id, const AABB &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); + virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) override; + virtual void move(ID p_id, const AABB &p_aabb) override; + virtual void set_static(ID p_id, bool p_static) override; + virtual void remove(ID p_id) override; - virtual GodotCollisionObject3D *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; + virtual GodotCollisionObject3D *get_object(ID p_id) const override; + virtual bool is_static(ID p_id) const override; + virtual int get_subindex(ID p_id) const override; - virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override; + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override; + virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override; - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) override; + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) override; - virtual void update(); + virtual void update() override; static GodotBroadPhase3D *_create(); GodotBroadPhase3DBVH(); diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h index 515b945564..0f09f21962 100644 --- a/servers/physics_3d/godot_collision_object_3d.h +++ b/servers/physics_3d/godot_collision_object_3d.h @@ -112,7 +112,7 @@ public: _FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; } _FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; } - void _shape_changed(); + void _shape_changed() override; _FORCE_INLINE_ Type get_type() const { return type; } void add_shape(GodotShape3D *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false); @@ -173,7 +173,7 @@ public: return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; } - void remove_shape(GodotShape3D *p_shape); + void remove_shape(GodotShape3D *p_shape) override; void remove_shape(int p_index); virtual void set_space(GodotSpace3D *p_space) = 0; diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index 81e1a88366..0adfabef78 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -141,7 +141,7 @@ struct _SoftBodyContactCollisionInfo { }; void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - _SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata); + _SoftBodyContactCollisionInfo &cinfo = *(static_cast<_SoftBodyContactCollisionInfo *>(p_userdata)); ++cinfo.contact_count; @@ -170,7 +170,7 @@ struct _SoftBodyQueryInfo { }; bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) { - _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); + _SoftBodyQueryInfo &query_cinfo = *(static_cast<_SoftBodyQueryInfo *>(p_userdata)); Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index); @@ -189,7 +189,7 @@ bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, voi } bool GodotCollisionSolver3D::soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex) { - _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); + _SoftBodyQueryInfo &query_cinfo = *(static_cast<_SoftBodyQueryInfo *>(p_userdata)); query_cinfo.shape_A = p_convex; @@ -292,7 +292,7 @@ struct _ConcaveCollisionInfo { }; bool GodotCollisionSolver3D::concave_callback(void *p_userdata, GodotShape3D *p_convex) { - _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); + _ConcaveCollisionInfo &cinfo = *(static_cast<_ConcaveCollisionInfo *>(p_userdata)); cinfo.aabb_tests++; bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, nullptr, cinfo.margin_A, cinfo.margin_B); @@ -422,7 +422,7 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T } bool GodotCollisionSolver3D::concave_distance_callback(void *p_userdata, GodotShape3D *p_convex) { - _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); + _ConcaveCollisionInfo &cinfo = *(static_cast<_ConcaveCollisionInfo *>(p_userdata)); cinfo.aabb_tests++; Vector3 close_A, close_B; diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index f7270713e0..e5107be74b 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -1570,7 +1570,7 @@ void GodotPhysicsServer3D::free(RID p_rid) { GodotSpace3D *space = space_owner.get_or_null(p_rid); while (space->get_objects().size()) { - GodotCollisionObject3D *co = (GodotCollisionObject3D *)space->get_objects().front()->get(); + GodotCollisionObject3D *co = static_cast<GodotCollisionObject3D *>(space->get_objects().front()->get()); co->set_space(nullptr); } @@ -1612,7 +1612,7 @@ void GodotPhysicsServer3D::step(real_t p_step) { active_objects = 0; collision_pairs = 0; for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { - stepper->step((GodotSpace3D *)E->get(), p_step); + stepper->step(const_cast<GodotSpace3D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); collision_pairs += E->get()->get_collision_pairs(); @@ -1636,7 +1636,7 @@ void GodotPhysicsServer3D::flush_queries() { uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { - GodotSpace3D *space = (GodotSpace3D *)E->get(); + GodotSpace3D *space = const_cast<GodotSpace3D *>(E->get()); space->call_queries(); } @@ -1709,7 +1709,7 @@ void GodotPhysicsServer3D::_update_shapes() { } void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - CollCbkData *cbk = (CollCbkData *)p_userdata; + CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata); if (cbk->max == 0) { return; diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index 00ed763e01..d2078a912c 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -74,7 +74,7 @@ public: struct CollCbkData { int max; int amount; - Vector3 *ptr; + Vector3 *ptr = nullptr; }; static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 7762c4829e..21595c9612 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -62,7 +62,7 @@ void GodotShape3D::configure(const AABB &p_aabb) { aabb = p_aabb; configured = true; for (const KeyValue<GodotShapeOwner3D *, int> &E : owners) { - GodotShapeOwner3D *co = (GodotShapeOwner3D *)E.key; + GodotShapeOwner3D *co = const_cast<GodotShapeOwner3D *>(E.key); co->_shape_changed(); } } diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index f09da92cae..be4b41292d 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -1272,7 +1272,7 @@ struct _SoftBodyIntersectSegmentInfo { real_t hit_dist_sq = INFINITY; static bool process_hit(uint32_t p_face_index, void *p_userdata) { - _SoftBodyIntersectSegmentInfo &query_info = *(_SoftBodyIntersectSegmentInfo *)(p_userdata); + _SoftBodyIntersectSegmentInfo &query_info = *(static_cast<_SoftBodyIntersectSegmentInfo *>(p_userdata)); Vector3 points[3]; query_info.soft_body->get_face_points(p_face_index, points[0], points[1], points[2]); diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index d9f5078313..96f63e5819 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -153,7 +153,7 @@ public: } } - virtual void set_space(GodotSpace3D *p_space); + virtual void set_space(GodotSpace3D *p_space) override; void set_mesh(RID p_mesh); @@ -204,8 +204,8 @@ public: void predict_motion(real_t p_delta); void solve_constraints(real_t p_delta); - _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return ((Node *)p_node)->index; } - _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return ((Face *)p_face)->index; } + _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return static_cast<Node *>(p_node)->index; } + _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return static_cast<Face *>(p_face)->index; } // Return true to stop the query. // p_index is the node index for AABB query, face index for Ray query. @@ -215,7 +215,7 @@ public: void query_ray(const Vector3 &p_from, const Vector3 &p_to, QueryResultCallback p_result_callback, void *p_userdata); protected: - virtual void _shapes_changed(); + virtual void _shapes_changed() override; private: void update_normals_and_centroids(); diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index e8af2d7283..0b84520c39 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -445,7 +445,7 @@ struct _RestCallbackData { }; static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - _RestCallbackData *rd = (_RestCallbackData *)p_userdata; + _RestCallbackData *rd = static_cast<_RestCallbackData *>(p_userdata); Vector3 contact_rel = p_point_B - p_point_A; real_t len = contact_rel.length(); @@ -1017,7 +1017,7 @@ void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A SWAP(type_A, type_B); } - GodotSpace3D *self = (GodotSpace3D *)p_self; + GodotSpace3D *self = static_cast<GodotSpace3D *>(p_self); self->collision_pairs++; @@ -1038,10 +1038,10 @@ void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A } } else if (type_A == GodotCollisionObject3D::TYPE_BODY) { if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) { - GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotSoftBody3D *)B)); + GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D(static_cast<GodotBody3D *>(A), p_subindex_A, static_cast<GodotSoftBody3D *>(B))); return soft_pair; } else { - GodotBodyPair3D *b = memnew(GodotBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotBody3D *)B, p_subindex_B)); + GodotBodyPair3D *b = memnew(GodotBodyPair3D(static_cast<GodotBody3D *>(A), p_subindex_A, static_cast<GodotBody3D *>(B), p_subindex_B)); return b; } } else { @@ -1056,9 +1056,9 @@ void GodotSpace3D::_broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_ return; } - GodotSpace3D *self = (GodotSpace3D *)p_self; + GodotSpace3D *self = static_cast<GodotSpace3D *>(p_self); self->collision_pairs--; - GodotConstraint3D *c = (GodotConstraint3D *)p_data; + GodotConstraint3D *c = static_cast<GodotConstraint3D *>(p_data); memdelete(c); } diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h index ac54c8bf69..6308ede9a9 100644 --- a/servers/physics_3d/godot_space_3d.h +++ b/servers/physics_3d/godot_space_3d.h @@ -47,7 +47,7 @@ class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D { GDCLASS(GodotPhysicsDirectSpaceState3D, PhysicsDirectSpaceState3D); public: - GodotSpace3D *space; + GodotSpace3D *space = nullptr; virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override; diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 63635b224b..204adae450 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -49,7 +49,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D } for (const KeyValue<GodotConstraint3D *, int> &E : p_body->get_constraint_map()) { - GodotConstraint3D *constraint = (GodotConstraint3D *)E.key; + GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E.key); if (constraint->get_island_step() == _step) { continue; // Already processed. } @@ -88,7 +88,7 @@ void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, Local p_soft_body->set_island_step(_step); for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { - GodotConstraint3D *constraint = (GodotConstraint3D *)E->get(); + GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E->get()); if (constraint->get_island_step() == _step) { continue; // Already processed. } diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index 219f468b2f..f7bd7d0d18 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -39,6 +39,8 @@ #include "servers/rendering/dummy/rasterizer_storage_dummy.h" #include "servers/rendering/dummy/storage/canvas_texture_storage.h" #include "servers/rendering/dummy/storage/decal_atlas_storage.h" +#include "servers/rendering/dummy/storage/material_storage.h" +#include "servers/rendering/dummy/storage/mesh_storage.h" #include "servers/rendering/dummy/storage/texture_storage.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering_server.h" @@ -51,6 +53,8 @@ private: protected: RasterizerCanvasDummy canvas; RendererDummy::CanvasTextureStorage canvas_texture_storage; + RendererDummy::MaterialStorage material_storage; + RendererDummy::MeshStorage mesh_storage; RendererDummy::TextureStorage texture_storage; RendererDummy::DecalAtlasStorage decal_atlas_storage; RasterizerStorageDummy storage; @@ -58,6 +62,8 @@ protected: public: RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; }; + RendererMaterialStorage *get_material_storage() override { return &material_storage; }; + RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; }; RendererTextureStorage *get_texture_storage() override { return &texture_storage; }; RendererDecalAtlasStorage *get_decal_atlas_storage() override { return &decal_atlas_storage; }; RendererStorage *get_storage() override { return &storage; } diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h index 1e753f8b6b..ea69d2f9a6 100644 --- a/servers/rendering/dummy/rasterizer_storage_dummy.h +++ b/servers/rendering/dummy/rasterizer_storage_dummy.h @@ -36,113 +36,6 @@ class RasterizerStorageDummy : public RendererStorage { public: - /* SHADER API */ - - RID shader_allocate() override { return RID(); } - void shader_initialize(RID p_rid) override {} - void shader_set_code(RID p_shader, const String &p_code) override {} - String shader_get_code(RID p_shader) const override { return ""; } - void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} - - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } - Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } - - RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; - - /* COMMON MATERIAL API */ - - RID material_allocate() override { return RID(); } - void material_initialize(RID p_rid) override {} - void material_set_render_priority(RID p_material, int priority) override {} - void material_set_shader(RID p_shader_material, RID p_shader) override {} - - void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {} - Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); } - - void material_set_next_pass(RID p_material, RID p_next_material) override {} - - bool material_is_animated(RID p_material) override { return false; } - bool material_casts_shadows(RID p_material) override { return false; } - void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} - void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {} - - /* MESH API */ - - RID mesh_allocate() override { return RID(); } - void mesh_initialize(RID p_rid) override {} - void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {} - bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; } - RID mesh_instance_create(RID p_base) override { return RID(); } - void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {} - void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {} - void mesh_instance_check_for_update(RID p_mesh_instance) override {} - void update_mesh_instances() override {} - void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {} - float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; } - - void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {} - - int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } - - void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {} - RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; } - - void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} - void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} - void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} - - void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} - RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } - - RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); } - int mesh_get_surface_count(RID p_mesh) const override { return 0; } - - void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} - AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } - - AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); } - void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {} - void mesh_clear(RID p_mesh) override {} - - /* MULTIMESH API */ - - RID multimesh_allocate() override { return RID(); } - void multimesh_initialize(RID p_rid) override {} - void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {} - int multimesh_get_instance_count(RID p_multimesh) const override { return 0; } - - void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {} - void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {} - void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {} - void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {} - void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {} - - RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); } - AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); } - - Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); } - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); } - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); } - Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); } - void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {} - Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); } - - void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {} - int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; } - - /* SKELETON API */ - - RID skeleton_allocate() override { return RID(); } - void skeleton_initialize(RID p_rid) override {} - void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {} - void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {} - int skeleton_get_bone_count(RID p_skeleton) const override { return 0; } - void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {} - Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); } - void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {} - Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); } - /* Light API */ RID directional_light_allocate() override { return RID(); } @@ -202,6 +95,8 @@ public: void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {} void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {} void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {} + void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {} + float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; } AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); } RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; } @@ -212,7 +107,6 @@ public: bool reflection_probe_renders_shadows(RID p_probe) const override { return false; } void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {} - void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {} /* VOXEL GI API */ @@ -352,6 +246,8 @@ public: void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {} void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {} + bool particles_is_inactive(RID p_particles) const override { return false; } + /* FOG VOLUMES */ RID fog_volume_allocate() override { return RID(); } @@ -372,26 +268,6 @@ public: virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); } virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {} - /* GLOBAL VARIABLES */ - - void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {} - void global_variable_remove(const StringName &p_name) override {} - Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); } - - void global_variable_set(const StringName &p_name, const Variant &p_value) override {} - void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {} - Variant global_variable_get(const StringName &p_name) const override { return Variant(); } - RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } - - void global_variables_load_settings(bool p_load_textures = true) override {} - void global_variables_clear() override {} - - int32_t global_variables_instance_allocate(RID p_instance) override { return 0; } - void global_variables_instance_free(RID p_instance) override {} - void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} - - bool particles_is_inactive(RID p_particles) const override { return false; } - /* RENDER TARGET */ RID render_target_create() override { return RID(); } diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h new file mode 100644 index 0000000000..8890be8ea9 --- /dev/null +++ b/servers/rendering/dummy/storage/material_storage.h @@ -0,0 +1,95 @@ +/*************************************************************************/ +/* material_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MATERIAL_STORAGE_DUMMY_H +#define MATERIAL_STORAGE_DUMMY_H + +#include "servers/rendering/storage/material_storage.h" + +namespace RendererDummy { + +class MaterialStorage : public RendererMaterialStorage { +public: + /* GLOBAL VARIABLE API */ + + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {} + virtual void global_variable_remove(const StringName &p_name) override {} + virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); } + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {} + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {} + virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); } + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } + + virtual void global_variables_load_settings(bool p_load_textures = true) override {} + virtual void global_variables_clear() override {} + + virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; } + virtual void global_variables_instance_free(RID p_instance) override {} + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} + + /* SHADER API */ + + virtual RID shader_allocate() override { return RID(); } + virtual void shader_initialize(RID p_rid) override {} + virtual void shader_free(RID p_rid) override{}; + + virtual void shader_set_code(RID p_shader, const String &p_code) override {} + virtual String shader_get_code(RID p_shader) const override { return ""; } + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } + virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; + + /* MATERIAL API */ + virtual RID material_allocate() override { return RID(); } + virtual void material_initialize(RID p_rid) override {} + virtual void material_free(RID p_rid) override{}; + + virtual void material_set_render_priority(RID p_material, int priority) override {} + virtual void material_set_shader(RID p_shader_material, RID p_shader) override {} + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {} + virtual Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); } + + virtual void material_set_next_pass(RID p_material, RID p_next_material) override {} + + virtual bool material_is_animated(RID p_material) override { return false; } + virtual bool material_casts_shadows(RID p_material) override { return false; } + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} + virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {} +}; + +} // namespace RendererDummy + +#endif // !MATERIAL_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h new file mode 100644 index 0000000000..dfbd265bba --- /dev/null +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* mesh_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_STORAGE_DUMMY_H +#define MESH_STORAGE_DUMMY_H + +#include "servers/rendering/storage/mesh_storage.h" + +namespace RendererDummy { + +class MeshStorage : public RendererMeshStorage { +public: + /* MESH API */ + + virtual RID mesh_allocate() override { return RID(); } + virtual void mesh_initialize(RID p_rid) override {} + virtual void mesh_free(RID p_rid) override {} + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {} + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; } + + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {} + + virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {} + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; } + + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); } + virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; } + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} + virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); } + virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {} + virtual void mesh_clear(RID p_mesh) override {} + + /* MESH INSTANCE */ + + virtual RID mesh_instance_create(RID p_base) override { return RID(); } + virtual void mesh_instance_free(RID p_rid) override {} + + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {} + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {} + virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {} + virtual void update_mesh_instances() override {} + + /* MULTIMESH API */ + + virtual RID multimesh_allocate() override { return RID(); } + virtual void multimesh_initialize(RID p_rid) override {} + virtual void multimesh_free(RID p_rid) override {} + + virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {} + virtual int multimesh_get_instance_count(RID p_multimesh) const override { return 0; } + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {} + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {} + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {} + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {} + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {} + + virtual RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); } + virtual AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); } + + virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); } + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); } + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); } + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); } + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {} + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); } + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {} + virtual int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; } + + /* SKELETON API */ + + virtual RID skeleton_allocate() override { return RID(); } + virtual void skeleton_initialize(RID p_rid) override {} + virtual void skeleton_free(RID p_rid) override {} + virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {} + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {} + virtual int skeleton_get_bone_count(RID p_skeleton) const override { return 0; } + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {} + virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); } + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {} + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); } + + virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {} +}; + +} // namespace RendererDummy + +#endif // !MESH_STORAGE_DUMMY_H diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 22149c9e43..f38d800aa7 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -997,8 +997,8 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con ERR_FAIL_COND(!m); m->mesh = p_mesh; if (canvas_item->skeleton.is_valid()) { - m->mesh_instance = RSG::storage->mesh_instance_create(p_mesh); - RSG::storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton); + m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh); + RSG::mesh_storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton); } m->texture = p_texture; @@ -1093,12 +1093,12 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c); if (canvas_item->skeleton.is_valid()) { if (cm->mesh_instance.is_null()) { - cm->mesh_instance = RSG::storage->mesh_instance_create(cm->mesh); + cm->mesh_instance = RSG::mesh_storage->mesh_instance_create(cm->mesh); } - RSG::storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton); + RSG::mesh_storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton); } else { if (cm->mesh_instance.is_valid()) { - RSG::storage->free(cm->mesh_instance); + RSG::mesh_storage->mesh_instance_free(cm->mesh_instance); cm->mesh_instance = RID(); } } diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index fc53ce2327..94bae30ae0 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -124,7 +124,7 @@ public: Set<RID> viewports; struct ChildItem { Point2 mirror; - Item *item; + Item *item = nullptr; bool operator<(const ChildItem &p_item) const { return item->index < p_item.item->index; } diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 1840925f78..46ca3b0da8 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -31,6 +31,7 @@ #ifndef RENDERINGSERVERCANVASRENDER_H #define RENDERINGSERVERCANVASRENDER_H +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_storage.h" class RendererCanvasRender { @@ -82,10 +83,10 @@ public: Transform2D light_shader_xform; //Vector2 light_shader_pos; - Light *shadows_next_ptr; - Light *filter_next_ptr; - Light *next_ptr; - Light *directional_next_ptr; + Light *shadows_next_ptr = nullptr; + Light *filter_next_ptr = nullptr; + Light *next_ptr = nullptr; + Light *directional_next_ptr = nullptr; RID light_internal; uint64_t version; @@ -167,7 +168,7 @@ public: MAX_SIZE = 4096 }; uint32_t usage; - uint8_t *memory; + uint8_t *memory = nullptr; }; struct Command { @@ -184,7 +185,7 @@ public: TYPE_ANIMATION_SLICE, }; - Command *next; + Command *next = nullptr; Type type; virtual ~Command() {} }; @@ -304,8 +305,8 @@ public: }; struct ViewportRender { - RenderingServer *owner; - void *udata; + RenderingServer *owner = nullptr; + void *udata = nullptr; Rect2 rect; }; @@ -333,22 +334,22 @@ public: RID material; RID skeleton; - Item *next; + Item *next = nullptr; struct CopyBackBuffer { Rect2 rect; Rect2 screen_rect; bool full; }; - CopyBackBuffer *copy_back_buffer; + CopyBackBuffer *copy_back_buffer = nullptr; Color final_modulate; Transform2D final_transform; Rect2 final_clip_rect; - Item *final_clip_owner; - Item *material_owner; - Item *canvas_group_owner; - ViewportRender *vp_render; + Item *final_clip_owner = nullptr; + Item *material_owner = nullptr; + Item *canvas_group_owner = nullptr; + ViewportRender *vp_render = nullptr; bool distance_field; bool light_masked; @@ -403,14 +404,14 @@ public: } break; case Item::Command::TYPE_MESH: { const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c); - AABB aabb = RendererStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); + AABB aabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(mesh->mesh, RID()); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); } break; case Item::Command::TYPE_MULTIMESH: { const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c); - AABB aabb = RendererStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh); + AABB aabb = RendererRD::MeshStorage::get_singleton()->multimesh_get_aabb(multimesh->multimesh); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); @@ -452,14 +453,14 @@ public: return rect; } - Command *commands; - Command *last_command; + Command *commands = nullptr; + Command *last_command = nullptr; Vector<CommandBlock> blocks; uint32_t current_block; template <class T> T *alloc_command() { - T *command; + T *command = nullptr; if (commands == nullptr) { // As the most common use case of canvas items is to // use only one command, the first is done with it's @@ -589,7 +590,7 @@ public: bool sdf_collision; RS::CanvasOccluderPolygonCullMode cull_cache; - LightOccluderInstance *next; + LightOccluderInstance *next = nullptr; LightOccluderInstance() { enabled = true; diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index 8d8fcee5a4..74eff4bb40 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -36,6 +36,8 @@ #include "servers/rendering/renderer_storage.h" #include "servers/rendering/storage/canvas_texture_storage.h" #include "servers/rendering/storage/decal_atlas_storage.h" +#include "servers/rendering/storage/material_storage.h" +#include "servers/rendering/storage/mesh_storage.h" #include "servers/rendering/storage/texture_storage.h" #include "servers/rendering_server.h" @@ -74,6 +76,8 @@ public: static RendererCompositor *create(); virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0; + virtual RendererMaterialStorage *get_material_storage() = 0; + virtual RendererMeshStorage *get_mesh_storage() = 0; virtual RendererTextureStorage *get_texture_storage() = 0; virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0; virtual RendererStorage *get_storage() = 0; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 24108b3a59..0b36fe3964 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -269,7 +269,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size); cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size); - render_elements = (RenderElementData *)memalloc(sizeof(RenderElementData *) * render_element_max); + render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData *) * render_element_max)); render_element_count = 0; element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 0ae51ed876..e24d020a14 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -31,6 +31,7 @@ #include "render_forward_clustered.h" #include "core/config/project_settings.h" #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" @@ -59,14 +60,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() if (msaa == RS::VIEWPORT_MSAA_DISABLED) { { Vector<RID> fb; - fb.push_back(color); - fb.push_back(specular); - fb.push_back(depth); - - color_specular_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector<RID> fb; fb.push_back(specular); specular_only_fb = RD::get_singleton()->framebuffer_create(fb); @@ -79,14 +72,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() { Vector<RID> fb; - fb.push_back(color_msaa); - fb.push_back(specular_msaa); - fb.push_back(depth_msaa); - - color_specular_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector<RID> fb; fb.push_back(specular_msaa); specular_only_fb = RD::get_singleton()->framebuffer_create(fb); @@ -165,11 +150,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { color = RID(); depth = RID(); - color_specular_fb = RID(); - specular_only_fb = RID(); - color_fb = RID(); depth_fb = RID(); + color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations + if (normal_roughness_buffer.is_valid()) { RD::get_singleton()->free(normal_roughness_buffer); if (normal_roughness_buffer_msaa.is_valid()) { @@ -203,7 +187,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c fb.push_back(p_color_buffer); fb.push_back(depth); - color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); + color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } { Vector<RID> fb; @@ -246,7 +230,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c fb.push_back(color_msaa); fb.push_back(depth_msaa); - color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); + color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } { Vector<RID> fb; @@ -257,6 +241,31 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c } } +RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) { + if (color_framebuffers.has(p_color_pass_flags)) { + return color_framebuffers[p_color_pass_flags]; + } + + bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED; + + Vector<RID> fb; + fb.push_back(use_msaa ? color_msaa : color); + + if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) { + ensure_specular(); + fb.push_back(use_msaa ? specular_msaa : specular); + } else { + fb.push_back(RID()); + } + + fb.push_back(use_msaa ? depth_msaa : depth); + + int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1; + RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count); + color_framebuffers[p_color_pass_flags] = framebuffer; + return framebuffer; +} + void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) { if (rb->normal_roughness_buffer.is_valid()) { return; @@ -306,8 +315,9 @@ bool RenderForwardClustered::free(RID p_rid) { /// RENDERING /// -template <RenderForwardClustered::PassMode p_pass_mode> +template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags> void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -340,7 +350,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; - if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { + if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass } @@ -403,10 +413,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p RID xforms_uniform_set = surf->owner->transforms_uniform_set; SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. - + uint32_t pipeline_color_pass_flags = 0; uint32_t pipeline_specialization = 0; - if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) { + if (p_pass_mode == PASS_MODE_COLOR) { if (element_info.uses_softshadow) { pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS; } @@ -422,28 +432,26 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p switch (p_pass_mode) { case PASS_MODE_COLOR: { if (element_info.uses_lightmap) { - pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS; - } else { - pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS; - } - } break; - case PASS_MODE_COLOR_TRANSPARENT: { - if (element_info.uses_lightmap) { - pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS; + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_LIGHTMAP; } else { if (element_info.uses_forward_gi) { pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI; } - pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS; } - } break; - case PASS_MODE_COLOR_SPECULAR: { - ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for specular pass"); - if (element_info.uses_lightmap) { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR; - } else { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR; + + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR; } + + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT; + } + + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MULTIVIEW; + } + + pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS; } break; case PASS_MODE_SHADOW: case PASS_MODE_DEPTH: { @@ -473,7 +481,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p PipelineCacheRD *pipeline = nullptr; - pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version]; + if constexpr (p_pass_mode == PASS_MODE_COLOR) { + pipeline = &shader->color_pipelines[cull_variant][primitive][pipeline_color_pass_flags]; + } else { + pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version]; + } RD::VertexFormatID vertex_format = -1; RID vertex_array_rd; @@ -481,12 +493,12 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p //skeleton and blend shape if (surf->owner->mesh_instance.is_valid()) { - storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } else { - storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } - index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); if (prev_vertex_array_rd != vertex_array_rd) { RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); @@ -544,14 +556,23 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis //use template for faster performance (pass mode comparisons are inlined) switch (p_params->pass_mode) { +#define VALID_FLAG_COMBINATION(f) \ + case f: { \ + _render_list_template<PASS_MODE_COLOR, f>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); \ + } break; + case PASS_MODE_COLOR: { - _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); - } break; - case PASS_MODE_COLOR_SPECULAR: { - _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); - } break; - case PASS_MODE_COLOR_TRANSPARENT: { - _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + switch (p_params->color_pass_flags) { + VALID_FLAG_COMBINATION(0); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW); + default: { + ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags)); + } + } + } break; case PASS_MODE_SHADOW: { _render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); @@ -663,7 +684,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.fog_enabled = false; if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); + RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } @@ -944,6 +965,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit return (p_indices - subtractor[p_primitive]) / divisor[p_primitive]; } void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -1080,7 +1103,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con // LOD - if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { //lod Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); @@ -1104,7 +1127,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } uint32_t indices; - surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1116,13 +1139,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } else { surf->sort.lod_index = 0; if (p_render_data->render_info) { - uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface); + uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); to_draw = _indices_to_primitives(surf->primitive, to_draw); to_draw *= inst->instance_count; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } } } @@ -1219,7 +1242,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RenderBufferDataForwardClustered *render_buffer = nullptr; if (p_render_data->render_buffers.is_valid()) { - render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); + render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); } RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; @@ -1238,12 +1261,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co scene_state.ubo.opaque_prepass_threshold = 0.99f; Size2i screen_size; - RID opaque_framebuffer; - RID opaque_specular_framebuffer; + RID color_framebuffer; + RID color_only_framebuffer; RID depth_framebuffer; - RID alpha_framebuffer; PassMode depth_pass_mode = PASS_MODE_DEPTH; + uint32_t color_pass_flags = 0; Vector<Color> depth_pass_clear; bool using_separate_specular = false; bool using_ssr = false; @@ -1256,15 +1279,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co screen_size.x = render_buffer->width; screen_size.y = render_buffer->height; - opaque_framebuffer = render_buffer->color_fb; - if (p_render_data->voxel_gi_instances->size() > 0) { using_voxelgi = true; } - if (!p_render_data->environment.is_valid() && using_voxelgi) { + if (p_render_data->view_count > 1) { + depth_pass_mode = PASS_MODE_DEPTH; + } else if (!p_render_data->environment.is_valid() && using_voxelgi) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; - } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { if (environment_is_sdfgi_enabled(p_render_data->environment)) { depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi @@ -1272,14 +1294,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } else { depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } - if (environment_is_ssr_enabled(p_render_data->environment)) { - render_buffer->ensure_specular(); using_separate_specular = true; using_ssr = true; - opaque_specular_framebuffer = render_buffer->color_specular_fb; + color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; } - } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } @@ -1304,15 +1323,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co }; } - alpha_framebuffer = opaque_framebuffer; + if (p_render_data->view_count > 1) { + color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW; + } + + color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags); + color_only_framebuffer = render_buffer->color_only_fb; } else if (p_render_data->reflection_probe.is_valid()) { uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; - opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + color_only_framebuffer = color_framebuffer; depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - alpha_framebuffer = opaque_framebuffer; if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors @@ -1342,11 +1366,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; - if (using_sss) { - using_separate_specular = true; - render_buffer->ensure_specular(); + if (using_sss && !using_separate_specular) { using_separate_specular = true; - opaque_specular_framebuffer = render_buffer->color_specular_fb; + color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; + color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags); } RID radiance_texture; bool draw_sky = false; @@ -1368,7 +1391,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.b *= bg_energy; if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } } break; case RS::ENV_BG_COLOR: { @@ -1378,7 +1401,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.b *= bg_energy; if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } } break; case RS::ENV_BG_SKY: { @@ -1449,7 +1472,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID()); bool finish_depth = using_ssao || using_sdfgi || using_voxelgi; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); @@ -1495,20 +1518,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); - //regular forward for now Vector<Color> c; - if (using_separate_specular) { + { Color cc = clear_color.to_linear(); - cc.a = 0; //subsurf scatter must be 0 + if (using_separate_specular) { + cc.a = 0; //subsurf scatter must be 0 + } c.push_back(cc); - c.push_back(Color(0, 0, 0, 0)); - } else { - c.push_back(clear_color.to_linear()); + + if (render_buffer) { + c.push_back(Color(0, 0, 0, 0)); + } } - RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); - _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); if (will_continue_color && using_separate_specular) { // close the specular framebuffer, as it's no longer used RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); @@ -1526,10 +1550,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co CameraMatrix dc; dc.set_depth_correction(true); CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { - gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); + gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); } RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); @@ -1543,9 +1567,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co CameraMatrix dc; dc.set_depth_correction(true); CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug SDFGI"); - _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm); + _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm); RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); } @@ -1559,9 +1583,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co CameraMatrix correction; correction.set_depth_correction(true); CameraMatrix projection = correction * p_render_data->cam_projection; - sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time); + sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time); } else { - sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); + sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); } RD::get_singleton()->draw_command_end_label(); } @@ -1588,12 +1612,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_ssr) { RENDER_TIMESTAMP("Screen-Space Reflections"); RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections"); - _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); + _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); + storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); } } @@ -1616,7 +1640,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); { - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~COLOR_PASS_FLAG_SEPARATE_SPECULAR; + RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); } @@ -1738,7 +1764,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); + RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); } @@ -1781,7 +1807,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con { //regular forward for now - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set); _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); } RD::get_singleton()->draw_command_end_label(); @@ -1818,7 +1844,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RENDER_TIMESTAMP("Render 3D Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set); //regular forward for now Vector<Color> clear = { Color(0, 0, 0, 0), @@ -1864,7 +1890,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p RENDER_TIMESTAMP("Render 3D Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, true); //regular forward for now Vector<Color> clear = { Color(0, 0, 0, 0), @@ -1918,7 +1944,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i _update_render_base_uniform_set(); - RenderBufferDataForwardClustered *render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForwardClustered *render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); ERR_FAIL_COND(!render_buffer); PassMode pass_mode = PASS_MODE_SDF; @@ -1984,7 +2010,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i E = sdfgi_framebuffer_size_cache.insert(fb_size, fb); } - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false); _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); } @@ -2165,7 +2191,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -2182,9 +2208,11 @@ void RenderForwardClustered::_update_render_base_uniform_set() { } RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RenderBufferDataForwardClustered *rb = nullptr; if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); + rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); } //default render buffer and scene state uniform set @@ -2429,6 +2457,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); Vector<RD::Uniform> uniforms; { @@ -2557,7 +2586,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te } RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { - RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); return rb->normal_roughness_buffer; } @@ -2585,6 +2614,8 @@ void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_g } void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; bool has_base_alpha = (p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha; bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; @@ -2633,12 +2664,12 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); - RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh); + RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); if (shadow_mesh.is_valid()) { - surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface); + surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface); } } else { @@ -2651,8 +2682,8 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet sdcache->shader = p_material->shader_data; sdcache->material_uniform_set = p_material->uniform_set; - sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface); - sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface); + sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); + sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { @@ -2688,23 +2719,25 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) { SceneShaderForwardClustered::MaterialData *material = p_material; + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh); while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); } - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh); } } void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RID m_src; m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; @@ -2712,7 +2745,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw SceneShaderForwardClustered::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2720,10 +2753,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw if (material) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2734,10 +2767,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); @@ -2746,6 +2779,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw } void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); if (ginstance->data->dirty_dependencies) { @@ -2759,7 +2793,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome uint32_t surface_count; RID mesh = ginstance->data->base; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { //if no materials, no surfaces. const RID *inst_materials = ginstance->data->surface_materials.ptr(); @@ -2776,19 +2810,19 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome } break; case RS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(ginstance->data->base); + RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base); if (mesh.is_valid()) { const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t j = 0; j < surface_count; j++) { _geometry_instance_add_surface(ginstance, j, materials[j], mesh); } } - ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base); } } break; @@ -2813,7 +2847,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t k = 0; k < surface_count; k++) { _geometry_instance_add_surface(ginstance, k, materials[k], mesh); @@ -2837,17 +2871,17 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; - if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { + if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; } - if (storage->multimesh_uses_colors(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; } - if (storage->multimesh_uses_custom_data(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; } - ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; @@ -2864,10 +2898,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { - if (storage->skeleton_is_valid(ginstance->data->skeleton)) { - ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { + ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); if (ginstance->data->dirty_dependencies) { - storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); + mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); } } } @@ -2907,7 +2941,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { - ginstance->instance_count = static_cast<RenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); } } break; default: { diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index b770cc8f0e..37366d3e14 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -103,10 +103,10 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID depth_fb; RID depth_normal_roughness_fb; RID depth_normal_roughness_voxelgi_fb; - RID color_fb; - RID color_specular_fb; + RID color_only_fb; RID specular_only_fb; int width, height; + Map<uint32_t, RID> color_framebuffers; uint32_t view_count; RID render_sdfgi_uniform_set; @@ -114,6 +114,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void ensure_voxelgi(); void clear(); virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count); + RID get_color_pass_fb(uint32_t p_color_pass_flags); ~RenderBufferDataForwardClustered(); }; @@ -135,8 +136,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { enum PassMode { PASS_MODE_COLOR, - PASS_MODE_COLOR_SPECULAR, - PASS_MODE_COLOR_TRANSPARENT, PASS_MODE_SHADOW, PASS_MODE_SHADOW_DP, PASS_MODE_DEPTH, @@ -146,6 +145,12 @@ class RenderForwardClustered : public RendererSceneRenderRD { PASS_MODE_SDF, }; + enum ColorPassFlags { + COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, + COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, + COLOR_PASS_FLAG_MULTIVIEW = 1 << 2 + }; + struct GeometryInstanceSurfaceDataCache; struct RenderElementInfo; @@ -155,6 +160,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { int element_count = 0; bool reverse_cull = false; PassMode pass_mode = PASS_MODE_COLOR; + uint32_t color_pass_flags = 0; bool no_gi = false; uint32_t view_count = 1; RID render_pass_uniform_set; @@ -168,12 +174,13 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t barrier = RD::BARRIER_MASK_ALL; bool use_directional_soft_shadow = false; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; reverse_cull = p_reverse_cull; pass_mode = p_pass_mode; + color_pass_flags = p_color_pass_flags; no_gi = p_no_gi; view_count = p_view_count; render_pass_uniform_set = p_render_pass_uniform_set; @@ -325,7 +332,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 }; LocalVector<InstanceData> instance_data[RENDER_LIST_MAX]; - LightmapCaptureData *lightmap_captures; + LightmapCaptureData *lightmap_captures = nullptr; uint32_t max_lightmap_captures; RID lightmap_capture_buffer; @@ -374,7 +381,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t lod_index : 8; }; - template <PassMode p_pass_mode> + template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0> _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 5a0ed7ebad..2acce8bab7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "render_forward_clustered.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" using namespace RendererSceneRenderImplementation; @@ -233,10 +234,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } } - RD::PipelineColorBlendState blend_state_blend; - blend_state_blend.attachments.push_back(blend_attachment); - RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); + // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular + RD::PipelineColorBlendState blend_state_color_blend; + blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment() }; + RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(2); RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1); RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2); @@ -279,18 +280,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_DEPTH_PASS_MULTIVIEW, - SHADER_VERSION_COLOR_PASS_MULTIVIEW, - SHADER_VERSION_COLOR_PASS_MULTIVIEW, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, + SHADER_VERSION_COLOR_PASS, }; shader_version = shader_version_table[k]; @@ -306,38 +297,62 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; RD::PipelineMultisampleState multisample_state; - if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS || k == PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW) { - if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { - multisample_state.enable_alpha_to_coverage = true; - } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { - multisample_state.enable_alpha_to_coverage = true; - multisample_state.enable_alpha_to_one = true; - } - - blend_state = blend_state_blend; - - if (depth_draw == DEPTH_DRAW_OPAQUE) { - depth_stencil.enable_depth_write = false; //alpha does not draw depth + if (k == PIPELINE_VERSION_COLOR_PASS) { + for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) { + if (!shader_singleton->valid_color_pass_pipelines.has(l)) { + continue; + } + + int shader_flags = 0; + if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) { + if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { + multisample_state.enable_alpha_to_coverage = true; + } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { + multisample_state.enable_alpha_to_coverage = true; + multisample_state.enable_alpha_to_one = true; + } + + blend_state = blend_state_color_blend; + + if (depth_draw == DEPTH_DRAW_OPAQUE) { + depth_stencil.enable_depth_write = false; //alpha does not draw depth + } + } else { + blend_state = blend_state_color_opaque; + + if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) { + shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR; + } + } + + if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) { + shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP; + } + + if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) { + shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW; + } + + int variant = shader_version + shader_flags; + RID shader_variant = shader_singleton->shader.version_get_shader(version, variant); + color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); } - } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS || k == PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW) { - blend_state = blend_state_opaque; - } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW || k == PIPELINE_VERSION_DEPTH_PASS_DP) { - //none, leave empty - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { - blend_state = blend_state_depth_normal_roughness; - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { - blend_state = blend_state_depth_normal_roughness_giprobe; - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) { - blend_state = RD::PipelineColorBlendState(); //no color targets for SDF } else { - //specular write - blend_state = blend_state_opaque_specular; - } + if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) { + //none, leave empty + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { + blend_state = blend_state_depth_normal_roughness; + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { + blend_state = blend_state_depth_normal_roughness_giprobe; + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) { + blend_state = RD::PipelineColorBlendState(); //no color targets for SDF + } - RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version); - pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); + RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version); + pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); + } } } } @@ -384,13 +399,13 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> } } -void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -445,7 +460,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { +RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -469,7 +484,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -484,17 +499,20 @@ SceneShaderForwardClustered::SceneShaderForwardClustered() { } SceneShaderForwardClustered::~SceneShaderForwardClustered() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RD::get_singleton()->free(default_vec4_xform_buffer); RD::get_singleton()->free(shadow_sampler); - storage->free(overdraw_material_shader); - storage->free(default_shader); + material_storage->shader_free(overdraw_material_shader); + material_storage->shader_free(default_shader); - storage->free(overdraw_material); - storage->free(default_material); + material_storage->material_free(overdraw_material); + material_storage->material_free(default_material); } void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); storage = p_storage; { @@ -505,27 +523,40 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF - shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR - shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR - - // multiview versions of our shaders shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW - shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW - shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW + + Vector<String> color_pass_flags = { + "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR + "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP + "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW + }; + + for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) { + String version = ""; + for (int j = 0; (1 << j) < SHADER_COLOR_PASS_FLAG_COUNT; j += 1) { + if ((1 << j) & i) { + version += color_pass_flags[j]; + } + } + shader_versions.push_back(version); + } shader.initialize(shader_versions, p_defines); if (!RendererCompositorRD::singleton->is_xr_enabled()) { shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false); - shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false); - shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false); + // TODO Add a way to enable/disable color pass flags } } - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); + valid_color_pass_pipelines.insert(0); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -710,9 +741,9 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin { //default material and shader - default_shader = storage->shader_allocate(); - storage->shader_initialize(default_shader); - storage->shader_set_code(default_shader, R"( + default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(default_shader); + material_storage->shader_set_code(default_shader, R"( // Default 3D material shader (clustered). shader_type spatial; @@ -727,11 +758,11 @@ void fragment() { METALLIC = 0.2; } )"); - default_material = storage->material_allocate(); - storage->material_initialize(default_material); - storage->material_set_shader(default_material, default_shader); + default_material = material_storage->material_allocate(); + material_storage->material_initialize(default_material); + material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); @@ -740,10 +771,10 @@ void fragment() { } { - overdraw_material_shader = storage->shader_allocate(); - storage->shader_initialize(overdraw_material_shader); + overdraw_material_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(overdraw_material_shader); // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. - storage->shader_set_code(overdraw_material_shader, R"( + material_storage->shader_set_code(overdraw_material_shader, R"( // 3D editor Overdraw debug draw mode shader (clustered). shader_type spatial; @@ -755,11 +786,11 @@ void fragment() { ALPHA = 0.1; } )"); - overdraw_material = storage->material_allocate(); - storage->material_initialize(overdraw_material); - storage->material_set_shader(overdraw_material, overdraw_material_shader); + overdraw_material = material_storage->material_allocate(); + material_storage->material_initialize(overdraw_material); + material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 4398517259..1b7709bedb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -42,7 +42,7 @@ private: static SceneShaderForwardClustered *singleton; public: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; enum ShaderVersion { SHADER_VERSION_DEPTH_PASS, @@ -51,18 +51,18 @@ public: SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_DEPTH_PASS_MULTIVIEW, - SHADER_VERSION_COLOR_PASS_MULTIVIEW, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, - + SHADER_VERSION_COLOR_PASS, SHADER_VERSION_MAX }; + enum ShaderColorPassFlags { + SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0, + SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1, + SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2, + SHADER_COLOR_PASS_FLAG_COUNT = 1 << 3 + }; + enum PipelineVersion { PIPELINE_VERSION_DEPTH_PASS, PIPELINE_VERSION_DEPTH_PASS_DP, @@ -70,22 +70,19 @@ public: PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL, PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, - PIPELINE_VERSION_OPAQUE_PASS, - PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR, - PIPELINE_VERSION_TRANSPARENT_PASS, - PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS, - PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR, - PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS, - PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW, - PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW, - PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW, - PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW, - PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW, - + PIPELINE_VERSION_COLOR_PASS, PIPELINE_VERSION_MAX }; + enum PipelineColorPassFlags { + PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, + PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, + PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2, + PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3, + PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 4, + }; + enum ShaderSpecializations { SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0, SHADER_SPECIALIZATION_PROJECTOR = 1 << 1, @@ -93,7 +90,7 @@ public: SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3, }; - struct ShaderData : public RendererStorageRD::ShaderData { + struct ShaderData : public RendererRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -137,6 +134,7 @@ public: RID version; uint32_t vertex_input_mask; PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX]; + PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT]; String path; @@ -180,7 +178,7 @@ public: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -195,13 +193,13 @@ public: SelfList<ShaderData>::List shader_list; - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { + RendererRD::ShaderData *_create_shader_func(); + static RendererRD::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererStorageRD::MaterialData { - ShaderData *shader_data; + struct MaterialData : public RendererRD::MaterialData { + ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; uint32_t index = 0; @@ -213,8 +211,8 @@ public: virtual ~MaterialData(); }; - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } @@ -240,6 +238,7 @@ public: ShaderData *overdraw_material_shader_ptr = nullptr; Vector<RD::PipelineSpecializationConstant> default_specialization_constants; + Set<uint32_t> valid_color_pass_pipelines; SceneShaderForwardClustered(); ~SceneShaderForwardClustered(); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index a09a604e49..156d535447 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -31,6 +31,7 @@ #include "render_forward_mobile.h" #include "core/config/project_settings.h" #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" @@ -290,12 +291,14 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() { } RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + //there should always be enough uniform buffers for render passes, otherwise bugs ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID()); RenderBufferDataForwardMobile *rb = nullptr; if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); + rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); } // default render buffer and scene state uniform set @@ -474,7 +477,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RenderBufferDataForwardMobile *render_buffer = nullptr; if (p_render_data->render_buffers.is_valid()) { - render_buffer = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); + render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); } RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); @@ -593,7 +596,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } */ } break; @@ -605,7 +608,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } */ } break; @@ -1300,7 +1303,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -1323,6 +1326,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit } void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -1412,7 +1417,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const // LOD - if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { //lod Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); @@ -1436,7 +1441,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } uint32_t indices; - surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1448,13 +1453,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } else { surf->lod_index = 0; if (p_render_data->render_info) { - uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface); + uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); to_draw = _indices_to_primitives(surf->primitive, to_draw); to_draw *= inst->instance_count; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); } } } @@ -1564,7 +1569,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.fog_enabled = false; if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardMobile *render_buffers = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); + RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } @@ -1812,6 +1817,8 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF template <RenderForwardMobile::PassMode p_pass_mode> void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -1954,12 +1961,12 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr //skeleton and blend shape if (surf->owner->mesh_instance.is_valid()) { - storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } else { - storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); } - index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); if (prev_vertex_array_rd != vertex_array_rd) { RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); @@ -2278,6 +2285,8 @@ void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geom } void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; bool has_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; @@ -2326,12 +2335,12 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); - RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh); + RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); if (shadow_mesh.is_valid()) { - surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface); + surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface); } } else { @@ -2344,8 +2353,8 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI sdcache->shader = p_material->shader_data; sdcache->material_uniform_set = p_material->uniform_set; - sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface); - sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface); + sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); + sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { @@ -2379,23 +2388,25 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) { SceneShaderForwardMobile::MaterialData *material = p_material; + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh); while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); } - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh); } } void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RID m_src; m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; @@ -2403,7 +2414,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward SceneShaderForwardMobile::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2411,10 +2422,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward if (material) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2425,10 +2436,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); @@ -2437,6 +2448,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward } void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); if (ginstance->data->dirty_dependencies) { @@ -2450,7 +2462,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry uint32_t surface_count; RID mesh = ginstance->data->base; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { //if no materials, no surfaces. const RID *inst_materials = ginstance->data->surface_materials.ptr(); @@ -2467,19 +2479,19 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry } break; case RS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(ginstance->data->base); + RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base); if (mesh.is_valid()) { const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t j = 0; j < surface_count; j++) { _geometry_instance_add_surface(ginstance, j, materials[j], mesh); } } - ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base); } } break; @@ -2504,7 +2516,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry const RID *materials = nullptr; uint32_t surface_count; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); if (materials) { for (uint32_t k = 0; k < surface_count; k++) { _geometry_instance_add_surface(ginstance, k, materials[k], mesh); @@ -2527,17 +2539,17 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; - if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { + if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; } - if (storage->multimesh_uses_colors(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; } - if (storage->multimesh_uses_custom_data(ginstance->data->base)) { + if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; } - ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; @@ -2557,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { - if (storage->skeleton_is_valid(ginstance->data->skeleton)) { - ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { + ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); if (ginstance->data->dirty_dependencies) { - storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); + mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); } } } @@ -2593,7 +2605,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage: case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { - ginstance->instance_count = static_cast<RenderForwardMobile *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); } } break; default: { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 6162ca55af..0ddfe89eea 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -328,7 +328,7 @@ protected: uint32_t max_lightmaps; RID lightmap_buffer; - LightmapCaptureData *lightmap_captures; + LightmapCaptureData *lightmap_captures = nullptr; uint32_t max_lightmap_captures; RID lightmap_capture_buffer; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 9452c7e6df..60badbdfee 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "render_forward_mobile.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" using namespace RendererSceneRenderImplementation; @@ -366,13 +367,13 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_ } } -void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -427,7 +428,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() { +RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -451,7 +452,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -469,6 +470,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() { void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) { storage = p_storage; + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); /* SCENE SHADER */ @@ -494,8 +496,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p } } - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -677,9 +679,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p { //default material and shader - default_shader = storage->shader_allocate(); - storage->shader_initialize(default_shader); - storage->shader_set_code(default_shader, R"( + default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(default_shader); + material_storage->shader_set_code(default_shader, R"( // Default 3D material shader (mobile). shader_type spatial; @@ -694,11 +696,11 @@ void fragment() { METALLIC = 0.2; } )"); - default_material = storage->material_allocate(); - storage->material_initialize(default_material); - storage->material_set_shader(default_material, default_shader); + default_material = material_storage->material_allocate(); + material_storage->material_initialize(default_material); + material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_material_shader_ptr = md->shader_data; @@ -706,10 +708,10 @@ void fragment() { } { - overdraw_material_shader = storage->shader_allocate(); - storage->shader_initialize(overdraw_material_shader); + overdraw_material_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(overdraw_material_shader); // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. - storage->shader_set_code(overdraw_material_shader, R"( + material_storage->shader_set_code(overdraw_material_shader, R"( // 3D editor Overdraw debug draw mode shader (mobile). shader_type spatial; @@ -721,11 +723,11 @@ void fragment() { ALPHA = 0.1; } )"); - overdraw_material = storage->material_allocate(); - storage->material_initialize(overdraw_material); - storage->material_set_shader(overdraw_material, overdraw_material_shader); + overdraw_material = material_storage->material_allocate(); + material_storage->material_initialize(overdraw_material); + material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } @@ -765,12 +767,14 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector } SceneShaderForwardMobile::~SceneShaderForwardMobile() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RD::get_singleton()->free(default_vec4_xform_buffer); RD::get_singleton()->free(shadow_sampler); - storage->free(overdraw_material_shader); - storage->free(default_shader); + material_storage->shader_free(overdraw_material_shader); + material_storage->shader_free(default_shader); - storage->free(overdraw_material); - storage->free(default_material); + material_storage->material_free(overdraw_material); + material_storage->material_free(default_material); } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 92db15e3b0..b89fe908d3 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -40,7 +40,7 @@ namespace RendererSceneRenderImplementation { class SceneShaderForwardMobile { private: static SceneShaderForwardMobile *singleton; - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; public: enum ShaderVersion { @@ -57,7 +57,7 @@ public: SHADER_VERSION_MAX }; - struct ShaderData : public RendererStorageRD::ShaderData { + struct ShaderData : public RendererRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -143,7 +143,7 @@ public: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -157,13 +157,13 @@ public: virtual ~ShaderData(); }; - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { + RendererRD::ShaderData *_create_shader_func(); + static RendererRD::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererStorageRD::MaterialData { - ShaderData *shader_data; + struct MaterialData : public RendererRD::MaterialData { + ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; uint32_t index = 0; @@ -177,8 +177,8 @@ public: SelfList<ShaderData>::List shader_list; - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp index e812a48d3d..9151c53823 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp @@ -58,7 +58,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass, specialization_constants); ERR_FAIL_COND_V(pipeline.is_null(), RID()); - versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); + versions = static_cast<Version *>(memrealloc(versions, sizeof(Version) * (version_count + 1))); versions[version_count].framebuffer_id = p_framebuffer_format_id; versions[version_count].vertex_id = p_vertex_format_id; versions[version_count].wireframe = wireframe; diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h index 8d82480b38..1e80381d88 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.h +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h @@ -57,7 +57,7 @@ class PipelineCacheRD { RID pipeline; }; - Version *versions; + Version *versions = nullptr; uint32_t version_count; RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index e56e263540..5b5a39c215 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -35,7 +35,10 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { @@ -106,6 +109,8 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve // This dramatically reduces the amount of pipeline objects // that need to be created for these formats. + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + uint32_t vertex_count = p_points.size(); uint32_t stride = 2; //vertices always repeat if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { @@ -188,7 +193,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[1] = vd; - buffers.write[1] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_COLOR); + buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR); } //uvs @@ -216,7 +221,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[2] = vd; - buffers.write[2] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_TEX_UV); + buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV); } //bones @@ -249,7 +254,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[3] = vd; - buffers.write[3] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES); + buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES); } //weights @@ -282,7 +287,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[4] = vd; - buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_WEIGHTS); + buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS); } //check that everything is as it should be @@ -359,7 +364,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI bool use_normal; bool use_specular; - bool success = canvas_texture_storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); + bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); //something odd happened if (!success) { _bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size); @@ -396,6 +401,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { //create an empty push constant + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RS::CanvasItemTextureFilter current_filter = default_filter; RS::CanvasItemTextureRepeat current_repeat = default_repeat; @@ -750,26 +756,26 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } else if (c->type == Item::Command::TYPE_MULTIMESH) { const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c); RID multimesh = mm->multimesh; - mesh = storage->multimesh_get_mesh(multimesh); + mesh = mesh_storage->multimesh_get_mesh(multimesh); texture = mm->texture; - if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { + if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { break; } - instance_count = storage->multimesh_get_instances_to_draw(multimesh); + instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh); if (instance_count == 0) { break; } - RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + RID uniform_set = mesh_storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); push_constant.flags |= 1; //multimesh, trails disabled - if (storage->multimesh_uses_colors(multimesh)) { + if (mesh_storage->multimesh_uses_colors(multimesh)) { push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; } - if (storage->multimesh_uses_custom_data(multimesh)) { + if (mesh_storage->multimesh_uses_custom_data(multimesh)) { push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; } } else if (c->type == Item::Command::TYPE_PARTICLES) { @@ -834,7 +840,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend _bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); - uint32_t surf_count = storage->mesh_get_surface_count(mesh); + uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh); static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; push_constant.modulation[0] = base_color.r * modulate.r; @@ -849,9 +855,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } for (uint32_t j = 0; j < surf_count; j++) { - void *surface = storage->mesh_get_surface(mesh, j); + void *surface = mesh_storage->mesh_get_surface(mesh, j); - RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface); + RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface); ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX); uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask(); @@ -860,15 +866,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID; if (mesh_instance.is_valid()) { - storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format); } else { - storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format); } RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - RID index_array = storage->mesh_surface_get_index_array(surface, 0); + RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0); if (index_array.is_valid()) { RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array); @@ -978,7 +984,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } else { screen = storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } u.append_id(screen); @@ -1021,7 +1027,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 9; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -1036,6 +1042,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); Item *current_clip = nullptr; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; @@ -1100,9 +1107,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co } if (material != prev_material) { - MaterialData *material_data = nullptr; + CanvasMaterialData *material_data = nullptr; if (material.is_valid()) { - material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D); + material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); } if (material_data) { @@ -1129,6 +1136,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co } void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + r_sdf_used = false; int item_count = 0; @@ -1364,7 +1374,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; if (material.is_valid()) { - MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D); + CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); if (md && md->shader_data->valid) { if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { @@ -1389,7 +1399,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c); if (cm->mesh_instance.is_valid()) { - storage->mesh_instance_check_for_update(cm->mesh_instance); + mesh_storage->mesh_instance_check_for_update(cm->mesh_instance); update_skeletons = true; } } @@ -1401,7 +1411,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (canvas_group_owner == nullptr) { //Canvas group begins here, render until before this item if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); @@ -1424,7 +1434,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (ci == canvas_group_owner) { if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } @@ -1441,7 +1451,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (backbuffer_copy) { //render anything pending, including clearing if no items if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); @@ -1457,7 +1467,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { if (update_skeletons) { - storage->update_mesh_instances(); + mesh_storage->update_mesh_instances(); update_skeletons = false; } @@ -1938,7 +1948,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS:: oc->cull_mode = p_mode; } -void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { +void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -1976,7 +1986,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); @@ -2120,7 +2130,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { valid = true; } -void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -2137,7 +2147,7 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN } } -void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -2158,13 +2168,13 @@ void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_pa } } -void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -2173,7 +2183,7 @@ void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererSt } } -bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const { +bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -2181,15 +2191,15 @@ bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_pa return uniforms[p_param].texture_order >= 0; } -bool RendererCanvasRenderRD::ShaderData::is_animated() const { +bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const { return false; } -bool RendererCanvasRenderRD::ShaderData::casts_shadows() const { +bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const { return false; } -Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererCanvasRenderRD::CanvasShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -2198,19 +2208,19 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa return Variant(); } -RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const { - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const { + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version); } -RendererCanvasRenderRD::ShaderData::ShaderData() { +RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() { valid = false; uses_screen_texture = false; uses_sdf = false; } -RendererCanvasRenderRD::ShaderData::~ShaderData() { - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() { + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); ERR_FAIL_COND(!canvas_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -2218,23 +2228,23 @@ RendererCanvasRenderRD::ShaderData::~ShaderData() { } } -RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { - ShaderData *shader_data = memnew(ShaderData); +RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { + CanvasShaderData *shader_data = memnew(CanvasShaderData); return shader_data; } -bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } -RendererCanvasRenderRD::MaterialData::~MaterialData() { +RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) { - MaterialData *material_data = memnew(MaterialData); +RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) { + CanvasMaterialData *material_data = memnew(CanvasMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; @@ -2248,8 +2258,8 @@ void RendererCanvasRenderRD::update() { } RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { - canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton(); - texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); storage = p_storage; { //create default samplers @@ -2573,7 +2583,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; - u.append_id(storage->get_default_rd_storage_buffer()); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); uniforms.push_back(u); } @@ -2586,16 +2596,16 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); //create functions for shader and material - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs); state.time = 0; { - default_canvas_group_shader = storage->shader_allocate(); - storage->shader_initialize(default_canvas_group_shader); + default_canvas_group_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(default_canvas_group_shader); - storage->shader_set_code(default_canvas_group_shader, R"( + material_storage->shader_set_code(default_canvas_group_shader, R"( // Default CanvasGroup shader. shader_type canvas_item; @@ -2610,10 +2620,10 @@ void fragment() { COLOR *= c; } )"); - default_canvas_group_material = storage->material_allocate(); - storage->material_initialize(default_canvas_group_material); + default_canvas_group_material = material_storage->material_allocate(); + material_storage->material_initialize(default_canvas_group_material); - storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); + material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); } static_assert(sizeof(PushConstant) == 128); @@ -2661,10 +2671,11 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) { } RendererCanvasRenderRD::~RendererCanvasRenderRD() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); //canvas state - storage->free(default_canvas_group_material); - storage->free(default_canvas_group_shader); + material_storage->material_free(default_canvas_group_material); + material_storage->shader_free(default_canvas_group_shader); { if (state.canvas_state_buffer.is_valid()) { @@ -2701,6 +2712,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { } RD::get_singleton()->free(state.shadow_texture); - canvas_texture_storage->canvas_texture_free(default_canvas_texture); + RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture); //pipelines don't need freeing, they are all gone after shaders are gone } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index c0138c4fe0..6448e1a664 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -37,15 +37,11 @@ #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h" -#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" -#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" class RendererCanvasRenderRD : public RendererCanvasRender { - RendererRD::CanvasTextureStorage *canvas_texture_storage; - RendererRD::TextureStorage *texture_storage; - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; enum { BASE_UNIFORM_SET = 0, @@ -155,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { ShaderCompiler compiler; } shader; - struct ShaderData : public RendererStorageRD::ShaderData { + struct CanvasShaderData : public RendererRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -186,7 +182,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -194,28 +190,28 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; - ShaderData(); - virtual ~ShaderData(); + CanvasShaderData(); + virtual ~CanvasShaderData(); }; - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { + RendererRD::ShaderData *_create_shader_func(); + static RendererRD::ShaderData *_create_shader_funcs() { return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererStorageRD::MaterialData { - ShaderData *shader_data; + struct CanvasMaterialData : public RendererRD::MaterialData { + CanvasShaderData *shader_data = nullptr; RID uniform_set; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~MaterialData(); + virtual ~CanvasMaterialData(); }; - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { - return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); + RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader); + static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader)); } /**************************/ @@ -365,7 +361,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t pad2; }; - LightUniform *light_uniforms; + LightUniform *light_uniforms = nullptr; RID lights_uniform_buffer; RID canvas_state_buffer; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 6d6cf0ce73..5b7c63b508 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -156,6 +156,8 @@ void RendererCompositorRD::finalize() { memdelete(canvas); memdelete(storage); memdelete(decal_atlas_storage); + memdelete(mesh_storage); + memdelete(material_storage); memdelete(texture_storage); memdelete(canvas_texture_storage); @@ -289,6 +291,8 @@ RendererCompositorRD::RendererCompositorRD() { canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage); texture_storage = memnew(RendererRD::TextureStorage); decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage); + material_storage = memnew(RendererRD::MaterialStorage); + mesh_storage = memnew(RendererRD::MeshStorage); storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index a860093bb1..542cff0159 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -41,18 +41,22 @@ #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" class RendererCompositorRD : public RendererCompositor { protected: - UniformSetCacheRD *uniform_set_cache; - RendererCanvasRenderRD *canvas; + UniformSetCacheRD *uniform_set_cache = nullptr; + RendererCanvasRenderRD *canvas = nullptr; RendererRD::CanvasTextureStorage *canvas_texture_storage; + RendererRD::MaterialStorage *material_storage; + RendererRD::MeshStorage *mesh_storage; RendererRD::TextureStorage *texture_storage; RendererRD::DecalAtlasStorage *decal_atlas_storage; - RendererStorageRD *storage; - RendererSceneRenderRD *scene; + RendererStorageRD *storage = nullptr; + RendererSceneRenderRD *scene = nullptr; enum BlitMode { BLIT_MODE_NORMAL, @@ -95,8 +99,10 @@ protected: public: RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; } - RendererTextureStorage *get_texture_storage() { return texture_storage; } RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; } + RendererMaterialStorage *get_material_storage() { return material_storage; }; + RendererMeshStorage *get_mesh_storage() { return mesh_storage; }; + RendererTextureStorage *get_texture_storage() { return texture_storage; }; RendererStorage *get_storage() { return storage; } RendererCanvasRender *get_canvas() { return canvas; } RendererSceneRender *get_scene() { return scene; } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index d51b1bf691..ed60bc4362 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -55,7 +55,7 @@ class RendererSceneRenderRD; class RendererSceneGIRD { private: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; /* VOXEL_GI INSTANCE */ @@ -331,8 +331,8 @@ public: struct VoxelGIInstance { // access to our containers - RendererStorageRD *storage; - RendererSceneGIRD *gi; + RendererStorageRD *storage = nullptr; + RendererSceneGIRD *gi = nullptr; RID probe; RID texture; @@ -455,8 +455,8 @@ public: }; // access to our containers - RendererStorageRD *storage; - RendererSceneGIRD *gi; + RendererStorageRD *storage = nullptr; + RendererSceneGIRD *gi = nullptr; // used for rendering (voxelization) RID render_albedo; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 4a6dbc137c..ac7ac692ce 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -34,6 +34,8 @@ #include "core/os/os.h" #include "renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" void get_vogel_disk(float *r_kernel, int p_sample_count) { @@ -2359,6 +2361,7 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR } void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); @@ -2571,6 +2574,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RD::get_singleton()->draw_command_begin_label("Post Process Subpass"); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); @@ -2647,6 +2651,7 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_ } void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); EffectsRD *effects = storage->get_effects(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); @@ -3860,7 +3865,7 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed."); @@ -3920,13 +3925,13 @@ void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_ } } -void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E->get()); p.info.name = E->key(); //supply name p.index = E->get().instance_index; @@ -3961,7 +3966,7 @@ Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const String } RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version); } @@ -3971,7 +3976,7 @@ RendererSceneRenderRD::FogShaderData::FogShaderData() { } RendererSceneRenderRD::FogShaderData::~FogShaderData() { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -3983,7 +3988,7 @@ RendererSceneRenderRD::FogShaderData::~FogShaderData() { // Fog material bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -3994,23 +3999,23 @@ RendererSceneRenderRD::FogMaterialData::~FogMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() { +RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() { FogShaderData *shader_data = memnew(FogShaderData); return shader_data; } -RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() { +RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() { return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func(); }; -RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); }; @@ -4068,6 +4073,9 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto } void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -4268,7 +4276,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e FogMaterialData *material = nullptr; if (fog_material.is_valid()) { - material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -4276,7 +4284,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (!material) { fog_material = volumetric_fog.default_material; - material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); } ERR_FAIL_COND(!material); @@ -5493,7 +5501,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto GeometryInstance *gi = geometry_instance_create(p_base); - uint32_t sc = RSG::storage->mesh_get_surface_count(p_base); + uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base); Vector<RID> materials; materials.resize(sc); @@ -5605,12 +5613,13 @@ uint32_t RendererSceneRenderRD::get_max_elements() const { } RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { - texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; singleton = this; } void RendererSceneRenderRD::init() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + max_cluster_elements = get_max_elements(); directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size"); @@ -5667,8 +5676,8 @@ void RendererSceneRenderRD::init() { volumetric_fog_modes.push_back(""); volumetric_fog.shader.initialize(volumetric_fog_modes); - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); } @@ -5707,9 +5716,9 @@ void RendererSceneRenderRD::init() { { // default material and shader for fog shader - volumetric_fog.default_shader = storage->shader_allocate(); - storage->shader_initialize(volumetric_fog.default_shader); - storage->shader_set_code(volumetric_fog.default_shader, R"( + volumetric_fog.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(volumetric_fog.default_shader); + material_storage->shader_set_code(volumetric_fog.default_shader, R"( // Default fog shader. shader_type fog; @@ -5719,11 +5728,11 @@ void fog() { ALBEDO = vec3(1.0); } )"); - volumetric_fog.default_material = storage->material_allocate(); - storage->material_initialize(volumetric_fog.default_material); - storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); + volumetric_fog.default_material = material_storage->material_allocate(); + material_storage->material_initialize(volumetric_fog.default_material); + material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); - FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG); + FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -5753,7 +5762,7 @@ void fog() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -5822,6 +5831,8 @@ void fog() { } RendererSceneRenderRD::~RendererSceneRenderRD() { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { RD::get_singleton()->free(E.value.cubemap); } @@ -5838,20 +5849,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); RD::get_singleton()->free(volumetric_fog.volume_ubo); RD::get_singleton()->free(volumetric_fog.params_ubo); - storage->free(volumetric_fog.default_shader); - storage->free(volumetric_fog.default_material); - } - - RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY); - sky.sky_shader.shader.version_free(md->shader_data->version); - RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer); - RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer); - memdelete_arr(sky.sky_scene_state.directional_lights); - memdelete_arr(sky.sky_scene_state.last_frame_directional_lights); - storage->free(sky.sky_shader.default_shader); - storage->free(sky.sky_shader.default_material); - storage->free(sky.sky_scene_state.fog_shader); - storage->free(sky.sky_scene_state.fog_material); + material_storage->shader_free(volumetric_fog.default_shader); + material_storage->material_free(volumetric_fog.default_material); + } + memdelete_arr(directional_penumbra_shadow_kernel); memdelete_arr(directional_soft_shadow_kernel); memdelete_arr(penumbra_shadow_kernel); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index e302db2631..b2c8daffb1 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -41,7 +41,6 @@ #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h" -#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -93,8 +92,7 @@ class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneGIRD; protected: - RendererRD::TextureStorage *texture_storage; - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; double time; double time_step = 0; @@ -316,10 +314,10 @@ private: float shadows_quality_radius = 1.0; float directional_shadow_quality_radius = 1.0; - float *directional_penumbra_shadow_kernel; - float *directional_soft_shadow_kernel; - float *penumbra_shadow_kernel; - float *soft_shadow_kernel; + float *directional_penumbra_shadow_kernel = nullptr; + float *directional_soft_shadow_kernel = nullptr; + float *penumbra_shadow_kernel = nullptr; + float *soft_shadow_kernel = nullptr; int directional_penumbra_shadow_samples = 0; int directional_soft_shadow_samples = 0; int penumbra_shadow_samples = 0; @@ -707,27 +705,27 @@ private: template <class T> struct InstanceSort { float depth; - T *instance; + T *instance = nullptr; bool operator<(const InstanceSort &p_sort) const { return depth < p_sort.depth; } }; - ReflectionData *reflections; + ReflectionData *reflections = nullptr; InstanceSort<ReflectionProbeInstance> *reflection_sort; uint32_t max_reflections; RID reflection_buffer; uint32_t max_reflection_probes_per_instance; uint32_t reflection_count = 0; - DecalData *decals; + DecalData *decals = nullptr; InstanceSort<DecalInstance> *decal_sort; uint32_t max_decals; RID decal_buffer; uint32_t decal_count; - LightData *omni_lights; - LightData *spot_lights; + LightData *omni_lights = nullptr; + LightData *spot_lights = nullptr; InstanceSort<LightInstance> *omni_light_sort; InstanceSort<LightInstance> *spot_light_sort; @@ -737,7 +735,7 @@ private: uint32_t omni_light_count = 0; uint32_t spot_light_count = 0; - DirectionalLightData *directional_lights; + DirectionalLightData *directional_lights = nullptr; uint32_t max_directional_lights; RID directional_light_buffer; @@ -909,7 +907,7 @@ private: void _volumetric_fog_erase(RenderBuffers *rb); void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); - struct FogShaderData : public RendererStorageRD::ShaderData { + struct FogShaderData : public RendererRD::ShaderData { bool valid; RID version; @@ -929,7 +927,7 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; @@ -939,8 +937,8 @@ private: virtual ~FogShaderData(); }; - struct FogMaterialData : public RendererStorageRD::MaterialData { - FogShaderData *shader_data; + struct FogMaterialData : public RendererRD::MaterialData { + FogShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -950,11 +948,11 @@ private: virtual ~FogMaterialData(); }; - RendererStorageRD::ShaderData *_create_fog_shader_func(); - static RendererStorageRD::ShaderData *_create_fog_shader_funcs(); + RendererRD::ShaderData *_create_fog_shader_func(); + static RendererRD::ShaderData *_create_fog_shader_funcs(); - RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader); + RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); + static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); RID shadow_sampler; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 44da9e40f8..061aa8b4aa 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" @@ -90,7 +91,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; // !BAS! Contemplate making `SkyShader sky` accessible from this struct or even part of this struct. - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); Error err = scene_singleton->sky.sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); @@ -177,13 +178,13 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par } } -void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -218,7 +219,7 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam } RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version); } @@ -228,7 +229,7 @@ RendererSceneSkyRD::SkyShaderData::SkyShaderData() { } RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -240,7 +241,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { // Sky material bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -767,24 +768,24 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, //////////////////////////////////////////////////////////////////////////////// // RendererSceneSkyRD -RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() { +RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { +RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); }; -RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) { +RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; @@ -797,6 +798,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() { void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); storage = p_storage; { @@ -833,8 +835,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { } // register our shader funds - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -896,10 +898,10 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { { // default material and shader for sky shader - sky_shader.default_shader = storage->shader_allocate(); - storage->shader_initialize(sky_shader.default_shader); + sky_shader.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(sky_shader.default_shader); - storage->shader_set_code(sky_shader.default_shader, R"( + material_storage->shader_set_code(sky_shader.default_shader, R"( // Default sky shader. shader_type sky; @@ -909,12 +911,12 @@ void sky() { } )"); - sky_shader.default_material = storage->material_allocate(); - storage->material_initialize(sky_shader.default_material); + sky_shader.default_material = material_storage->material_allocate(); + material_storage->material_initialize(sky_shader.default_material); - storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); + material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO)); @@ -947,7 +949,7 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.append_id(storage->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -986,10 +988,10 @@ void sky() { { // Need defaults for using fog with clear color - sky_scene_state.fog_shader = storage->shader_allocate(); - storage->shader_initialize(sky_scene_state.fog_shader); + sky_scene_state.fog_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(sky_scene_state.fog_shader); - storage->shader_set_code(sky_scene_state.fog_shader, R"( + material_storage->shader_set_code(sky_scene_state.fog_shader, R"( // Default clear color sky shader. shader_type sky; @@ -1000,10 +1002,10 @@ void sky() { COLOR = clear_color.rgb; } )"); - sky_scene_state.fog_material = storage->material_allocate(); - storage->material_initialize(sky_scene_state.fog_material); + sky_scene_state.fog_material = material_storage->material_allocate(); + material_storage->material_initialize(sky_scene_state.fog_material); - storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader); + material_storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader); Vector<RD::Uniform> uniforms; { @@ -1054,7 +1056,19 @@ void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) { } RendererSceneSkyRD::~RendererSceneSkyRD() { - // TODO cleanup anything created in init... + // cleanup anything created in init... + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + sky_shader.shader.version_free(md->shader_data->version); + RD::get_singleton()->free(sky_scene_state.directional_light_buffer); + RD::get_singleton()->free(sky_scene_state.uniform_buffer); + memdelete_arr(sky_scene_state.directional_lights); + memdelete_arr(sky_scene_state.last_frame_directional_lights); + material_storage->shader_free(sky_shader.default_shader); + material_storage->material_free(sky_shader.default_material); + material_storage->shader_free(sky_scene_state.fog_shader); + material_storage->material_free(sky_scene_state.fog_material); if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) { RD::get_singleton()->free(sky_scene_state.uniform_set); @@ -1072,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() { } void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); SkyMaterialData *material = nullptr; @@ -1085,7 +1100,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1093,7 +1108,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1282,6 +1297,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b } void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); Sky *sky = get_sky(p_env->sky); @@ -1292,7 +1308,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM SkyMaterialData *material = nullptr; if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1300,7 +1316,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1450,6 +1466,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM } void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1467,7 +1484,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1475,13 +1492,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1556,6 +1573,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont } void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1570,7 +1588,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1578,7 +1596,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1640,6 +1658,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u } void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1657,7 +1676,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme sky_material = sky_get_material(p_env->sky); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1665,13 +1684,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 13d24e2508..010e2178a9 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -63,7 +63,7 @@ public: }; private: - RendererStorageRD *storage; + RendererStorageRD *storage = nullptr; RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; RID index_buffer; @@ -105,7 +105,7 @@ private: // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; - struct SkyShaderData : public RendererStorageRD::ShaderData { + struct SkyShaderData : public RendererRD::ShaderData { bool valid; RID version; @@ -129,7 +129,7 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; @@ -162,8 +162,8 @@ public: UBO ubo; - SkyDirectionalLightData *directional_lights; - SkyDirectionalLightData *last_frame_directional_lights; + SkyDirectionalLightData *directional_lights = nullptr; + SkyDirectionalLightData *last_frame_directional_lights = nullptr; uint32_t max_directional_lights; uint32_t last_frame_directional_light_count; RID directional_light_buffer; @@ -227,8 +227,8 @@ public: RID default_shader_rd; } sky_shader; - struct SkyMaterialData : public RendererStorageRD::MaterialData { - SkyShaderData *shader_data; + struct SkyMaterialData : public RendererRD::MaterialData { + SkyShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -262,7 +262,7 @@ public: Sky *dirty_list = nullptr; //State to track when radiance cubemap needs updating - SkyMaterialData *prev_material; + SkyMaterialData *prev_material = nullptr; Vector3 prev_position; float prev_time; @@ -281,11 +281,11 @@ public: mutable RID_Owner<Sky, true> sky_owner; int roughness_layers; - RendererStorageRD::ShaderData *_create_sky_shader_func(); - static RendererStorageRD::ShaderData *_create_sky_shader_funcs(); + RendererRD::ShaderData *_create_sky_shader_func(); + static RendererRD::ShaderData *_create_sky_shader_funcs(); - RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader); + RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); RendererSceneSkyRD(); void init(RendererStorageRD *p_storage); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 5b6dfbe19f..72f98a4690 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -37,6 +37,7 @@ #include "renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_language.h" @@ -137,3105 +138,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { } } -/* SHADER API */ - -RID RendererStorageRD::shader_allocate() { - return shader_owner.allocate_rid(); -} -void RendererStorageRD::shader_initialize(RID p_rid) { - Shader shader; - shader.data = nullptr; - shader.type = SHADER_TYPE_MAX; - - shader_owner.initialize_rid(p_rid, shader); -} - -void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - - shader->code = p_code; - String mode_string = ShaderLanguage::get_shader_type(p_code); - - ShaderType new_type; - if (mode_string == "canvas_item") { - new_type = SHADER_TYPE_2D; - } else if (mode_string == "particles") { - new_type = SHADER_TYPE_PARTICLES; - } else if (mode_string == "spatial") { - new_type = SHADER_TYPE_3D; - } else if (mode_string == "sky") { - new_type = SHADER_TYPE_SKY; - } else if (mode_string == "fog") { - new_type = SHADER_TYPE_FOG; - } else { - new_type = SHADER_TYPE_MAX; - } - - if (new_type != shader->type) { - if (shader->data) { - memdelete(shader->data); - shader->data = nullptr; - } - - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - material->shader_type = new_type; - if (material->data) { - memdelete(material->data); - material->data = nullptr; - } - } - - shader->type = new_type; - - if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) { - shader->data = shader_data_request_func[new_type](); - } else { - shader->type = SHADER_TYPE_MAX; //invalid - } - - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - if (shader->data) { - material->data = material_data_request_func[new_type](shader->data); - material->data->self = material->self; - material->data->set_next_pass(material->next_pass); - material->data->set_render_priority(material->priority); - } - material->shader_type = new_type; - } - - if (shader->data) { - for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { - for (const KeyValue<int, RID> &E2 : E.value) { - shader->data->set_default_texture_param(E.key, E2.value, E2.key); - } - } - } - } - - if (shader->data) { - shader->data->set_code(p_code); - } - - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - _material_queue_update(material, true, true); - } -} - -String RendererStorageRD::shader_get_code(RID p_shader) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, String()); - return shader->code; -} - -void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - if (shader->data) { - return shader->data->get_param_list(p_param_list); - } -} - -void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - - if (p_texture.is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)) { - if (!shader->default_texture_parameter.has(p_name)) { - shader->default_texture_parameter[p_name] = Map<int, RID>(); - } - shader->default_texture_parameter[p_name][p_index] = p_texture; - } else { - if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { - shader->default_texture_parameter[p_name].erase(p_index); - - if (shader->default_texture_parameter[p_name].is_empty()) { - shader->default_texture_parameter.erase(p_name); - } - } - } - if (shader->data) { - shader->data->set_default_texture_param(p_name, p_texture, p_index); - } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - _material_queue_update(material, false, true); - } -} - -RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, RID()); - if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { - return shader->default_texture_parameter[p_name][p_index]; - } - - return RID(); -} - -Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, Variant()); - if (shader->data) { - return shader->data->get_default_parameter(p_param); - } - return Variant(); -} - -void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { - ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); - shader_data_request_func[p_shader_type] = p_function; -} - -RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const { - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); - if (shader->data) { - return shader->data->get_native_source_code(); - } - return RS::ShaderNativeSourceCode(); -} - -/* COMMON MATERIAL API */ - -RID RendererStorageRD::material_allocate() { - return material_owner.allocate_rid(); -} -void RendererStorageRD::material_initialize(RID p_rid) { - material_owner.initialize_rid(p_rid); - Material *material = material_owner.get_or_null(p_rid); - material->self = p_rid; -} - -void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { - material->uniform_dirty = material->uniform_dirty || p_uniform; - material->texture_dirty = material->texture_dirty || p_texture; - - if (material->update_element.in_list()) { - return; - } - - material_update_list.add(&material->update_element); -} - -void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - - if (material->data) { - memdelete(material->data); - material->data = nullptr; - } - - if (material->shader) { - material->shader->owners.erase(material); - material->shader = nullptr; - material->shader_type = SHADER_TYPE_MAX; - } - - if (p_shader.is_null()) { - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - material->shader_id = 0; - return; - } - - Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); - material->shader = shader; - material->shader_type = shader->type; - material->shader_id = p_shader.get_local_index(); - shader->owners.insert(material); - - if (shader->type == SHADER_TYPE_MAX) { - return; - } - - ERR_FAIL_COND(shader->data == nullptr); - - material->data = material_data_request_func[shader->type](shader->data); - material->data->self = p_material; - material->data->set_next_pass(material->next_pass); - material->data->set_render_priority(material->priority); - //updating happens later - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - _material_queue_update(material, true, true); -} - -void RendererStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type() == Variant::NIL) { - material->params.erase(p_param); - } else { - ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed - material->params[p_param] = p_value; - } - - if (material->shader && material->shader->data) { //shader is valid - bool is_texture = material->shader->data->is_param_texture(p_param); - _material_queue_update(material, !is_texture, is_texture); - } else { - _material_queue_update(material, true, true); - } -} - -Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, Variant()); - if (material->params.has(p_param)) { - return material->params[p_param]; - } else { - return Variant(); - } -} - -void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - - if (material->next_pass == p_next_material) { - return; - } - - material->next_pass = p_next_material; - if (material->data) { - material->data->set_next_pass(p_next_material); - } - - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); -} - -void RendererStorageRD::material_set_render_priority(RID p_material, int priority) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - material->priority = priority; - if (material->data) { - material->data->set_render_priority(priority); - } -} - -bool RendererStorageRD::material_is_animated(RID p_material) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, false); - if (material->shader && material->shader->data) { - if (material->shader->data->is_animated()) { - return true; - } else if (material->next_pass.is_valid()) { - return material_is_animated(material->next_pass); - } - } - return false; //by default nothing is animated -} - -bool RendererStorageRD::material_casts_shadows(RID p_material) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, true); - if (material->shader && material->shader->data) { - if (material->shader->data->casts_shadows()) { - return true; - } else if (material->next_pass.is_valid()) { - return material_casts_shadows(material->next_pass); - } - } - return true; //by default everything casts shadows -} - -void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - if (material->shader && material->shader->data) { - material->shader->data->get_instance_param_list(r_parameters); - - if (material->next_pass.is_valid()) { - material_get_instance_shader_parameters(material->next_pass, r_parameters); - } - } -} - -void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) { - Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); - p_instance->update_dependency(&material->dependency); - if (material->next_pass.is_valid()) { - material_update_dependency(material->next_pass, p_instance); - } -} - -void RendererStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { - ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); - material_data_request_func[p_shader_type] = p_function; -} - -_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) { - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = (r[i] != 0) ? 1 : 0; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - bool v = value; - gui[0] = v ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_BVEC2: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - int count = 2 * p_array_size; - - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i] ? 1 : 0; - gui[j + 1] = r[i + 1] ? 1 : 0; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = v & 1 ? 1 : 0; - gui[1] = v & 2 ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_BVEC3: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - int count = 3 * p_array_size; - - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i] ? 1 : 0; - gui[j + 1] = r[i + 1] ? 1 : 0; - gui[j + 2] = r[i + 2] ? 1 : 0; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = (v & 1) ? 1 : 0; - gui[1] = (v & 2) ? 1 : 0; - gui[2] = (v & 4) ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_BVEC4: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - const PackedInt32Array &ba = value; - int s = ba.size(); - const int *r = ba.ptr(); - int count = 4 * p_array_size; - - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i] ? 1 : 0; - gui[i + 1] = r[i + 1] ? 1 : 0; - gui[i + 2] = r[i + 2] ? 1 : 0; - gui[i + 3] = r[i + 3] ? 1 : 0; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } else { - int v = value; - gui[0] = (v & 1) ? 1 : 0; - gui[1] = (v & 2) ? 1 : 0; - gui[2] = (v & 4) ? 1 : 0; - gui[3] = (v & 8) ? 1 : 0; - } - } break; - case ShaderLanguage::TYPE_INT: { - int32_t *gui = (int32_t *)data; - - if (p_array_size > 0) { - Vector<int> iv = value; - int s = iv.size(); - const int *r = iv.ptr(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = r[i]; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = v; - } - } break; - case ShaderLanguage::TYPE_IVEC2: { - Vector<int> iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_IVEC3: { - Vector<int> iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_IVEC4: { - Vector<int> iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } break; - case ShaderLanguage::TYPE_UINT: { - uint32_t *gui = (uint32_t *)data; - - if (p_array_size > 0) { - Vector<int> iv = value; - int s = iv.size(); - const int *r = iv.ptr(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = r[i]; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - int v = value; - gui[0] = v; - } - } break; - case ShaderLanguage::TYPE_UVEC2: { - Vector<int> iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - Vector<int> iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_UVEC4: { - Vector<int> iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i++) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = a[i]; - } else { - gui[j] = 0; - } - gui[j + 1] = 0; // ignored - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - float v = value; - gui[0] = v; - } - } break; - case ShaderLanguage::TYPE_VEC2: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedVector2Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = a[i].x; - gui[j + 1] = a[i].y; - } else { - gui[j] = 0; - gui[j + 1] = 0; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - } - } else { - Vector2 v = value; - gui[0] = v.x; - gui[1] = v.y; - } - } break; - case ShaderLanguage::TYPE_VEC3: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedVector3Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - gui[j] = a[i].x; - gui[j + 1] = a[i].y; - gui[j + 2] = a[i].z; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - } - gui[j + 3] = 0; // ignored - } - } else { - Vector3 v = value; - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - } - } break; - case ShaderLanguage::TYPE_VEC4: { - float *gui = (float *)data; - - if (p_array_size > 0) { - if (value.get_type() == Variant::PACKED_COLOR_ARRAY) { - const PackedColorArray &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { - if (i < s) { - Color color = a[i]; - if (p_linear_color) { - color = color.to_linear(); - } - gui[j] = color.r; - gui[j + 1] = color.g; - gui[j + 2] = color.b; - gui[j + 3] = color.a; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; - gui[j + 3] = 0; - } - } - } else { - const PackedFloat32Array &a = value; - int s = a.size(); - int count = 4 * p_array_size; - - for (int i = 0; i < count; i += 4) { - if (i + 3 < s) { - gui[i] = a[i]; - gui[i + 1] = a[i + 1]; - gui[i + 2] = a[i + 2]; - gui[i + 3] = a[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - } - } - } - } else { - if (value.get_type() == Variant::COLOR) { - Color v = value; - - if (p_linear_color) { - v = v.to_linear(); - } - - gui[0] = v.r; - gui[1] = v.g; - gui[2] = v.b; - gui[3] = v.a; - } else if (value.get_type() == Variant::RECT2) { - Rect2 v = value; - - gui[0] = v.position.x; - gui[1] = v.position.y; - gui[2] = v.size.x; - gui[3] = v.size.y; - } else if (value.get_type() == Variant::QUATERNION) { - Quaternion v = value; - - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - gui[3] = v.w; - } else { - Plane v = value; - - gui[0] = v.normal.x; - gui[1] = v.normal.y; - gui[2] = v.normal.z; - gui[3] = v.d; - } - } - } break; - case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) { - if (i + 3 < s) { - gui[j] = a[i]; - gui[j + 1] = a[i + 1]; - - gui[j + 4] = a[i + 2]; - gui[j + 5] = a[i + 3]; - } else { - gui[j] = 1; - gui[j + 1] = 0; - - gui[j + 4] = 0; - gui[j + 5] = 1; - } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored - gui[j + 6] = 0; // ignored - gui[j + 7] = 0; // ignored - } - } else { - Transform2D v = value; - - //in std140 members of mat2 are treated as vec4s - gui[0] = v.elements[0][0]; - gui[1] = v.elements[0][1]; - gui[2] = 0; // ignored - gui[3] = 0; // ignored - - gui[4] = v.elements[1][0]; - gui[5] = v.elements[1][1]; - gui[6] = 0; // ignored - gui[7] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_MAT3: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) { - if (i + 8 < s) { - gui[j] = a[i]; - gui[j + 1] = a[i + 1]; - gui[j + 2] = a[i + 2]; - - gui[j + 4] = a[i + 3]; - gui[j + 5] = a[i + 4]; - gui[j + 6] = a[i + 5]; - - gui[j + 8] = a[i + 6]; - gui[j + 9] = a[i + 7]; - gui[j + 10] = a[i + 8]; - } else { - gui[j] = 1; - gui[j + 1] = 0; - gui[j + 2] = 0; - - gui[j + 4] = 0; - gui[j + 5] = 1; - gui[j + 6] = 0; - - gui[j + 8] = 0; - gui[j + 9] = 0; - gui[j + 10] = 1; - } - gui[j + 3] = 0; // ignored - gui[j + 7] = 0; // ignored - gui[j + 11] = 0; // ignored - } - } else { - Basis v = value; - gui[0] = v.elements[0][0]; - gui[1] = v.elements[1][0]; - gui[2] = v.elements[2][0]; - gui[3] = 0; // ignored - - gui[4] = v.elements[0][1]; - gui[5] = v.elements[1][1]; - gui[6] = v.elements[2][1]; - gui[7] = 0; // ignored - - gui[8] = v.elements[0][2]; - gui[9] = v.elements[1][2]; - gui[10] = v.elements[2][2]; - gui[11] = 0; // ignored - } - } break; - case ShaderLanguage::TYPE_MAT4: { - float *gui = (float *)data; - - if (p_array_size > 0) { - const PackedFloat32Array &a = value; - int s = a.size(); - - for (int i = 0; i < p_array_size * 16; i += 16) { - if (i + 15 < s) { - gui[i] = a[i]; - gui[i + 1] = a[i + 1]; - gui[i + 2] = a[i + 2]; - gui[i + 3] = a[i + 3]; - - gui[i + 4] = a[i + 4]; - gui[i + 5] = a[i + 5]; - gui[i + 6] = a[i + 6]; - gui[i + 7] = a[i + 7]; - - gui[i + 8] = a[i + 8]; - gui[i + 9] = a[i + 9]; - gui[i + 10] = a[i + 10]; - gui[i + 11] = a[i + 11]; - - gui[i + 12] = a[i + 12]; - gui[i + 13] = a[i + 13]; - gui[i + 14] = a[i + 14]; - gui[i + 15] = a[i + 15]; - } else { - gui[i] = 1; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; - - gui[i + 4] = 0; - gui[i + 5] = 1; - gui[i + 6] = 0; - gui[i + 7] = 0; - - gui[i + 8] = 0; - gui[i + 9] = 0; - gui[i + 10] = 1; - gui[i + 11] = 0; - - gui[i + 12] = 0; - gui[i + 13] = 0; - gui[i + 14] = 0; - gui[i + 15] = 1; - } - } - } else { - Transform3D v = value; - gui[0] = v.basis.elements[0][0]; - gui[1] = v.basis.elements[1][0]; - gui[2] = v.basis.elements[2][0]; - gui[3] = 0; - - gui[4] = v.basis.elements[0][1]; - gui[5] = v.basis.elements[1][1]; - gui[6] = v.basis.elements[2][1]; - gui[7] = 0; - - gui[8] = v.basis.elements[0][2]; - gui[9] = v.basis.elements[1][2]; - gui[10] = v.basis.elements[2][2]; - gui[11] = 0; - - gui[12] = v.origin.x; - gui[13] = v.origin.y; - gui[14] = v.origin.z; - gui[15] = 1; - } - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) { - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - uint32_t *gui = (uint32_t *)data; - *gui = value[0].boolean ? 1 : 0; - } break; - case ShaderLanguage::TYPE_BVEC2: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC3: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - gui[2] = value[2].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC4: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - gui[2] = value[2].boolean ? 1 : 0; - gui[3] = value[3].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_INT: { - int32_t *gui = (int32_t *)data; - gui[0] = value[0].sint; - - } break; - case ShaderLanguage::TYPE_IVEC2: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC3: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC4: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_UINT: { - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].uint; - - } break; - case ShaderLanguage::TYPE_UVEC2: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].uint; - } - - } break; - case ShaderLanguage::TYPE_UVEC4: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - float *gui = (float *)data; - gui[0] = value[0].real; - - } break; - case ShaderLanguage::TYPE_VEC2: { - float *gui = (float *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC3: { - float *gui = (float *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC4: { - float *gui = (float *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].real; - } - } break; - case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; - - //in std140 members of mat2 are treated as vec4s - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = 0; - gui[3] = 0; - gui[4] = value[2].real; - gui[5] = value[3].real; - gui[6] = 0; - gui[7] = 0; - } break; - case ShaderLanguage::TYPE_MAT3: { - float *gui = (float *)data; - - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = value[2].real; - gui[3] = 0; - gui[4] = value[3].real; - gui[5] = value[4].real; - gui[6] = value[5].real; - gui[7] = 0; - gui[8] = value[6].real; - gui[9] = value[7].real; - gui[10] = value[8].real; - gui[11] = 0; - } break; - case ShaderLanguage::TYPE_MAT4: { - float *gui = (float *)data; - - for (int i = 0; i < 16; i++) { - gui[i] = value[i].real; - } - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) { - if (p_array_size <= 0) { - p_array_size = 1; - } - - switch (type) { - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_INT: - case ShaderLanguage::TYPE_UINT: - case ShaderLanguage::TYPE_FLOAT: { - memset(data, 0, 4 * p_array_size); - } break; - case ShaderLanguage::TYPE_BVEC2: - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_VEC2: { - memset(data, 0, 8 * p_array_size); - } break; - case ShaderLanguage::TYPE_BVEC3: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_VEC3: - case ShaderLanguage::TYPE_BVEC4: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC4: - case ShaderLanguage::TYPE_VEC4: { - memset(data, 0, 16 * p_array_size); - } break; - case ShaderLanguage::TYPE_MAT2: { - memset(data, 0, 32 * p_array_size); - } break; - case ShaderLanguage::TYPE_MAT3: { - memset(data, 0, 48 * p_array_size); - } break; - case ShaderLanguage::TYPE_MAT4: { - memset(data, 0, 64 * p_array_size); - } break; - - default: { - } - } -} - -void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { - bool uses_global_buffer = false; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) { - if (E.value.order < 0) { - continue; // texture, does not go here - } - - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; //instance uniforms don't appear in the buffer - } - - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { - //this is a global variable, get the index to it - RendererStorageRD *rs = base_singleton; - - GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E.key); - uint32_t index = 0; - if (gv) { - index = gv->buffer_index; - } else { - WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly."); - } - - uint32_t offset = p_uniform_offsets[E.value.order]; - uint32_t *intptr = (uint32_t *)&p_buffer[offset]; - *intptr = index; - uses_global_buffer = true; - continue; - } - - //regular uniform - uint32_t offset = p_uniform_offsets[E.value.order]; -#ifdef DEBUG_ENABLED - uint32_t size = 0U; - // The following code enforces a 16-byte alignment of uniform arrays. - if (E.value.array_size > 0) { - size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size; - int m = (16 * E.value.array_size); - if ((size % m) != 0U) { - size += m - (size % m); - } - } else { - size = ShaderLanguage::get_datatype_size(E.value.type); - } - ERR_CONTINUE(offset + size > p_buffer_size); -#endif - uint8_t *data = &p_buffer[offset]; - const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); - - if (V) { - //user provided - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); - - } else if (E.value.default_value.size()) { - //default value - _fill_std140_ubo_value(E.value.type, E.value.default_value, data); - //value=E.value.default_value; - } else { - //zero because it was not provided - if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - //colors must be set as black, with alpha as 1.0 - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color); - } else { - //else just zero it out - _fill_std140_ubo_empty(E.value.type, E.value.array_size, data); - } - } - } - - if (uses_global_buffer != (global_buffer_E != nullptr)) { - RendererStorageRD *rs = base_singleton; - if (uses_global_buffer) { - global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self); - } else { - rs->global_variables.materials_using_buffer.erase(global_buffer_E); - global_buffer_E = nullptr; - } - } -} - -RendererStorageRD::MaterialData::~MaterialData() { - if (global_buffer_E) { - //unregister global buffers - RendererStorageRD *rs = base_singleton; - rs->global_variables.materials_using_buffer.erase(global_buffer_E); - } - - if (global_texture_E) { - //unregister global textures - RendererStorageRD *rs = base_singleton; - - for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { - GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E.key); - if (v) { - v->texture_materials.erase(self); - } - } - //unregister material from those using global textures - rs->global_variables.materials_using_texture.erase(global_texture_E); - } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } -} - -void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - -#ifdef TOOLS_ENABLED - RendererRD::Texture *roughness_detect_texture = nullptr; - RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; - RendererRD::Texture *normal_detect_texture = nullptr; -#endif - - bool uses_global_textures = false; - global_textures_pass++; - - for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { - const StringName &uniform_name = p_texture_uniforms[i].name; - int uniform_array_size = p_texture_uniforms[i].array_size; - - Vector<RID> textures; - - if (p_texture_uniforms[i].global) { - RendererStorageRD *rs = base_singleton; - - uses_global_textures = true; - - GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name); - if (v) { - if (v->buffer_index >= 0) { - WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); - - } else { - Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); - if (!E) { - E = used_global_textures.insert(uniform_name, global_textures_pass); - v->texture_materials.insert(self); - } else { - E->get() = global_textures_pass; - } - - textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); - } - - } else { - WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); - } - } else { - const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); - if (V) { - if (V->get().is_array()) { - Array array = (Array)V->get(); - if (uniform_array_size > 0) { - for (int j = 0; j < array.size(); j++) { - textures.push_back(array[j]); - } - } else { - if (array.size() > 0) { - textures.push_back(array[0]); - } - } - } else { - textures.push_back(V->get()); - } - } - - if (uniform_array_size > 0) { - if (textures.size() < uniform_array_size) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - for (int j = textures.size(); j < uniform_array_size; j++) { - if (W && W->get().has(j)) { - textures.push_back(W->get()[j]); - } else { - textures.push_back(RID()); - } - } - } - } else if (textures.is_empty()) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - if (W && W->get().has(0)) { - textures.push_back(W->get()[0]); - } - } - } - - RID rd_texture; - - if (textures.is_empty()) { - //check default usage - switch (p_texture_uniforms[i].type) { - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER2D: - case ShaderLanguage::TYPE_SAMPLER2D: { - switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_ANISO); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); - } break; - default: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); - } break; - } - } break; - - case ShaderLanguage::TYPE_SAMPLERCUBE: { - switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - } break; - default: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); - } break; - } - } break; - case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); - } break; - - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: - case ShaderLanguage::TYPE_SAMPLER3D: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); - } break; - - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); - } break; - - default: { - } - } -#ifdef TOOLS_ENABLED - if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { - roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); - } -#endif - if (uniform_array_size > 0) { - for (int j = 0; j < uniform_array_size; j++) { - p_textures[k++] = rd_texture; - } - } else { - p_textures[k++] = rd_texture; - } - } else { - bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); - - for (int j = 0; j < textures.size(); j++) { - RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(textures[j]); - - if (tex) { - rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; -#ifdef TOOLS_ENABLED - if (tex->detect_3d_callback && p_use_linear_color) { - tex->detect_3d_callback(tex->detect_3d_callback_ud); - } - if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { - if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { - normal_detect_texture = tex; - } - tex->detect_normal_callback(tex->detect_normal_callback_ud); - } - if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { - //find the normal texture - roughness_detect_texture = tex; - roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); - } -#endif - } - if (rd_texture.is_null()) { - rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); - } -#ifdef TOOLS_ENABLED - if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { - roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); - } -#endif - p_textures[k++] = rd_texture; - } - } - } - { - //for textures no longer used, unregister them - List<Map<StringName, uint64_t>::Element *> to_delete; - RendererStorageRD *rs = base_singleton; - - for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { - if (E->get() != global_textures_pass) { - to_delete.push_back(E); - - GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key()); - if (v) { - v->texture_materials.erase(self); - } - } - } - - while (to_delete.front()) { - used_global_textures.erase(to_delete.front()->get()); - to_delete.pop_front(); - } - //handle registering/unregistering global textures - if (uses_global_textures != (global_texture_E != nullptr)) { - if (uses_global_textures) { - global_texture_E = rs->global_variables.materials_using_texture.push_back(self); - } else { - rs->global_variables.materials_using_texture.erase(global_texture_E); - global_texture_E = nullptr; - } - } - } -} - -void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) { - if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { - RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr); - RD::get_singleton()->free(p_uniform_set); - } -} - -bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { - if ((uint32_t)ubo_data.size() != p_ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(p_ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); - } - - uint32_t tex_uniform_count = 0U; - for (int i = 0; i < p_texture_uniforms.size(); i++) { - tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1); - } - - if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); - } - - if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return false; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return false; - } - - Vector<RD::Uniform> uniforms; - - { - if (p_ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.append_id(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { - const int array_size = p_texture_uniforms[i].array_size; - - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + k; - if (array_size > 0) { - for (int j = 0; j < array_size; j++) { - u.append_id(textures[k++]); - } - } else { - u.append_id(textures[k++]); - } - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set); - - RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self); - - return true; -} - -void RendererStorageRD::_material_uniform_set_erased(void *p_material) { - RID rid = *(RID *)p_material; - Material *material = base_singleton->material_owner.get_or_null(rid); - if (material) { - if (material->data) { - // Uniform set may be gone because a dependency was erased. This happens - // if a texture is deleted, so re-create it. - base_singleton->_material_queue_update(material, false, true); - } - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - } -} - -void RendererStorageRD::_update_queued_materials() { - while (material_update_list.first()) { - Material *material = material_update_list.first()->self(); - bool uniforms_changed = false; - - if (material->data) { - uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); - } - material->texture_dirty = false; - material->uniform_dirty = false; - - material_update_list.remove(&material->update_element); - - if (uniforms_changed) { - //some implementations such as 3D renderer cache the matreial uniform set, so update is required - material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - } - } -} - -/* MESH API */ - -RID RendererStorageRD::mesh_allocate() { - return mesh_owner.allocate_rid(); -} -void RendererStorageRD::mesh_initialize(RID p_rid) { - mesh_owner.initialize_rid(p_rid, Mesh()); -} - -void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) { - ERR_FAIL_COND(p_blend_shape_count < 0); - - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist - - mesh->blend_shape_count = p_blend_shape_count; -} - -/// Returns stride -void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES); - -#ifdef DEBUG_ENABLED - //do a validation, to catch errors first - { - uint32_t stride = 0; - uint32_t attrib_stride = 0; - uint32_t skin_stride = 0; - - for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { - if ((p_surface.format & (1 << i))) { - switch (i) { - case RS::ARRAY_VERTEX: { - if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) { - stride += sizeof(float) * 2; - } else { - stride += sizeof(float) * 3; - } - - } break; - case RS::ARRAY_NORMAL: { - stride += sizeof(int32_t); - - } break; - case RS::ARRAY_TANGENT: { - stride += sizeof(int32_t); - - } break; - case RS::ARRAY_COLOR: { - attrib_stride += sizeof(uint32_t); - } break; - case RS::ARRAY_TEX_UV: { - attrib_stride += sizeof(float) * 2; - - } break; - case RS::ARRAY_TEX_UV2: { - attrib_stride += sizeof(float) * 2; - - } break; - case RS::ARRAY_CUSTOM0: - case RS::ARRAY_CUSTOM1: - case RS::ARRAY_CUSTOM2: - case RS::ARRAY_CUSTOM3: { - int idx = i - RS::ARRAY_CUSTOM0; - uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; - uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; - uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; - attrib_stride += fmtsize[fmt]; - - } break; - case RS::ARRAY_WEIGHTS: - case RS::ARRAY_BONES: { - //uses a separate array - bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS; - skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8); - } break; - } - } - } - - int expected_size = stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); - - int bs_expected_size = expected_size * mesh->blend_shape_count; - - ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")"); - - int expected_attrib_size = attrib_stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")"); - - if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) { - expected_size = skin_stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); - } - } - -#endif - - Mesh::Surface *s = memnew(Mesh::Surface); - - s->format = p_surface.format; - s->primitive = p_surface.primitive; - - bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); - - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); - s->vertex_buffer_size = p_surface.vertex_data.size(); - - if (p_surface.attribute_data.size()) { - s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); - } - if (p_surface.skin_data.size()) { - s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage); - s->skin_buffer_size = p_surface.skin_data.size(); - } - - s->vertex_count = p_surface.vertex_count; - - if (p_surface.format & RS::ARRAY_FORMAT_BONES) { - mesh->has_bone_weights = true; - } - - if (p_surface.index_count) { - bool is_index_16 = p_surface.vertex_count <= 65536; - - s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); - s->index_count = p_surface.index_count; - s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); - if (p_surface.lods.size()) { - s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); - s->lod_count = p_surface.lods.size(); - - for (int i = 0; i < p_surface.lods.size(); i++) { - uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); - s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); - s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); - s->lods[i].edge_length = p_surface.lods[i].edge_length; - s->lods[i].index_count = indices; - } - } - } - - s->aabb = p_surface.aabb; - s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. - - if (mesh->blend_shape_count > 0) { - s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data); - } - - if (use_as_storage) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(s->vertex_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 1; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - if (s->skin_buffer.is_valid()) { - u.append_id(s->skin_buffer); - } else { - u.append_id(default_rd_storage_buffer); - } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - if (s->blend_shape_buffer.is_valid()) { - u.append_id(s->blend_shape_buffer); - } else { - u.append_id(default_rd_storage_buffer); - } - uniforms.push_back(u); - } - - s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE); - } - - if (mesh->surface_count == 0) { - mesh->bone_aabbs = p_surface.bone_aabbs; - mesh->aabb = p_surface.aabb; - } else { - if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) { - // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone - // Each surface may affect different numbers of bones. - mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); - } - for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); - } - mesh->aabb.merge_with(p_surface.aabb); - } - - s->material = p_surface.material; - - mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); - mesh->surfaces[mesh->surface_count] = s; - mesh->surface_count++; - - for (MeshInstance *mi : mesh->instances) { - _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); - } - - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); - shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - } - - mesh->material_cache.clear(); -} - -int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const { - const Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - return mesh->blend_shape_count; -} - -void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX((int)p_mode, 2); - - mesh->blend_shape_mode = p_mode; -} - -RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); - return mesh->blend_shape_mode; -} - -void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); -} - -void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null()); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r); -} - -void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null()); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r); -} - -void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - mesh->surfaces[p_surface]->material = p_material; - - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); - mesh->material_cache.clear(); -} - -RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); - - return mesh->surfaces[p_surface]->material; -} - -RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); - - Mesh::Surface &s = *mesh->surfaces[p_surface]; - - RS::SurfaceData sd; - sd.format = s.format; - sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); - if (s.attribute_buffer.is_valid()) { - sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); - } - if (s.skin_buffer.is_valid()) { - sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer); - } - sd.vertex_count = s.vertex_count; - sd.index_count = s.index_count; - sd.primitive = s.primitive; - - if (sd.index_count) { - sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); - } - sd.aabb = s.aabb; - for (uint32_t i = 0; i < s.lod_count; i++) { - RS::SurfaceData::LOD lod; - lod.edge_length = s.lods[i].edge_length; - lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); - sd.lods.push_back(lod); - } - - sd.bone_aabbs = s.bone_aabbs; - - if (s.blend_shape_buffer.is_valid()) { - sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer); - } - - return sd; -} - -int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - return mesh->surface_count; -} - -void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - mesh->custom_aabb = p_aabb; -} - -AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - return mesh->custom_aabb; -} - -AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - - if (mesh->custom_aabb != AABB()) { - return mesh->custom_aabb; - } - - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - if (!skeleton || skeleton->size == 0) { - return mesh->aabb; - } - - AABB aabb; - - for (uint32_t i = 0; i < mesh->surface_count; i++) { - AABB laabb; - if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { - int bs = mesh->surfaces[i]->bone_aabbs.size(); - const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr(); - - int sbs = skeleton->size; - ERR_CONTINUE(bs > sbs); - const float *baseptr = skeleton->data.ptr(); - - bool first = true; - - if (skeleton->use_2d) { - for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { - continue; //bone is unused - } - - const float *dataptr = baseptr + j * 8; - - Transform3D mtx; - - mtx.basis.elements[0].x = dataptr[0]; - mtx.basis.elements[1].x = dataptr[1]; - mtx.origin.x = dataptr[3]; - - mtx.basis.elements[0].y = dataptr[4]; - mtx.basis.elements[1].y = dataptr[5]; - mtx.origin.y = dataptr[7]; - - AABB baabb = mtx.xform(skbones[j]); - - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } else { - for (int j = 0; j < bs; j++) { - if (skbones[0].size == Vector3()) { - continue; //bone is unused - } - - const float *dataptr = baseptr + j * 12; - - Transform3D mtx; - - mtx.basis.elements[0][0] = dataptr[0]; - mtx.basis.elements[0][1] = dataptr[1]; - mtx.basis.elements[0][2] = dataptr[2]; - mtx.origin.x = dataptr[3]; - mtx.basis.elements[1][0] = dataptr[4]; - mtx.basis.elements[1][1] = dataptr[5]; - mtx.basis.elements[1][2] = dataptr[6]; - mtx.origin.y = dataptr[7]; - mtx.basis.elements[2][0] = dataptr[8]; - mtx.basis.elements[2][1] = dataptr[9]; - mtx.basis.elements[2][2] = dataptr[10]; - mtx.origin.z = dataptr[11]; - - AABB baabb = mtx.xform(skbones[j]); - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } - - if (laabb.size == Vector3()) { - laabb = mesh->surfaces[i]->aabb; - } - } else { - laabb = mesh->surfaces[i]->aabb; - } - - if (i == 0) { - aabb = laabb; - } else { - aabb.merge_with(laabb); - } - } - - return aabb; -} - -void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - - Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); - if (shadow_mesh) { - shadow_mesh->shadow_owners.erase(mesh); - } - mesh->shadow_mesh = p_shadow_mesh; - - shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); - - if (shadow_mesh) { - shadow_mesh->shadow_owners.insert(mesh); - } - - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); -} - -void RendererStorageRD::mesh_clear(RID p_mesh) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); - for (uint32_t i = 0; i < mesh->surface_count; i++) { - Mesh::Surface &s = *mesh->surfaces[i]; - RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions - if (s.attribute_buffer.is_valid()) { - RD::get_singleton()->free(s.attribute_buffer); - } - if (s.skin_buffer.is_valid()) { - RD::get_singleton()->free(s.skin_buffer); - } - if (s.versions) { - memfree(s.versions); //reallocs, so free with memfree. - } - - if (s.index_buffer.is_valid()) { - RD::get_singleton()->free(s.index_buffer); - } - - if (s.lod_count) { - for (uint32_t j = 0; j < s.lod_count; j++) { - RD::get_singleton()->free(s.lods[j].index_buffer); - } - memdelete_arr(s.lods); - } - - if (s.blend_shape_buffer.is_valid()) { - RD::get_singleton()->free(s.blend_shape_buffer); - } - - memdelete(mesh->surfaces[i]); - } - if (mesh->surfaces) { - memfree(mesh->surfaces); - } - - mesh->surfaces = nullptr; - mesh->surface_count = 0; - mesh->material_cache.clear(); - //clear instance data - for (MeshInstance *mi : mesh->instances) { - _mesh_instance_clear(mi); - } - mesh->has_bone_weights = false; - mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); - shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - } -} - -bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, false); - - return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); -} - -/* MESH INSTANCE */ - -RID RendererStorageRD::mesh_instance_create(RID p_base) { - Mesh *mesh = mesh_owner.get_or_null(p_base); - ERR_FAIL_COND_V(!mesh, RID()); - - RID rid = mesh_instance_owner.make_rid(); - MeshInstance *mi = mesh_instance_owner.get_or_null(rid); - - mi->mesh = mesh; - - for (uint32_t i = 0; i < mesh->surface_count; i++) { - _mesh_instance_add_surface(mi, mesh, i); - } - - mi->I = mesh->instances.push_back(mi); - - mi->dirty = true; - - return rid; -} -void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - if (mi->skeleton == p_skeleton) { - return; - } - mi->skeleton = p_skeleton; - mi->skeleton_version = 0; - mi->dirty = true; -} - -void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - ERR_FAIL_COND(!mi); - ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size()); - mi->blend_weights[p_shape] = p_weight; - mi->weights_dirty = true; - //will be eventually updated -} - -void RendererStorageRD::_mesh_instance_clear(MeshInstance *mi) { - for (uint32_t i = 0; i < mi->surfaces.size(); i++) { - if (mi->surfaces[i].versions) { - for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { - RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); - } - memfree(mi->surfaces[i].versions); - } - if (mi->surfaces[i].vertex_buffer.is_valid()) { - RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); - } - } - mi->surfaces.clear(); - - if (mi->blend_weights_buffer.is_valid()) { - RD::get_singleton()->free(mi->blend_weights_buffer); - } - mi->blend_weights.clear(); - mi->weights_dirty = false; - mi->skeleton_version = 0; -} - -void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) { - if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) { - mi->blend_weights.resize(mesh->blend_shape_count); - for (uint32_t i = 0; i < mi->blend_weights.size(); i++) { - mi->blend_weights[i] = 0; - } - mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array()); - mi->weights_dirty = true; - } - - MeshInstance::Surface s; - if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { - //surface warrants transform - s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 1; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(s.vertex_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - if (mi->blend_weights_buffer.is_valid()) { - u.append_id(mi->blend_weights_buffer); - } else { - u.append_id(default_rd_storage_buffer); - } - uniforms.push_back(u); - } - s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE); - } - - mi->surfaces.push_back(s); - mi->dirty = true; -} - -void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - - bool needs_update = mi->dirty; - - if (mi->weights_dirty && !mi->weight_update_list.in_list()) { - dirty_mesh_instance_weights.add(&mi->weight_update_list); - needs_update = true; - } - - if (mi->array_update_list.in_list()) { - return; - } - - if (!needs_update && mi->skeleton.is_valid()) { - Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); - if (sk && sk->version != mi->skeleton_version) { - needs_update = true; - } - } - - if (needs_update) { - dirty_mesh_instance_arrays.add(&mi->array_update_list); - } -} - -void RendererStorageRD::update_mesh_instances() { - while (dirty_mesh_instance_weights.first()) { - MeshInstance *mi = dirty_mesh_instance_weights.first()->self(); - - if (mi->blend_weights_buffer.is_valid()) { - RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr()); - } - dirty_mesh_instance_weights.remove(&mi->weight_update_list); - mi->weights_dirty = false; - } - if (dirty_mesh_instance_arrays.first() == nullptr) { - return; //nothing to do - } - - //process skeletons and blend shapes - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - while (dirty_mesh_instance_arrays.first()) { - MeshInstance *mi = dirty_mesh_instance_arrays.first()->self(); - - Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); - - for (uint32_t i = 0; i < mi->surfaces.size(); i++) { - if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) { - continue; - } - - bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE); - if (sk && sk->uniform_set_mi.is_valid()) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON); - } - - SkeletonShader::PushConstant push_constant; - - push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL; - push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT; - push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES); - push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0; - - push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count; - push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; - push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; - push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; - - push_constant.blend_shape_count = mi->mesh->blend_shape_count; - push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; - push_constant.pad0 = 0; - push_constant.pad1 = 0; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant)); - - //dispatch without barrier, so all is done at the same time - RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1); - } - - mi->dirty = false; - if (sk) { - mi->skeleton_version = sk->version; - } - dirty_mesh_instance_arrays.remove(&mi->array_update_list); - } - - RD::get_singleton()->compute_list_end(); -} - -void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) { - Vector<RD::VertexAttribute> attributes; - Vector<RID> buffers; - - uint32_t stride = 0; - uint32_t attribute_stride = 0; - uint32_t skin_stride = 0; - - for (int i = 0; i < RS::ARRAY_INDEX; i++) { - RD::VertexAttribute vd; - RID buffer; - vd.location = i; - - if (!(s->format & (1 << i))) { - // Not supplied by surface, use default value - buffer = mesh_default_rd_buffers[i]; - vd.stride = 0; - switch (i) { - case RS::ARRAY_VERTEX: { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - - } break; - case RS::ARRAY_NORMAL: { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } break; - case RS::ARRAY_TANGENT: { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - case RS::ARRAY_COLOR: { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - - } break; - case RS::ARRAY_TEX_UV: { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - - } break; - case RS::ARRAY_TEX_UV2: { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - } break; - case RS::ARRAY_CUSTOM0: - case RS::ARRAY_CUSTOM1: - case RS::ARRAY_CUSTOM2: - case RS::ARRAY_CUSTOM3: { - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - case RS::ARRAY_BONES: { - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - } break; - case RS::ARRAY_WEIGHTS: { - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - } - } else { - //Supplied, use it - - vd.stride = 1; //mark that it needs a stride set (default uses 0) - - switch (i) { - case RS::ARRAY_VERTEX: { - vd.offset = stride; - - if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - stride += sizeof(float) * 3; - } - - if (mis) { - buffer = mis->vertex_buffer; - } else { - buffer = s->vertex_buffer; - } - - } break; - case RS::ARRAY_NORMAL: { - vd.offset = stride; - - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - - stride += sizeof(uint32_t); - if (mis) { - buffer = mis->vertex_buffer; - } else { - buffer = s->vertex_buffer; - } - } break; - case RS::ARRAY_TANGENT: { - vd.offset = stride; - - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - stride += sizeof(uint32_t); - if (mis) { - buffer = mis->vertex_buffer; - } else { - buffer = s->vertex_buffer; - } - } break; - case RS::ARRAY_COLOR: { - vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - attribute_stride += sizeof(int8_t) * 4; - buffer = s->attribute_buffer; - } break; - case RS::ARRAY_TEX_UV: { - vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - attribute_stride += sizeof(float) * 2; - buffer = s->attribute_buffer; - - } break; - case RS::ARRAY_TEX_UV2: { - vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - attribute_stride += sizeof(float) * 2; - buffer = s->attribute_buffer; - } break; - case RS::ARRAY_CUSTOM0: - case RS::ARRAY_CUSTOM1: - case RS::ARRAY_CUSTOM2: - case RS::ARRAY_CUSTOM3: { - vd.offset = attribute_stride; - - int idx = i - RS::ARRAY_CUSTOM0; - uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; - uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; - uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; - RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; - vd.format = fmtrd[fmt]; - attribute_stride += fmtsize[fmt]; - buffer = s->attribute_buffer; - } break; - case RS::ARRAY_BONES: { - vd.offset = skin_stride; - - vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT; - skin_stride += sizeof(int16_t) * 4; - buffer = s->skin_buffer; - } break; - case RS::ARRAY_WEIGHTS: { - vd.offset = skin_stride; - - vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; - skin_stride += sizeof(int16_t) * 4; - buffer = s->skin_buffer; - } break; - } - } - - if (!(p_input_mask & (1 << i))) { - continue; // Shader does not need this, skip it (but computing stride was important anyway) - } - - attributes.push_back(vd); - buffers.push_back(buffer); - } - - //update final stride - for (int i = 0; i < attributes.size(); i++) { - if (attributes[i].stride == 0) { - continue; //default location - } - int loc = attributes[i].location; - - if (loc < RS::ARRAY_COLOR) { - attributes.write[i].stride = stride; - } else if (loc < RS::ARRAY_BONES) { - attributes.write[i].stride = attribute_stride; - } else { - attributes.write[i].stride = skin_stride; - } - } - - v.input_mask = p_input_mask; - v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); - v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); -} - -////////////////// MULTIMESH - -RID RendererStorageRD::multimesh_allocate() { - return multimesh_owner.allocate_rid(); -} -void RendererStorageRD::multimesh_initialize(RID p_rid) { - multimesh_owner.initialize_rid(p_rid, MultiMesh()); -} - -void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { - return; - } - - if (multimesh->buffer.is_valid()) { - RD::get_singleton()->free(multimesh->buffer); - multimesh->buffer = RID(); - multimesh->uniform_set_2d = RID(); //cleared by dependency - multimesh->uniform_set_3d = RID(); //cleared by dependency - } - - if (multimesh->data_cache_dirty_regions) { - memdelete_arr(multimesh->data_cache_dirty_regions); - multimesh->data_cache_dirty_regions = nullptr; - multimesh->data_cache_used_dirty_regions = 0; - } - - multimesh->instances = p_instances; - multimesh->xform_format = p_transform_format; - multimesh->uses_colors = p_use_colors; - multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12; - multimesh->uses_custom_data = p_use_custom_data; - multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); - multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); - multimesh->buffer_set = false; - - //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); - multimesh->data_cache = Vector<float>(); - multimesh->aabb = AABB(); - multimesh->aabb_dirty = false; - multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); - - if (multimesh->instances) { - multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); - } - - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH); -} - -int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - return multimesh->instances; -} - -void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - if (multimesh->mesh == p_mesh) { - return; - } - multimesh->mesh = p_mesh; - - if (multimesh->instances == 0) { - return; - } - - if (multimesh->data_cache.size()) { - //we have a data cache, just mark it dirt - _multimesh_mark_all_dirty(multimesh, false, true); - } else if (multimesh->instances) { - //need to re-create AABB unfortunately, calling this has a penalty - if (multimesh->buffer_set) { - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - const uint8_t *r = buffer.ptr(); - const float *data = (const float *)r; - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - } - } - - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); -} - -#define MULTIMESH_DIRTY_REGION_SIZE 512 - -void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { - if (multimesh->data_cache.size() > 0) { - return; //already local - } - ERR_FAIL_COND(multimesh->data_cache.size() > 0); - // this means that the user wants to load/save individual elements, - // for this, the data must reside on CPU, so just copy it there. - multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); - { - float *w = multimesh->data_cache.ptrw(); - - if (multimesh->buffer_set) { - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - { - const uint8_t *r = buffer.ptr(); - memcpy(w, r, buffer.size()); - } - } else { - memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); - } - } - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - multimesh->data_cache_used_dirty_regions = 0; -} - -void RendererStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { - uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; -#ifdef DEBUG_ENABLED - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug -#endif - if (!multimesh->data_cache_dirty_regions[region_index]) { - multimesh->data_cache_dirty_regions[region_index] = true; - multimesh->data_cache_used_dirty_regions++; - } - - if (p_aabb) { - multimesh->aabb_dirty = true; - } - - if (!multimesh->dirty) { - multimesh->dirty_list = multimesh_dirty_list; - multimesh_dirty_list = multimesh; - multimesh->dirty = true; - } -} - -void RendererStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { - if (p_data) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - if (!multimesh->data_cache_dirty_regions[i]) { - multimesh->data_cache_dirty_regions[i] = true; - multimesh->data_cache_used_dirty_regions++; - } - } - } - - if (p_aabb) { - multimesh->aabb_dirty = true; - } - - if (!multimesh->dirty) { - multimesh->dirty_list = multimesh_dirty_list; - multimesh_dirty_list = multimesh; - multimesh->dirty = true; - } -} - -void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { - ERR_FAIL_COND(multimesh->mesh.is_null()); - AABB aabb; - AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); - for (int i = 0; i < p_instances; i++) { - const float *data = p_data + multimesh->stride_cache * i; - Transform3D t; - - if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) { - t.basis.elements[0][0] = data[0]; - t.basis.elements[0][1] = data[1]; - t.basis.elements[0][2] = data[2]; - t.origin.x = data[3]; - t.basis.elements[1][0] = data[4]; - t.basis.elements[1][1] = data[5]; - t.basis.elements[1][2] = data[6]; - t.origin.y = data[7]; - t.basis.elements[2][0] = data[8]; - t.basis.elements[2][1] = data[9]; - t.basis.elements[2][2] = data[10]; - t.origin.z = data[11]; - - } else { - t.basis.elements[0].x = data[0]; - t.basis.elements[1].x = data[1]; - t.origin.x = data[3]; - - t.basis.elements[0].y = data[4]; - t.basis.elements[1].y = data[5]; - t.origin.y = data[7]; - } - - if (i == 0) { - aabb = t.xform(mesh_aabb); - } else { - aabb.merge_with(t.xform(mesh_aabb)); - } - } - - multimesh->aabb = aabb; -} - -void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - } - - _multimesh_mark_dirty(multimesh, p_index, true); -} - -void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - } - - _multimesh_mark_dirty(multimesh, p_index, true); -} - -void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(!multimesh->uses_colors); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; - - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - _multimesh_mark_dirty(multimesh, p_index, false); -} - -void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(!multimesh->uses_custom_data); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; - - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - _multimesh_mark_dirty(multimesh, p_index, false); -} - -RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, RID()); - - return multimesh->mesh; -} - -Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform3D()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D()); - ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D()); - - _multimesh_make_local(multimesh); - - Transform3D t; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache; - - t.basis.elements[0][0] = dataptr[0]; - t.basis.elements[0][1] = dataptr[1]; - t.basis.elements[0][2] = dataptr[2]; - t.origin.x = dataptr[3]; - t.basis.elements[1][0] = dataptr[4]; - t.basis.elements[1][1] = dataptr[5]; - t.basis.elements[1][2] = dataptr[6]; - t.origin.y = dataptr[7]; - t.basis.elements[2][0] = dataptr[8]; - t.basis.elements[2][1] = dataptr[9]; - t.basis.elements[2][2] = dataptr[10]; - t.origin.z = dataptr[11]; - } - - return t; -} - -Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform2D()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); - ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D()); - - _multimesh_make_local(multimesh); - - Transform2D t; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache; - - t.elements[0][0] = dataptr[0]; - t.elements[1][0] = dataptr[1]; - t.elements[2][0] = dataptr[3]; - t.elements[0][1] = dataptr[4]; - t.elements[1][1] = dataptr[5]; - t.elements[2][1] = dataptr[7]; - } - - return t; -} - -Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); - ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); - - _multimesh_make_local(multimesh); - - Color c; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; - - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - } - - return c; -} - -Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); - ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); - - _multimesh_make_local(multimesh); - - Color c; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; - - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - } - - return c; -} - -void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); - - { - const float *r = p_buffer.ptr(); - RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r); - multimesh->buffer_set = true; - } - - if (multimesh->data_cache.size()) { - //if we have a data cache, just update it - multimesh->data_cache = p_buffer; - { - //clear dirty since nothing will be dirty anymore - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - multimesh->data_cache_used_dirty_regions = 0; - } - - _multimesh_mark_all_dirty(multimesh, false, true); //update AABB - } else if (multimesh->mesh.is_valid()) { - //if we have a mesh set, we need to re-generate the AABB from the new data - const float *data = p_buffer.ptr(); - - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); - } -} - -Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Vector<float>()); - if (multimesh->buffer.is_null()) { - return Vector<float>(); - } else if (multimesh->data_cache.size()) { - return multimesh->data_cache; - } else { - //get from memory - - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - Vector<float> ret; - ret.resize(multimesh->instances * multimesh->stride_cache); - { - float *w = ret.ptrw(); - const uint8_t *r = buffer.ptr(); - memcpy(w, r, buffer.size()); - } - - return ret; - } -} - -void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); - if (multimesh->visible_instances == p_visible) { - return; - } - - if (multimesh->data_cache.size()) { - //there is a data cache.. - _multimesh_mark_all_dirty(multimesh, false, true); - } - - multimesh->visible_instances = p_visible; - - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); -} - -int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - return multimesh->visible_instances; -} - -AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, AABB()); - if (multimesh->aabb_dirty) { - const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes(); - } - return multimesh->aabb; -} - -void RendererStorageRD::_update_dirty_multimeshes() { - while (multimesh_dirty_list) { - MultiMesh *multimesh = multimesh_dirty_list; - - if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists - const float *data = multimesh->data_cache.ptr(); - - uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; - - if (multimesh->data_cache_used_dirty_regions) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - - uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); - - if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { - //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much - RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); - } else { - //not that many regions? update them all - for (uint32_t i = 0; i < visible_region_count; i++) { - if (multimesh->data_cache_dirty_regions[i]) { - uint32_t offset = i * region_size; - uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); - uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i; - RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]); - } - } - } - - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - - multimesh->data_cache_used_dirty_regions = 0; - } - - if (multimesh->aabb_dirty) { - //aabb is dirty.. - _multimesh_re_create_aabb(multimesh, data, visible_instances); - multimesh->aabb_dirty = false; - multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); - } - } - - multimesh_dirty_list = multimesh->dirty_list; - - multimesh->dirty_list = nullptr; - multimesh->dirty = false; - } - - multimesh_dirty_list = nullptr; -} - /* PARTICLES */ RID RendererStorageRD::particles_allocate() { @@ -3519,7 +421,7 @@ void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4); memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size()); - particles->emission_buffer = (ParticleEmissionBuffer *)particles->emission_buffer_data.ptrw(); + particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw()); particles->emission_buffer->particle_max = particles->amount; particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data); @@ -3643,7 +545,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) { float longest_axis_size = 0; for (int i = 0; i < particles->draw_passes.size(); i++) { if (particles->draw_passes[i].is_valid()) { - AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID()); + AABB maabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID()); longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size); } } @@ -3705,6 +607,7 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -3731,7 +634,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (p_particles->emission_storage_buffer.is_valid()) { u.append_id(p_particles->emission_storage_buffer); } else { - u.append_id(default_rd_storage_buffer); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); } uniforms.push_back(u); } @@ -3746,7 +649,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt } u.append_id(sub_emitter->emission_storage_buffer); } else { - u.append_id(default_rd_storage_buffer); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); } uniforms.push_back(u); } @@ -4094,9 +997,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = (ParticlesMaterialData *)material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES); + ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, RendererRD::SHADER_TYPE_PARTICLES)); if (!m) { - m = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES); + m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -4249,7 +1152,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & void RendererStorageRD::_particles_update_buffers(Particles *particles) { uint32_t userdata_count = 0; - const Material *material = material_owner.get_or_null(particles->process_material); + const RendererRD::Material *material = RendererRD::MaterialStorage::get_singleton()->get_material(particles->process_material); if (material && material->shader && material->shader->data) { const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); userdata_count = shader_data->userdata_count; @@ -4389,7 +1292,7 @@ void RendererStorageRD::update_particles() { if (particles->trail_bind_pose_buffer.is_valid()) { u.append_id(particles->trail_bind_pose_buffer); } else { - u.append_id(default_rd_storage_buffer); + u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); } uniforms.push_back(u); } @@ -4636,13 +1539,13 @@ void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> * } } -void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { +void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RendererStorage::InstanceShaderParam p; + RendererMaterialStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E.value); p.info.name = E.key; //supply name p.index = E.value.instance_index; @@ -4691,7 +1594,7 @@ RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() { } } -RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func() { +RendererRD::ShaderData *RendererStorageRD::_create_particles_shader_func() { ParticlesShaderData *shader_data = memnew(ParticlesShaderData); return shader_data; } @@ -4704,7 +1607,7 @@ RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { +RendererRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -5025,195 +1928,6 @@ void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, b } } -/* SKELETON API */ - -RID RendererStorageRD::skeleton_allocate() { - return skeleton_owner.allocate_rid(); -} -void RendererStorageRD::skeleton_initialize(RID p_rid) { - skeleton_owner.initialize_rid(p_rid, Skeleton()); -} - -void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { - if (!skeleton->dirty) { - skeleton->dirty = true; - skeleton->dirty_list = skeleton_dirty_list; - skeleton_dirty_list = skeleton; - } -} - -void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_COND(p_bones < 0); - - if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) { - return; - } - - skeleton->size = p_bones; - skeleton->use_2d = p_2d_skeleton; - skeleton->uniform_set_3d = RID(); - - if (skeleton->buffer.is_valid()) { - RD::get_singleton()->free(skeleton->buffer); - skeleton->buffer = RID(); - skeleton->data.clear(); - skeleton->uniform_set_mi = RID(); - } - - if (skeleton->size) { - skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12)); - skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float)); - memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float)); - - _skeleton_make_dirty(skeleton); - - { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(skeleton->buffer); - uniforms.push_back(u); - } - skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); - } - } - - skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA); -} - -int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, 0); - - return skeleton->size; -} - -void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(skeleton->use_2d); - - float *dataptr = skeleton->data.ptrw() + p_bone * 12; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - - _skeleton_make_dirty(skeleton); -} - -Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform3D()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D()); - ERR_FAIL_COND_V(skeleton->use_2d, Transform3D()); - - const float *dataptr = skeleton->data.ptr() + p_bone * 12; - - Transform3D t; - - t.basis.elements[0][0] = dataptr[0]; - t.basis.elements[0][1] = dataptr[1]; - t.basis.elements[0][2] = dataptr[2]; - t.origin.x = dataptr[3]; - t.basis.elements[1][0] = dataptr[4]; - t.basis.elements[1][1] = dataptr[5]; - t.basis.elements[1][2] = dataptr[6]; - t.origin.y = dataptr[7]; - t.basis.elements[2][0] = dataptr[8]; - t.basis.elements[2][1] = dataptr[9]; - t.basis.elements[2][2] = dataptr[10]; - t.origin.z = dataptr[11]; - - return t; -} - -void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(!skeleton->use_2d); - - float *dataptr = skeleton->data.ptrw() + p_bone * 8; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - - _skeleton_make_dirty(skeleton); -} - -Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform2D()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); - ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); - - const float *dataptr = skeleton->data.ptr() + p_bone * 8; - - Transform2D t; - t.elements[0][0] = dataptr[0]; - t.elements[1][0] = dataptr[1]; - t.elements[2][0] = dataptr[3]; - t.elements[0][1] = dataptr[4]; - t.elements[1][1] = dataptr[5]; - t.elements[2][1] = dataptr[7]; - - return t; -} - -void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - - ERR_FAIL_COND(!skeleton->use_2d); - - skeleton->base_transform_2d = p_base_transform; -} - -void RendererStorageRD::_update_dirty_skeletons() { - while (skeleton_dirty_list) { - Skeleton *skeleton = skeleton_dirty_list; - - if (skeleton->size) { - RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr()); - } - - skeleton_dirty_list = skeleton->dirty_list; - - skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES); - - skeleton->version++; - - skeleton->dirty = false; - skeleton->dirty_list = nullptr; - } - - skeleton_dirty_list = nullptr; -} - /* LIGHT */ void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) { @@ -6929,11 +3643,11 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta } void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) { - if (mesh_owner.owns(p_base)) { - Mesh *mesh = mesh_owner.get_or_null(p_base); + if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) { + RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base); p_instance->update_dependency(&mesh->dependency); - } else if (multimesh_owner.owns(p_base)) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_base); + } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) { + RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base); p_instance->update_dependency(&multimesh->dependency); if (multimesh->mesh.is_valid()) { base_update_dependency(multimesh->mesh, p_instance); @@ -6968,18 +3682,11 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_ } } -void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); - - p_instance->update_dependency(&skeleton->dependency); -} - RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { - if (mesh_owner.owns(p_rid)) { + if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { return RS::INSTANCE_MESH; } - if (multimesh_owner.owns(p_rid)) { + if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { return RS::INSTANCE_MULTIMESH; } if (reflection_probe_owner.owns(p_rid)) { @@ -7013,675 +3720,11 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { return RS::INSTANCE_NONE; } -int32_t RendererStorageRD::_global_variable_allocate(uint32_t p_elements) { - int32_t idx = 0; - while (idx + p_elements <= global_variables.buffer_size) { - if (global_variables.buffer_usage[idx].elements == 0) { - bool valid = true; - for (uint32_t i = 1; i < p_elements; i++) { - if (global_variables.buffer_usage[idx + i].elements > 0) { - valid = false; - idx += i + global_variables.buffer_usage[idx + i].elements; - break; - } - } - - if (!valid) { - continue; //if not valid, idx is in new position - } - - return idx; - } else { - idx += global_variables.buffer_usage[idx].elements; - } - } - - return -1; -} - -void RendererStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { - switch (p_type) { - case RS::GLOBAL_VAR_TYPE_BOOL: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - bool b = p_value; - bv.x = b ? 1.0 : 0.0; - bv.y = 0.0; - bv.z = 0.0; - bv.w = 0.0; - - } break; - case RS::GLOBAL_VAR_TYPE_BVEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - uint32_t bvec = p_value; - bv.x = (bvec & 1) ? 1.0 : 0.0; - bv.y = (bvec & 2) ? 1.0 : 0.0; - bv.z = 0.0; - bv.w = 0.0; - } break; - case RS::GLOBAL_VAR_TYPE_BVEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - uint32_t bvec = p_value; - bv.x = (bvec & 1) ? 1.0 : 0.0; - bv.y = (bvec & 2) ? 1.0 : 0.0; - bv.z = (bvec & 4) ? 1.0 : 0.0; - bv.w = 0.0; - } break; - case RS::GLOBAL_VAR_TYPE_BVEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - uint32_t bvec = p_value; - bv.x = (bvec & 1) ? 1.0 : 0.0; - bv.y = (bvec & 2) ? 1.0 : 0.0; - bv.z = (bvec & 4) ? 1.0 : 0.0; - bv.w = (bvec & 8) ? 1.0 : 0.0; - } break; - case RS::GLOBAL_VAR_TYPE_INT: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - int32_t v = p_value; - bv.x = v; - bv.y = 0; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_IVEC2: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Vector2i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_IVEC3: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Vector3i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = v.z; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_IVEC4: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Vector<int32_t> v = p_value; - bv.x = v.size() >= 1 ? v[0] : 0; - bv.y = v.size() >= 2 ? v[1] : 0; - bv.z = v.size() >= 3 ? v[2] : 0; - bv.w = v.size() >= 4 ? v[3] : 0; - } break; - case RS::GLOBAL_VAR_TYPE_RECT2I: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; - Rect2i v = p_value; - bv.x = v.position.x; - bv.y = v.position.y; - bv.z = v.size.x; - bv.w = v.size.y; - } break; - case RS::GLOBAL_VAR_TYPE_UINT: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - uint32_t v = p_value; - bv.x = v; - bv.y = 0; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_UVEC2: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - Vector2i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_UVEC3: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - Vector3i v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = v.z; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_UVEC4: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; - Vector<int32_t> v = p_value; - bv.x = v.size() >= 1 ? v[0] : 0; - bv.y = v.size() >= 2 ? v[1] : 0; - bv.z = v.size() >= 3 ? v[2] : 0; - bv.w = v.size() >= 4 ? v[3] : 0; - } break; - case RS::GLOBAL_VAR_TYPE_FLOAT: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - float v = p_value; - bv.x = v; - bv.y = 0; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_VEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Vector2 v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = 0; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_VEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Vector3 v = p_value; - bv.x = v.x; - bv.y = v.y; - bv.z = v.z; - bv.w = 0; - } break; - case RS::GLOBAL_VAR_TYPE_VEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Plane v = p_value; - bv.x = v.normal.x; - bv.y = v.normal.y; - bv.z = v.normal.z; - bv.w = v.d; - } break; - case RS::GLOBAL_VAR_TYPE_COLOR: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Color v = p_value; - bv.x = v.r; - bv.y = v.g; - bv.z = v.b; - bv.w = v.a; - - GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; - v = v.to_linear(); - bv_linear.x = v.r; - bv_linear.y = v.g; - bv_linear.z = v.b; - bv_linear.w = v.a; - - } break; - case RS::GLOBAL_VAR_TYPE_RECT2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; - Rect2 v = p_value; - bv.x = v.position.x; - bv.y = v.position.y; - bv.z = v.size.x; - bv.w = v.size.y; - } break; - case RS::GLOBAL_VAR_TYPE_MAT2: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Vector<float> m2 = p_value; - if (m2.size() < 4) { - m2.resize(4); - } - bv[0].x = m2[0]; - bv[0].y = m2[1]; - bv[0].z = 0; - bv[0].w = 0; - - bv[1].x = m2[2]; - bv[1].y = m2[3]; - bv[1].z = 0; - bv[1].w = 0; - - } break; - case RS::GLOBAL_VAR_TYPE_MAT3: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Basis v = p_value; - bv[0].x = v.elements[0][0]; - bv[0].y = v.elements[1][0]; - bv[0].z = v.elements[2][0]; - bv[0].w = 0; - - bv[1].x = v.elements[0][1]; - bv[1].y = v.elements[1][1]; - bv[1].z = v.elements[2][1]; - bv[1].w = 0; - - bv[2].x = v.elements[0][2]; - bv[2].y = v.elements[1][2]; - bv[2].z = v.elements[2][2]; - bv[2].w = 0; - - } break; - case RS::GLOBAL_VAR_TYPE_MAT4: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - - Vector<float> m2 = p_value; - if (m2.size() < 16) { - m2.resize(16); - } - - bv[0].x = m2[0]; - bv[0].y = m2[1]; - bv[0].z = m2[2]; - bv[0].w = m2[3]; - - bv[1].x = m2[4]; - bv[1].y = m2[5]; - bv[1].z = m2[6]; - bv[1].w = m2[7]; - - bv[2].x = m2[8]; - bv[2].y = m2[9]; - bv[2].z = m2[10]; - bv[2].w = m2[11]; - - bv[3].x = m2[12]; - bv[3].y = m2[13]; - bv[3].z = m2[14]; - bv[3].w = m2[15]; - - } break; - case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Transform2D v = p_value; - bv[0].x = v.elements[0][0]; - bv[0].y = v.elements[0][1]; - bv[0].z = 0; - bv[0].w = 0; - - bv[1].x = v.elements[1][0]; - bv[1].y = v.elements[1][1]; - bv[1].z = 0; - bv[1].w = 0; - - bv[2].x = v.elements[2][0]; - bv[2].y = v.elements[2][1]; - bv[2].z = 1; - bv[2].w = 0; - - } break; - case RS::GLOBAL_VAR_TYPE_TRANSFORM: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; - Transform3D v = p_value; - bv[0].x = v.basis.elements[0][0]; - bv[0].y = v.basis.elements[1][0]; - bv[0].z = v.basis.elements[2][0]; - bv[0].w = 0; - - bv[1].x = v.basis.elements[0][1]; - bv[1].y = v.basis.elements[1][1]; - bv[1].z = v.basis.elements[2][1]; - bv[1].w = 0; - - bv[2].x = v.basis.elements[0][2]; - bv[2].y = v.basis.elements[1][2]; - bv[2].z = v.basis.elements[2][2]; - bv[2].w = 0; - - bv[3].x = v.origin.x; - bv[3].y = v.origin.y; - bv[3].z = v.origin.z; - bv[3].w = 1; - - } break; - default: { - ERR_FAIL(); - } - } -} - -void RendererStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { - int32_t prev_chunk = -1; - - for (int32_t i = 0; i < p_elements; i++) { - int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (chunk != prev_chunk) { - if (!global_variables.buffer_dirty_regions[chunk]) { - global_variables.buffer_dirty_regions[chunk] = true; - global_variables.buffer_dirty_region_count++; - } - } - - prev_chunk = chunk; - } -} - -void RendererStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { - ERR_FAIL_COND(global_variables.variables.has(p_name)); - GlobalVariables::Variable gv; - gv.type = p_type; - gv.value = p_value; - gv.buffer_index = -1; - - if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { - //is texture - global_variables.must_update_texture_materials = true; //normally there are none - } else { - gv.buffer_elements = 1; - if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { - //color needs to elements to store srgb and linear - gv.buffer_elements = 2; - } - if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) { - //color needs to elements to store srgb and linear - gv.buffer_elements = 3; - } - if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) { - //color needs to elements to store srgb and linear - gv.buffer_elements = 4; - } - - //is vector, allocate in buffer and update index - gv.buffer_index = _global_variable_allocate(gv.buffer_elements); - ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); - global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - - global_variables.must_update_buffer_materials = true; //normally there are none - } - - global_variables.variables[p_name] = gv; -} - -void RendererStorageRD::global_variable_remove(const StringName &p_name) { - if (!global_variables.variables.has(p_name)) { - return; - } - GlobalVariables::Variable &gv = global_variables.variables[p_name]; - - if (gv.buffer_index >= 0) { - global_variables.buffer_usage[gv.buffer_index].elements = 0; - global_variables.must_update_buffer_materials = true; - } else { - global_variables.must_update_texture_materials = true; - } - - global_variables.variables.erase(p_name); -} - -Vector<StringName> RendererStorageRD::global_variable_get_list() const { - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); - } - - const StringName *K = nullptr; - Vector<StringName> names; - while ((K = global_variables.variables.next(K))) { - names.push_back(*K); - } - names.sort_custom<StringName::AlphCompare>(); - return names; -} - -void RendererStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND(!global_variables.variables.has(p_name)); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; - gv.value = p_value; - if (gv.override.get_type() == Variant::NIL) { - if (gv.buffer_index >= 0) { - //buffer - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - } else { - //texture - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { - Material *material = material_owner.get_or_null(E->get()); - ERR_CONTINUE(!material); - _material_queue_update(material, false, true); - } - } - } -} - -void RendererStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) { - if (!global_variables.variables.has(p_name)) { - return; //variable may not exist - } - - ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - - GlobalVariables::Variable &gv = global_variables.variables[p_name]; - - gv.override = p_value; - - if (gv.buffer_index >= 0) { - //buffer - if (gv.override.get_type() == Variant::NIL) { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - } else { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); - } - - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - } else { - //texture - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { - Material *material = material_owner.get_or_null(E->get()); - ERR_CONTINUE(!material); - _material_queue_update(material, false, true); - } - } -} - -Variant RendererStorageRD::global_variable_get(const StringName &p_name) const { - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); - } - - if (!global_variables.variables.has(p_name)) { - return Variant(); - } - - return global_variables.variables[p_name].value; -} - -RS::GlobalVariableType RendererStorageRD::global_variable_get_type_internal(const StringName &p_name) const { - if (!global_variables.variables.has(p_name)) { - return RS::GLOBAL_VAR_TYPE_MAX; - } - - return global_variables.variables[p_name].type; -} - -RS::GlobalVariableType RendererStorageRD::global_variable_get_type(const StringName &p_name) const { - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); - } - - return global_variable_get_type_internal(p_name); -} - -void RendererStorageRD::global_variables_load_settings(bool p_load_textures) { - List<PropertyInfo> settings; - ProjectSettings::get_singleton()->get_property_list(&settings); - - for (const PropertyInfo &E : settings) { - if (E.name.begins_with("shader_globals/")) { - StringName name = E.name.get_slice("/", 1); - Dictionary d = ProjectSettings::get_singleton()->get(E.name); - - ERR_CONTINUE(!d.has("type")); - ERR_CONTINUE(!d.has("value")); - - String type = d["type"]; - - static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = { - "bool", - "bvec2", - "bvec3", - "bvec4", - "int", - "ivec2", - "ivec3", - "ivec4", - "rect2i", - "uint", - "uvec2", - "uvec3", - "uvec4", - "float", - "vec2", - "vec3", - "vec4", - "color", - "rect2", - "mat2", - "mat3", - "mat4", - "transform_2d", - "transform", - "sampler2D", - "sampler2DArray", - "sampler3D", - "samplerCube", - }; - - RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; - - for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { - if (global_var_type_names[i] == type) { - gvtype = RS::GlobalVariableType(i); - break; - } - } - - ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid - - Variant value = d["value"]; - - if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { - //textire - if (!p_load_textures) { - value = RID(); - continue; - } - - String path = value; - RES resource = ResourceLoader::load(path); - ERR_CONTINUE(resource.is_null()); - value = resource; - } - - if (global_variables.variables.has(name)) { - //has it, update it - global_variable_set(name, value); - } else { - global_variable_add(name, gvtype, value); - } - } - } -} - -void RendererStorageRD::global_variables_clear() { - global_variables.variables.clear(); //not right but for now enough -} - -RID RendererStorageRD::global_variables_get_storage_buffer() const { - return global_variables.buffer; -} - -int32_t RendererStorageRD::global_variables_instance_allocate(RID p_instance) { - ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); - int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - global_variables.instance_buffer_pos[p_instance] = pos; //save anyway - ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); - global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; - return pos; -} - -void RendererStorageRD::global_variables_instance_free(RID p_instance) { - ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); - int32_t pos = global_variables.instance_buffer_pos[p_instance]; - if (pos >= 0) { - global_variables.buffer_usage[pos].elements = 0; - } - global_variables.instance_buffer_pos.erase(p_instance); -} - -void RendererStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { - if (!global_variables.instance_buffer_pos.has(p_instance)) { - return; //just not allocated, ignore - } - int32_t pos = global_variables.instance_buffer_pos[p_instance]; - - if (pos < 0) { - return; //again, not allocated, ignore - } - ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported - - ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = { - ShaderLanguage::TYPE_MAX, //nil - ShaderLanguage::TYPE_BOOL, //bool - ShaderLanguage::TYPE_INT, //int - ShaderLanguage::TYPE_FLOAT, //float - ShaderLanguage::TYPE_MAX, //string - ShaderLanguage::TYPE_VEC2, //vec2 - ShaderLanguage::TYPE_IVEC2, //vec2i - ShaderLanguage::TYPE_VEC4, //rect2 - ShaderLanguage::TYPE_IVEC4, //rect2i - ShaderLanguage::TYPE_VEC3, // vec3 - ShaderLanguage::TYPE_IVEC3, //vec3i - ShaderLanguage::TYPE_MAX, //xform2d not supported here - ShaderLanguage::TYPE_VEC4, //plane - ShaderLanguage::TYPE_VEC4, //quat - ShaderLanguage::TYPE_MAX, //aabb not supported here - ShaderLanguage::TYPE_MAX, //basis not supported here - ShaderLanguage::TYPE_MAX, //xform not supported here - ShaderLanguage::TYPE_VEC4 //color - }; - - ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()]; - - ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported - - pos += p_index; - - _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer - _global_variable_mark_buffer_dirty(pos, 1); -} - -void RendererStorageRD::_update_global_variables() { - if (global_variables.buffer_dirty_region_count > 0) { - uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (total_regions / global_variables.buffer_dirty_region_count <= 4) { - // 25% of regions dirty, just update all buffer - RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); - } else { - uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - - for (uint32_t i = 0; i < total_regions; i++) { - if (global_variables.buffer_dirty_regions[i]) { - RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); - - global_variables.buffer_dirty_regions[i] = false; - } - } - } - - global_variables.buffer_dirty_region_count = 0; - } - - if (global_variables.must_update_buffer_materials) { - // only happens in the case of a buffer variable added or removed, - // so not often. - for (const RID &E : global_variables.materials_using_buffer) { - Material *material = material_owner.get_or_null(E); - ERR_CONTINUE(!material); //wtf - - _material_queue_update(material, true, false); - } - - global_variables.must_update_buffer_materials = false; - } - - if (global_variables.must_update_texture_materials) { - // only happens in the case of a buffer variable added or removed, - // so not often. - for (const RID &E : global_variables.materials_using_texture) { - Material *material = material_owner.get_or_null(E); - ERR_CONTINUE(!material); //wtf - - _material_queue_update(material, false, true); - } - - global_variables.must_update_texture_materials = false; - } -} - void RendererStorageRD::update_dirty_resources() { - _update_global_variables(); //must do before materials, so it can queue them for update - _update_queued_materials(); - _update_dirty_multimeshes(); - _update_dirty_skeletons(); + RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update + RendererRD::MaterialStorage::get_singleton()->_update_queued_materials(); + RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes(); + RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons(); RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas(); } @@ -7710,60 +3753,18 @@ bool RendererStorageRD::free(RID p_rid) { RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); } else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid); - } else if (shader_owner.owns(p_rid)) { - Shader *shader = shader_owner.get_or_null(p_rid); - //make material unreference this - while (shader->owners.size()) { - material_set_shader(shader->owners.front()->get()->self, RID()); - } - //clear data if exists - if (shader->data) { - memdelete(shader->data); - } - shader_owner.free(p_rid); - - } else if (material_owner.owns(p_rid)) { - Material *material = material_owner.get_or_null(p_rid); - material_set_shader(p_rid, RID()); //clean up shader - material->dependency.deleted_notify(p_rid); - - material_owner.free(p_rid); - } else if (mesh_owner.owns(p_rid)) { - mesh_clear(p_rid); - mesh_set_shadow_mesh(p_rid, RID()); - Mesh *mesh = mesh_owner.get_or_null(p_rid); - mesh->dependency.deleted_notify(p_rid); - if (mesh->instances.size()) { - ERR_PRINT("deleting mesh with active instances"); - } - if (mesh->shadow_owners.size()) { - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); - shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); - } - } - mesh_owner.free(p_rid); - } else if (mesh_instance_owner.owns(p_rid)) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid); - _mesh_instance_clear(mi); - mi->mesh->instances.erase(mi->I); - mi->I = nullptr; - - mesh_instance_owner.free(p_rid); - - } else if (multimesh_owner.owns(p_rid)) { - _update_dirty_multimeshes(); - multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); - MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid); - multimesh->dependency.deleted_notify(p_rid); - multimesh_owner.free(p_rid); - } else if (skeleton_owner.owns(p_rid)) { - _update_dirty_skeletons(); - skeleton_allocate_data(p_rid, 0); - Skeleton *skeleton = skeleton_owner.get_or_null(p_rid); - skeleton->dependency.deleted_notify(p_rid); - skeleton_owner.free(p_rid); + } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) { + RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid); + } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) { + RendererRD::MaterialStorage::get_singleton()->material_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { + RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) { + RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid); } else if (reflection_probe_owner.owns(p_rid)) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); reflection_probe->dependency.deleted_notify(p_rid); @@ -7902,20 +3903,7 @@ RendererStorageRD::RendererStorageRD() { base_singleton = this; RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - - for (int i = 0; i < SHADER_TYPE_MAX; i++) { - shader_data_request_func[i] = nullptr; - } - - static_assert(sizeof(GlobalVariables::Value) == 16); - - global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); - global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); - memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); - global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); - global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); //default samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { @@ -8005,120 +3993,6 @@ RendererStorageRD::RendererStorageRD() { //custom sampler sampler_rd_configure_custom(0.0f); - //default rd buffers - { - Vector<uint8_t> buffer; - { - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //normal - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //tangent - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //color - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 1.0; - fptr[2] = 1.0; - fptr[3] = 1.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //tex uv 1 - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - { //tex uv 2 - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //bones - buffer.resize(sizeof(uint32_t) * 4); - { - uint8_t *w = buffer.ptrw(); - uint32_t *fptr = (uint32_t *)w; - fptr[0] = 0; - fptr[1] = 0; - fptr[2] = 0; - fptr[3] = 0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - - { //weights - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); - } - } - using_lightmap_array = true; // high end if (using_lightmap_array) { uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); @@ -8144,8 +4018,8 @@ RendererStorageRD::RendererStorageRD() { particles_modes.push_back(""); particles_shader.shader.initialize(particles_modes, String()); } - shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); - material_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); + RendererRD::MaterialStorage::get_singleton()->shader_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); + RendererRD::MaterialStorage::get_singleton()->material_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -8209,9 +4083,9 @@ RendererStorageRD::RendererStorageRD() { { // default material and shader for particles shader - particles_shader.default_shader = shader_allocate(); - shader_initialize(particles_shader.default_shader); - shader_set_code(particles_shader.default_shader, R"( + particles_shader.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(particles_shader.default_shader); + material_storage->shader_set_code(particles_shader.default_shader, R"( // Default particles shader. shader_type particles; @@ -8220,11 +4094,11 @@ void process() { COLOR = vec4(1.0); } )"); - particles_shader.default_material = material_allocate(); - material_initialize(particles_shader.default_material); - material_set_shader(particles_shader.default_material, particles_shader.default_shader); + particles_shader.default_material = material_storage->material_allocate(); + material_storage->material_initialize(particles_shader.default_material); + material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES); + ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -8254,15 +4128,13 @@ void process() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.append_id(global_variables_get_storage_buffer()); + u.append_id(material_storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0); } - default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); - { Vector<String> copy_modes; for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { @@ -8305,37 +4177,10 @@ void process() { rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i)); } } - { - Vector<String> skeleton_modes; - skeleton_modes.push_back("\n#define MODE_2D\n"); - skeleton_modes.push_back(""); - - skeleton_shader.shader.initialize(skeleton_modes); - skeleton_shader.version = skeleton_shader.shader.version_create(); - for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) { - skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i); - skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]); - } - - { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(default_rd_storage_buffer); - uniforms.push_back(u); - } - skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); - } - } } RendererStorageRD::~RendererStorageRD() { - memdelete_arr(global_variables.buffer_values); - memdelete_arr(global_variables.buffer_usage); - memdelete_arr(global_variables.buffer_dirty_regions); - RD::get_singleton()->free(global_variables.buffer); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); //def samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { @@ -8353,20 +4198,11 @@ RendererStorageRD::~RendererStorageRD() { } } - //def buffers - for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { - RD::get_singleton()->free(mesh_default_rd_buffers[i]); - } - particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); rt_sdf.shader.version_free(rt_sdf.shader_version); - skeleton_shader.shader.version_free(skeleton_shader.version); - - RenderingServer::get_singleton()->free(particles_shader.default_material); - RenderingServer::get_singleton()->free(particles_shader.default_shader); - - RD::get_singleton()->free(default_rd_storage_buffer); + material_storage->material_free(particles_shader.default_material); + material_storage->shader_free(particles_shader.default_shader); if (effects) { memdelete(effects); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 3aa475b34d..4c45dd4295 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -39,10 +39,8 @@ #include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h" -#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" -#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" @@ -127,331 +125,11 @@ public: } } - enum ShaderType { - SHADER_TYPE_2D, - SHADER_TYPE_3D, - SHADER_TYPE_PARTICLES, - SHADER_TYPE_SKY, - SHADER_TYPE_FOG, - SHADER_TYPE_MAX - }; - - struct ShaderData { - virtual void set_code(const String &p_Code) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; - virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; - - virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0; - virtual bool is_param_texture(const StringName &p_param) const = 0; - virtual bool is_animated() const = 0; - virtual bool casts_shadows() const = 0; - virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; - virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } - - virtual ~ShaderData() {} - }; - - typedef ShaderData *(*ShaderDataRequestFunction)(); - - struct MaterialData { - void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - - virtual void set_render_priority(int p_priority) = 0; - virtual void set_next_pass(RID p_pass) = 0; - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; - virtual ~MaterialData(); - - //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void free_parameters_uniform_set(RID p_uniform_set); - - private: - friend class RendererStorageRD; - RID self; - List<RID>::Element *global_buffer_E = nullptr; - List<RID>::Element *global_texture_E = nullptr; - uint64_t global_textures_pass = 0; - Map<StringName, uint64_t> used_global_textures; - - //internally by update_parameters_uniform_set - Vector<uint8_t> ubo_data; - RID uniform_buffer; - Vector<RID> texture_cache; - }; - typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); - static void _material_uniform_set_erased(void *p_material); - - enum DefaultRDBuffer { - DEFAULT_RD_BUFFER_VERTEX, - DEFAULT_RD_BUFFER_NORMAL, - DEFAULT_RD_BUFFER_TANGENT, - DEFAULT_RD_BUFFER_COLOR, - DEFAULT_RD_BUFFER_TEX_UV, - DEFAULT_RD_BUFFER_TEX_UV2, - DEFAULT_RD_BUFFER_CUSTOM0, - DEFAULT_RD_BUFFER_CUSTOM1, - DEFAULT_RD_BUFFER_CUSTOM2, - DEFAULT_RD_BUFFER_CUSTOM3, - DEFAULT_RD_BUFFER_BONES, - DEFAULT_RD_BUFFER_WEIGHTS, - DEFAULT_RD_BUFFER_MAX, - }; - private: /* TEXTURE API */ RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - RID default_rd_storage_buffer; - - /* SHADER */ - - struct Material; - - struct Shader { - ShaderData *data; - String code; - ShaderType type; - Map<StringName, Map<int, RID>> default_texture_parameter; - Set<Material *> owners; - }; - - ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; - mutable RID_Owner<Shader, true> shader_owner; - - /* Material */ - - struct Material { - RID self; - MaterialData *data = nullptr; - Shader *shader = nullptr; - //shortcut to shader data and type - ShaderType shader_type = SHADER_TYPE_MAX; - uint32_t shader_id = 0; - bool uniform_dirty = false; - bool texture_dirty = false; - Map<StringName, Variant> params; - int32_t priority = 0; - RID next_pass; - SelfList<Material> update_element; - - Dependency dependency; - - Material() : - update_element(this) {} - }; - - MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; - mutable RID_Owner<Material, true> material_owner; - - SelfList<Material>::List material_update_list; - void _material_queue_update(Material *material, bool p_uniform, bool p_texture); - void _update_queued_materials(); - - /* Mesh */ - - struct MeshInstance; - - struct Mesh { - struct Surface { - RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; - uint32_t format = 0; - - RID vertex_buffer; - RID attribute_buffer; - RID skin_buffer; - uint32_t vertex_count = 0; - uint32_t vertex_buffer_size = 0; - uint32_t skin_buffer_size = 0; - - // A different pipeline needs to be allocated - // depending on the inputs available in the - // material. - // There are never that many geometry/material - // combinations, so a simple array is the most - // cache-efficient structure. - - struct Version { - uint32_t input_mask = 0; - RD::VertexFormatID vertex_format = 0; - RID vertex_array; - }; - - SpinLock version_lock; //needed to access versions - Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; - - RID index_buffer; - RID index_array; - uint32_t index_count = 0; - - struct LOD { - float edge_length = 0.0; - uint32_t index_count = 0; - RID index_buffer; - RID index_array; - }; - - LOD *lods = nullptr; - uint32_t lod_count = 0; - - AABB aabb; - - Vector<AABB> bone_aabbs; - - RID blend_shape_buffer; - - RID material; - - uint32_t render_index = 0; - uint64_t render_pass = 0; - - uint32_t multimesh_render_index = 0; - uint64_t multimesh_render_pass = 0; - - uint32_t particles_render_index = 0; - uint64_t particles_render_pass = 0; - - RID uniform_set; - }; - - uint32_t blend_shape_count = 0; - RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; - - Surface **surfaces = nullptr; - uint32_t surface_count = 0; - - Vector<AABB> bone_aabbs; - - bool has_bone_weights = false; - - AABB aabb; - AABB custom_aabb; - - Vector<RID> material_cache; - - List<MeshInstance *> instances; - - RID shadow_mesh; - Set<Mesh *> shadow_owners; - - Dependency dependency; - }; - - mutable RID_Owner<Mesh, true> mesh_owner; - - struct MeshInstance { - Mesh *mesh; - RID skeleton; - struct Surface { - RID vertex_buffer; - RID uniform_set; - - Mesh::Surface::Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; - }; - LocalVector<Surface> surfaces; - LocalVector<float> blend_weights; - - RID blend_weights_buffer; - List<MeshInstance *>::Element *I = nullptr; //used to erase itself - uint64_t skeleton_version = 0; - bool dirty = false; - bool weights_dirty = false; - SelfList<MeshInstance> weight_update_list; - SelfList<MeshInstance> array_update_list; - MeshInstance() : - weight_update_list(this), array_update_list(this) {} - }; - - void _mesh_instance_clear(MeshInstance *mi); - void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); - - mutable RID_Owner<MeshInstance> mesh_instance_owner; - - SelfList<MeshInstance>::List dirty_mesh_instance_weights; - SelfList<MeshInstance>::List dirty_mesh_instance_arrays; - - struct SkeletonShader { - struct PushConstant { - uint32_t has_normal; - uint32_t has_tangent; - uint32_t has_skeleton; - uint32_t has_blend_shape; - - uint32_t vertex_count; - uint32_t vertex_stride; - uint32_t skin_stride; - uint32_t skin_weight_offset; - - uint32_t blend_shape_count; - uint32_t normalized_blend_shapes; - uint32_t pad0; - uint32_t pad1; - }; - - enum { - UNIFORM_SET_INSTANCE = 0, - UNIFORM_SET_SURFACE = 1, - UNIFORM_SET_SKELETON = 2, - }; - enum { - SHADER_MODE_2D, - SHADER_MODE_3D, - SHADER_MODE_MAX - }; - - SkeletonShaderRD shader; - RID version; - RID version_shader[SHADER_MODE_MAX]; - RID pipeline[SHADER_MODE_MAX]; - - RID default_skeleton_uniform_set; - } skeleton_shader; - - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); - - RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - - /* MultiMesh */ - struct MultiMesh { - RID mesh; - int instances = 0; - RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; - bool uses_colors = false; - bool uses_custom_data = false; - int visible_instances = -1; - AABB aabb; - bool aabb_dirty = false; - bool buffer_set = false; - uint32_t stride_cache = 0; - uint32_t color_offset_cache = 0; - uint32_t custom_data_offset_cache = 0; - - Vector<float> data_cache; //used if individual setting is used - bool *data_cache_dirty_regions = nullptr; - uint32_t data_cache_used_dirty_regions = 0; - - RID buffer; //storage buffer - RID uniform_set_3d; - RID uniform_set_2d; - - bool dirty = false; - MultiMesh *dirty_list = nullptr; - - Dependency dependency; - }; - - mutable RID_Owner<MultiMesh, true> multimesh_owner; - - MultiMesh *multimesh_dirty_list = nullptr; - - _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; - _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); - _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); - _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); - void _update_dirty_multimeshes(); /* PARTICLES */ @@ -714,7 +392,7 @@ private: Particles *particle_update_list = nullptr; - struct ParticlesShaderData : public ShaderData { + struct ParticlesShaderData : public RendererRD::ShaderData { bool valid; RID version; bool uses_collision = false; @@ -740,7 +418,7 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; @@ -751,12 +429,12 @@ private: virtual ~ParticlesShaderData(); }; - ShaderData *_create_particles_shader_func(); - static RendererStorageRD::ShaderData *_create_particles_shader_funcs() { + RendererRD::ShaderData *_create_particles_shader_func(); + static RendererRD::ShaderData *_create_particles_shader_funcs() { return base_singleton->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialData { + struct ParticlesMaterialData : public RendererRD::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; @@ -766,8 +444,8 @@ private: virtual ~ParticlesMaterialData(); }; - MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { + RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); + static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) { return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); } @@ -829,34 +507,6 @@ private: mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner; - /* Skeleton */ - - struct Skeleton { - bool use_2d = false; - int size = 0; - Vector<float> data; - RID buffer; - - bool dirty = false; - Skeleton *dirty_list = nullptr; - Transform2D base_transform_2d; - - RID uniform_set_3d; - RID uniform_set_mi; - - uint64_t version = 1; - - Dependency dependency; - }; - - mutable RID_Owner<Skeleton, true> skeleton_owner; - - _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton); - - Skeleton *skeleton_dirty_list = nullptr; - - void _update_dirty_skeletons(); - /* LIGHT */ struct Light { @@ -1054,72 +704,6 @@ private: RID pipelines[SHADER_MAX]; } rt_sdf; - /* GLOBAL SHADER VARIABLES */ - - struct GlobalVariables { - enum { - BUFFER_DIRTY_REGION_SIZE = 1024 - }; - struct Variable { - Set<RID> texture_materials; // materials using this - - RS::GlobalVariableType type; - Variant value; - Variant override; - int32_t buffer_index; //for vectors - int32_t buffer_elements; //for vectors - }; - - HashMap<StringName, Variable> variables; - - struct Value { - float x; - float y; - float z; - float w; - }; - - struct ValueInt { - int32_t x; - int32_t y; - int32_t z; - int32_t w; - }; - - struct ValueUInt { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; - }; - - struct ValueUsage { - uint32_t elements = 0; - }; - - List<RID> materials_using_buffer; - List<RID> materials_using_texture; - - RID buffer; - Value *buffer_values; - ValueUsage *buffer_usage; - bool *buffer_dirty_regions; - uint32_t buffer_dirty_region_count = 0; - - uint32_t buffer_size; - - bool must_update_texture_materials = false; - bool must_update_buffer_materials = false; - - HashMap<RID, int32_t> instance_buffer_pos; - - } global_variables; - - int32_t _global_variable_allocate(uint32_t p_elements); - void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); - void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); - - void _update_global_variables(); /* EFFECTS */ EffectsRD *effects = nullptr; @@ -1138,412 +722,6 @@ public: void sampler_rd_set_default(float p_mipmap_bias); - /* SHADER API */ - - RID shader_allocate(); - void shader_initialize(RID p_shader); - - void shader_set_code(RID p_shader, const String &p_code); - String shader_get_code(RID p_shader) const; - void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index); - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const; - Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; - void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); - - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const; - - /* COMMON MATERIAL API */ - - RID material_allocate(); - void material_initialize(RID p_material); - - void material_set_shader(RID p_material, RID p_shader); - - void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value); - Variant material_get_param(RID p_material, const StringName &p_param) const; - - void material_set_next_pass(RID p_material, RID p_next_material); - void material_set_render_priority(RID p_material, int priority); - - bool material_is_animated(RID p_material); - bool material_casts_shadows(RID p_material); - - void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters); - - void material_update_dependency(RID p_material, DependencyTracker *p_instance); - - void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); - - _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { - Material *material = material_owner.get_or_null(p_material); - return material->shader_id; - } - - _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { - Material *material = material_owner.get_or_null(p_material); - if (!material || material->shader_type != p_shader_type) { - return nullptr; - } else { - return material->data; - } - } - - /* MESH API */ - - RID mesh_allocate(); - void mesh_initialize(RID p_mesh); - - virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count); - - /// Return stride - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface); - - virtual int mesh_get_blend_shape_count(RID p_mesh) const; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode); - virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; - - virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); - virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); - virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const; - - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()); - virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh); - - virtual void mesh_clear(RID p_mesh); - - virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton); - - /* MESH INSTANCE */ - - virtual RID mesh_instance_create(RID p_base); - virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton); - virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight); - virtual void mesh_instance_check_for_update(RID p_mesh_instance); - virtual void update_mesh_instances(); - - _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); - r_surface_count = mesh->surface_count; - if (r_surface_count == 0) { - return nullptr; - } - if (mesh->material_cache.is_empty()) { - mesh->material_cache.resize(mesh->surface_count); - for (uint32_t i = 0; i < r_surface_count; i++) { - mesh->material_cache.write[i] = mesh->surfaces[i]->material; - } - } - - return mesh->material_cache.ptr(); - } - - _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); - ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr); - - return mesh->surfaces[p_surface_index]; - } - - _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - - return mesh->shadow_mesh; - } - - _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) { - Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface); - return surface->primitive; - } - - _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - return s->lod_count > 0; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - return s->index_count ? s->index_count : s->vertex_count; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - - int32_t current_lod = -1; - if (r_index_count) { - *r_index_count = s->index_count; - } - for (uint32_t i = 0; i < s->lod_count; i++) { - float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold; - if (screen_size > p_mesh_lod_threshold) { - break; - } - current_lod = i; - } - if (current_lod == -1) { - return 0; - } else { - if (r_index_count) { - *r_index_count = s->lods[current_lod].index_count; - } - return current_lod + 1; - } - } - - _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - - if (p_lod == 0) { - return s->index_array; - } else { - return s->lods[p_lod - 1].index_array; - } - } - - _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { - Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); - - s->version_lock.lock(); - - //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way - - for (uint32_t i = 0; i < s->version_count; i++) { - if (s->versions[i].input_mask != p_input_mask) { - continue; - } - //we have this version, hooray - r_vertex_format = s->versions[i].vertex_format; - r_vertex_array_rd = s->versions[i].vertex_array; - s->version_lock.unlock(); - return; - } - - uint32_t version = s->version_count; - s->version_count++; - s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); - - _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask); - - r_vertex_format = s->versions[version].vertex_format; - r_vertex_array_rd = s->versions[version].vertex_array; - - s->version_lock.unlock(); - } - - _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { - MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - ERR_FAIL_COND(!mi); - Mesh *mesh = mi->mesh; - ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); - - MeshInstance::Surface *mis = &mi->surfaces[p_surface_index]; - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - s->version_lock.lock(); - - //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way - - for (uint32_t i = 0; i < mis->version_count; i++) { - if (mis->versions[i].input_mask != p_input_mask) { - continue; - } - //we have this version, hooray - r_vertex_format = mis->versions[i].vertex_format; - r_vertex_array_rd = mis->versions[i].vertex_array; - s->version_lock.unlock(); - return; - } - - uint32_t version = mis->version_count; - mis->version_count++; - mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); - - _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis); - - r_vertex_format = mis->versions[version].vertex_format; - r_vertex_array_rd = mis->versions[version].vertex_array; - - s->version_lock.unlock(); - } - - _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { - ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); - return mesh_default_rd_buffers[p_buffer]; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->render_pass != p_render_pass) { - (*r_index)++; - s->render_pass = p_render_pass; - s->render_index = *r_index; - } - - return s->render_index; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->multimesh_render_pass != p_render_pass) { - (*r_index)++; - s->multimesh_render_pass = p_render_pass; - s->multimesh_render_index = *r_index; - } - - return s->multimesh_render_index; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.get_or_null(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->particles_render_pass != p_render_pass) { - (*r_index)++; - s->particles_render_pass = p_render_pass; - s->particles_render_index = *r_index; - } - - return s->particles_render_index; - } - - /* MULTIMESH API */ - - RID multimesh_allocate(); - void multimesh_initialize(RID p_multimesh); - - void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false); - int multimesh_get_instance_count(RID p_multimesh) const; - - void multimesh_set_mesh(RID p_multimesh, RID p_mesh); - void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform); - void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); - void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); - void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color); - - RID multimesh_get_mesh(RID p_multimesh) const; - - Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const; - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; - Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; - - void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer); - Vector<float> multimesh_get_buffer(RID p_multimesh) const; - - void multimesh_set_visible_instances(RID p_multimesh, int p_visible); - int multimesh_get_visible_instances(RID p_multimesh) const; - - AABB multimesh_get_aabb(RID p_multimesh) const; - - _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - return multimesh->xform_format; - } - - _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - return multimesh->uses_colors; - } - - _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - return multimesh->uses_custom_data; - } - - _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - if (multimesh->visible_instances >= 0) { - return multimesh->visible_instances; - } - return multimesh->instances; - } - - _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - if (!multimesh->uniform_set_3d.is_valid()) { - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(multimesh->buffer); - uniforms.push_back(u); - multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return multimesh->uniform_set_3d; - } - - _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - if (!multimesh->uniform_set_2d.is_valid()) { - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(multimesh->buffer); - uniforms.push_back(u); - multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return multimesh->uniform_set_2d; - } - - /* SKELETON API */ - - RID skeleton_allocate(); - void skeleton_initialize(RID p_skeleton); - - void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false); - void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); - void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform); - int skeleton_get_bone_count(RID p_skeleton) const; - void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform); - Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; - void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); - Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; - - _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) { - return skeleton_owner.get_or_null(p_skeleton) != nullptr; - } - - _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { - Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, RID()); - ERR_FAIL_COND_V(skeleton->size == 0, RID()); - if (skeleton->use_2d) { - return RID(); - } - if (!skeleton->uniform_set_3d.is_valid()) { - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(skeleton->buffer); - uniforms.push_back(u); - skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return skeleton->uniform_set_3d; - } /* Light API */ void _light_initialize(RID p_rid, RS::LightType p_type); @@ -1713,7 +891,6 @@ public: float reflection_probe_get_ambient_color_energy(RID p_probe) const; void base_update_dependency(RID p_base, DependencyTracker *p_instance); - void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance); /* VOXEL GI API */ @@ -1972,27 +1149,6 @@ public: virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform); virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active); - /* GLOBAL VARIABLES API */ - - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value); - virtual void global_variable_remove(const StringName &p_name); - virtual Vector<StringName> global_variable_get_list() const; - - virtual void global_variable_set(const StringName &p_name, const Variant &p_value); - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value); - virtual Variant global_variable_get(const StringName &p_name) const; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const; - RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; - - virtual void global_variables_load_settings(bool p_load_textures = true); - virtual void global_variables_clear(); - - virtual int32_t global_variables_instance_allocate(RID p_instance); - virtual void global_variables_instance_free(RID p_instance); - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value); - - RID global_variables_get_storage_buffer() const; - /* RENDER TARGET API */ RID render_target_create(); @@ -2065,8 +1221,6 @@ public: virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; virtual String get_captured_timestamp_name(uint32_t p_index) const; - RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } - static RendererStorageRD *base_singleton; void init_effects(bool p_prefer_raster_effects); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 4e6e50bc44..abe1a09b06 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -499,14 +499,14 @@ layout(location = 1) out uvec2 voxel_gi_buffer; #endif //MODE_RENDER_NORMAL #else // RENDER DEPTH -#ifdef MODE_MULTIPLE_RENDER_TARGETS +#ifdef MODE_SEPARATE_SPECULAR layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter) #else layout(location = 0) out vec4 frag_color; -#endif // MODE_MULTIPLE_RENDER_TARGETS +#endif // MODE_SEPARATE_SPECULAR #endif // RENDER DEPTH @@ -1966,7 +1966,7 @@ void main() { //restore fog fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba)); -#ifdef MODE_MULTIPLE_RENDER_TARGETS +#ifdef MODE_SEPARATE_SPECULAR #ifdef MODE_UNSHADED diffuse_buffer = vec4(albedo.rgb, 0.0); @@ -1984,7 +1984,7 @@ void main() { diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a); specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); -#else //MODE_MULTIPLE_RENDER_TARGETS +#else //MODE_SEPARATE_SPECULAR #ifdef MODE_UNSHADED frag_color = vec4(albedo, alpha); @@ -1996,7 +1996,7 @@ void main() { // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); -#endif //MODE_MULTIPLE_RENDER_TARGETS +#endif //MODE_SEPARATE_SPECULAR #endif //MODE_RENDER_DEPTH } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp new file mode 100644 index 0000000000..9e3d124bbb --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -0,0 +1,2392 @@ +/*************************************************************************/ +/* material_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "material_storage.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/io/resource_loader.h" +#include "texture_storage.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// UBI helper functions + +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) { + switch (type) { + case ShaderLanguage::TYPE_BOOL: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = (r[i] != 0) ? 1 : 0; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + bool v = value; + gui[0] = v ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_BVEC2: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + int count = 2 * p_array_size; + + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i] ? 1 : 0; + gui[j + 1] = r[i + 1] ? 1 : 0; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = v & 1 ? 1 : 0; + gui[1] = v & 2 ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_BVEC3: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + int count = 3 * p_array_size; + + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i] ? 1 : 0; + gui[j + 1] = r[i + 1] ? 1 : 0; + gui[j + 2] = r[i + 2] ? 1 : 0; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = (v & 1) ? 1 : 0; + gui[1] = (v & 2) ? 1 : 0; + gui[2] = (v & 4) ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_BVEC4: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + const PackedInt32Array &ba = value; + int s = ba.size(); + const int *r = ba.ptr(); + int count = 4 * p_array_size; + + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i] ? 1 : 0; + gui[i + 1] = r[i + 1] ? 1 : 0; + gui[i + 2] = r[i + 2] ? 1 : 0; + gui[i + 3] = r[i + 3] ? 1 : 0; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } else { + int v = value; + gui[0] = (v & 1) ? 1 : 0; + gui[1] = (v & 2) ? 1 : 0; + gui[2] = (v & 4) ? 1 : 0; + gui[3] = (v & 8) ? 1 : 0; + } + } break; + case ShaderLanguage::TYPE_INT: { + int32_t *gui = (int32_t *)data; + + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + const int *r = iv.ptr(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = r[i]; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = v; + } + } break; + case ShaderLanguage::TYPE_IVEC2: { + Vector<int> iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 2 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_IVEC3: { + Vector<int> iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_IVEC4: { + Vector<int> iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } break; + case ShaderLanguage::TYPE_UINT: { + uint32_t *gui = (uint32_t *)data; + + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + const int *r = iv.ptr(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = r[i]; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + int v = value; + gui[0] = v; + } + } break; + case ShaderLanguage::TYPE_UVEC2: { + Vector<int> iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 2 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + Vector<int> iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_UVEC4: { + Vector<int> iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i++) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = a[i]; + } else { + gui[j] = 0; + } + gui[j + 1] = 0; // ignored + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + float v = value; + gui[0] = v; + } + } break; + case ShaderLanguage::TYPE_VEC2: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedVector2Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = a[i].x; + gui[j + 1] = a[i].y; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + } + } else { + Vector2 v = value; + gui[0] = v.x; + gui[1] = v.y; + } + } break; + case ShaderLanguage::TYPE_VEC3: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedVector3Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + gui[j] = a[i].x; + gui[j + 1] = a[i].y; + gui[j + 2] = a[i].z; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } else { + Vector3 v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + } + } break; + case ShaderLanguage::TYPE_VEC4: { + float *gui = (float *)data; + + if (p_array_size > 0) { + if (value.get_type() == Variant::PACKED_COLOR_ARRAY) { + const PackedColorArray &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { + if (i < s) { + Color color = a[i]; + if (p_linear_color) { + color = color.to_linear(); + } + gui[j] = color.r; + gui[j + 1] = color.g; + gui[j + 2] = color.b; + gui[j + 3] = color.a; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + gui[j + 3] = 0; + } + } + } else { + const PackedFloat32Array &a = value; + int s = a.size(); + int count = 4 * p_array_size; + + for (int i = 0; i < count; i += 4) { + if (i + 3 < s) { + gui[i] = a[i]; + gui[i + 1] = a[i + 1]; + gui[i + 2] = a[i + 2]; + gui[i + 3] = a[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } + } else { + if (value.get_type() == Variant::COLOR) { + Color v = value; + + if (p_linear_color) { + v = v.to_linear(); + } + + gui[0] = v.r; + gui[1] = v.g; + gui[2] = v.b; + gui[3] = v.a; + } else if (value.get_type() == Variant::RECT2) { + Rect2 v = value; + + gui[0] = v.position.x; + gui[1] = v.position.y; + gui[2] = v.size.x; + gui[3] = v.size.y; + } else if (value.get_type() == Variant::QUATERNION) { + Quaternion v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; + } else { + Plane v = value; + + gui[0] = v.normal.x; + gui[1] = v.normal.y; + gui[2] = v.normal.z; + gui[3] = v.d; + } + } + } break; + case ShaderLanguage::TYPE_MAT2: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) { + if (i + 3 < s) { + gui[j] = a[i]; + gui[j + 1] = a[i + 1]; + + gui[j + 4] = a[i + 2]; + gui[j + 5] = a[i + 3]; + } else { + gui[j] = 1; + gui[j + 1] = 0; + + gui[j + 4] = 0; + gui[j + 5] = 1; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored + gui[j + 6] = 0; // ignored + gui[j + 7] = 0; // ignored + } + } else { + Transform2D v = value; + + //in std140 members of mat2 are treated as vec4s + gui[0] = v.elements[0][0]; + gui[1] = v.elements[0][1]; + gui[2] = 0; // ignored + gui[3] = 0; // ignored + + gui[4] = v.elements[1][0]; + gui[5] = v.elements[1][1]; + gui[6] = 0; // ignored + gui[7] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_MAT3: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) { + if (i + 8 < s) { + gui[j] = a[i]; + gui[j + 1] = a[i + 1]; + gui[j + 2] = a[i + 2]; + + gui[j + 4] = a[i + 3]; + gui[j + 5] = a[i + 4]; + gui[j + 6] = a[i + 5]; + + gui[j + 8] = a[i + 6]; + gui[j + 9] = a[i + 7]; + gui[j + 10] = a[i + 8]; + } else { + gui[j] = 1; + gui[j + 1] = 0; + gui[j + 2] = 0; + + gui[j + 4] = 0; + gui[j + 5] = 1; + gui[j + 6] = 0; + + gui[j + 8] = 0; + gui[j + 9] = 0; + gui[j + 10] = 1; + } + gui[j + 3] = 0; // ignored + gui[j + 7] = 0; // ignored + gui[j + 11] = 0; // ignored + } + } else { + Basis v = value; + gui[0] = v.elements[0][0]; + gui[1] = v.elements[1][0]; + gui[2] = v.elements[2][0]; + gui[3] = 0; // ignored + + gui[4] = v.elements[0][1]; + gui[5] = v.elements[1][1]; + gui[6] = v.elements[2][1]; + gui[7] = 0; // ignored + + gui[8] = v.elements[0][2]; + gui[9] = v.elements[1][2]; + gui[10] = v.elements[2][2]; + gui[11] = 0; // ignored + } + } break; + case ShaderLanguage::TYPE_MAT4: { + float *gui = (float *)data; + + if (p_array_size > 0) { + const PackedFloat32Array &a = value; + int s = a.size(); + + for (int i = 0; i < p_array_size * 16; i += 16) { + if (i + 15 < s) { + gui[i] = a[i]; + gui[i + 1] = a[i + 1]; + gui[i + 2] = a[i + 2]; + gui[i + 3] = a[i + 3]; + + gui[i + 4] = a[i + 4]; + gui[i + 5] = a[i + 5]; + gui[i + 6] = a[i + 6]; + gui[i + 7] = a[i + 7]; + + gui[i + 8] = a[i + 8]; + gui[i + 9] = a[i + 9]; + gui[i + 10] = a[i + 10]; + gui[i + 11] = a[i + 11]; + + gui[i + 12] = a[i + 12]; + gui[i + 13] = a[i + 13]; + gui[i + 14] = a[i + 14]; + gui[i + 15] = a[i + 15]; + } else { + gui[i] = 1; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + + gui[i + 4] = 0; + gui[i + 5] = 1; + gui[i + 6] = 0; + gui[i + 7] = 0; + + gui[i + 8] = 0; + gui[i + 9] = 0; + gui[i + 10] = 1; + gui[i + 11] = 0; + + gui[i + 12] = 0; + gui[i + 13] = 0; + gui[i + 14] = 0; + gui[i + 15] = 1; + } + } + } else { + Transform3D v = value; + gui[0] = v.basis.elements[0][0]; + gui[1] = v.basis.elements[1][0]; + gui[2] = v.basis.elements[2][0]; + gui[3] = 0; + + gui[4] = v.basis.elements[0][1]; + gui[5] = v.basis.elements[1][1]; + gui[6] = v.basis.elements[2][1]; + gui[7] = 0; + + gui[8] = v.basis.elements[0][2]; + gui[9] = v.basis.elements[1][2]; + gui[10] = v.basis.elements[2][2]; + gui[11] = 0; + + gui[12] = v.origin.x; + gui[13] = v.origin.y; + gui[14] = v.origin.z; + gui[15] = 1; + } + } break; + default: { + } + } +} + +_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) { + switch (type) { + case ShaderLanguage::TYPE_BOOL: { + uint32_t *gui = (uint32_t *)data; + *gui = value[0].boolean ? 1 : 0; + } break; + case ShaderLanguage::TYPE_BVEC2: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + gui[2] = value[2].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + gui[2] = value[2].boolean ? 1 : 0; + gui[3] = value[3].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_INT: { + int32_t *gui = (int32_t *)data; + gui[0] = value[0].sint; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_IVEC4: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_UINT: { + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].uint; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].uint; + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].uint; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].uint; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + float *gui = (float *)data; + gui[0] = value[0].real; + + } break; + case ShaderLanguage::TYPE_VEC2: { + float *gui = (float *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC3: { + float *gui = (float *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC4: { + float *gui = (float *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT2: { + float *gui = (float *)data; + + //in std140 members of mat2 are treated as vec4s + gui[0] = value[0].real; + gui[1] = value[1].real; + gui[2] = 0; + gui[3] = 0; + gui[4] = value[2].real; + gui[5] = value[3].real; + gui[6] = 0; + gui[7] = 0; + } break; + case ShaderLanguage::TYPE_MAT3: { + float *gui = (float *)data; + + gui[0] = value[0].real; + gui[1] = value[1].real; + gui[2] = value[2].real; + gui[3] = 0; + gui[4] = value[3].real; + gui[5] = value[4].real; + gui[6] = value[5].real; + gui[7] = 0; + gui[8] = value[6].real; + gui[9] = value[7].real; + gui[10] = value[8].real; + gui[11] = 0; + } break; + case ShaderLanguage::TYPE_MAT4: { + float *gui = (float *)data; + + for (int i = 0; i < 16; i++) { + gui[i] = value[i].real; + } + } break; + default: { + } + } +} + +_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) { + if (p_array_size <= 0) { + p_array_size = 1; + } + + switch (type) { + case ShaderLanguage::TYPE_BOOL: + case ShaderLanguage::TYPE_INT: + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_FLOAT: { + memset(data, 0, 4 * p_array_size); + } break; + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_VEC2: { + memset(data, 0, 8 * p_array_size); + } break; + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_VEC3: + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: + case ShaderLanguage::TYPE_VEC4: { + memset(data, 0, 16 * p_array_size); + } break; + case ShaderLanguage::TYPE_MAT2: { + memset(data, 0, 32 * p_array_size); + } break; + case ShaderLanguage::TYPE_MAT3: { + memset(data, 0, 48 * p_array_size); + } break; + case ShaderLanguage::TYPE_MAT4: { + memset(data, 0, 64 * p_array_size); + } break; + + default: { + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// MaterialData + +void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + bool uses_global_buffer = false; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) { + if (E.value.order < 0) { + continue; // texture, does not go here + } + + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; //instance uniforms don't appear in the buffer + } + + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { + //this is a global variable, get the index to it + GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key); + uint32_t index = 0; + if (gv) { + index = gv->buffer_index; + } else { + WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly."); + } + + uint32_t offset = p_uniform_offsets[E.value.order]; + uint32_t *intptr = (uint32_t *)&p_buffer[offset]; + *intptr = index; + uses_global_buffer = true; + continue; + } + + //regular uniform + uint32_t offset = p_uniform_offsets[E.value.order]; +#ifdef DEBUG_ENABLED + uint32_t size = 0U; + // The following code enforces a 16-byte alignment of uniform arrays. + if (E.value.array_size > 0) { + size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size; + int m = (16 * E.value.array_size); + if ((size % m) != 0U) { + size += m - (size % m); + } + } else { + size = ShaderLanguage::get_datatype_size(E.value.type); + } + ERR_CONTINUE(offset + size > p_buffer_size); +#endif + uint8_t *data = &p_buffer[offset]; + const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); + + if (V) { + //user provided + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); + + } else if (E.value.default_value.size()) { + //default value + _fill_std140_ubo_value(E.value.type, E.value.default_value, data); + //value=E.value.default_value; + } else { + //zero because it was not provided + if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + //colors must be set as black, with alpha as 1.0 + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color); + } else { + //else just zero it out + _fill_std140_ubo_empty(E.value.type, E.value.array_size, data); + } + } + } + + if (uses_global_buffer != (global_buffer_E != nullptr)) { + if (uses_global_buffer) { + global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self); + } else { + material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + global_buffer_E = nullptr; + } + } +} + +MaterialData::~MaterialData() { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + + if (global_buffer_E) { + //unregister global buffers + material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + } + + if (global_texture_E) { + //unregister global textures + + for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + if (v) { + v->texture_materials.erase(self); + } + } + //unregister material from those using global textures + material_storage->global_variables.materials_using_texture.erase(global_texture_E); + } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } +} + +void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { + TextureStorage *texture_storage = TextureStorage::get_singleton(); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + +#ifdef TOOLS_ENABLED + Texture *roughness_detect_texture = nullptr; + RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; + Texture *normal_detect_texture = nullptr; +#endif + + bool uses_global_textures = false; + global_textures_pass++; + + for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { + const StringName &uniform_name = p_texture_uniforms[i].name; + int uniform_array_size = p_texture_uniforms[i].array_size; + + Vector<RID> textures; + + if (p_texture_uniforms[i].global) { + uses_global_textures = true; + + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name); + if (v) { + if (v->buffer_index >= 0) { + WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); + + } else { + Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); + if (!E) { + E = used_global_textures.insert(uniform_name, global_textures_pass); + v->texture_materials.insert(self); + } else { + E->get() = global_textures_pass; + } + + textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); + } + + } else { + WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); + } + } else { + const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); + if (V) { + if (V->get().is_array()) { + Array array = (Array)V->get(); + if (uniform_array_size > 0) { + for (int j = 0; j < array.size(); j++) { + textures.push_back(array[j]); + } + } else { + if (array.size() > 0) { + textures.push_back(array[0]); + } + } + } else { + textures.push_back(V->get()); + } + } + + if (uniform_array_size > 0) { + if (textures.size() < uniform_array_size) { + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + for (int j = textures.size(); j < uniform_array_size; j++) { + if (W && W->get().has(j)) { + textures.push_back(W->get()[j]); + } else { + textures.push_back(RID()); + } + } + } + } else if (textures.is_empty()) { + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + if (W && W->get().has(0)) { + textures.push_back(W->get()[0]); + } + } + } + + RID rd_texture; + + if (textures.is_empty()) { + //check default usage + switch (p_texture_uniforms[i].type) { + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: + case ShaderLanguage::TYPE_SAMPLER2D: { + switch (p_texture_uniforms[i].hint) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; + default: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + } break; + } + } break; + + case ShaderLanguage::TYPE_SAMPLERCUBE: { + switch (p_texture_uniforms[i].hint) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + } break; + default: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); + } break; + } + } break; + case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + } break; + + case ShaderLanguage::TYPE_ISAMPLER3D: + case ShaderLanguage::TYPE_USAMPLER3D: + case ShaderLanguage::TYPE_SAMPLER3D: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + } break; + + case ShaderLanguage::TYPE_ISAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_SAMPLER2DARRAY: { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + } break; + + default: { + } + } +#ifdef TOOLS_ENABLED + if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { + roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); + } +#endif + if (uniform_array_size > 0) { + for (int j = 0; j < uniform_array_size; j++) { + p_textures[k++] = rd_texture; + } + } else { + p_textures[k++] = rd_texture; + } + } else { + bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); + + for (int j = 0; j < textures.size(); j++) { + Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); + + if (tex) { + rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; +#ifdef TOOLS_ENABLED + if (tex->detect_3d_callback && p_use_linear_color) { + tex->detect_3d_callback(tex->detect_3d_callback_ud); + } + if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { + if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { + normal_detect_texture = tex; + } + tex->detect_normal_callback(tex->detect_normal_callback_ud); + } + if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { + //find the normal texture + roughness_detect_texture = tex; + roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); + } +#endif + } + if (rd_texture.is_null()) { + rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + } +#ifdef TOOLS_ENABLED + if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { + roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); + } +#endif + p_textures[k++] = rd_texture; + } + } + } + { + //for textures no longer used, unregister them + List<Map<StringName, uint64_t>::Element *> to_delete; + for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { + if (E->get() != global_textures_pass) { + to_delete.push_back(E); + + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key()); + if (v) { + v->texture_materials.erase(self); + } + } + } + + while (to_delete.front()) { + used_global_textures.erase(to_delete.front()->get()); + to_delete.pop_front(); + } + //handle registering/unregistering global textures + if (uses_global_textures != (global_texture_E != nullptr)) { + if (uses_global_textures) { + global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self); + } else { + material_storage->global_variables.materials_using_texture.erase(global_texture_E); + global_texture_E = nullptr; + } + } + } +} + +void MaterialData::free_parameters_uniform_set(RID p_uniform_set) { + if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { + RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr); + RD::get_singleton()->free(p_uniform_set); + } +} + +bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { + if ((uint32_t)ubo_data.size() != p_ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(p_ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); + } + + uint32_t tex_uniform_count = 0U; + for (int i = 0; i < p_texture_uniforms.size(); i++) { + tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1); + } + + if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr); + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); + } + + if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { + // This material does not require an uniform set, so don't create it. + return false; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return false; + } + + Vector<RD::Uniform> uniforms; + + { + if (p_ubo_size) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.append_id(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) { + const int array_size = p_texture_uniforms[i].array_size; + + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1 + k; + if (array_size > 0) { + for (int j = 0; j < array_size; j++) { + u.append_id(textures[k++]); + } + } else { + u.append_id(textures[k++]); + } + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set); + + RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self); + + return true; +} + +/////////////////////////////////////////////////////////////////////////// +// MaterialStorage + +MaterialStorage *MaterialStorage::singleton = nullptr; + +MaterialStorage *MaterialStorage::get_singleton() { + return singleton; +} + +MaterialStorage::MaterialStorage() { + singleton = this; + + for (int i = 0; i < SHADER_TYPE_MAX; i++) { + shader_data_request_func[i] = nullptr; + } + + static_assert(sizeof(GlobalVariables::Value) == 16); + + global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); + global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); + memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); + global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); + global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); + memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); + global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); +} + +MaterialStorage::~MaterialStorage() { + memdelete_arr(global_variables.buffer_values); + memdelete_arr(global_variables.buffer_usage); + memdelete_arr(global_variables.buffer_dirty_regions); + RD::get_singleton()->free(global_variables.buffer); + + singleton = nullptr; +} + +/* GLOBAL VARIABLE API */ + +int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { + int32_t idx = 0; + while (idx + p_elements <= global_variables.buffer_size) { + if (global_variables.buffer_usage[idx].elements == 0) { + bool valid = true; + for (uint32_t i = 1; i < p_elements; i++) { + if (global_variables.buffer_usage[idx + i].elements > 0) { + valid = false; + idx += i + global_variables.buffer_usage[idx + i].elements; + break; + } + } + + if (!valid) { + continue; //if not valid, idx is in new position + } + + return idx; + } else { + idx += global_variables.buffer_usage[idx].elements; + } + } + + return -1; +} + +void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { + switch (p_type) { + case RS::GLOBAL_VAR_TYPE_BOOL: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + bool b = p_value; + bv.x = b ? 1.0 : 0.0; + bv.y = 0.0; + bv.z = 0.0; + bv.w = 0.0; + + } break; + case RS::GLOBAL_VAR_TYPE_BVEC2: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + uint32_t bvec = p_value; + bv.x = (bvec & 1) ? 1.0 : 0.0; + bv.y = (bvec & 2) ? 1.0 : 0.0; + bv.z = 0.0; + bv.w = 0.0; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC3: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + uint32_t bvec = p_value; + bv.x = (bvec & 1) ? 1.0 : 0.0; + bv.y = (bvec & 2) ? 1.0 : 0.0; + bv.z = (bvec & 4) ? 1.0 : 0.0; + bv.w = 0.0; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC4: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + uint32_t bvec = p_value; + bv.x = (bvec & 1) ? 1.0 : 0.0; + bv.y = (bvec & 2) ? 1.0 : 0.0; + bv.z = (bvec & 4) ? 1.0 : 0.0; + bv.w = (bvec & 8) ? 1.0 : 0.0; + } break; + case RS::GLOBAL_VAR_TYPE_INT: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + int32_t v = p_value; + bv.x = v; + bv.y = 0; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC2: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Vector2i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC3: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Vector3i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = v.z; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC4: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Vector<int32_t> v = p_value; + bv.x = v.size() >= 1 ? v[0] : 0; + bv.y = v.size() >= 2 ? v[1] : 0; + bv.z = v.size() >= 3 ? v[2] : 0; + bv.w = v.size() >= 4 ? v[3] : 0; + } break; + case RS::GLOBAL_VAR_TYPE_RECT2I: { + GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + Rect2i v = p_value; + bv.x = v.position.x; + bv.y = v.position.y; + bv.z = v.size.x; + bv.w = v.size.y; + } break; + case RS::GLOBAL_VAR_TYPE_UINT: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + uint32_t v = p_value; + bv.x = v; + bv.y = 0; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC2: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + Vector2i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC3: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + Vector3i v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = v.z; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC4: { + GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + Vector<int32_t> v = p_value; + bv.x = v.size() >= 1 ? v[0] : 0; + bv.y = v.size() >= 2 ? v[1] : 0; + bv.z = v.size() >= 3 ? v[2] : 0; + bv.w = v.size() >= 4 ? v[3] : 0; + } break; + case RS::GLOBAL_VAR_TYPE_FLOAT: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + float v = p_value; + bv.x = v; + bv.y = 0; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_VEC2: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Vector2 v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = 0; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_VEC3: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Vector3 v = p_value; + bv.x = v.x; + bv.y = v.y; + bv.z = v.z; + bv.w = 0; + } break; + case RS::GLOBAL_VAR_TYPE_VEC4: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Plane v = p_value; + bv.x = v.normal.x; + bv.y = v.normal.y; + bv.z = v.normal.z; + bv.w = v.d; + } break; + case RS::GLOBAL_VAR_TYPE_COLOR: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Color v = p_value; + bv.x = v.r; + bv.y = v.g; + bv.z = v.b; + bv.w = v.a; + + GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; + v = v.to_linear(); + bv_linear.x = v.r; + bv_linear.y = v.g; + bv_linear.z = v.b; + bv_linear.w = v.a; + + } break; + case RS::GLOBAL_VAR_TYPE_RECT2: { + GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + Rect2 v = p_value; + bv.x = v.position.x; + bv.y = v.position.y; + bv.z = v.size.x; + bv.w = v.size.y; + } break; + case RS::GLOBAL_VAR_TYPE_MAT2: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Vector<float> m2 = p_value; + if (m2.size() < 4) { + m2.resize(4); + } + bv[0].x = m2[0]; + bv[0].y = m2[1]; + bv[0].z = 0; + bv[0].w = 0; + + bv[1].x = m2[2]; + bv[1].y = m2[3]; + bv[1].z = 0; + bv[1].w = 0; + + } break; + case RS::GLOBAL_VAR_TYPE_MAT3: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Basis v = p_value; + bv[0].x = v.elements[0][0]; + bv[0].y = v.elements[1][0]; + bv[0].z = v.elements[2][0]; + bv[0].w = 0; + + bv[1].x = v.elements[0][1]; + bv[1].y = v.elements[1][1]; + bv[1].z = v.elements[2][1]; + bv[1].w = 0; + + bv[2].x = v.elements[0][2]; + bv[2].y = v.elements[1][2]; + bv[2].z = v.elements[2][2]; + bv[2].w = 0; + + } break; + case RS::GLOBAL_VAR_TYPE_MAT4: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + + Vector<float> m2 = p_value; + if (m2.size() < 16) { + m2.resize(16); + } + + bv[0].x = m2[0]; + bv[0].y = m2[1]; + bv[0].z = m2[2]; + bv[0].w = m2[3]; + + bv[1].x = m2[4]; + bv[1].y = m2[5]; + bv[1].z = m2[6]; + bv[1].w = m2[7]; + + bv[2].x = m2[8]; + bv[2].y = m2[9]; + bv[2].z = m2[10]; + bv[2].w = m2[11]; + + bv[3].x = m2[12]; + bv[3].y = m2[13]; + bv[3].z = m2[14]; + bv[3].w = m2[15]; + + } break; + case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Transform2D v = p_value; + bv[0].x = v.elements[0][0]; + bv[0].y = v.elements[0][1]; + bv[0].z = 0; + bv[0].w = 0; + + bv[1].x = v.elements[1][0]; + bv[1].y = v.elements[1][1]; + bv[1].z = 0; + bv[1].w = 0; + + bv[2].x = v.elements[2][0]; + bv[2].y = v.elements[2][1]; + bv[2].z = 1; + bv[2].w = 0; + + } break; + case RS::GLOBAL_VAR_TYPE_TRANSFORM: { + GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + Transform3D v = p_value; + bv[0].x = v.basis.elements[0][0]; + bv[0].y = v.basis.elements[1][0]; + bv[0].z = v.basis.elements[2][0]; + bv[0].w = 0; + + bv[1].x = v.basis.elements[0][1]; + bv[1].y = v.basis.elements[1][1]; + bv[1].z = v.basis.elements[2][1]; + bv[1].w = 0; + + bv[2].x = v.basis.elements[0][2]; + bv[2].y = v.basis.elements[1][2]; + bv[2].z = v.basis.elements[2][2]; + bv[2].w = 0; + + bv[3].x = v.origin.x; + bv[3].y = v.origin.y; + bv[3].z = v.origin.z; + bv[3].w = 1; + + } break; + default: { + ERR_FAIL(); + } + } +} + +void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { + int32_t prev_chunk = -1; + + for (int32_t i = 0; i < p_elements; i++) { + int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + if (chunk != prev_chunk) { + if (!global_variables.buffer_dirty_regions[chunk]) { + global_variables.buffer_dirty_regions[chunk] = true; + global_variables.buffer_dirty_region_count++; + } + } + + prev_chunk = chunk; + } +} + +void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { + ERR_FAIL_COND(global_variables.variables.has(p_name)); + GlobalVariables::Variable gv; + gv.type = p_type; + gv.value = p_value; + gv.buffer_index = -1; + + if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { + //is texture + global_variables.must_update_texture_materials = true; //normally there are none + } else { + gv.buffer_elements = 1; + if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { + //color needs to elements to store srgb and linear + gv.buffer_elements = 2; + } + if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) { + //color needs to elements to store srgb and linear + gv.buffer_elements = 3; + } + if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) { + //color needs to elements to store srgb and linear + gv.buffer_elements = 4; + } + + //is vector, allocate in buffer and update index + gv.buffer_index = _global_variable_allocate(gv.buffer_elements); + ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); + global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + + global_variables.must_update_buffer_materials = true; //normally there are none + } + + global_variables.variables[p_name] = gv; +} + +void MaterialStorage::global_variable_remove(const StringName &p_name) { + if (!global_variables.variables.has(p_name)) { + return; + } + GlobalVariables::Variable &gv = global_variables.variables[p_name]; + + if (gv.buffer_index >= 0) { + global_variables.buffer_usage[gv.buffer_index].elements = 0; + global_variables.must_update_buffer_materials = true; + } else { + global_variables.must_update_texture_materials = true; + } + + global_variables.variables.erase(p_name); +} + +Vector<StringName> MaterialStorage::global_variable_get_list() const { + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); + } + + const StringName *K = nullptr; + Vector<StringName> names; + while ((K = global_variables.variables.next(K))) { + names.push_back(*K); + } + names.sort_custom<StringName::AlphCompare>(); + return names; +} + +void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) { + ERR_FAIL_COND(!global_variables.variables.has(p_name)); + GlobalVariables::Variable &gv = global_variables.variables[p_name]; + gv.value = p_value; + if (gv.override.get_type() == Variant::NIL) { + if (gv.buffer_index >= 0) { + //buffer + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + } else { + //texture + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + Material *material = material_storage->get_material(E->get()); + ERR_CONTINUE(!material); + material_storage->_material_queue_update(material, false, true); + } + } + } +} + +void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) { + if (!global_variables.variables.has(p_name)) { + return; //variable may not exist + } + + ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); + + GlobalVariables::Variable &gv = global_variables.variables[p_name]; + + gv.override = p_value; + + if (gv.buffer_index >= 0) { + //buffer + if (gv.override.get_type() == Variant::NIL) { + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + } else { + _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); + } + + _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + } else { + //texture + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + Material *material = material_storage->get_material(E->get()); + ERR_CONTINUE(!material); + material_storage->_material_queue_update(material, false, true); + } + } +} + +Variant MaterialStorage::global_variable_get(const StringName &p_name) const { + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); + } + + if (!global_variables.variables.has(p_name)) { + return Variant(); + } + + return global_variables.variables[p_name].value; +} + +RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const { + if (!global_variables.variables.has(p_name)) { + return RS::GLOBAL_VAR_TYPE_MAX; + } + + return global_variables.variables[p_name].type; +} + +RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const { + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); + } + + return global_variable_get_type_internal(p_name); +} + +void MaterialStorage::global_variables_load_settings(bool p_load_textures) { + List<PropertyInfo> settings; + ProjectSettings::get_singleton()->get_property_list(&settings); + + for (const PropertyInfo &E : settings) { + if (E.name.begins_with("shader_globals/")) { + StringName name = E.name.get_slice("/", 1); + Dictionary d = ProjectSettings::get_singleton()->get(E.name); + + ERR_CONTINUE(!d.has("type")); + ERR_CONTINUE(!d.has("value")); + + String type = d["type"]; + + static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = { + "bool", + "bvec2", + "bvec3", + "bvec4", + "int", + "ivec2", + "ivec3", + "ivec4", + "rect2i", + "uint", + "uvec2", + "uvec3", + "uvec4", + "float", + "vec2", + "vec3", + "vec4", + "color", + "rect2", + "mat2", + "mat3", + "mat4", + "transform_2d", + "transform", + "sampler2D", + "sampler2DArray", + "sampler3D", + "samplerCube", + }; + + RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; + + for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { + if (global_var_type_names[i] == type) { + gvtype = RS::GlobalVariableType(i); + break; + } + } + + ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid + + Variant value = d["value"]; + + if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { + //textire + if (!p_load_textures) { + value = RID(); + continue; + } + + String path = value; + RES resource = ResourceLoader::load(path); + ERR_CONTINUE(resource.is_null()); + value = resource; + } + + if (global_variables.variables.has(name)) { + //has it, update it + global_variable_set(name, value); + } else { + global_variable_add(name, gvtype, value); + } + } + } +} + +void MaterialStorage::global_variables_clear() { + global_variables.variables.clear(); //not right but for now enough +} + +RID MaterialStorage::global_variables_get_storage_buffer() const { + return global_variables.buffer; +} + +int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) { + ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); + int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + global_variables.instance_buffer_pos[p_instance] = pos; //save anyway + ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); + global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; + return pos; +} + +void MaterialStorage::global_variables_instance_free(RID p_instance) { + ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); + int32_t pos = global_variables.instance_buffer_pos[p_instance]; + if (pos >= 0) { + global_variables.buffer_usage[pos].elements = 0; + } + global_variables.instance_buffer_pos.erase(p_instance); +} + +void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { + if (!global_variables.instance_buffer_pos.has(p_instance)) { + return; //just not allocated, ignore + } + int32_t pos = global_variables.instance_buffer_pos[p_instance]; + + if (pos < 0) { + return; //again, not allocated, ignore + } + ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported + + ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = { + ShaderLanguage::TYPE_MAX, //nil + ShaderLanguage::TYPE_BOOL, //bool + ShaderLanguage::TYPE_INT, //int + ShaderLanguage::TYPE_FLOAT, //float + ShaderLanguage::TYPE_MAX, //string + ShaderLanguage::TYPE_VEC2, //vec2 + ShaderLanguage::TYPE_IVEC2, //vec2i + ShaderLanguage::TYPE_VEC4, //rect2 + ShaderLanguage::TYPE_IVEC4, //rect2i + ShaderLanguage::TYPE_VEC3, // vec3 + ShaderLanguage::TYPE_IVEC3, //vec3i + ShaderLanguage::TYPE_MAX, //xform2d not supported here + ShaderLanguage::TYPE_VEC4, //plane + ShaderLanguage::TYPE_VEC4, //quat + ShaderLanguage::TYPE_MAX, //aabb not supported here + ShaderLanguage::TYPE_MAX, //basis not supported here + ShaderLanguage::TYPE_MAX, //xform not supported here + ShaderLanguage::TYPE_VEC4 //color + }; + + ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()]; + + ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported + + pos += p_index; + + _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer + _global_variable_mark_buffer_dirty(pos, 1); +} + +void MaterialStorage::_update_global_variables() { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + if (global_variables.buffer_dirty_region_count > 0) { + uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + if (total_regions / global_variables.buffer_dirty_region_count <= 4) { + // 25% of regions dirty, just update all buffer + RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values); + memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); + } else { + uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + + for (uint32_t i = 0; i < total_regions; i++) { + if (global_variables.buffer_dirty_regions[i]) { + RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); + + global_variables.buffer_dirty_regions[i] = false; + } + } + } + + global_variables.buffer_dirty_region_count = 0; + } + + if (global_variables.must_update_buffer_materials) { + // only happens in the case of a buffer variable added or removed, + // so not often. + for (const RID &E : global_variables.materials_using_buffer) { + Material *material = material_storage->get_material(E); + ERR_CONTINUE(!material); //wtf + + material_storage->_material_queue_update(material, true, false); + } + + global_variables.must_update_buffer_materials = false; + } + + if (global_variables.must_update_texture_materials) { + // only happens in the case of a buffer variable added or removed, + // so not often. + for (const RID &E : global_variables.materials_using_texture) { + Material *material = material_storage->get_material(E); + ERR_CONTINUE(!material); //wtf + + material_storage->_material_queue_update(material, false, true); + } + + global_variables.must_update_texture_materials = false; + } +} + +/* SHADER API */ + +RID MaterialStorage::shader_allocate() { + return shader_owner.allocate_rid(); +} + +void MaterialStorage::shader_initialize(RID p_rid) { + Shader shader; + shader.data = nullptr; + shader.type = SHADER_TYPE_MAX; + + shader_owner.initialize_rid(p_rid, shader); +} + +void MaterialStorage::shader_free(RID p_rid) { + Shader *shader = shader_owner.get_or_null(p_rid); + ERR_FAIL_COND(!shader); + + //make material unreference this + while (shader->owners.size()) { + material_set_shader(shader->owners.front()->get()->self, RID()); + } + + //clear data if exists + if (shader->data) { + memdelete(shader->data); + } + shader_owner.free(p_rid); +} + +void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + shader->code = p_code; + String mode_string = ShaderLanguage::get_shader_type(p_code); + + ShaderType new_type; + if (mode_string == "canvas_item") { + new_type = SHADER_TYPE_2D; + } else if (mode_string == "particles") { + new_type = SHADER_TYPE_PARTICLES; + } else if (mode_string == "spatial") { + new_type = SHADER_TYPE_3D; + } else if (mode_string == "sky") { + new_type = SHADER_TYPE_SKY; + } else if (mode_string == "fog") { + new_type = SHADER_TYPE_FOG; + } else { + new_type = SHADER_TYPE_MAX; + } + + if (new_type != shader->type) { + if (shader->data) { + memdelete(shader->data); + shader->data = nullptr; + } + + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + material->shader_type = new_type; + if (material->data) { + memdelete(material->data); + material->data = nullptr; + } + } + + shader->type = new_type; + + if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) { + shader->data = shader_data_request_func[new_type](); + } else { + shader->type = SHADER_TYPE_MAX; //invalid + } + + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + if (shader->data) { + material->data = material_get_data_request_function(new_type)(shader->data); + material->data->self = material->self; + material->data->set_next_pass(material->next_pass); + material->data->set_render_priority(material->priority); + } + material->shader_type = new_type; + } + + if (shader->data) { + for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<int, RID> &E2 : E.value) { + shader->data->set_default_texture_param(E.key, E2.value, E2.key); + } + } + } + } + + if (shader->data) { + shader->data->set_code(p_code); + } + + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + _material_queue_update(material, true, true); + } +} + +String MaterialStorage::shader_get_code(RID p_shader) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, String()); + return shader->code; +} + +void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + if (shader->data) { + return shader->data->get_param_list(p_param_list); + } +} + +void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) { + if (!shader->default_texture_parameter.has(p_name)) { + shader->default_texture_parameter[p_name] = Map<int, RID>(); + } + shader->default_texture_parameter[p_name][p_index] = p_texture; + } else { + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + shader->default_texture_parameter[p_name].erase(p_index); + + if (shader->default_texture_parameter[p_name].is_empty()) { + shader->default_texture_parameter.erase(p_name); + } + } + } + if (shader->data) { + shader->data->set_default_texture_param(p_name, p_texture, p_index); + } + for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + _material_queue_update(material, false, true); + } +} + +RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, RID()); + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + return shader->default_texture_parameter[p_name][p_index]; + } + + return RID(); +} + +Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, Variant()); + if (shader->data) { + return shader->data->get_default_parameter(p_param); + } + return Variant(); +} + +void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { + ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); + shader_data_request_func[p_shader_type] = p_function; +} + +RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); + if (shader->data) { + return shader->data->get_native_source_code(); + } + return RS::ShaderNativeSourceCode(); +} + +/* MATERIAL API */ + +void MaterialStorage::_material_uniform_set_erased(void *p_material) { + RID rid = *(RID *)p_material; + Material *material = MaterialStorage::get_singleton()->get_material(rid); + if (material) { + if (material->data) { + // Uniform set may be gone because a dependency was erased. This happens + // if a texture is deleted, so re-create it. + MaterialStorage::get_singleton()->_material_queue_update(material, false, true); + } + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + } +} + +void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { + material->uniform_dirty = material->uniform_dirty || p_uniform; + material->texture_dirty = material->texture_dirty || p_texture; + + if (material->update_element.in_list()) { + return; + } + + material_update_list.add(&material->update_element); +} + +void MaterialStorage::_update_queued_materials() { + while (material_update_list.first()) { + Material *material = material_update_list.first()->self(); + bool uniforms_changed = false; + + if (material->data) { + uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); + } + material->texture_dirty = false; + material->uniform_dirty = false; + + material_update_list.remove(&material->update_element); + + if (uniforms_changed) { + //some implementations such as 3D renderer cache the matreial uniform set, so update is required + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + } + } +} + +RID MaterialStorage::material_allocate() { + return material_owner.allocate_rid(); +} + +void MaterialStorage::material_initialize(RID p_rid) { + material_owner.initialize_rid(p_rid); + Material *material = material_owner.get_or_null(p_rid); + material->self = p_rid; +} + +void MaterialStorage::material_free(RID p_rid) { + Material *material = material_owner.get_or_null(p_rid); + ERR_FAIL_COND(!material); + + material_set_shader(p_rid, RID()); //clean up shader + material->dependency.deleted_notify(p_rid); + + material_owner.free(p_rid); +} + +void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + + if (material->data) { + memdelete(material->data); + material->data = nullptr; + } + + if (material->shader) { + material->shader->owners.erase(material); + material->shader = nullptr; + material->shader_type = SHADER_TYPE_MAX; + } + + if (p_shader.is_null()) { + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->shader_id = 0; + return; + } + + Shader *shader = get_shader(p_shader); + ERR_FAIL_COND(!shader); + material->shader = shader; + material->shader_type = shader->type; + material->shader_id = p_shader.get_local_index(); + shader->owners.insert(material); + + if (shader->type == SHADER_TYPE_MAX) { + return; + } + + ERR_FAIL_COND(shader->data == nullptr); + + material->data = material_data_request_func[shader->type](shader->data); + material->data->self = p_material; + material->data->set_next_pass(material->next_pass); + material->data->set_render_priority(material->priority); + //updating happens later + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + _material_queue_update(material, true, true); +} + +void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + + if (p_value.get_type() == Variant::NIL) { + material->params.erase(p_param); + } else { + ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed + material->params[p_param] = p_value; + } + + if (material->shader && material->shader->data) { //shader is valid + bool is_texture = material->shader->data->is_param_texture(p_param); + _material_queue_update(material, !is_texture, is_texture); + } else { + _material_queue_update(material, true, true); + } +} + +Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND_V(!material, Variant()); + if (material->params.has(p_param)) { + return material->params[p_param]; + } else { + return Variant(); + } +} + +void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + + if (material->next_pass == p_next_material) { + return; + } + + material->next_pass = p_next_material; + if (material->data) { + material->data->set_next_pass(p_next_material); + } + + material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); +} + +void MaterialStorage::material_set_render_priority(RID p_material, int priority) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + material->priority = priority; + if (material->data) { + material->data->set_render_priority(priority); + } +} + +bool MaterialStorage::material_is_animated(RID p_material) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND_V(!material, false); + if (material->shader && material->shader->data) { + if (material->shader->data->is_animated()) { + return true; + } else if (material->next_pass.is_valid()) { + return material_is_animated(material->next_pass); + } + } + return false; //by default nothing is animated +} + +bool MaterialStorage::material_casts_shadows(RID p_material) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND_V(!material, true); + if (material->shader && material->shader->data) { + if (material->shader->data->casts_shadows()) { + return true; + } else if (material->next_pass.is_valid()) { + return material_casts_shadows(material->next_pass); + } + } + return true; //by default everything casts shadows +} + +void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + if (material->shader && material->shader->data) { + material->shader->data->get_instance_param_list(r_parameters); + + if (material->next_pass.is_valid()) { + material_get_instance_shader_parameters(material->next_pass, r_parameters); + } + } +} + +void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) { + Material *material = material_owner.get_or_null(p_material); + ERR_FAIL_COND(!material); + p_instance->update_dependency(&material->dependency); + if (material->next_pass.is_valid()) { + material_update_dependency(material->next_pass, p_instance); + } +} + +void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { + ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); + material_data_request_func[p_shader_type] = p_function; +} + +MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) { + ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr); + return material_data_request_func[p_shader_type]; +} diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h new file mode 100644 index 0000000000..270d9f0982 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -0,0 +1,315 @@ +/*************************************************************************/ +/* material_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MATERIAL_STORAGE_RD_H +#define MATERIAL_STORAGE_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/shader_compiler.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering/storage/material_storage.h" + +namespace RendererRD { + +class MaterialStorage; + +/* SHADER Structs */ + +enum ShaderType { + SHADER_TYPE_2D, + SHADER_TYPE_3D, + SHADER_TYPE_PARTICLES, + SHADER_TYPE_SKY, + SHADER_TYPE_FOG, + SHADER_TYPE_MAX +}; + +struct ShaderData { + virtual void set_code(const String &p_Code) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; + virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; + + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; + virtual bool is_param_texture(const StringName &p_param) const = 0; + virtual bool is_animated() const = 0; + virtual bool casts_shadows() const = 0; + virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; + virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } + + virtual ~ShaderData() {} +}; + +typedef ShaderData *(*ShaderDataRequestFunction)(); + +struct Material; + +struct Shader { + ShaderData *data = nullptr; + String code; + ShaderType type; + Map<StringName, Map<int, RID>> default_texture_parameter; + Set<Material *> owners; +}; + +/* Material structs */ + +struct MaterialData { + void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + + virtual void set_render_priority(int p_priority) = 0; + virtual void set_next_pass(RID p_pass) = 0; + virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual ~MaterialData(); + + //to be used internally by update_parameters, in the most common configuration of material parameters + bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void free_parameters_uniform_set(RID p_uniform_set); + +private: + friend class MaterialStorage; + RID self; + List<RID>::Element *global_buffer_E = nullptr; + List<RID>::Element *global_texture_E = nullptr; + uint64_t global_textures_pass = 0; + Map<StringName, uint64_t> used_global_textures; + + //internally by update_parameters_uniform_set + Vector<uint8_t> ubo_data; + RID uniform_buffer; + Vector<RID> texture_cache; +}; + +typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); + +struct Material { + RID self; + MaterialData *data = nullptr; + Shader *shader = nullptr; + //shortcut to shader data and type + ShaderType shader_type = SHADER_TYPE_MAX; + uint32_t shader_id = 0; + bool uniform_dirty = false; + bool texture_dirty = false; + Map<StringName, Variant> params; + int32_t priority = 0; + RID next_pass; + SelfList<Material> update_element; + + RendererStorage::Dependency dependency; + + Material() : + update_element(this) {} +}; + +/* Global variable structs */ +struct GlobalVariables { + enum { + BUFFER_DIRTY_REGION_SIZE = 1024 + }; + struct Variable { + Set<RID> texture_materials; // materials using this + + RS::GlobalVariableType type; + Variant value; + Variant override; + int32_t buffer_index; //for vectors + int32_t buffer_elements; //for vectors + }; + + HashMap<StringName, Variable> variables; + + struct Value { + float x; + float y; + float z; + float w; + }; + + struct ValueInt { + int32_t x; + int32_t y; + int32_t z; + int32_t w; + }; + + struct ValueUInt { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; + }; + + struct ValueUsage { + uint32_t elements = 0; + }; + + List<RID> materials_using_buffer; + List<RID> materials_using_texture; + + RID buffer; + Value *buffer_values = nullptr; + ValueUsage *buffer_usage = nullptr; + bool *buffer_dirty_regions = nullptr; + uint32_t buffer_dirty_region_count = 0; + + uint32_t buffer_size; + + bool must_update_texture_materials = false; + bool must_update_buffer_materials = false; + + HashMap<RID, int32_t> instance_buffer_pos; +}; + +class MaterialStorage : public RendererMaterialStorage { +private: + friend struct MaterialData; + static MaterialStorage *singleton; + + /* GLOBAL VARIABLE API */ + + GlobalVariables global_variables; + + int32_t _global_variable_allocate(uint32_t p_elements); + void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); + void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); + + /* SHADER API */ + + ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner<Shader, true> shader_owner; + + /* MATERIAL API */ + MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner<Material, true> material_owner; + + SelfList<Material>::List material_update_list; + + static void _material_uniform_set_erased(void *p_material); + +public: + static MaterialStorage *get_singleton(); + + MaterialStorage(); + virtual ~MaterialStorage(); + + /* GLOBAL VARIABLE API */ + + void _update_global_variables(); + + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override; + virtual void global_variable_remove(const StringName &p_name) override; + virtual Vector<StringName> global_variable_get_list() const override; + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override; + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override; + virtual Variant global_variable_get(const StringName &p_name) const override; + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override; + RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; + + virtual void global_variables_load_settings(bool p_load_textures = true) override; + virtual void global_variables_clear() override; + + virtual int32_t global_variables_instance_allocate(RID p_instance) override; + virtual void global_variables_instance_free(RID p_instance) override; + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override; + + RID global_variables_get_storage_buffer() const; + + /* SHADER API */ + + Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }; + bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; + + virtual RID shader_allocate() override; + virtual void shader_initialize(RID p_shader) override; + virtual void shader_free(RID p_rid) override; + + virtual void shader_set_code(RID p_shader, const String &p_code) override; + virtual String shader_get_code(RID p_shader) const override; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override; + virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override; + void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override; + + /* MATERIAL API */ + + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; + bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; + + void _material_queue_update(Material *material, bool p_uniform, bool p_texture); + void _update_queued_materials(); + + virtual RID material_allocate() override; + virtual void material_initialize(RID p_material) override; + virtual void material_free(RID p_rid) override; + + virtual void material_set_shader(RID p_material, RID p_shader) override; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const override; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) override; + virtual void material_set_render_priority(RID p_material, int priority) override; + + virtual bool material_is_animated(RID p_material) override; + virtual bool material_casts_shadows(RID p_material) override; + + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; + + virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override; + + void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); + MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type); + + _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { + Material *material = material_owner.get_or_null(p_material); + return material->shader_id; + } + + _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { + Material *material = material_owner.get_or_null(p_material); + if (!material || material->shader_type != p_shader_type) { + return nullptr; + } else { + return material->data; + } + } +}; + +} // namespace RendererRD + +#endif // !MATERIAL_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp new file mode 100644 index 0000000000..8c60264ce3 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -0,0 +1,1921 @@ +/*************************************************************************/ +/* mesh_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "mesh_storage.h" + +using namespace RendererRD; + +MeshStorage *MeshStorage::singleton = nullptr; + +MeshStorage *MeshStorage::get_singleton() { + return singleton; +} + +MeshStorage::MeshStorage() { + singleton = this; + + default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); + + //default rd buffers + { + Vector<uint8_t> buffer; + { + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //normal + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //tangent + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //color + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 1.0; + fptr[2] = 1.0; + fptr[3] = 1.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //tex uv 1 + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + { //tex uv 2 + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //bones + buffer.resize(sizeof(uint32_t) * 4); + { + uint8_t *w = buffer.ptrw(); + uint32_t *fptr = (uint32_t *)w; + fptr[0] = 0; + fptr[1] = 0; + fptr[2] = 0; + fptr[3] = 0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + + { //weights + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + } + + { + Vector<String> skeleton_modes; + skeleton_modes.push_back("\n#define MODE_2D\n"); + skeleton_modes.push_back(""); + + skeleton_shader.shader.initialize(skeleton_modes); + skeleton_shader.version = skeleton_shader.shader.version_create(); + for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) { + skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i); + skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]); + } + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(default_rd_storage_buffer); + uniforms.push_back(u); + } + skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); + } + } +} + +MeshStorage::~MeshStorage() { + //def buffers + for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { + RD::get_singleton()->free(mesh_default_rd_buffers[i]); + } + + skeleton_shader.shader.version_free(skeleton_shader.version); + + RD::get_singleton()->free(default_rd_storage_buffer); + + singleton = nullptr; +} + +/* MESH API */ + +RID MeshStorage::mesh_allocate() { + return mesh_owner.allocate_rid(); +} + +void MeshStorage::mesh_initialize(RID p_rid) { + mesh_owner.initialize_rid(p_rid, Mesh()); +} + +void MeshStorage::mesh_free(RID p_rid) { + mesh_clear(p_rid); + mesh_set_shadow_mesh(p_rid, RID()); + Mesh *mesh = mesh_owner.get_or_null(p_rid); + mesh->dependency.deleted_notify(p_rid); + if (mesh->instances.size()) { + ERR_PRINT("deleting mesh with active instances"); + } + if (mesh->shadow_owners.size()) { + for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + Mesh *shadow_owner = E->get(); + shadow_owner->shadow_mesh = RID(); + shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + } + } + mesh_owner.free(p_rid); +} + +void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) { + ERR_FAIL_COND(p_blend_shape_count < 0); + + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + + ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist + + mesh->blend_shape_count = p_blend_shape_count; +} + +/// Returns stride +void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + + ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES); + +#ifdef DEBUG_ENABLED + //do a validation, to catch errors first + { + uint32_t stride = 0; + uint32_t attrib_stride = 0; + uint32_t skin_stride = 0; + + for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { + if ((p_surface.format & (1 << i))) { + switch (i) { + case RS::ARRAY_VERTEX: { + if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + stride += sizeof(float) * 2; + } else { + stride += sizeof(float) * 3; + } + + } break; + case RS::ARRAY_NORMAL: { + stride += sizeof(int32_t); + + } break; + case RS::ARRAY_TANGENT: { + stride += sizeof(int32_t); + + } break; + case RS::ARRAY_COLOR: { + attrib_stride += sizeof(uint32_t); + } break; + case RS::ARRAY_TEX_UV: { + attrib_stride += sizeof(float) * 2; + + } break; + case RS::ARRAY_TEX_UV2: { + attrib_stride += sizeof(float) * 2; + + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + int idx = i - RS::ARRAY_CUSTOM0; + uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; + uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + attrib_stride += fmtsize[fmt]; + + } break; + case RS::ARRAY_WEIGHTS: + case RS::ARRAY_BONES: { + //uses a separate array + bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS; + skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8); + } break; + } + } + } + + int expected_size = stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + + int bs_expected_size = expected_size * mesh->blend_shape_count; + + ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")"); + + int expected_attrib_size = attrib_stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")"); + + if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) { + expected_size = skin_stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + } + } + +#endif + + Mesh::Surface *s = memnew(Mesh::Surface); + + s->format = p_surface.format; + s->primitive = p_surface.primitive; + + bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); + + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); + s->vertex_buffer_size = p_surface.vertex_data.size(); + + if (p_surface.attribute_data.size()) { + s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); + } + if (p_surface.skin_data.size()) { + s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage); + s->skin_buffer_size = p_surface.skin_data.size(); + } + + s->vertex_count = p_surface.vertex_count; + + if (p_surface.format & RS::ARRAY_FORMAT_BONES) { + mesh->has_bone_weights = true; + } + + if (p_surface.index_count) { + bool is_index_16 = p_surface.vertex_count <= 65536; + + s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); + s->index_count = p_surface.index_count; + s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); + if (p_surface.lods.size()) { + s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); + s->lod_count = p_surface.lods.size(); + + for (int i = 0; i < p_surface.lods.size(); i++) { + uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); + s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); + s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); + s->lods[i].edge_length = p_surface.lods[i].edge_length; + s->lods[i].index_count = indices; + } + } + } + + s->aabb = p_surface.aabb; + s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. + + if (mesh->blend_shape_count > 0) { + s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data); + } + + if (use_as_storage) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(s->vertex_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (s->skin_buffer.is_valid()) { + u.append_id(s->skin_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (s->blend_shape_buffer.is_valid()) { + u.append_id(s->blend_shape_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + + s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE); + } + + if (mesh->surface_count == 0) { + mesh->bone_aabbs = p_surface.bone_aabbs; + mesh->aabb = p_surface.aabb; + } else { + if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) { + // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone + // Each surface may affect different numbers of bones. + mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); + } + for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { + mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); + } + mesh->aabb.merge_with(p_surface.aabb); + } + + s->material = p_surface.material; + + mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); + mesh->surfaces[mesh->surface_count] = s; + mesh->surface_count++; + + for (MeshInstance *mi : mesh->instances) { + _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); + } + + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + + for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + Mesh *shadow_owner = E->get(); + shadow_owner->shadow_mesh = RID(); + shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + } + + mesh->material_cache.clear(); +} + +int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const { + const Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, -1); + return mesh->blend_shape_count; +} + +void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_INDEX((int)p_mode, 2); + + mesh->blend_shape_mode = p_mode; +} + +RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); + return mesh->blend_shape_mode; +} + +void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); +} + +void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null()); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r); +} + +void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null()); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r); +} + +void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + mesh->surfaces[p_surface]->material = p_material; + + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + mesh->material_cache.clear(); +} + +RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RID()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); + + return mesh->surfaces[p_surface]->material; +} + +RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); + + Mesh::Surface &s = *mesh->surfaces[p_surface]; + + RS::SurfaceData sd; + sd.format = s.format; + sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + if (s.attribute_buffer.is_valid()) { + sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); + } + if (s.skin_buffer.is_valid()) { + sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer); + } + sd.vertex_count = s.vertex_count; + sd.index_count = s.index_count; + sd.primitive = s.primitive; + + if (sd.index_count) { + sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); + } + sd.aabb = s.aabb; + for (uint32_t i = 0; i < s.lod_count; i++) { + RS::SurfaceData::LOD lod; + lod.edge_length = s.lods[i].edge_length; + lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); + sd.lods.push_back(lod); + } + + sd.bone_aabbs = s.bone_aabbs; + + if (s.blend_shape_buffer.is_valid()) { + sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer); + } + + return sd; +} + +int MeshStorage::mesh_get_surface_count(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, 0); + return mesh->surface_count; +} + +void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + mesh->custom_aabb = p_aabb; +} + +AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, AABB()); + return mesh->custom_aabb; +} + +AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, AABB()); + + if (mesh->custom_aabb != AABB()) { + return mesh->custom_aabb; + } + + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + if (!skeleton || skeleton->size == 0) { + return mesh->aabb; + } + + AABB aabb; + + for (uint32_t i = 0; i < mesh->surface_count; i++) { + AABB laabb; + if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { + int bs = mesh->surfaces[i]->bone_aabbs.size(); + const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr(); + + int sbs = skeleton->size; + ERR_CONTINUE(bs > sbs); + const float *baseptr = skeleton->data.ptr(); + + bool first = true; + + if (skeleton->use_2d) { + for (int j = 0; j < bs; j++) { + if (skbones[0].size == Vector3()) { + continue; //bone is unused + } + + const float *dataptr = baseptr + j * 8; + + Transform3D mtx; + + mtx.basis.elements[0].x = dataptr[0]; + mtx.basis.elements[1].x = dataptr[1]; + mtx.origin.x = dataptr[3]; + + mtx.basis.elements[0].y = dataptr[4]; + mtx.basis.elements[1].y = dataptr[5]; + mtx.origin.y = dataptr[7]; + + AABB baabb = mtx.xform(skbones[j]); + + if (first) { + laabb = baabb; + first = false; + } else { + laabb.merge_with(baabb); + } + } + } else { + for (int j = 0; j < bs; j++) { + if (skbones[0].size == Vector3()) { + continue; //bone is unused + } + + const float *dataptr = baseptr + j * 12; + + Transform3D mtx; + + mtx.basis.elements[0][0] = dataptr[0]; + mtx.basis.elements[0][1] = dataptr[1]; + mtx.basis.elements[0][2] = dataptr[2]; + mtx.origin.x = dataptr[3]; + mtx.basis.elements[1][0] = dataptr[4]; + mtx.basis.elements[1][1] = dataptr[5]; + mtx.basis.elements[1][2] = dataptr[6]; + mtx.origin.y = dataptr[7]; + mtx.basis.elements[2][0] = dataptr[8]; + mtx.basis.elements[2][1] = dataptr[9]; + mtx.basis.elements[2][2] = dataptr[10]; + mtx.origin.z = dataptr[11]; + + AABB baabb = mtx.xform(skbones[j]); + if (first) { + laabb = baabb; + first = false; + } else { + laabb.merge_with(baabb); + } + } + } + + if (laabb.size == Vector3()) { + laabb = mesh->surfaces[i]->aabb; + } + } else { + laabb = mesh->surfaces[i]->aabb; + } + + if (i == 0) { + aabb = laabb; + } else { + aabb.merge_with(laabb); + } + } + + return aabb; +} + +void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + + Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); + if (shadow_mesh) { + shadow_mesh->shadow_owners.erase(mesh); + } + mesh->shadow_mesh = p_shadow_mesh; + + shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); + + if (shadow_mesh) { + shadow_mesh->shadow_owners.insert(mesh); + } + + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); +} + +void MeshStorage::mesh_clear(RID p_mesh) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!mesh); + for (uint32_t i = 0; i < mesh->surface_count; i++) { + Mesh::Surface &s = *mesh->surfaces[i]; + RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + if (s.attribute_buffer.is_valid()) { + RD::get_singleton()->free(s.attribute_buffer); + } + if (s.skin_buffer.is_valid()) { + RD::get_singleton()->free(s.skin_buffer); + } + if (s.versions) { + memfree(s.versions); //reallocs, so free with memfree. + } + + if (s.index_buffer.is_valid()) { + RD::get_singleton()->free(s.index_buffer); + } + + if (s.lod_count) { + for (uint32_t j = 0; j < s.lod_count; j++) { + RD::get_singleton()->free(s.lods[j].index_buffer); + } + memdelete_arr(s.lods); + } + + if (s.blend_shape_buffer.is_valid()) { + RD::get_singleton()->free(s.blend_shape_buffer); + } + + memdelete(mesh->surfaces[i]); + } + if (mesh->surfaces) { + memfree(mesh->surfaces); + } + + mesh->surfaces = nullptr; + mesh->surface_count = 0; + mesh->material_cache.clear(); + //clear instance data + for (MeshInstance *mi : mesh->instances) { + _mesh_instance_clear(mi); + } + mesh->has_bone_weights = false; + mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + + for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + Mesh *shadow_owner = E->get(); + shadow_owner->shadow_mesh = RID(); + shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + } +} + +bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, false); + + return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); +} + +/* MESH INSTANCE */ + +RID MeshStorage::mesh_instance_create(RID p_base) { + Mesh *mesh = mesh_owner.get_or_null(p_base); + ERR_FAIL_COND_V(!mesh, RID()); + + RID rid = mesh_instance_owner.make_rid(); + MeshInstance *mi = mesh_instance_owner.get_or_null(rid); + + mi->mesh = mesh; + + for (uint32_t i = 0; i < mesh->surface_count; i++) { + _mesh_instance_add_surface(mi, mesh, i); + } + + mi->I = mesh->instances.push_back(mi); + + mi->dirty = true; + + return rid; +} + +void MeshStorage::mesh_instance_free(RID p_rid) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid); + _mesh_instance_clear(mi); + mi->mesh->instances.erase(mi->I); + mi->I = nullptr; + + mesh_instance_owner.free(p_rid); +} + +void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + if (mi->skeleton == p_skeleton) { + return; + } + mi->skeleton = p_skeleton; + mi->skeleton_version = 0; + mi->dirty = true; +} + +void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + ERR_FAIL_COND(!mi); + ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size()); + mi->blend_weights[p_shape] = p_weight; + mi->weights_dirty = true; + //will be eventually updated +} + +void MeshStorage::_mesh_instance_clear(MeshInstance *mi) { + for (uint32_t i = 0; i < mi->surfaces.size(); i++) { + if (mi->surfaces[i].versions) { + for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { + RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); + } + memfree(mi->surfaces[i].versions); + } + if (mi->surfaces[i].vertex_buffer.is_valid()) { + RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); + } + } + mi->surfaces.clear(); + + if (mi->blend_weights_buffer.is_valid()) { + RD::get_singleton()->free(mi->blend_weights_buffer); + } + mi->blend_weights.clear(); + mi->weights_dirty = false; + mi->skeleton_version = 0; +} + +void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) { + if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) { + mi->blend_weights.resize(mesh->blend_shape_count); + for (uint32_t i = 0; i < mi->blend_weights.size(); i++) { + mi->blend_weights[i] = 0; + } + mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array()); + mi->weights_dirty = true; + } + + MeshInstance::Surface s; + if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { + //surface warrants transform + s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(s.vertex_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (mi->blend_weights_buffer.is_valid()) { + u.append_id(mi->blend_weights_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE); + } + + mi->surfaces.push_back(s); + mi->dirty = true; +} + +void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + + bool needs_update = mi->dirty; + + if (mi->weights_dirty && !mi->weight_update_list.in_list()) { + dirty_mesh_instance_weights.add(&mi->weight_update_list); + needs_update = true; + } + + if (mi->array_update_list.in_list()) { + return; + } + + if (!needs_update && mi->skeleton.is_valid()) { + Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); + if (sk && sk->version != mi->skeleton_version) { + needs_update = true; + } + } + + if (needs_update) { + dirty_mesh_instance_arrays.add(&mi->array_update_list); + } +} + +void MeshStorage::update_mesh_instances() { + while (dirty_mesh_instance_weights.first()) { + MeshInstance *mi = dirty_mesh_instance_weights.first()->self(); + + if (mi->blend_weights_buffer.is_valid()) { + RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr()); + } + dirty_mesh_instance_weights.remove(&mi->weight_update_list); + mi->weights_dirty = false; + } + if (dirty_mesh_instance_arrays.first() == nullptr) { + return; //nothing to do + } + + //process skeletons and blend shapes + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + while (dirty_mesh_instance_arrays.first()) { + MeshInstance *mi = dirty_mesh_instance_arrays.first()->self(); + + Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton); + + for (uint32_t i = 0; i < mi->surfaces.size(); i++) { + if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) { + continue; + } + + bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE); + if (sk && sk->uniform_set_mi.is_valid()) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON); + } + + SkeletonShader::PushConstant push_constant; + + push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL; + push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT; + push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES); + push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0; + + push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count; + push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; + + push_constant.blend_shape_count = mi->mesh->blend_shape_count; + push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; + push_constant.pad0 = 0; + push_constant.pad1 = 0; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant)); + + //dispatch without barrier, so all is done at the same time + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1); + } + + mi->dirty = false; + if (sk) { + mi->skeleton_version = sk->version; + } + dirty_mesh_instance_arrays.remove(&mi->array_update_list); + } + + RD::get_singleton()->compute_list_end(); +} + +void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) { + Vector<RD::VertexAttribute> attributes; + Vector<RID> buffers; + + uint32_t stride = 0; + uint32_t attribute_stride = 0; + uint32_t skin_stride = 0; + + for (int i = 0; i < RS::ARRAY_INDEX; i++) { + RD::VertexAttribute vd; + RID buffer; + vd.location = i; + + if (!(s->format & (1 << i))) { + // Not supplied by surface, use default value + buffer = mesh_default_rd_buffers[i]; + vd.stride = 0; + switch (i) { + case RS::ARRAY_VERTEX: { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + + } break; + case RS::ARRAY_NORMAL: { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } break; + case RS::ARRAY_TANGENT: { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + case RS::ARRAY_COLOR: { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + + } break; + case RS::ARRAY_TEX_UV: { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + + } break; + case RS::ARRAY_TEX_UV2: { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + case RS::ARRAY_BONES: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + } break; + case RS::ARRAY_WEIGHTS: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + } + } else { + //Supplied, use it + + vd.stride = 1; //mark that it needs a stride set (default uses 0) + + switch (i) { + case RS::ARRAY_VERTEX: { + vd.offset = stride; + + if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + stride += sizeof(float) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + stride += sizeof(float) * 3; + } + + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + + } break; + case RS::ARRAY_NORMAL: { + vd.offset = stride; + + vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + + stride += sizeof(uint32_t); + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + } break; + case RS::ARRAY_TANGENT: { + vd.offset = stride; + + vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + stride += sizeof(uint32_t); + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + } break; + case RS::ARRAY_COLOR: { + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + attribute_stride += sizeof(int8_t) * 4; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_TEX_UV: { + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + buffer = s->attribute_buffer; + + } break; + case RS::ARRAY_TEX_UV2: { + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + vd.offset = attribute_stride; + + int idx = i - RS::ARRAY_CUSTOM0; + uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; + uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; + vd.format = fmtrd[fmt]; + attribute_stride += fmtsize[fmt]; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_BONES: { + vd.offset = skin_stride; + + vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT; + skin_stride += sizeof(int16_t) * 4; + buffer = s->skin_buffer; + } break; + case RS::ARRAY_WEIGHTS: { + vd.offset = skin_stride; + + vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; + skin_stride += sizeof(int16_t) * 4; + buffer = s->skin_buffer; + } break; + } + } + + if (!(p_input_mask & (1 << i))) { + continue; // Shader does not need this, skip it (but computing stride was important anyway) + } + + attributes.push_back(vd); + buffers.push_back(buffer); + } + + //update final stride + for (int i = 0; i < attributes.size(); i++) { + if (attributes[i].stride == 0) { + continue; //default location + } + int loc = attributes[i].location; + + if (loc < RS::ARRAY_COLOR) { + attributes.write[i].stride = stride; + } else if (loc < RS::ARRAY_BONES) { + attributes.write[i].stride = attribute_stride; + } else { + attributes.write[i].stride = skin_stride; + } + } + + v.input_mask = p_input_mask; + v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); + v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); +} + +////////////////// MULTIMESH + +RID MeshStorage::multimesh_allocate() { + return multimesh_owner.allocate_rid(); +} +void MeshStorage::multimesh_initialize(RID p_rid) { + multimesh_owner.initialize_rid(p_rid, MultiMesh()); +} + +void MeshStorage::multimesh_free(RID p_rid) { + _update_dirty_multimeshes(); + multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); + MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid); + multimesh->dependency.deleted_notify(p_rid); + multimesh_owner.free(p_rid); +} + +void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + + if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { + return; + } + + if (multimesh->buffer.is_valid()) { + RD::get_singleton()->free(multimesh->buffer); + multimesh->buffer = RID(); + multimesh->uniform_set_2d = RID(); //cleared by dependency + multimesh->uniform_set_3d = RID(); //cleared by dependency + } + + if (multimesh->data_cache_dirty_regions) { + memdelete_arr(multimesh->data_cache_dirty_regions); + multimesh->data_cache_dirty_regions = nullptr; + multimesh->data_cache_used_dirty_regions = 0; + } + + multimesh->instances = p_instances; + multimesh->xform_format = p_transform_format; + multimesh->uses_colors = p_use_colors; + multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12; + multimesh->uses_custom_data = p_use_custom_data; + multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); + multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); + multimesh->buffer_set = false; + + //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); + multimesh->data_cache = Vector<float>(); + multimesh->aabb = AABB(); + multimesh->aabb_dirty = false; + multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); + + if (multimesh->instances) { + multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); + } + + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH); +} + +int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->instances; +} + +void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + if (multimesh->mesh == p_mesh) { + return; + } + multimesh->mesh = p_mesh; + + if (multimesh->instances == 0) { + return; + } + + if (multimesh->data_cache.size()) { + //we have a data cache, just mark it dirt + _multimesh_mark_all_dirty(multimesh, false, true); + } else if (multimesh->instances) { + //need to re-create AABB unfortunately, calling this has a penalty + if (multimesh->buffer_set) { + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + const uint8_t *r = buffer.ptr(); + const float *data = (const float *)r; + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + } + } + + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); +} + +#define MULTIMESH_DIRTY_REGION_SIZE 512 + +void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { + if (multimesh->data_cache.size() > 0) { + return; //already local + } + ERR_FAIL_COND(multimesh->data_cache.size() > 0); + // this means that the user wants to load/save individual elements, + // for this, the data must reside on CPU, so just copy it there. + multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); + { + float *w = multimesh->data_cache.ptrw(); + + if (multimesh->buffer_set) { + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + { + const uint8_t *r = buffer.ptr(); + memcpy(w, r, buffer.size()); + } + } else { + memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); + } + } + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + multimesh->data_cache_used_dirty_regions = 0; +} + +void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { + uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; +#ifdef DEBUG_ENABLED + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug +#endif + if (!multimesh->data_cache_dirty_regions[region_index]) { + multimesh->data_cache_dirty_regions[region_index] = true; + multimesh->data_cache_used_dirty_regions++; + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { + if (p_data) { + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + if (!multimesh->data_cache_dirty_regions[i]) { + multimesh->data_cache_dirty_regions[i] = true; + multimesh->data_cache_used_dirty_regions++; + } + } + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { + ERR_FAIL_COND(multimesh->mesh.is_null()); + AABB aabb; + AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); + for (int i = 0; i < p_instances; i++) { + const float *data = p_data + multimesh->stride_cache * i; + Transform3D t; + + if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) { + t.basis.elements[0][0] = data[0]; + t.basis.elements[0][1] = data[1]; + t.basis.elements[0][2] = data[2]; + t.origin.x = data[3]; + t.basis.elements[1][0] = data[4]; + t.basis.elements[1][1] = data[5]; + t.basis.elements[1][2] = data[6]; + t.origin.y = data[7]; + t.basis.elements[2][0] = data[8]; + t.basis.elements[2][1] = data[9]; + t.basis.elements[2][2] = data[10]; + t.origin.z = data[11]; + + } else { + t.basis.elements[0].x = data[0]; + t.basis.elements[1].x = data[1]; + t.origin.x = data[3]; + + t.basis.elements[0].y = data[4]; + t.basis.elements[1].y = data[5]; + t.origin.y = data[7]; + } + + if (i == 0) { + aabb = t.xform(mesh_aabb); + } else { + aabb.merge_with(t.xform(mesh_aabb)); + } + } + + multimesh->aabb = aabb; +} + +void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.basis.elements[0][0]; + dataptr[1] = p_transform.basis.elements[0][1]; + dataptr[2] = p_transform.basis.elements[0][2]; + dataptr[3] = p_transform.origin.x; + dataptr[4] = p_transform.basis.elements[1][0]; + dataptr[5] = p_transform.basis.elements[1][1]; + dataptr[6] = p_transform.basis.elements[1][2]; + dataptr[7] = p_transform.origin.y; + dataptr[8] = p_transform.basis.elements[2][0]; + dataptr[9] = p_transform.basis.elements[2][1]; + dataptr[10] = p_transform.basis.elements[2][2]; + dataptr[11] = p_transform.origin.z; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} + +void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.elements[0][0]; + dataptr[1] = p_transform.elements[1][0]; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2][0]; + dataptr[4] = p_transform.elements[0][1]; + dataptr[5] = p_transform.elements[1][1]; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2][1]; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} + +void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(!multimesh->uses_colors); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} + +void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(!multimesh->uses_custom_data); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} + +RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, RID()); + + return multimesh->mesh; +} + +Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform3D()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D()); + ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D()); + + _multimesh_make_local(multimesh); + + Transform3D t; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache; + + t.basis.elements[0][0] = dataptr[0]; + t.basis.elements[0][1] = dataptr[1]; + t.basis.elements[0][2] = dataptr[2]; + t.origin.x = dataptr[3]; + t.basis.elements[1][0] = dataptr[4]; + t.basis.elements[1][1] = dataptr[5]; + t.basis.elements[1][2] = dataptr[6]; + t.origin.y = dataptr[7]; + t.basis.elements[2][0] = dataptr[8]; + t.basis.elements[2][1] = dataptr[9]; + t.basis.elements[2][2] = dataptr[10]; + t.origin.z = dataptr[11]; + } + + return t; +} + +Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform2D()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); + ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D()); + + _multimesh_make_local(multimesh); + + Transform2D t; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache; + + t.elements[0][0] = dataptr[0]; + t.elements[1][0] = dataptr[1]; + t.elements[2][0] = dataptr[3]; + t.elements[0][1] = dataptr[4]; + t.elements[1][1] = dataptr[5]; + t.elements[2][1] = dataptr[7]; + } + + return t; +} + +Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} + +Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} + +void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); + + { + const float *r = p_buffer.ptr(); + RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r); + multimesh->buffer_set = true; + } + + if (multimesh->data_cache.size()) { + //if we have a data cache, just update it + multimesh->data_cache = p_buffer; + { + //clear dirty since nothing will be dirty anymore + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + multimesh->data_cache_used_dirty_regions = 0; + } + + _multimesh_mark_all_dirty(multimesh, false, true); //update AABB + } else if (multimesh->mesh.is_valid()) { + //if we have a mesh set, we need to re-generate the AABB from the new data + const float *data = p_buffer.ptr(); + + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + } +} + +Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Vector<float>()); + if (multimesh->buffer.is_null()) { + return Vector<float>(); + } else if (multimesh->data_cache.size()) { + return multimesh->data_cache; + } else { + //get from memory + + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + Vector<float> ret; + ret.resize(multimesh->instances * multimesh->stride_cache); + { + float *w = ret.ptrw(); + const uint8_t *r = buffer.ptr(); + memcpy(w, r, buffer.size()); + } + + return ret; + } +} + +void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); + if (multimesh->visible_instances == p_visible) { + return; + } + + if (multimesh->data_cache.size()) { + //there is a data cache.. + _multimesh_mark_all_dirty(multimesh, false, true); + } + + multimesh->visible_instances = p_visible; + + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); +} + +int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->visible_instances; +} + +AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, AABB()); + if (multimesh->aabb_dirty) { + const_cast<MeshStorage *>(this)->_update_dirty_multimeshes(); + } + return multimesh->aabb; +} + +void MeshStorage::_update_dirty_multimeshes() { + while (multimesh_dirty_list) { + MultiMesh *multimesh = multimesh_dirty_list; + + if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists + const float *data = multimesh->data_cache.ptr(); + + uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + + if (multimesh->data_cache_used_dirty_regions) { + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); + + if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { + //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much + RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); + } else { + //not that many regions? update them all + for (uint32_t i = 0; i < visible_region_count; i++) { + if (multimesh->data_cache_dirty_regions[i]) { + uint32_t offset = i * region_size; + uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); + uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i; + RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]); + } + } + } + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + + multimesh->data_cache_used_dirty_regions = 0; + } + + if (multimesh->aabb_dirty) { + //aabb is dirty.. + _multimesh_re_create_aabb(multimesh, data, visible_instances); + multimesh->aabb_dirty = false; + multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + } + } + + multimesh_dirty_list = multimesh->dirty_list; + + multimesh->dirty_list = nullptr; + multimesh->dirty = false; + } + + multimesh_dirty_list = nullptr; +} + +/* SKELETON API */ + +RID MeshStorage::skeleton_allocate() { + return skeleton_owner.allocate_rid(); +} +void MeshStorage::skeleton_initialize(RID p_rid) { + skeleton_owner.initialize_rid(p_rid, Skeleton()); +} + +void MeshStorage::skeleton_free(RID p_rid) { + _update_dirty_skeletons(); + skeleton_allocate_data(p_rid, 0); + Skeleton *skeleton = skeleton_owner.get_or_null(p_rid); + skeleton->dependency.deleted_notify(p_rid); + skeleton_owner.free(p_rid); +} + +void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) { + if (!skeleton->dirty) { + skeleton->dirty = true; + skeleton->dirty_list = skeleton_dirty_list; + skeleton_dirty_list = skeleton; + } +} + +void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND(!skeleton); + ERR_FAIL_COND(p_bones < 0); + + if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) { + return; + } + + skeleton->size = p_bones; + skeleton->use_2d = p_2d_skeleton; + skeleton->uniform_set_3d = RID(); + + if (skeleton->buffer.is_valid()) { + RD::get_singleton()->free(skeleton->buffer); + skeleton->buffer = RID(); + skeleton->data.clear(); + skeleton->uniform_set_mi = RID(); + } + + if (skeleton->size) { + skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12)); + skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float)); + memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float)); + + _skeleton_make_dirty(skeleton); + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.append_id(skeleton->buffer); + uniforms.push_back(u); + } + skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); + } + } + + skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA); +} + +int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND_V(!skeleton, 0); + + return skeleton->size; +} + +void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone, skeleton->size); + ERR_FAIL_COND(skeleton->use_2d); + + float *dataptr = skeleton->data.ptrw() + p_bone * 12; + + dataptr[0] = p_transform.basis.elements[0][0]; + dataptr[1] = p_transform.basis.elements[0][1]; + dataptr[2] = p_transform.basis.elements[0][2]; + dataptr[3] = p_transform.origin.x; + dataptr[4] = p_transform.basis.elements[1][0]; + dataptr[5] = p_transform.basis.elements[1][1]; + dataptr[6] = p_transform.basis.elements[1][2]; + dataptr[7] = p_transform.origin.y; + dataptr[8] = p_transform.basis.elements[2][0]; + dataptr[9] = p_transform.basis.elements[2][1]; + dataptr[10] = p_transform.basis.elements[2][2]; + dataptr[11] = p_transform.origin.z; + + _skeleton_make_dirty(skeleton); +} + +Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND_V(!skeleton, Transform3D()); + ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D()); + ERR_FAIL_COND_V(skeleton->use_2d, Transform3D()); + + const float *dataptr = skeleton->data.ptr() + p_bone * 12; + + Transform3D t; + + t.basis.elements[0][0] = dataptr[0]; + t.basis.elements[0][1] = dataptr[1]; + t.basis.elements[0][2] = dataptr[2]; + t.origin.x = dataptr[3]; + t.basis.elements[1][0] = dataptr[4]; + t.basis.elements[1][1] = dataptr[5]; + t.basis.elements[1][2] = dataptr[6]; + t.origin.y = dataptr[7]; + t.basis.elements[2][0] = dataptr[8]; + t.basis.elements[2][1] = dataptr[9]; + t.basis.elements[2][2] = dataptr[10]; + t.origin.z = dataptr[11]; + + return t; +} + +void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone, skeleton->size); + ERR_FAIL_COND(!skeleton->use_2d); + + float *dataptr = skeleton->data.ptrw() + p_bone * 8; + + dataptr[0] = p_transform.elements[0][0]; + dataptr[1] = p_transform.elements[1][0]; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2][0]; + dataptr[4] = p_transform.elements[0][1]; + dataptr[5] = p_transform.elements[1][1]; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2][1]; + + _skeleton_make_dirty(skeleton); +} + +Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND_V(!skeleton, Transform2D()); + ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); + ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); + + const float *dataptr = skeleton->data.ptr() + p_bone * 8; + + Transform2D t; + t.elements[0][0] = dataptr[0]; + t.elements[1][0] = dataptr[1]; + t.elements[2][0] = dataptr[3]; + t.elements[0][1] = dataptr[4]; + t.elements[1][1] = dataptr[5]; + t.elements[2][1] = dataptr[7]; + + return t; +} + +void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + + ERR_FAIL_COND(!skeleton->use_2d); + + skeleton->base_transform_2d = p_base_transform; +} + +void MeshStorage::_update_dirty_skeletons() { + while (skeleton_dirty_list) { + Skeleton *skeleton = skeleton_dirty_list; + + if (skeleton->size) { + RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr()); + } + + skeleton_dirty_list = skeleton->dirty_list; + + skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES); + + skeleton->version++; + + skeleton->dirty = false; + skeleton->dirty_list = nullptr; + } + + skeleton_dirty_list = nullptr; +} + +void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND(!skeleton); + + p_instance->update_dependency(&skeleton->dependency); +} diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h new file mode 100644 index 0000000000..e8da8ad563 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -0,0 +1,694 @@ +/*************************************************************************/ +/* mesh_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_STORAGE_RD_H +#define MESH_STORAGE_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering/storage/mesh_storage.h" + +namespace RendererRD { + +/* Mesh */ + +enum DefaultRDBuffer { + DEFAULT_RD_BUFFER_VERTEX, + DEFAULT_RD_BUFFER_NORMAL, + DEFAULT_RD_BUFFER_TANGENT, + DEFAULT_RD_BUFFER_COLOR, + DEFAULT_RD_BUFFER_TEX_UV, + DEFAULT_RD_BUFFER_TEX_UV2, + DEFAULT_RD_BUFFER_CUSTOM0, + DEFAULT_RD_BUFFER_CUSTOM1, + DEFAULT_RD_BUFFER_CUSTOM2, + DEFAULT_RD_BUFFER_CUSTOM3, + DEFAULT_RD_BUFFER_BONES, + DEFAULT_RD_BUFFER_WEIGHTS, + DEFAULT_RD_BUFFER_MAX, +}; + +struct MeshInstance; + +struct Mesh { + struct Surface { + RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; + uint32_t format = 0; + + RID vertex_buffer; + RID attribute_buffer; + RID skin_buffer; + uint32_t vertex_count = 0; + uint32_t vertex_buffer_size = 0; + uint32_t skin_buffer_size = 0; + + // A different pipeline needs to be allocated + // depending on the inputs available in the + // material. + // There are never that many geometry/material + // combinations, so a simple array is the most + // cache-efficient structure. + + struct Version { + uint32_t input_mask = 0; + RD::VertexFormatID vertex_format = 0; + RID vertex_array; + }; + + SpinLock version_lock; //needed to access versions + Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + + RID index_buffer; + RID index_array; + uint32_t index_count = 0; + + struct LOD { + float edge_length = 0.0; + uint32_t index_count = 0; + RID index_buffer; + RID index_array; + }; + + LOD *lods = nullptr; + uint32_t lod_count = 0; + + AABB aabb; + + Vector<AABB> bone_aabbs; + + RID blend_shape_buffer; + + RID material; + + uint32_t render_index = 0; + uint64_t render_pass = 0; + + uint32_t multimesh_render_index = 0; + uint64_t multimesh_render_pass = 0; + + uint32_t particles_render_index = 0; + uint64_t particles_render_pass = 0; + + RID uniform_set; + }; + + uint32_t blend_shape_count = 0; + RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; + + Surface **surfaces = nullptr; + uint32_t surface_count = 0; + + Vector<AABB> bone_aabbs; + + bool has_bone_weights = false; + + AABB aabb; + AABB custom_aabb; + + Vector<RID> material_cache; + + List<MeshInstance *> instances; + + RID shadow_mesh; + Set<Mesh *> shadow_owners; + + RendererStorage::Dependency dependency; +}; + +/* Mesh Instance */ + +struct MeshInstance { + Mesh *mesh = nullptr; + RID skeleton; + struct Surface { + RID vertex_buffer; + RID uniform_set; + + Mesh::Surface::Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + }; + LocalVector<Surface> surfaces; + LocalVector<float> blend_weights; + + RID blend_weights_buffer; + List<MeshInstance *>::Element *I = nullptr; //used to erase itself + uint64_t skeleton_version = 0; + bool dirty = false; + bool weights_dirty = false; + SelfList<MeshInstance> weight_update_list; + SelfList<MeshInstance> array_update_list; + MeshInstance() : + weight_update_list(this), array_update_list(this) {} +}; + +/* MultiMesh */ + +struct MultiMesh { + RID mesh; + int instances = 0; + RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; + bool uses_colors = false; + bool uses_custom_data = false; + int visible_instances = -1; + AABB aabb; + bool aabb_dirty = false; + bool buffer_set = false; + uint32_t stride_cache = 0; + uint32_t color_offset_cache = 0; + uint32_t custom_data_offset_cache = 0; + + Vector<float> data_cache; //used if individual setting is used + bool *data_cache_dirty_regions = nullptr; + uint32_t data_cache_used_dirty_regions = 0; + + RID buffer; //storage buffer + RID uniform_set_3d; + RID uniform_set_2d; + + bool dirty = false; + MultiMesh *dirty_list = nullptr; + + RendererStorage::Dependency dependency; +}; + +/* Skeleton */ + +struct SkeletonShader { + struct PushConstant { + uint32_t has_normal; + uint32_t has_tangent; + uint32_t has_skeleton; + uint32_t has_blend_shape; + + uint32_t vertex_count; + uint32_t vertex_stride; + uint32_t skin_stride; + uint32_t skin_weight_offset; + + uint32_t blend_shape_count; + uint32_t normalized_blend_shapes; + uint32_t pad0; + uint32_t pad1; + }; + + enum { + UNIFORM_SET_INSTANCE = 0, + UNIFORM_SET_SURFACE = 1, + UNIFORM_SET_SKELETON = 2, + }; + enum { + SHADER_MODE_2D, + SHADER_MODE_3D, + SHADER_MODE_MAX + }; + + SkeletonShaderRD shader; + RID version; + RID version_shader[SHADER_MODE_MAX]; + RID pipeline[SHADER_MODE_MAX]; + + RID default_skeleton_uniform_set; +}; + +struct Skeleton { + bool use_2d = false; + int size = 0; + Vector<float> data; + RID buffer; + + bool dirty = false; + Skeleton *dirty_list = nullptr; + Transform2D base_transform_2d; + + RID uniform_set_3d; + RID uniform_set_mi; + + uint64_t version = 1; + + RendererStorage::Dependency dependency; +}; + +class MeshStorage : public RendererMeshStorage { +private: + static MeshStorage *singleton; + + RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; + RID default_rd_storage_buffer; + + /* Mesh */ + + mutable RID_Owner<Mesh, true> mesh_owner; + + void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); + + /* Mesh Instance API */ + + void _mesh_instance_clear(MeshInstance *mi); + void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); + + mutable RID_Owner<MeshInstance> mesh_instance_owner; + + SelfList<MeshInstance>::List dirty_mesh_instance_weights; + SelfList<MeshInstance>::List dirty_mesh_instance_arrays; + + /* MultiMesh */ + + mutable RID_Owner<MultiMesh, true> multimesh_owner; + + MultiMesh *multimesh_dirty_list = nullptr; + + _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; + _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); + _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); + _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); + + /* Skeleton */ + + SkeletonShader skeleton_shader; + + mutable RID_Owner<Skeleton, true> skeleton_owner; + + _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton); + + Skeleton *skeleton_dirty_list = nullptr; + +public: + static MeshStorage *get_singleton(); + + MeshStorage(); + virtual ~MeshStorage(); + + RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } + + /* MESH API */ + + Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + + virtual RID mesh_allocate() override; + virtual void mesh_initialize(RID p_mesh) override; + virtual void mesh_free(RID p_rid) override; + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override; + + /// Return stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const override; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override; + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override; + + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override; + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override; + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override; + + virtual int mesh_get_surface_count(RID p_mesh) const override; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const override; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override; + virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override; + + virtual void mesh_clear(RID p_mesh) override; + + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override; + + _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, nullptr); + r_surface_count = mesh->surface_count; + if (r_surface_count == 0) { + return nullptr; + } + if (mesh->material_cache.is_empty()) { + mesh->material_cache.resize(mesh->surface_count); + for (uint32_t i = 0; i < r_surface_count; i++) { + mesh->material_cache.write[i] = mesh->surfaces[i]->material; + } + } + + return mesh->material_cache.ptr(); + } + + _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, nullptr); + ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr); + + return mesh->surfaces[p_surface_index]; + } + + _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RID()); + + return mesh->shadow_mesh; + } + + _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) { + Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface); + return surface->primitive; + } + + _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->lod_count > 0; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->index_count ? s->index_count : s->vertex_count; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + int32_t current_lod = -1; + if (r_index_count) { + *r_index_count = s->index_count; + } + for (uint32_t i = 0; i < s->lod_count; i++) { + float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold; + if (screen_size > p_mesh_lod_threshold) { + break; + } + current_lod = i; + } + if (current_lod == -1) { + return 0; + } else { + if (r_index_count) { + *r_index_count = s->lods[current_lod].index_count; + } + return current_lod + 1; + } + } + + _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + if (p_lod == 0) { + return s->index_array; + } else { + return s->lods[p_lod - 1].index_array; + } + } + + _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + s->version_lock.lock(); + + //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way + + for (uint32_t i = 0; i < s->version_count; i++) { + if (s->versions[i].input_mask != p_input_mask) { + continue; + } + //we have this version, hooray + r_vertex_format = s->versions[i].vertex_format; + r_vertex_array_rd = s->versions[i].vertex_array; + s->version_lock.unlock(); + return; + } + + uint32_t version = s->version_count; + s->version_count++; + s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); + + _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask); + + r_vertex_format = s->versions[version].vertex_format; + r_vertex_array_rd = s->versions[version].vertex_array; + + s->version_lock.unlock(); + } + + _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + ERR_FAIL_COND(!mi); + Mesh *mesh = mi->mesh; + ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); + + MeshInstance::Surface *mis = &mi->surfaces[p_surface_index]; + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + s->version_lock.lock(); + + //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way + + for (uint32_t i = 0; i < mis->version_count; i++) { + if (mis->versions[i].input_mask != p_input_mask) { + continue; + } + //we have this version, hooray + r_vertex_format = mis->versions[i].vertex_format; + r_vertex_array_rd = mis->versions[i].vertex_array; + s->version_lock.unlock(); + return; + } + + uint32_t version = mis->version_count; + mis->version_count++; + mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); + + _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis); + + r_vertex_format = mis->versions[version].vertex_format; + r_vertex_array_rd = mis->versions[version].vertex_array; + + s->version_lock.unlock(); + } + + _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { + ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); + return mesh_default_rd_buffers[p_buffer]; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->render_pass != p_render_pass) { + (*r_index)++; + s->render_pass = p_render_pass; + s->render_index = *r_index; + } + + return s->render_index; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->multimesh_render_pass != p_render_pass) { + (*r_index)++; + s->multimesh_render_pass = p_render_pass; + s->multimesh_render_index = *r_index; + } + + return s->multimesh_render_index; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->particles_render_pass != p_render_pass) { + (*r_index)++; + s->particles_render_pass = p_render_pass; + s->particles_render_index = *r_index; + } + + return s->particles_render_index; + } + + /* MESH INSTANCE API */ + + MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }; + bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }; + + virtual RID mesh_instance_create(RID p_base) override; + virtual void mesh_instance_free(RID p_rid) override; + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override; + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override; + virtual void mesh_instance_check_for_update(RID p_mesh_instance) override; + virtual void update_mesh_instances() override; + + /* MULTIMESH API */ + + MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }; + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + + virtual RID multimesh_allocate() override; + virtual void multimesh_initialize(RID p_multimesh) override; + virtual void multimesh_free(RID p_rid) override; + + virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override; + virtual int multimesh_get_instance_count(RID p_multimesh) const override; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override; + + virtual RID multimesh_get_mesh(RID p_multimesh) const override; + + virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override; + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override; + virtual int multimesh_get_visible_instances(RID p_multimesh) const override; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const override; + + void _update_dirty_multimeshes(); + + _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + return multimesh->xform_format; + } + + _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + return multimesh->uses_colors; + } + + _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + return multimesh->uses_custom_data; + } + + _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + if (multimesh->visible_instances >= 0) { + return multimesh->visible_instances; + } + return multimesh->instances; + } + + _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + if (!multimesh->uniform_set_3d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_3d; + } + + _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + if (!multimesh->uniform_set_2d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_2d; + } + + /* SKELETON API */ + + Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }; + bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }; + + virtual RID skeleton_allocate() override; + virtual void skeleton_initialize(RID p_skeleton) override; + virtual void skeleton_free(RID p_rid) override; + + virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override; + void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform); + virtual int skeleton_get_bone_count(RID p_skeleton) const override; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override; + virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override; + + virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override; + + void _update_dirty_skeletons(); + + _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) { + return skeleton_owner.get_or_null(p_skeleton) != nullptr; + } + + _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { + Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_COND_V(!skeleton, RID()); + ERR_FAIL_COND_V(skeleton->size == 0, RID()); + if (skeleton->use_2d) { + return RID(); + } + if (!skeleton->uniform_set_3d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(skeleton->buffer); + uniforms.push_back(u); + skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return skeleton->uniform_set_3d; + } +}; + +} // namespace RendererRD + +#endif // !MESH_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index f1a5383295..a3ca7d3720 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -949,7 +949,7 @@ void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { } String TextureStorage::texture_get_path(RID p_texture) const { - RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND_V(!tex, String()); return tex->path; diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp index 5843b9db24..84529ca400 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp @@ -36,7 +36,7 @@ void UniformSetCacheRD::_invalidate(Cache *p_cache) { if (p_cache->prev) { p_cache->prev->next = p_cache->next; } else { - // At begining of table + // At beginning of table uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE; hash_table[table_idx] = p_cache->next; } diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 0d5b98f1cb..1304c811f7 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -464,10 +464,10 @@ void RendererSceneCull::instance_initialize(RID p_rid) { } void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) { - bool needs_instance = RSG::storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid()); + bool needs_instance = RSG::mesh_storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid()); if (needs_instance != p_instance->mesh_instance.is_valid()) { if (needs_instance) { - p_instance->mesh_instance = RSG::storage->mesh_instance_create(p_instance->base); + p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base); } else { RSG::storage->free(p_instance->mesh_instance); @@ -488,7 +488,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) { } if (p_instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton); + RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton); } } @@ -890,7 +890,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight); + RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight); } } @@ -900,7 +900,7 @@ void RendererSceneCull::instance_set_surface_override_material(RID p_instance, i if (instance->base_type == RS::INSTANCE_MESH) { //may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case - instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base))); + instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base))); } ERR_FAIL_INDEX(p_surface, instance->materials.size()); @@ -997,7 +997,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) if (p_skeleton.is_valid()) { //update the dependency now, so if cleared, we remove it - RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker); + RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker); } _instance_queue_update(instance, true, true); @@ -1438,7 +1438,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c E->get().value = p_value; if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) { //update directly - RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value); + RSG::material_storage->global_variables_instance_update(p_instance, E->get().index, p_value); } } } @@ -1847,7 +1847,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { if (p_instance->custom_aabb) { new_aabb = *p_instance->custom_aabb; } else { - new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); + new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); } } break; @@ -1856,7 +1856,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { if (p_instance->custom_aabb) { new_aabb = *p_instance->custom_aabb; } else { - new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base); + new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base); } } break; @@ -2271,14 +2271,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance); } } shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0); shadow_data.light = light->instance; @@ -2348,14 +2348,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons animated_material_found = true; } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance); } } shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0); shadow_data.light = light->instance; @@ -2412,13 +2412,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } if (instance->mesh_instance.is_valid()) { - RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance); } } shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0); shadow_data.light = light->instance; @@ -3037,9 +3037,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (scene_cull_result.mesh_instances.size()) { for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) { - RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]); + RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]); } - RSG::storage->update_mesh_instances(); + RSG::mesh_storage->update_mesh_instances(); } } @@ -3627,9 +3627,9 @@ void RendererSceneCull::render_particle_colliders() { } void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { - List<RendererStorage::InstanceShaderParam> plist; - RSG::storage->material_get_instance_shader_parameters(p_material, &plist); - for (const RendererStorage::InstanceShaderParam &E : plist) { + List<RendererMaterialStorage::InstanceShaderParam> plist; + RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist); + for (const RendererMaterialStorage::InstanceShaderParam &E : plist) { StringName name = E.info.name; if (isparams.has(name)) { if (isparams[name].info.type != E.info.type) { @@ -3667,17 +3667,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->material_override.is_valid()) { - RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker); } if (p_instance->material_overlay.is_valid()) { - RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker); } if (p_instance->base_type == RS::INSTANCE_MESH) { //remove materials no longer used and un-own them - int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base); + int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base); p_instance->materials.resize(new_mat_count); _instance_update_mesh_instance(p_instance); @@ -3688,7 +3688,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { RID particle_material = RSG::storage->particles_get_process_material(p_instance->base); if (particle_material.is_valid()) { - RSG::storage->material_update_dependency(particle_material, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker); } } @@ -3704,10 +3704,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->material_override.is_valid()) { - if (!RSG::storage->material_casts_shadows(p_instance->material_override)) { + if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) { can_cast_shadows = false; } - is_animated = RSG::storage->material_is_animated(p_instance->material_override); + is_animated = RSG::material_storage->material_is_animated(p_instance->material_override); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override); } else { if (p_instance->base_type == RS::INSTANCE_MESH) { @@ -3717,22 +3717,22 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { bool cast_shadows = false; for (int i = 0; i < p_instance->materials.size(); i++) { - RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i); + RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i); if (!mat.is_valid()) { cast_shadows = true; } else { - if (RSG::storage->material_casts_shadows(mat)) { + if (RSG::material_storage->material_casts_shadows(mat)) { cast_shadows = true; } - if (RSG::storage->material_is_animated(mat)) { + if (RSG::material_storage->material_is_animated(mat)) { is_animated = true; } _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } } @@ -3742,28 +3742,28 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } } else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) { - RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base); + RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base); if (mesh.is_valid()) { bool cast_shadows = false; - int sc = RSG::storage->mesh_get_surface_count(mesh); + int sc = RSG::mesh_storage->mesh_get_surface_count(mesh); for (int i = 0; i < sc; i++) { - RID mat = RSG::storage->mesh_surface_get_material(mesh, i); + RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i); if (!mat.is_valid()) { cast_shadows = true; } else { - if (RSG::storage->material_casts_shadows(mat)) { + if (RSG::material_storage->material_casts_shadows(mat)) { cast_shadows = true; } - if (RSG::storage->material_is_animated(mat)) { + if (RSG::material_storage->material_is_animated(mat)) { is_animated = true; } _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } } @@ -3784,24 +3784,24 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { continue; } - int sc = RSG::storage->mesh_get_surface_count(mesh); + int sc = RSG::mesh_storage->mesh_get_surface_count(mesh); for (int j = 0; j < sc; j++) { - RID mat = RSG::storage->mesh_surface_get_material(mesh, j); + RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j); if (!mat.is_valid()) { cast_shadows = true; } else { - if (RSG::storage->material_casts_shadows(mat)) { + if (RSG::material_storage->material_casts_shadows(mat)) { cast_shadows = true; } - if (RSG::storage->material_is_animated(mat)) { + if (RSG::material_storage->material_is_animated(mat)) { is_animated = true; } _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } } } @@ -3813,8 +3813,8 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->material_overlay.is_valid()) { - can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay); - is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay); + can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay); + is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay); _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay); } @@ -3834,16 +3834,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) { p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0); if (p_instance->instance_allocated_shader_parameters) { - p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self); + p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self); scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset); for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) { if (E.value.value.get_type() != Variant::NIL) { - RSG::storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value); + RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value); } } } else { - RSG::storage->global_variables_instance_free(p_instance->self); + RSG::material_storage->global_variables_instance_free(p_instance->self); p_instance->instance_allocated_shader_parameters_offset = -1; scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1); } @@ -3851,7 +3851,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } if (p_instance->skeleton.is_valid()) { - RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker); + RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker); } p_instance->dependency_tracker.update_end(); @@ -3939,7 +3939,7 @@ bool RendererSceneCull::free(RID p_rid) { if (instance->instance_allocated_shader_parameters) { //free the used shader parameters - RSG::storage->global_variables_instance_free(instance->self); + RSG::material_storage->global_variables_instance_free(instance->self); } update_dirty_instances(); //in case something changed this diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 2112118673..5f71250ced 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -47,7 +47,7 @@ class RendererSceneCull : public RendererScene { public: - RendererSceneRender *scene_render; + RendererSceneRender *scene_render = nullptr; enum { SDFGI_MAX_CASCADES = 8, @@ -115,7 +115,7 @@ public: /* VISIBILITY NOTIFIER API */ - RendererSceneOcclusionCull *dummy_occlusion_culling; + RendererSceneOcclusionCull *dummy_occlusion_culling = nullptr; /* SCENARIO API */ @@ -273,7 +273,7 @@ public: union { uint64_t instance_data_rid; RendererSceneRender::GeometryInstance *instance_geometry; - InstanceVisibilityNotifierData *visibility_notifier; + InstanceVisibilityNotifierData *visibility_notifier = nullptr; }; Instance *instance = nullptr; int32_t parent_array_index = -1; @@ -365,8 +365,8 @@ public: /* INSTANCING API */ struct InstancePair { - Instance *a; - Instance *b; + Instance *a = nullptr; + Instance *b = nullptr; SelfList<InstancePair> list_a; SelfList<InstancePair> list_b; InstancePair() : @@ -409,7 +409,7 @@ public: bool dynamic_gi : 2; //same above for dynamic objects bool redraw_if_visible : 4; - Instance *lightmap; + Instance *lightmap = nullptr; Rect2 lightmap_uv_scale; int lightmap_slice_index; uint32_t lightmap_cull_index; @@ -455,7 +455,7 @@ public: SelfList<Instance> update_item; - AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? + AABB *custom_aabb = nullptr; // <Zylann> would using aabb directly with a bool be better? float extra_margin; ObjectID object_id; @@ -465,7 +465,7 @@ public: uint64_t version; // changes to this, and changes to base increase version - InstanceBaseData *base_data; + InstanceBaseData *base_data = nullptr; SelfList<InstancePair>::List pairs; uint64_t pair_check; @@ -597,7 +597,7 @@ public: }; struct InstanceReflectionProbeData : public InstanceBaseData { - Instance *owner; + Instance *owner = nullptr; Set<Instance *> geometries; @@ -613,7 +613,7 @@ public: }; struct InstanceDecalData : public InstanceBaseData { - Instance *owner; + Instance *owner = nullptr; RID instance; Set<Instance *> geometries; @@ -656,7 +656,7 @@ public: Set<Instance *> geometries; - Instance *baked_light; + Instance *baked_light = nullptr; RS::LightBakeMode bake_mode; uint32_t max_sdfgi_cascade = 2; @@ -671,7 +671,7 @@ public: }; struct InstanceVoxelGIData : public InstanceBaseData { - Instance *owner; + Instance *owner = nullptr; Set<Instance *> geometries; Set<Instance *> dynamic_geometries; @@ -1023,7 +1023,7 @@ public: struct VisibilityCullData { uint64_t viewport_mask; - Scenario *scenario; + Scenario *scenario = nullptr; Vector3 camera_position; uint32_t cull_offset; uint32_t cull_count; @@ -1035,12 +1035,12 @@ public: _FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask); struct CullData { - Cull *cull; - Scenario *scenario; + Cull *cull = nullptr; + Scenario *scenario = nullptr; RID shadow_atlas; Transform3D cam_transform; uint32_t visible_layers; - Instance *render_reflection_probe; + Instance *render_reflection_probe = nullptr; const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer; const CameraMatrix *camera_matrix; uint64_t visibility_viewport_mask; diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 5f9c4bb816..0b8734e68c 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -223,7 +223,7 @@ public: struct RenderSDFGIUpdateData { bool update_static = false; uint32_t static_cascade_count; - uint32_t *static_cascade_indices; + uint32_t *static_cascade_indices = nullptr; PagedArray<RID> *static_positional_lights; const Vector<RID> *directional_lights; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 69659aa62c..7bbd414465 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -65,7 +65,6 @@ public: Map<DependencyTracker *, uint32_t> instances; }; -public: struct DependencyTracker { void *userdata = nullptr; typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *); @@ -120,135 +119,6 @@ public: Set<Dependency *> dependencies; }; - /* SHADER API */ - - virtual RID shader_allocate() = 0; - virtual void shader_initialize(RID p_rid) = 0; - - virtual void shader_set_code(RID p_shader, const String &p_code) = 0; - virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; - virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; - - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; - - /* COMMON MATERIAL API */ - - virtual RID material_allocate() = 0; - virtual void material_initialize(RID p_rid) = 0; - - virtual void material_set_render_priority(RID p_material, int priority) = 0; - virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; - - virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; - virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; - - virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; - - virtual bool material_is_animated(RID p_material) = 0; - virtual bool material_casts_shadows(RID p_material) = 0; - - struct InstanceShaderParam { - PropertyInfo info; - int index; - Variant default_value; - }; - - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; - - virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0; - - /* MESH API */ - - virtual RID mesh_allocate() = 0; - virtual void mesh_initialize(RID p_rid) = 0; - - virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0; - - /// Returns stride - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; - - virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; - virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - - virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; - - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; - - virtual int mesh_get_surface_count(RID p_mesh) const = 0; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; - virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; - - virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0; - - virtual void mesh_clear(RID p_mesh) = 0; - - virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0; - - /* MESH INSTANCE */ - - virtual RID mesh_instance_create(RID p_base) = 0; - virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0; - virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0; - virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0; - virtual void update_mesh_instances() = 0; - - /* MULTIMESH API */ - - virtual RID multimesh_allocate() = 0; - virtual void multimesh_initialize(RID p_rid) = 0; - - virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; - - virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0; - virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; - virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; - - virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; - - virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; - virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - - virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; - virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; - virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; - - virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; - - /* SKELETON API */ - - virtual RID skeleton_allocate() = 0; - virtual void skeleton_initialize(RID p_rid) = 0; - - virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; - virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; - virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0; - virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; - virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - /* Light API */ virtual RID directional_light_allocate() = 0; @@ -324,7 +194,6 @@ public: virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0; virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; - virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; /* VOXEL GI API */ @@ -491,24 +360,6 @@ public: virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0; virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0; - /* GLOBAL VARIABLES */ - - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; - virtual void global_variable_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_variable_get_list() const = 0; - - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_variable_get(const StringName &p_name) const = 0; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; - - virtual void global_variables_load_settings(bool p_load_textures = true) = 0; - virtual void global_variables_clear() = 0; - - virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; - virtual void global_variables_instance_free(RID p_instance) = 0; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; - /* RENDER TARGET */ enum RenderTargetFlags { diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 2245d9a216..b6e44e8436 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -129,7 +129,7 @@ public: }; struct CanvasData { - CanvasBase *canvas; + CanvasBase *canvas = nullptr; Transform2D transform; int layer; int sublayer; diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 6ed4448638..1902b5f74a 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -528,6 +528,7 @@ public: /*********************/ struct AttachmentFormat { + enum { UNUSED_ATTACHMENT = 0xFFFFFFFF }; DataFormat format; TextureSamples samples; uint32_t usage_flags; @@ -729,7 +730,7 @@ public: int binding; // Binding index as specified in shader. private: - // In most cases only one ID is provided per binding, so avoid allocating memory unnecesarily for performance. + // In most cases only one ID is provided per binding, so avoid allocating memory unnecessarily for performance. RID id; // If only one is provided, this is used. Vector<RID> ids; // If multiple ones are provided, this is used instead. diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index d5a55c28f5..2dab7cb84c 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -400,6 +400,8 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : RSG::rasterizer = RendererCompositor::create(); RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage(); RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage(); + RSG::material_storage = RSG::rasterizer->get_material_storage(); + RSG::mesh_storage = RSG::rasterizer->get_mesh_storage(); RSG::texture_storage = RSG::rasterizer->get_texture_storage(); RSG::storage = RSG::rasterizer->get_storage(); RSG::canvas_render = RSG::rasterizer->get_canvas(); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index ea8e8aa056..cc1edc728a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -213,14 +213,13 @@ public: FUNC2(texture_set_force_redraw_if_visible, RID, bool) -//from now on, calls forwarded to this singleton + /* SHADER API */ + #undef ServerName #undef server_name -#define ServerName RendererStorage -#define server_name RSG::storage - - /* SHADER API */ +#define ServerName RendererMaterialStorage +#define server_name RSG::material_storage FUNCRIDSPLIT(shader) @@ -249,8 +248,15 @@ public: /* MESH API */ +//from now on, calls forwarded to this singleton +#undef ServerName +#undef server_name + +#define ServerName RendererMeshStorage +#define server_name RSG::mesh_storage + virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override { - RID mesh = RSG::storage->mesh_allocate(); + RID mesh = RSG::mesh_storage->mesh_allocate(); // TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!! @@ -258,16 +264,16 @@ public: if (Thread::get_caller_id() == server_thread) { command_queue.flush_if_pending(); } - RSG::storage->mesh_initialize(mesh); - RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count); + RSG::mesh_storage->mesh_initialize(mesh); + RSG::mesh_storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { - RSG::storage->mesh_add_surface(mesh, p_surfaces[i]); + RSG::mesh_storage->mesh_add_surface(mesh, p_surfaces[i]); } } else { - command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh); - command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count); + command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_initialize, mesh); + command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { - command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]); + command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_add_surface, mesh, p_surfaces[i]); } } @@ -342,6 +348,11 @@ public: FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &) /* Light API */ +#undef ServerName +#undef server_name + +#define ServerName RendererStorage +#define server_name RSG::storage FUNCRIDSPLIT(directional_light) FUNCRIDSPLIT(omni_light) @@ -870,8 +881,8 @@ public: #undef server_name #undef ServerName //from now on, calls forwarded to this singleton -#define ServerName RendererStorage -#define server_name RSG::storage +#define ServerName RendererMaterialStorage +#define server_name RSG::material_storage FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &) FUNC1(global_variable_remove, const StringName &) diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index fb93ae7383..2be87c27b1 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -34,6 +34,8 @@ bool RenderingServerGlobals::threaded = false; RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr; RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr; +RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr; +RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr; RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr; RendererStorage *RenderingServerGlobals::storage = nullptr; RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index 7d00318d8f..40fd638425 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -36,6 +36,8 @@ #include "servers/rendering/renderer_scene.h" #include "servers/rendering/storage/canvas_texture_storage.h" #include "servers/rendering/storage/decal_atlas_storage.h" +#include "servers/rendering/storage/material_storage.h" +#include "servers/rendering/storage/mesh_storage.h" #include "servers/rendering/storage/texture_storage.h" class RendererCanvasCull; @@ -47,6 +49,8 @@ public: static bool threaded; static RendererCanvasTextureStorage *canvas_texture_storage; + static RendererMaterialStorage *material_storage; + static RendererMeshStorage *mesh_storage; static RendererTextureStorage *texture_storage; static RendererDecalAtlasStorage *decal_atlas_storage; static RendererStorage *storage; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index a6f3a48398..a0769ef106 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2813,7 +2813,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI bool error = false; if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) { - const VariableNode *vn = (VariableNode *)p_func->arguments[arg]; + const VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg]); bool is_const = false; ConstantNode::Value value; @@ -2825,7 +2825,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } } else { if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) { - ConstantNode *cn = (ConstantNode *)p_func->arguments[arg]; + const ConstantNode *cn = static_cast<ConstantNode *>(p_func->arguments[arg]); if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) { int value = cn->values[0].sint; @@ -4132,7 +4132,7 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St bool ShaderLanguage::_check_node_constness(const Node *p_node) const { switch (p_node->type) { case Node::TYPE_OPERATOR: { - OperatorNode *op_node = (OperatorNode *)p_node; + const OperatorNode *op_node = static_cast<const OperatorNode *>(p_node); for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) { if (!_check_node_constness(op_node->arguments[i])) { return false; @@ -4142,13 +4142,13 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const { case Node::TYPE_CONSTANT: break; case Node::TYPE_VARIABLE: { - VariableNode *varn = (VariableNode *)p_node; + const VariableNode *varn = static_cast<const VariableNode *>(p_node); if (!varn->is_const) { return false; } } break; case Node::TYPE_ARRAY: { - ArrayNode *arrn = (ArrayNode *)p_node; + const ArrayNode *arrn = static_cast<const ArrayNode *>(p_node); if (!arrn->is_const) { return false; } @@ -5134,9 +5134,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } else if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_ARRAY; + } call_expression = _parse_and_reduce_expression(p_block, p_function_info); - p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_GLOBAL; + } if (!call_expression) { return nullptr; } @@ -5153,7 +5157,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index_expression->type == Node::TYPE_CONSTANT) { - ConstantNode *cnode = (ConstantNode *)index_expression; + ConstantNode *cnode = static_cast<ConstantNode *>(index_expression); if (cnode) { if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; @@ -5287,9 +5291,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!expr->is_indexed() && expr->get_array_size() > 0) { completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_ARRAY; + } Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info); - p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_GLOBAL; + } if (!call_expression) { return nullptr; } @@ -5587,9 +5595,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons mn->assign_expression = assign_expression; } else if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_ARRAY; + } Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info); - p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (p_block != nullptr) { + p_block->block_tag = SubClassTag::TAG_GLOBAL; + } if (!call_expression) { return nullptr; } @@ -5607,7 +5619,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index_expression->type == Node::TYPE_CONSTANT) { - ConstantNode *cnode = (ConstantNode *)index_expression; + ConstantNode *cnode = static_cast<ConstantNode *>(index_expression); if (cnode) { if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; @@ -6690,7 +6702,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } - if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) { _set_error(RTR("Expected a constant expression.")); return ERR_PARSE_ERROR; } @@ -6746,8 +6758,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!n) { return ERR_PARSE_ERROR; } - if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - OperatorNode *op = ((OperatorNode *)n); + if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) { + OperatorNode *op = static_cast<OperatorNode *>(n); for (int i = 1; i < op->arguments.size(); i++) { if (!_check_node_constness(op->arguments[i])) { _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1)); @@ -6791,7 +6803,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } while (tk.type == TK_COMMA); //another variable - p_block->statements.push_back((Node *)vdnode); + p_block->statements.push_back(static_cast<Node *>(vdnode)); } else if (tk.type == TK_CURLY_BRACKET_OPEN) { //a sub block, just because.. BlockNode *block = alloc_node<BlockNode>(); @@ -6913,7 +6925,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } else { Set<int> constants; for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. - ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; + ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]); if (flow) { if (flow->flow_op == FLOW_OP_CASE) { if (flow->expressions[0]->type == Node::TYPE_CONSTANT) { @@ -8455,7 +8467,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + if (n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) { _set_error(RTR("Expected constant expression.")); return ERR_PARSE_ERROR; } @@ -8511,8 +8523,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (!expr) { return ERR_PARSE_ERROR; } - if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { - OperatorNode *op = ((OperatorNode *)expr); + if (expr->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) { + OperatorNode *op = static_cast<OperatorNode *>(expr); for (int i = 1; i < op->arguments.size(); i++) { if (!_check_node_constness(op->arguments[i])) { _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1)); @@ -8849,7 +8861,7 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper for (int i = p_flow->blocks.size() - 1; i >= 0; i--) { if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) { - BlockNode *last_block = (BlockNode *)p_flow->blocks[i]; + BlockNode *last_block = static_cast<BlockNode *>(p_flow->blocks[i]); if (_find_last_flow_op_in_block(last_block, p_op) == OK) { found = true; break; @@ -8867,7 +8879,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat for (int i = p_block->statements.size() - 1; i >= 0; i--) { if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) { - ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i]; + ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]); if (flow->flow_op == p_op) { found = true; break; @@ -8878,7 +8890,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat } } } else if (p_block->statements[i]->type == Node::TYPE_BLOCK) { - BlockNode *block = (BlockNode *)p_block->statements[i]; + BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]); if (_find_last_flow_op_in_block(block, p_op) == OK) { found = true; break; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index e5ac14a7db..25ec8760af 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -386,7 +386,7 @@ public: return node; } - Node *nodes; + Node *nodes = nullptr; struct OperatorNode : public Node { DataType return_cache = TYPE_VOID; @@ -615,20 +615,20 @@ public: DataType type; StringName type_str; DataPrecision precision; - ConstantNode *initializer; + ConstantNode *initializer = nullptr; int array_size; }; struct Function { StringName name; - FunctionNode *function; + FunctionNode *function = nullptr; Set<StringName> uses_function; bool callable; }; struct Struct { StringName name; - StructNode *shader_struct; + StructNode *shader_struct = nullptr; }; struct Varying { @@ -715,7 +715,7 @@ public: bool is_op; union { Operator op; - Node *node; + Node *node = nullptr; }; }; @@ -973,7 +973,7 @@ private: Token _make_token(TokenType p_type, const StringName &p_text = StringName()); Token _get_token(); - ShaderNode *shader; + ShaderNode *shader = nullptr; enum IdentifierType { IDENTIFIER_FUNCTION, @@ -1021,7 +1021,7 @@ private: CompletionType completion_type; int completion_line; - BlockNode *completion_block; + BlockNode *completion_block = nullptr; DataType completion_base; bool completion_base_array; SubClassTag completion_class; diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h new file mode 100644 index 0000000000..f0363f129a --- /dev/null +++ b/servers/rendering/storage/material_storage.h @@ -0,0 +1,101 @@ +/*************************************************************************/ +/* material_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MATERIAL_STORAGE_H +#define MATERIAL_STORAGE_H + +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering_server.h" + +class RendererMaterialStorage { +public: + virtual ~RendererMaterialStorage(){}; + + /* GLOBAL VARIABLE API */ + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; + virtual void global_variable_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_variable_get_list() const = 0; + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual Variant global_variable_get(const StringName &p_name) const = 0; + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; + + virtual void global_variables_load_settings(bool p_load_textures = true) = 0; + virtual void global_variables_clear() = 0; + + virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; + virtual void global_variables_instance_free(RID p_instance) = 0; + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; + + /* SHADER API */ + virtual RID shader_allocate() = 0; + virtual void shader_initialize(RID p_rid) = 0; + virtual void shader_free(RID p_rid) = 0; + + virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual String shader_get_code(RID p_shader) const = 0; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; + virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; + + /* MATERIAL API */ + + virtual RID material_allocate() = 0; + virtual void material_initialize(RID p_rid) = 0; + virtual void material_free(RID p_rid) = 0; + + virtual void material_set_render_priority(RID p_material, int priority) = 0; + virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; + + virtual bool material_is_animated(RID p_material) = 0; + virtual bool material_casts_shadows(RID p_material) = 0; + + struct InstanceShaderParam { + PropertyInfo info; + int index; + Variant default_value; + }; + + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; + + virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) = 0; +}; + +#endif // !MATERIAL_STORAGE_H diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h new file mode 100644 index 0000000000..1dac51319c --- /dev/null +++ b/servers/rendering/storage/mesh_storage.h @@ -0,0 +1,136 @@ +/*************************************************************************/ +/* mesh_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_STORAGE_H +#define MESH_STORAGE_H + +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering_server.h" + +class RendererMeshStorage { +public: + virtual ~RendererMeshStorage() {} + + /* MESH API */ + + virtual RID mesh_allocate() = 0; + virtual void mesh_initialize(RID p_rid) = 0; + virtual void mesh_free(RID p_rid) = 0; + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0; + + /// Returns stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; + + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; + + virtual int mesh_get_surface_count(RID p_mesh) const = 0; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; + + virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0; + + virtual void mesh_clear(RID p_mesh) = 0; + + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0; + + /* MESH INSTANCE */ + + virtual RID mesh_instance_create(RID p_base) = 0; + virtual void mesh_instance_free(RID p_rid) = 0; + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0; + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0; + virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0; + virtual void update_mesh_instances() = 0; + + /* MULTIMESH API */ + + virtual RID multimesh_allocate() = 0; + virtual void multimesh_initialize(RID p_rid) = 0; + virtual void multimesh_free(RID p_rid) = 0; + + virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; + + virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; + + virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; + + /* SKELETON API */ + + virtual RID skeleton_allocate() = 0; + virtual void skeleton_initialize(RID p_rid) = 0; + virtual void skeleton_free(RID p_rid) = 0; + + virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; + virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0; + virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + + virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0; +}; + +#endif // !MESH_STORAGE_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 668bd31a49..fa6c3fac68 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -979,7 +979,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Invalid array format for surface."); Vector<uint8_t> blend_shape_data; - uint32_t blend_shape_count = 0; if (p_blend_shapes.size()) { uint32_t bs_format = format & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK; @@ -996,7 +995,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa ERR_FAIL_COND_V_MSG(err2 != OK, ERR_INVALID_DATA, "Invalid blend shape array format for surface."); blend_shape_data.append_array(vertex_array_shape); - blend_shape_count++; } } Vector<SurfaceData::LOD> lods; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index ec31885cae..2f32e81f06 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -758,7 +758,7 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, in int word_start = range.x; - int l_size = shaped_text_get_glyph_count(p_shaped); + const int l_size = shaped_text_get_glyph_count(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); for (int i = 0; i < l_size; i++) { |